From 964888499727798db28ab622bcf42bcaf193309a Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Sat, 23 Apr 2022 20:01:30 -0500 Subject: [PATCH] Move `?` operator to DSL module --- src/syndicate.nim | 91 ++++++++++++++++++++++++++++++++++++-- src/syndicate/patterns.nim | 72 +++--------------------------- 2 files changed, 93 insertions(+), 70 deletions(-) diff --git a/src/syndicate.nim b/src/syndicate.nim index df12f10..d322fb1 100644 --- a/src/syndicate.nim +++ b/src/syndicate.nim @@ -24,15 +24,98 @@ runnableExamples: poll() -import std/macros -import preserves, preserves/jsonhooks +import std/[macros, tables, typetraits] +import preserves import ./syndicate/[actors, dataspaces, durings, patterns] from ./syndicate/relays import connectStdio, connectUnix export Assertion, Facet, Handle, Ref, Symbol, Turn, TurnAction, bootDataspace, - `?`, `$`, connectStdio, connectUnix, facet, drop, grab, message, publish, - retract, replace, run, stop, unembed + `$`, connectStdio, connectUnix, drop, facet, grab, message, publish, + retract, replace, run, stop, unembed + +proc `?`*(T: static typedesc): Pattern = + ## Construct a `Pattern` from type `T`. + runnableExamples: + import preserves + + type Point = tuple[x: int; y: int] + assert $(?Point) == "> >]>" + + type Rect {.preservesRecord: "rect".} = tuple[a: Point; B: Point] + assert $(?Rect) == "> >]> > >]>]>" + + type ColoredRect {.preservesDictionary.} = tuple[color: string; rect: Rect] + assert $(?ColoredRect) == ">, rect: > >]> > >]>]>}>" + + ## 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 is ref: + ?pointerBase(T) + elif T is Preserve: grab() + elif T.hasPreservesRecordPragma: + var + label = T.recordLabel.tosymbol(Ref) + fields = newSeq[Pattern]() + for key, val in fieldPairs(default T): + fields.add ?(typeOf val) + result = ?DCompound( + orKind: DCompoundKind.rec, + rec: DCompoundRec( + label: label, fields: fields)) + elif T.hasPreservesDictionaryPragma: + 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.hasPreservesTuplePragma or T is tuple: + var arr = DCompoundArr() + for key, val in fieldPairs(default T): + arr.items.add ?(typeOf val) + ?DCompound( + orKind: DCompoundKind.arr, + arr: arr) + else: + grab() # otherwise an abritrary capture + +proc `?`*(T: typedesc; bindings: sink openArray[(int, Pattern)]): Pattern = + ## Construct a `Pattern` from type `T` that selectively captures fields. + runnableExamples: + import preserves + + type Point = tuple[x: int; y: int; z: int] + assert $(Point ? {2: grab()}) == " <_> >]>" + + when T is ref: + `?`(pointerBase(T), bindings) + elif T.hasPreservesRecordPragma: + var + label = T.recordLabel.tosymbol(Ref) + fields = newSeq[Pattern]() + for (i, pat) in bindings: + if i > fields.high: fields.setLen(succ i) + fields[i] = pat + for pat in bindings.mitems: + if pat.isNil: pat = drop() + result = ?DCompound( + orKind: DCompoundKind.rec, + rec: DCompoundRec( + label: label, fields: fields)) + elif T is tuple: + var arr = DCompoundArr() + for (i, pat) in bindings: + if i > arr.items.high: arr.items.setLen(succ i) + arr.items[i] = pat + for pat in arr.items.mitems: + if pat.isNil: pat = drop() + result = ?DCompound( + orKind: DCompoundKind.arr, + arr: arr) + else: + {.error: "no preserves pragma on " & $T.} type PublishProc = proc (turn: var Turn; v: Assertion; h: Handle) {.closure.} diff --git a/src/syndicate/patterns.nim b/src/syndicate/patterns.nim index e0beff9..24213d6 100644 --- a/src/syndicate/patterns.nim +++ b/src/syndicate/patterns.nim @@ -11,12 +11,12 @@ export dataspacePatterns.`$`, PatternKind, DCompoundKind type AnyAtom* = dataspacePatterns.AnyAtom[Ref] - DBind = dataspacePatterns.DBind[Ref] - DCompound = dataspacePatterns.DCompound[Ref] - DCompoundArr = dataspacePatterns.DCompoundArr[Ref] - DCompoundDict = dataspacePatterns.DCompoundDict[Ref] - DCompoundRec = dataspacePatterns.DCompoundRec[Ref] - DLit = dataspacePatterns.DLit[Ref] + DBind* = dataspacePatterns.DBind[Ref] + DCompound* = dataspacePatterns.DCompound[Ref] + DCompoundArr* = dataspacePatterns.DCompoundArr[Ref] + DCompoundDict* = dataspacePatterns.DCompoundDict[Ref] + DCompoundRec* = dataspacePatterns.DCompoundRec[Ref] + DLit* = dataspacePatterns.DLit[Ref] Pattern* = dataspacePatterns.Pattern[Ref] proc `?`*(d: DBind): Pattern = @@ -55,66 +55,6 @@ proc grab*(): Pattern = ?DBind(pattern: drop()) proc `?_`*(): Pattern = drop() proc `?*`*(): Pattern = grab() -proc `?`*(T: typedesc; bindings: sink openArray[(int, Pattern)]): Pattern = - ## Pattern constructor operator. - # TODO: get a pattern for T and then replace the inner patterns with bindings. - when T.hasPreservesRecordPragma: - var - label = T.recordLabel.tosymbol(Ref) - fields = newSeq[Pattern]() - for (i, pat) in bindings: - if i > fields.high: fields.setLen(succ i) - fields[i] = pat - result = ?DCompound( - orKind: DCompoundKind.rec, - rec: DCompoundRec( - label: label, fields: fields)) - elif T is ref: - `?`(pointerBase(T), bindings) - else: - {.error: "no preserves pragma on " & $T.} - -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 is ref: - ?pointerBase(T) - elif T is Preserve: grab() - elif T.hasPreservesRecordPragma: - var - label = T.recordLabel.tosymbol(Ref) - fields = newSeq[Pattern]() - for key, val in fieldPairs(default T): - fields.add ?(typeOf val) - result = ?DCompound( - orKind: DCompoundKind.rec, - rec: DCompoundRec( - label: label, fields: fields)) - elif T.hasPreservesTuplePragma: - var arr = DCompoundArr() - for key, val in fieldPairs(default T): - arr.items.add grab() - ?DCompound( - orKind: DCompoundKind.arr, - arr: arr) - elif T.hasPreservesDictionaryPragma: - 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() - for key, val in fieldPairs(default T): - arr.items.add ?(typeOf val) - result = ?DCompound( - orKind: DCompoundKind.arr, - arr: arr) - else: - grab() # capture any value - type Value = Preserve[Ref] Path = seq[Value]