diff --git a/src/preserves.nim b/src/preserves.nim index b5d8d3d..3c40733 100644 --- a/src/preserves.nim +++ b/src/preserves.nim @@ -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`