Improved declareField

This commit is contained in:
Emery Hemingway 2021-06-27 15:57:28 +02:00
parent e156335d9a
commit 0e493d0696
1 changed files with 24 additions and 87 deletions

View File

@ -68,7 +68,9 @@ type
updateProc: Script[EndpointSpec]
spec: EndpointSpec
Fields = seq[Preserve]
Field* = object of RootObj
id*: FieldId
Fields* = seq[Preserve]
# TODO: compile-time tuples
Turn = object
@ -301,7 +303,7 @@ proc terminate(facet) =
actor = facet.actor
parent = facet.parent
if parent.isSome:
parent.get.children.del(facet.id)
get(parent).children.del(facet.id)
else:
reset actor.rootFacet
facet.isLive = false
@ -552,88 +554,23 @@ proc bootModule*(bootProc: ActivationScript): Future[void] =
true
return g.future
template declareField*(facet: Facet; F: untyped; T: typedesc; init: T): untyped =
## Declare getter and setter procs for field `F` of type `T` initalized with `init`.
# TODO: do more at compile-time, use a tuple rather than a sequence of Preserves.
facet.fields.add(toPreserve(init))
let
`F FieldOff` = facet.fields.high
`F FieldId` = facet.actor.dataspace.generateId.FieldId
facet.actor.dataspace.dataflow.defineObservableProperty(`F FieldId`)
proc `F`(fields: Fields): T =
facet.actor.dataspace.dataflow.recordObservation(`F FieldId`)
fromPreserve[T](result, facet.fields[`F FieldOff`])
proc `F =`(fields: var Fields; x: T) =
facet.actor.dataspace.dataflow.recordDamage(`F FieldId`)
facet.fields[`F FieldOff`] = toPreserve[T](x)
proc `F =`(fields: var Fields; x: Preserve) =
assert(x.kind == facet.fields[`F FieldOff`].kind, "invalid Preserves item for field type")
facet.actor.dataspace.dataflow.recordDamage(`F FieldId`)
facet.fields[`F FieldOff`] = x
#[
# Some early macros
proc send() =
discard
proc generateField(stmt: NimNode): NimNode =
stmt.expectLen 3
let l = stmt[1]
let r = stmt[2]
case r.kind
of nnkStmtList:
r.expectLen 1
result = newNimNode(nnkVarSection).add(newIdentDefs(l, r[0]))
else:
raiseAssert("unhandled field " & r.treeRepr)
proc generateStopOnTuple(output: var NimNode; stmt: NimNode): NimNode =
stmt.expectLen 3
let
cond = stmt[1]
body = stmt[2]
# symCond = genSym(ident="stopOnCond")
symStop = genSym(ident="stopOnCb")
# output.add(newProc(name = symCond, params = [ident"bool"], body = cond))
output.add(newProc(name = symStop, body = body))
newPar(newColonExpr(ident"cond", cond), newColonExpr(ident"body", symStop))
macro spawn*(label: string; body: untyped) =
## Spawn actor.
result = newNimNode(nnkStmtList)
let blockBody = newNimNode(nnkStmtList)
let actorSym = genSym(nskVar, label.strVal)
result.add(newNimNode(nnkVarSection).add(
newIdentDefs(actorSym, ident"Actor")))
var stopOnSeq = newNimNode(nnkBracket)
body.expectKind nnkStmtList
for stmt in body:
case stmt.kind
of nnkCommentStmt:
result.add(stmt)
of nnkCommand:
let cmd = stmt[0]
cmd.expectKind nnkIdent
if eqIdent(cmd, "field"):
result.add(generateField(stmt))
elif eqIdent(cmd, "stopOn"):
let stop = generateStopOnTuple(result, stmt)
stopOnSeq.add(stop)
else:
raiseAssert("unhandled spawn command " & cmd.repr)
else:
raiseAssert("unhandled statment " & stmt.treeRepr)
result.add(
newAssignment(newDotExpr(actorSym, ident"stops"), prefix(stopOnSeq, "@")))
#result.add(newBlockStmt(blockBody))
echo result.repr
# echo result.treeRepr
macro dumpStuff*(body: untyped): untyped =
echo body.treeRepr
]#
template declareField*(facet: Facet; F: untyped; T: typedesc; initial: T): untyped =
## Declare getter and setter procs for field `F` of type `T` initalized with `initial`.
type DistinctField = object of Field
discard
let `F` {.inject.} = DistinctField(id: facet.actor.dataspace.generateId.FieldId)
facet.actor.dataspace.dataflow.defineObservableProperty(`F`.id)
facet.fields.add(toPreserve(initial))
let fieldOff = facet.fields.high
proc set(f: DistinctField; x: T) =
facet.actor.dataspace.dataflow.recordDamage(f.id)
facet.fields[fieldOff] = toPreserve[T](x)
proc set(f: DistinctField; x: Preserve) =
facet.actor.dataspace.dataflow.recordDamage(f.id)
facet.fields[fieldOff] = x
proc get(f: DistinctField): T =
facet.actor.dataspace.dataflow.recordObservation(f.id)
fromPreserve[T](result, facet.fields[fieldOff])
proc getPreserve(f: DistinctField): Preserve =
facet.actor.dataspace.dataflow.recordObservation(f.id)
facet.fields[fieldOff]