Add expand, contract for embedded conversions

This commit is contained in:
Emery Hemingway 2022-12-07 03:23:10 -06:00
parent c9268b2a5d
commit 92834a8968
1 changed files with 50 additions and 0 deletions

View File

@ -1213,6 +1213,56 @@ proc mapEmbeds*[A, B](pr: sink Preserve[A]; op: proc (v: A): B): Preserve[B] =
of pkEmbedded:
result = embed op(pr.embed)
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.
if not pr.embedded:
case pr.kind
of pkBoolean, pkFloat, pkDouble, pkSignedInteger, pkString, pkByteString, pkSymbol:
result = cast[Preserve[void]](pr)
of pkRecord:
result = Preserve[void](kind: pr.kind)
result.record = map(pr.record) do (x: Preserve[E]) -> Preserve[void]:
contract(x, op)
of pkSequence:
result = Preserve[void](kind: pr.kind)
result.sequence = map(pr.sequence) do (x: Preserve[E]) -> Preserve[void]:
contract(x, op)
of pkSet:
result = Preserve[void](kind: pr.kind)
result.set = map(pr.set) do (x: Preserve[E]) -> Preserve[void]:
contract(x, op)
of pkDictionary:
result = Preserve[void](kind: pr.kind)
result.dict = map(pr.dict) do (e: DictEntry[E]) -> DictEntry[void]:
(contract(e.key, op), contract(e.val, op))
of pkEmbedded:
result = embed op(pr.embed)
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.
if not pr.embedded:
case pr.kind
of pkBoolean, pkFloat, pkDouble, pkSignedInteger, pkString, pkByteString, pkSymbol:
result = cast[Preserve[E]](pr)
of pkRecord:
result = Preserve[E](kind: pr.kind)
result.record = map(pr.record) do (x: Preserve[void]) -> Preserve[E]:
expand(x, op)
of pkSequence:
result = Preserve[E](kind: pr.kind)
result.sequence = map(pr.sequence) do (x: Preserve[void]) -> Preserve[E]:
expand(x, op)
of pkSet:
result = Preserve[E](kind: pr.kind)
result.set = map(pr.set) do (x: Preserve[void]) -> Preserve[E]:
expand(x, op)
of pkDictionary:
result = Preserve[E](kind: pr.kind)
result.dict = map(pr.dict) do (e: DictEntry[void]) -> DictEntry[E]:
(expand(e.key, op), expand(e.val, op))
of pkEmbedded:
result = op(pr.embed)
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`
## or returns the `default` value.