From b4fd18ffcd66259d8987b96e214aba707534f63e Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Wed, 8 Jun 2022 20:19:12 -0500 Subject: [PATCH] Generate literal patterns for values --- src/syndicate.nim | 13 +++++--- src/syndicate/patterns.nim | 62 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/syndicate.nim b/src/syndicate.nim index d322fb1..928d7dd 100644 --- a/src/syndicate.nim +++ b/src/syndicate.nim @@ -31,7 +31,7 @@ import ./syndicate/[actors, dataspaces, durings, patterns] from ./syndicate/relays import connectStdio, connectUnix export Assertion, Facet, Handle, Ref, Symbol, Turn, TurnAction, bootDataspace, - `$`, connectStdio, connectUnix, drop, facet, grab, message, publish, + `$`, `?`, connectStdio, connectUnix, drop, facet, grab, message, publish, retract, replace, run, stop, unembed proc `?`*(T: static typedesc): Pattern = @@ -81,7 +81,11 @@ proc `?`*(T: static typedesc): Pattern = else: grab() # otherwise an abritrary capture -proc `?`*(T: typedesc; bindings: sink openArray[(int, Pattern)]): Pattern = +proc fieldCount(T: typedesc): int = + for _, _ in fieldPairs(default T): + inc result + +proc `?`*(T: static typedesc; bindings: sink openArray[(int, Pattern)]): Pattern = ## Construct a `Pattern` from type `T` that selectively captures fields. runnableExamples: import preserves @@ -94,11 +98,10 @@ proc `?`*(T: typedesc; bindings: sink openArray[(int, Pattern)]): Pattern = elif T.hasPreservesRecordPragma: var label = T.recordLabel.tosymbol(Ref) - fields = newSeq[Pattern]() + fields = newSeq[Pattern](fieldCount T) for (i, pat) in bindings: - if i > fields.high: fields.setLen(succ i) fields[i] = pat - for pat in bindings.mitems: + for pat in fields.mitems: if pat.isNil: pat = drop() result = ?DCompound( orKind: DCompoundKind.rec, diff --git a/src/syndicate/patterns.nim b/src/syndicate/patterns.nim index 24213d6..555d6bd 100644 --- a/src/syndicate/patterns.nim +++ b/src/syndicate/patterns.nim @@ -55,6 +55,68 @@ proc grab*(): Pattern = ?DBind(pattern: drop()) proc `?_`*(): Pattern = drop() proc `?*`*(): Pattern = grab() +proc `?`*[A, B](table: TableRef[A,B]): Pattern = + raiseAssert "not implemented" + +proc `?`*[T](val: T): Pattern = + ## Construct a `Pattern` from value of type `T`. + when T is Pattern: result = val + elif T is Ref: + result = Pattern(orKind: PatternKind.DLit, dlit: DLit( + value: AnyAtom( + orKind: AnyAtomKind.embedded, + embedded: embed(val)))) + elif T is ptr | ref: + if system.`==`(val, nil): result = ?(Symbol "null") + else: result = ?(val[]) + elif T is bool: + result = Pattern(orKind: PatternKind.DLit, dlit: DLit( + value: AnyAtom( + orKind: AnyAtomKind.bool, + bool: val))) + elif T is float32: + result = Pattern(orKind: PatternKind.DLit, dlit: DLit( + value: AnyAtom( + orKind: AnyAtomKind.float, + float: val))) + elif T is float64: + result = Pattern(orKind: PatternKind.DLit, dlit: DLit( + value: AnyAtom( + orKind: AnyAtomKind.double, + double: val))) + elif T is SomeInteger: + result = Pattern(orKind: PatternKind.DLit, dlit: DLit( + value: AnyAtom( + orKind: AnyAtomKind.int, + int: AnyAtomInt val))) + elif T is string: + result = Pattern(orKind: PatternKind.DLit, dlit: DLit( + value: AnyAtom( + orKind: AnyAtomKind.string, + string: val))) + elif T is seq[byte]: + result = Pattern(orKind: PatternKind.DLit, dlit: DLit( + value: AnyAtom( + orKind: AnyAtomKind.bytes, + bytes: val))) + elif T is enum or T is Symbol: + result = Pattern(orKind: PatternKind.DLit, dlit: DLit( + value: AnyAtom( + orKind: AnyAtomKind.symbol, + symbol: Symbol $val))) + elif T.hasPreservesRecordPragma: + var + label = T.recordLabel.tosymbol(Ref) + fields = newSeq[Pattern]() + for f in fields(val): + fields.add ?f + result = ?DCompound( + orKind: DCompoundKind.rec, + rec: DCompoundRec( + label: label, fields: fields)) + else: + {.error: "cannot derive pattern from " & $T.} + type Value = Preserve[Ref] Path = seq[Value]