Cannonicalize values at toPreserve

This commit is contained in:
Emery Hemingway 2023-06-11 21:26:58 +01:00
parent a7a90097a8
commit fa5441bd01
1 changed files with 9 additions and 0 deletions

View File

@ -833,6 +833,7 @@ proc toPreserve*[T](x: T; E = void): Preserve[E] =
result = cast[Preserve[E]](x)
elif compiles(toPreserveHook(x, E)):
result = toPreserveHook(x, E)
cannonicalize(result)
elif T is enum:
result = toSymbol($x, E)
elif T is seq[byte]:
@ -843,6 +844,7 @@ proc toPreserve*[T](x: T; E = void): Preserve[E] =
elif T is set:
result = Preserve[E](kind: pkSet, set: newSeqOfCap[Preserve[E]](x.len))
for v in x.items: result.incl(toPreserve(v, E))
cannonicalize(result)
elif T is bool:
result = Preserve[E](kind: pkBoolean, bool: x)
elif T is float32:
@ -914,6 +916,7 @@ proc toPreserve*[T](x: T; E = void): Preserve[E] =
var pr = fieldToPreserve(key, val)
applyEmbed(key, pr)
result[toSymbol(key, E)] = pr
cannonicalize(result)
else:
{.warning: "failed to preserve object " & $T .}
result = toPreserveHook(x, E)
@ -927,12 +930,14 @@ proc toPreserveHook*[T](set: HashSet[T]; E: typedesc): Preserve[E] =
## Hook for preserving ``HashSet``.
result = Preserve[E](kind: pkSet, set: newSeqOfCap[Preserve[E]](set.len))
for e in set: result.incl toPreserve(e, E)
cannonicalize(result)
proc toPreserveHook*[A, B](table: Table[A, B]|TableRef[A, B], E: typedesc): Preserve[E] =
## Hook for preserving ``Table``.
result = initDictionary(E)
for k, v in table.pairs:
result[toPreserve(k, E)] = toPreserve(v, E)
cannonicalize(result)
func containsNativeEmbeds[E](pr: Preserve[E]): bool =
## Check if a `Preserve[E]` is convertible to `Preserve[void]`.
@ -1216,6 +1221,7 @@ proc apply*[E](result: var Preserve[E]; op: proc(_: var Preserve[E])) =
apply(result.dict) do (e: var DictEntry[E]):
recurse(e.key)
recurse(e.val)
cannonicalize(result)
proc mapEmbeds*(pr: sink Preserve[void]; E: typedesc): Preserve[E] =
## Convert `Preserve[void]` to `Preserve[E]` using `fromPreserve` for `E`.
@ -1294,6 +1300,7 @@ proc mapEmbeds*[A, B](pr: sink Preserve[A]; op: proc (v: A): B): Preserve[B] =
(mapEmbeds(e.key, op), mapEmbeds(e.val, op))
of pkEmbedded:
result = embed op(pr.embed)
cannonicalize(result)
proc contract*[E](pr: sink Preserve[E]; op: proc (v: E): Preserve[void]): Preserve[void] =
## Convert `Preserve[E]` to `Preserve[void]` using an `E → Preserve[void]` procedure.
@ -1319,6 +1326,7 @@ proc contract*[E](pr: sink Preserve[E]; op: proc (v: E): Preserve[void]): Preser
(contract(e.key, op), contract(e.val, op))
of pkEmbedded:
result = embed op(pr.embed)
cannonicalize(result)
proc expand*[E](pr: sink Preserve[void]; op: proc (v: Preserve[void]): Preserve[E]): Preserve[E] =
## Convert `Preserve[void]` to `Preserve[E]` using an `Preserve[void] → Preserve[E]` procedure.
@ -1346,6 +1354,7 @@ proc expand*[E](pr: sink Preserve[void]; op: proc (v: Preserve[void]): Preserve[
(expand(e.key, op), expand(e.val, op))
of pkEmbedded:
result = op(pr.embed)
cannonicalize(result)
proc getOrDefault*[T, V](pr: Preserve[T]; key: string; default: V): V =
## Retrieves the value of `pr[key]` if `pr` is a dictionary containing `key`