Adapt to non-throwing fromPreserve

Use the new fromPreserve proc that indicates failure with its
return value to test if a handler can process a pattern match.
This commit is contained in:
Emery Hemingway 2021-08-27 22:03:02 +02:00
parent 4f7f7e7780
commit 2a09e61f2b
3 changed files with 35 additions and 20 deletions

View File

@ -1,10 +1,12 @@
# SPDX-License-Identifier: ISC
import std/[asyncdispatch, macros, options]
import preserves
import preserves, preserves/records
import syndicate/[assertions, dataspaces, events, skeletons]
export preserves.`%`
export preserves.fromPreserve
export records.init
export assertions.`?_`
export assertions.`?*`
export assertions.Observe
@ -28,6 +30,7 @@ export events.EventKind
export skeletons.Analysis
export asyncdispatch.`callback=`
export options.get
proc getCurrentFacet*(): Facet = raiseAssert("must be called from within the DSL")
## Return the current `Facet` for this context.
@ -50,13 +53,13 @@ proc wrapDoHandler(pattern, handler: NimNode): NimNode =
## Generate a procedure that unpacks a `pattern` match to fit the
## parameters of `handler`, and calls the body of `handler`.
handler.expectKind nnkDo
let
var
formalArgs = handler[3]
cbFacetSym = genSym(nskParam, "facet")
scriptFacetSym = genSym(nskParam, "facet")
recSym = genSym(nskParam, "bindings")
var
letSection = newNimNode(nnkLetSection, handler)
varSection = newNimNode(nnkVarSection, handler)
conditional: NimNode
argCount: int
for i, arg in formalArgs:
if i > 0:
@ -67,16 +70,27 @@ proc wrapDoHandler(pattern, handler: NimNode): NimNode =
else:
if arg[1].kind == nnkEmpty:
error("type required for capture", arg)
var letDef = newNimNode(nnkIdentDefs, arg)
arg.copyChildrenTo letDef
letDef[2] = newCall("preserveTo",
newNimNode(nnkBracketExpr).add(recSym, newLit(pred i)),
letDef[1])
letSection.add(letDef)
var varDef = newNimNode(nnkIdentDefs, arg)
arg.copyChildrenTo varDef
varSection.add(varDef)
var conversion = newCall("fromPreserve", varDef[0],
newNimNode(nnkBracketExpr).add(recSym, newLit(pred i)))
if conditional.isNil:
conditional = conversion
else:
conditional = infix(conditional, "and", conversion)
inc(argCount)
let
var scriptBody = newStmtList()
if argCount > 0:
scriptBody.add(
varSection,
newNimNode(nnkIfStmt).add(
newNimNode(nnkElifBranch).add(
conditional, handler[6])))
else:
scriptBody.add(handler[6])
var
scriptSym = genSym(nskProc, "script")
scriptBody = newStmtList(letSection, handler[6])
handlerSym = genSym(nskProc, "handler")
litArgCount = newLit argCount
quote do:
@ -85,7 +99,7 @@ proc wrapDoHandler(pattern, handler: NimNode): NimNode =
# this should be a compile-time check
assert(
`litArgCount` == len(`recSym`),
"cannot unpack " & $`litArgCount` & " bindings from " & $(%`recSym`))
"cannot unpack " & $`litArgCount` & " bindings from " & $(toPreserve `recSym`))
proc `scriptSym`(`scriptFacetSym`: Facet) =
proc getCurrentFacet(): Facet {.inject, used.} = `scriptFacetSym`
`scriptBody`
@ -114,7 +128,7 @@ proc onEvent(event: EventKind, pattern, handler: NimNode): NimNode =
proc getCurrentFacet(): Facet {.inject, used.} = facet
`handler`
let a = `pattern`
result.assertion = Observe % a
result.assertion = Observe.init(a)
result.analysis = some(analyzeAssertion(a))
result.callback = wrap(facet, EventKind(`event`), `handlerSym`)

View File

@ -553,7 +553,8 @@ template declareField*(facet: Facet; F: untyped; T: typedesc; initial: T): untyp
facet.fields[fieldOff] = x
proc get(f: DistinctField): T {.used.} =
facet.actor.dataspace.dataflow.recordObservation(f.id)
fromPreserve[T](result, facet.fields[fieldOff])
if not fromPreserve[T](result, facet.fields[fieldOff]):
raise newException(ValueError, "cannot convert field " & $F & " to " & $T)
proc getPreserve(f: DistinctField): Preserve {.used.} =
facet.actor.dataspace.dataflow.recordObservation(f.id)
facet.fields[fieldOff]

View File

@ -7,12 +7,12 @@ import syndicate
const TimeLaterThan* = RecordClass(label: symbol"TimeLaterThan", arity: 1)
proc toPreserveHook*(time: Monotime): Preserve =
%time.ticks
time.ticks.toPreserve
proc fromPreserveHook*(result: var Monotime; p: Preserve) =
if p.kind != pkSignedInteger:
raise newException(ValueError, "not a preserved time: " & $p)
result = cast[MonoTime]((p.int.int64,))
proc fromPreserveHook*(mt: var Monotime; p: Preserve): bool =
if p.kind == pkSignedInteger:
mt = cast[MonoTime]((p.int.int64,))
result = true
syndicate timerDriver: