Parameterize Preserve type
This commit is contained in:
parent
cfd863fbf9
commit
a5830a4a07
|
@ -1,14 +1,11 @@
|
|||
# SPDX-License-Identifier: ISC
|
||||
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
import std/[asyncdispatch, macros, options]
|
||||
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
|
||||
export dataspaces.Facet
|
||||
export dataspaces.FieldId
|
||||
|
@ -128,7 +125,7 @@ proc onEvent(event: EventKind, pattern, handler: NimNode): NimNode =
|
|||
proc getCurrentFacet(): Facet {.inject, used.} = facet
|
||||
`handler`
|
||||
let a = `pattern`
|
||||
result.assertion = Observe.init(a)
|
||||
result.assertion = observe(a)
|
||||
result.analysis = some(analyzeAssertion(a))
|
||||
result.callback = wrap(facet, EventKind(`event`), `handlerSym`)
|
||||
|
||||
|
@ -197,13 +194,13 @@ template withFacet*(f: Facet; body: untyped): untyped =
|
|||
## Execute a Syndicate ``body`` using the ``Facet`` at ``f``.
|
||||
runnableExamples:
|
||||
import preserves, preserves/records
|
||||
type Foo = ref object
|
||||
type Foo {.record: "foo".} = ref object
|
||||
facet: Facet
|
||||
i: int
|
||||
proc incAndAssert(foo: Foo) =
|
||||
inc(foo.i)
|
||||
withFacet foo.facet:
|
||||
react: assert: initRecord("Foo", %foo.i)
|
||||
react: assert: foo
|
||||
proc getCurrentFacet(): Facet {.inject, used.} = f
|
||||
body
|
||||
|
||||
|
@ -219,3 +216,13 @@ type BootProc* = proc (facet: Facet) {.gcsafe.}
|
|||
template boot*(module: BootProc) =
|
||||
mixin getCurrentFacet
|
||||
module(getCurrentFacet())
|
||||
|
||||
macro `?`*(x: untyped): untyped =
|
||||
## Sugar for generating Syndicate patterns.
|
||||
## `?_` is a pattern that matches but discards arbitrary
|
||||
## values and `?` combined with any other identifier is
|
||||
## a match and capture.
|
||||
if eqIdent(x, "_"):
|
||||
quote: toPreserve(Discard())
|
||||
else:
|
||||
quote: toPreserve(Capture())
|
||||
|
|
|
@ -1,21 +1,29 @@
|
|||
# SPDX-License-Identifier: ISC
|
||||
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
import preserves, preserves/records
|
||||
import std/options
|
||||
import preserves
|
||||
|
||||
const
|
||||
Discard* = RecordClass(label: symbol"discard", arity: 0)
|
||||
Capture* = RecordClass(label: symbol"capture", arity: 1)
|
||||
Observe* = RecordClass(label: symbol"observe", arity: 1)
|
||||
#Inbound* = RecordClass(label: symbol"inbound", arity: 1)
|
||||
#Outbound* = RecordClass(label: symbol"outbound", arity: 1)
|
||||
#Instance* = RecordClass(label: symbol"instance", arity: 1)
|
||||
type
|
||||
Discard* {.record: "discard", pure.} = object
|
||||
discard
|
||||
|
||||
`?_`* = initRecord("discard")
|
||||
`?*`* = Capture % `?_`
|
||||
Capture* {.record: "capture", pure.} = object
|
||||
_: Discard
|
||||
|
||||
Observe* {.record: "observe", pure.} = object
|
||||
pattern: Preserve
|
||||
|
||||
proc observe*[T](x: T): Preserve =
|
||||
Observe(pattern: x.toPreserve).toPreserve
|
||||
|
||||
proc captureCount*(pattern: Preserve): int =
|
||||
if Capture.isClassOf pattern:
|
||||
if pattern.preserveTo(Capture).isSome:
|
||||
result = 1
|
||||
else:
|
||||
for e in pattern.items:
|
||||
result.inc captureCount(e)
|
||||
|
||||
when isMainModule:
|
||||
let a = observe(`?*`)
|
||||
assert($toPreserve(a) == "<capture <discard>>")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# SPDX-License-Identifier: ISC
|
||||
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
import ./bags, ./dataflow, ./events, ./skeletons
|
||||
import preserves
|
||||
|
@ -70,7 +71,7 @@ type
|
|||
|
||||
Field* = object of RootObj
|
||||
id*: FieldId
|
||||
Fields* = seq[Preserve]
|
||||
Fields* = seq[Value]
|
||||
# TODO: compile-time tuples
|
||||
|
||||
Turn = object
|
||||
|
@ -403,7 +404,7 @@ proc initActivationAction(script: ActivationScript; name: string): Action =
|
|||
ds.activations.add(script)
|
||||
proc boot(root: Facet) =
|
||||
root.addStartScript(script)
|
||||
ds.addActor(name, boot, Preserve(kind: pkSet), actor)
|
||||
ds.addActor(name, boot, Value(kind: pkSet), actor)
|
||||
Action(impl: impl, kind: activationAction)
|
||||
|
||||
proc activate(facet; name: string; script: ActivationScript) =
|
||||
|
@ -547,15 +548,15 @@ template declareField*(facet: Facet; F: untyped; T: typedesc; initial: T): untyp
|
|||
let fieldOff = facet.fields.high
|
||||
proc set(f: DistinctField; x: T) {.used.} =
|
||||
facet.actor.dataspace.dataflow.recordDamage(f.id)
|
||||
facet.fields[fieldOff] = toPreserve[T](x)
|
||||
proc set(f: DistinctField; x: Preserve) {.used.} =
|
||||
facet.fields[fieldOff] = toPreserve(x)
|
||||
proc set(f: DistinctField; x: Value) {.used.} =
|
||||
facet.actor.dataspace.dataflow.recordDamage(f.id)
|
||||
facet.fields[fieldOff] = x
|
||||
proc get(f: DistinctField): T {.used.} =
|
||||
facet.actor.dataspace.dataflow.recordObservation(f.id)
|
||||
if not fromPreserve[T](result, facet.fields[fieldOff]):
|
||||
if not fromPreserve(result, facet.fields[fieldOff]):
|
||||
raise newException(ValueError, "cannot convert field " & $F & " to " & $T)
|
||||
proc getPreserve(f: DistinctField): Preserve {.used.} =
|
||||
proc getPreserve(f: DistinctField): Value {.used.} =
|
||||
facet.actor.dataspace.dataflow.recordObservation(f.id)
|
||||
facet.fields[fieldOff]
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import std/[asyncdispatch, monotimes, times]
|
||||
import preserves, preserves/records
|
||||
import syndicate
|
||||
import syndicate, syndicate/assertions
|
||||
|
||||
type TimeLaterThan* {.record: "TimeLaterThan".} = object
|
||||
`deadline`*: Monotime
|
||||
|
@ -21,7 +21,7 @@ proc fromPreserveHook*(mt: var Monotime; p: Preserve): bool =
|
|||
syndicate timerDriver:
|
||||
|
||||
spawn "timer":
|
||||
during(Observe % (prsTimeLaterThan(`?*`))) do (deadline: MonoTime):
|
||||
during(observe(prsTimeLaterThan(?deadline))) do (deadline: MonoTime):
|
||||
let
|
||||
now = getMonoTime()
|
||||
period = inMilliseconds(deadline - now)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# SPDX-License-Identifier: ISC
|
||||
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
import ./assertions, ./bags, ./events
|
||||
import preserves, preserves/records
|
||||
|
@ -36,9 +37,9 @@ proc projectPaths(v: Value; paths: seq[Path]): seq[Value] =
|
|||
proc analyzeAssertion*(a: Value): Analysis =
|
||||
var path: Path
|
||||
proc walk(analysis: var Analysis; a: Value): Skeleton[Shape] =
|
||||
if Discard.isClassOf a:
|
||||
if a.preserveTo(Discard).isSome:
|
||||
discard
|
||||
elif Capture.isClassOf a:
|
||||
elif a.preserveTo(Capture).isSome:
|
||||
analysis.capturePaths.add(path)
|
||||
result = walk(analysis, a.fields[0])
|
||||
else:
|
||||
|
|
|
@ -9,4 +9,4 @@ srcDir = "src"
|
|||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 1.4.8", "preserves >= 0.3.0"
|
||||
requires "nim >= 1.4.8", "preserves >= 1.0.0"
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
|
||||
## Date of generation: 2021-08-28 10:14
|
||||
## Date of generation: 2021-09-01 13:32
|
||||
import
|
||||
std/typetraits, preserves
|
||||
|
||||
type
|
||||
EmbeddedType = void
|
||||
BoxState* {.record: "box-state".} = object ## ``<box-state @value int>``
|
||||
`value`*: BiggestInt
|
||||
|
||||
|
@ -11,7 +12,9 @@ type
|
|||
`value`*: BiggestInt
|
||||
|
||||
proc prsBoxState*(value: Preserve | BiggestInt): Preserve =
|
||||
initRecord(symbol("box-state"), value)
|
||||
initRecord[EmbeddedType](symbol("box-state", EmbeddedType),
|
||||
toPreserve(value, EmbeddedType))
|
||||
|
||||
proc prsSetBox*(value: Preserve | BiggestInt): Preserve =
|
||||
initRecord(symbol("set-box"), value)
|
||||
initRecord[EmbeddedType](symbol("set-box", EmbeddedType),
|
||||
toPreserve(value, EmbeddedType))
|
||||
|
|
|
@ -8,9 +8,9 @@ import ./box_and_client
|
|||
|
||||
const N = 100000
|
||||
|
||||
const
|
||||
`?_` = init(Discard)
|
||||
`?$` = init(Capture, `?_`)
|
||||
let
|
||||
`?_` = Discard().toPreserve
|
||||
`?$` = Capture().toPreserve
|
||||
|
||||
proc boot(facet: Facet) =
|
||||
|
||||
|
@ -28,19 +28,19 @@ proc boot(facet: Facet) =
|
|||
echo "terminated box root facet"
|
||||
|
||||
facet.addEndpoint do (facet: Facet) -> EndpointSpec:
|
||||
const a = prsSetBox(`?$`)
|
||||
let a = prsSetBox(`?$`)
|
||||
result.analysis = some analyzeAssertion(a)
|
||||
proc cb(facet: Facet; vs: seq[Value]) =
|
||||
facet.scheduleScript do (facet: Facet):
|
||||
value.set(vs[0])
|
||||
# echo "box updated value ", vs[0]
|
||||
result.callback = facet.wrap(messageEvent, cb)
|
||||
result.assertion = Observe.init(prsSetBox(`?$`))
|
||||
result.assertion = observe(prsSetBox(`?$`))
|
||||
|
||||
facet.spawn("client") do (facet: Facet):
|
||||
|
||||
facet.addEndpoint do (facet: Facet) -> EndpointSpec:
|
||||
const a = prsBoxState(`?$`)
|
||||
let a = prsBoxState(`?$`)
|
||||
result.analysis = some analyzeAssertion(a)
|
||||
proc cb(facet: Facet; vs: seq[Value]) =
|
||||
facet.scheduleScript do (facet: Facet):
|
||||
|
@ -48,16 +48,16 @@ proc boot(facet: Facet) =
|
|||
# echo "client sending ", v
|
||||
facet.send(v)
|
||||
result.callback = facet.wrap(addedEvent, cb)
|
||||
result.assertion = Observe.init(prsBoxState(`?$`))
|
||||
result.assertion = observe(prsBoxState(`?$`))
|
||||
|
||||
facet.addEndpoint do (facet: Facet) -> EndpointSpec:
|
||||
const a = prsBoxState(`?_`)
|
||||
let a = prsBoxState(`?_`)
|
||||
result.analysis = some analyzeAssertion(a)
|
||||
proc cb(facet: Facet; vs: seq[Value]) =
|
||||
facet.scheduleScript do (facet: Facet):
|
||||
echo "box gone"
|
||||
result.callback = facet.wrap(removedEvent, cb)
|
||||
result.assertion = Observe.init(prsBoxState(`?_`))
|
||||
result.assertion = observe(prsBoxState(`?_`))
|
||||
|
||||
facet.actor.dataspace.ground.addStopHandler do (_: Dataspace):
|
||||
echo "stopping box-and-client"
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# SPDX-License-Identifier: ISC
|
||||
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
import asyncdispatch
|
||||
import preserves, preserves/records
|
||||
import std/asyncdispatch
|
||||
import preserves
|
||||
import syndicate
|
||||
|
||||
import ./box_and_client
|
||||
|
@ -13,7 +14,7 @@ syndicate testDsl:
|
|||
asserting prsBoxState(currentValue.get)
|
||||
stopIf currentValue.get == 10:
|
||||
echo "box: terminating"
|
||||
onMessage(prsSetBox(`?*`)) do (newValue: int):
|
||||
onMessage(prsSetBox(?newValue)) do (newValue: int):
|
||||
# The SetBox message is unpacked to `newValue: int`
|
||||
echo "box: taking on new value ", newValue
|
||||
currentValue.set(newValue)
|
||||
|
@ -21,10 +22,10 @@ syndicate testDsl:
|
|||
spawn "client":
|
||||
#stopIf retracted(observe(SetBox, _)):
|
||||
# echo "client: box has gone"
|
||||
onAsserted(prsBoxState(`?*`)) do (v: BiggestInt):
|
||||
onAsserted(prsBoxState(?v)) do (v: BiggestInt):
|
||||
echo "client: learned that box's value is now ", v
|
||||
send(prsSetBox(v.succ))
|
||||
onRetracted(prsBoxState(`?_`)) do (_):
|
||||
onRetracted(prsBoxState(?_)) do (_):
|
||||
echo "client: box state disappeared"
|
||||
onStop:
|
||||
quit(0) # Quit explicitly rather than let the dispatcher run empty.
|
||||
|
|
Loading…
Reference in New Issue