Generate dataspace patterns from Nim types
This commit is contained in:
parent
1912574ed8
commit
a101a0ecb3
|
@ -1 +1 @@
|
|||
Subproject commit 1cf0df255f0f18d2e07fe43943f114a66ddb89e9
|
||||
Subproject commit 5f746706b6e36534c579a09d693924058325adf1
|
|
@ -1,18 +1,19 @@
|
|||
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
import std/[macros, tables, typetraits]
|
||||
import std/[tables, typetraits]
|
||||
import preserves/private/macros
|
||||
|
||||
import preserves
|
||||
import ./protocols/dataspacePatterns
|
||||
from ./actors import Ref
|
||||
|
||||
export dataspacePatterns.`$`
|
||||
export dataspacePatterns.`$`, PatternKind, DCompoundKind
|
||||
|
||||
type
|
||||
AnyAtom = dataspacePatterns.AnyAtom[Ref]
|
||||
AnyAtom* = dataspacePatterns.AnyAtom[Ref]
|
||||
DBind = dataspacePatterns.DBind[Ref]
|
||||
DCompound* = dataspacePatterns.DCompound[Ref]
|
||||
DCompound = dataspacePatterns.DCompound[Ref]
|
||||
DCompoundArr = dataspacePatterns.DCompoundArr[Ref]
|
||||
DCompoundDict = dataspacePatterns.DCompoundDict[Ref]
|
||||
DCompoundRec = dataspacePatterns.DCompoundRec[Ref]
|
||||
|
@ -74,40 +75,86 @@ proc `?`*(T: typedesc; bindings: sink openArray[(int, Pattern)]): Pattern =
|
|||
else:
|
||||
{.error: "no preserves pragma on " & $T.}
|
||||
|
||||
proc `?`*(T: typedesc): Pattern =
|
||||
proc `?`*(T: static typedesc): Pattern =
|
||||
## Derive a `Pattern` from type `T`.
|
||||
## This works for `tuple` and `object` types but in the
|
||||
## general case will return a wildcard binding.
|
||||
when T.hasCustomPragma(preservesRecord):
|
||||
when T is ref:
|
||||
?pointerBase(T)
|
||||
elif T.hasCustomPragma(preservesRecord):
|
||||
var
|
||||
label = tosymbol(T.getCustomPragmaVal(preservesRecord), Ref)
|
||||
fields = newSeq[Pattern]()
|
||||
dummy: ptr T
|
||||
for key, val in fieldPairs(dummy[]):
|
||||
fields.add grab()
|
||||
for key, val in fieldPairs(default T):
|
||||
fields.add ?(typeOf val)
|
||||
result = ?DCompound(
|
||||
orKind: DCompoundKind.rec,
|
||||
rec: DCompoundRec(
|
||||
label: label, fields: fields))
|
||||
elif T.hasCustomPragma(preservesTuple):
|
||||
var arr = DCompoundArr()
|
||||
for key, val in fieldPairs(default T):
|
||||
arr.items.add grab()
|
||||
?DCompound(
|
||||
orKind: DCompoundKind.arr,
|
||||
arr: arr)
|
||||
elif T.hasCustomPragma(preservesDictionary):
|
||||
var dict = DCompoundDict()
|
||||
for key, val in fieldPairs(default T):
|
||||
dict.entries[key.toSymbol(Ref)] = ?(typeOf val)
|
||||
?DCompound(
|
||||
orKind: DCompoundKind.dict,
|
||||
dict: dict)
|
||||
elif T is tuple:
|
||||
var
|
||||
arr = DCompoundArr()
|
||||
dummy: ptr T
|
||||
for key, val in fieldPairs(dummy[]):
|
||||
var arr = DCompoundArr()
|
||||
for key, val in fieldPairs(default T):
|
||||
arr.items.add ?(typeOf val)
|
||||
result = ?DCompound(
|
||||
orKind: DCompoundKind.arr,
|
||||
arr: arr)
|
||||
elif T is object:
|
||||
var
|
||||
dict = DCompoundDict()
|
||||
dummy: ptr T
|
||||
for key, val in fieldPairs(dummy[]):
|
||||
dict.entries[key.toSymbol(Ref)] = grab() #?(typeOf val)
|
||||
var dict = DCompoundDict()
|
||||
for key, val in fieldPairs(default T):
|
||||
dict.entries[key.toSymbol(Ref)] = ?(typeOf val)
|
||||
result = ?DCompound(
|
||||
orKind: DCompoundKind.dict,
|
||||
dict: dict)
|
||||
elif T is ref:
|
||||
?pointerBase(T)
|
||||
else:
|
||||
grab() # capture any value
|
||||
|
||||
type
|
||||
Value = Preserve[Ref]
|
||||
Path = seq[Value]
|
||||
Analysis* = tuple
|
||||
constPaths: seq[Path]
|
||||
constValues: seq[Value]
|
||||
capturePaths: seq[Path]
|
||||
|
||||
func walk(result: var Analysis; path: var Path; p: Pattern)
|
||||
|
||||
func walk(result: var Analysis; path: var Path; key: int|Value; pat: Pattern) =
|
||||
path.add(key.toPreserve(Ref))
|
||||
walk(result, path, pat)
|
||||
discard path.pop
|
||||
|
||||
func walk(result: var Analysis; path: var Path; p: Pattern) =
|
||||
case p.orKind
|
||||
of PatternKind.DCompound:
|
||||
case p.dcompound.orKind
|
||||
of DCompoundKind.rec:
|
||||
for k, e in p.dcompound.rec.fields: walk(result, path, k, e)
|
||||
of DCompoundKind.arr:
|
||||
for k, e in p.dcompound.arr.items: walk(result, path, k, e)
|
||||
of DCompoundKind.dict:
|
||||
for k, e in p.dcompound.dict.entries: walk(result, path, k, e)
|
||||
of PatternKind.DBind:
|
||||
result.capturePaths.add(path)
|
||||
walk(result, path, p.dbind.pattern)
|
||||
of PatternKind.DDiscard: discard
|
||||
of PatternKind.DLit:
|
||||
result.constPaths.add(path)
|
||||
result.constValues.add(p.dlit.value.toPreserve(Ref))
|
||||
|
||||
func analyse*(p: Pattern): Analysis =
|
||||
var path: Path
|
||||
walk(result, path, p)
|
||||
|
|
Loading…
Reference in New Issue