2021-09-01 11:44:28 +00:00
|
|
|
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
|
|
|
# SPDX-License-Identifier: Unlicense
|
2021-06-29 15:18:09 +00:00
|
|
|
|
2021-10-29 14:55:49 +00:00
|
|
|
import std/macros
|
2021-09-24 19:25:47 +00:00
|
|
|
import preserves
|
2022-03-12 16:35:03 +00:00
|
|
|
import ./syndicate/[actors, dataspaces, durings, patterns]
|
|
|
|
|
|
|
|
from ./syndicate/relays import connectStdio, connectUnix
|
|
|
|
|
|
|
|
export Assertion, Handle, Ref, Turn, bootDataspace, `?`, connectStdio, connectUnix, drop, grab, publish
|
2021-09-24 19:25:47 +00:00
|
|
|
|
2022-03-12 16:08:22 +00:00
|
|
|
type
|
|
|
|
PublishProc = proc (turn: var Turn; v: Assertion; h: Handle) {.closure.}
|
|
|
|
RetractProc = proc (turn: var Turn; h: Handle) {.closure.}
|
|
|
|
MessageProc = proc (turn: var Turn; v: Assertion) {.closure.}
|
|
|
|
ClosureEntity = ref object of Entity
|
|
|
|
publishImpl: PublishProc
|
|
|
|
retractImpl: RetractProc
|
|
|
|
messageImpl: MessageProc
|
|
|
|
|
|
|
|
method publish(e: ClosureEntity; turn: var Turn; v: Assertion; h: Handle) =
|
|
|
|
if not e.publishImpl.isNil: e.publishImpl(turn, v, h)
|
|
|
|
|
|
|
|
method retract(e: ClosureEntity; turn: var Turn; h: Handle) =
|
|
|
|
if not e.retractImpl.isNil: e.retractImpl(turn, h)
|
|
|
|
|
|
|
|
method message(e: ClosureEntity; turn: var Turn; v: Assertion) =
|
|
|
|
if not e.messageImpl.isNil: e.messageImpl(turn, v)
|
2021-11-03 18:21:52 +00:00
|
|
|
|
2021-10-29 14:55:49 +00:00
|
|
|
proc wrapPublishHandler(handler: NimNode): NimNode =
|
2021-06-30 11:30:56 +00:00
|
|
|
handler.expectKind nnkDo
|
2021-10-29 14:55:49 +00:00
|
|
|
var innerProc = newNimNode(nnkProcDef)
|
|
|
|
handler.copyChildrenTo innerProc
|
|
|
|
innerProc[0] = genSym(nskProc, "message")
|
2021-08-27 20:03:02 +00:00
|
|
|
var
|
2021-06-30 11:30:56 +00:00
|
|
|
formalArgs = handler[3]
|
2021-10-29 14:55:49 +00:00
|
|
|
valuesSym = genSym(nskVar, "values")
|
|
|
|
valuesTuple = newNimNode(nnkTupleTy, handler)
|
|
|
|
innerTuple = newNimNode(nnkVarTuple, handler)
|
|
|
|
varSectionInner = newNimNode(nnkVarSection, handler).add(innerTuple)
|
2021-06-29 15:18:09 +00:00
|
|
|
for i, arg in formalArgs:
|
|
|
|
if i > 0:
|
|
|
|
arg.expectKind nnkIdentDefs
|
2021-10-29 14:55:49 +00:00
|
|
|
if arg[1].kind == nnkEmpty:
|
|
|
|
error("type required for capture", arg)
|
|
|
|
var def = newNimNode(nnkIdentDefs, arg)
|
|
|
|
arg.copyChildrenTo def
|
|
|
|
valuesTuple.add(def)
|
|
|
|
innerTuple.add(arg[0])
|
|
|
|
innerTuple.add(newEmptyNode(), valuesSym)
|
2021-08-27 20:03:02 +00:00
|
|
|
var
|
2021-10-29 14:55:49 +00:00
|
|
|
varSectionOuter = newNimNode(nnkVarSection, handler).add(
|
|
|
|
newIdentDefs(valuesSym, valuesTuple))
|
2021-11-02 12:02:20 +00:00
|
|
|
publishBody = newStmtList(varSectionInner, handler[6])
|
2021-10-29 14:55:49 +00:00
|
|
|
turnSym = ident"turn"
|
|
|
|
handleSym = ident"handle"
|
|
|
|
handlerSym = genSym(nskProc, "publish")
|
2021-07-08 09:50:13 +00:00
|
|
|
quote do:
|
2022-03-12 16:08:22 +00:00
|
|
|
proc `handlerSym`(`turnSym`: var Turn; bindings: Assertion; `handleSym`: Handle) =
|
2021-10-29 14:55:49 +00:00
|
|
|
`varSectionOuter`
|
|
|
|
if fromPreserve(`valuesSym`, bindings):
|
2021-11-02 12:02:20 +00:00
|
|
|
`publishBody`
|
2021-07-08 09:50:13 +00:00
|
|
|
|
2021-10-29 14:55:49 +00:00
|
|
|
proc wrapMessageHandler(handler: NimNode): NimNode =
|
|
|
|
handler.expectKind nnkDo
|
|
|
|
var innerProc = newNimNode(nnkProcDef)
|
|
|
|
handler.copyChildrenTo innerProc
|
|
|
|
innerProc[0] = genSym(nskProc, "message")
|
|
|
|
var
|
|
|
|
formalArgs = handler[3]
|
|
|
|
valuesSym = genSym(nskVar, "values")
|
|
|
|
valuesTuple = newNimNode(nnkTupleTy, handler)
|
|
|
|
innerTuple = newNimNode(nnkVarTuple, handler)
|
|
|
|
varSectionInner = newNimNode(nnkVarSection, handler).add(innerTuple)
|
|
|
|
for i, arg in formalArgs:
|
|
|
|
if i > 0:
|
|
|
|
arg.expectKind nnkIdentDefs
|
|
|
|
if arg[1].kind == nnkEmpty:
|
|
|
|
error("type required for capture", arg)
|
|
|
|
var def = newNimNode(nnkIdentDefs, arg)
|
|
|
|
arg.copyChildrenTo def
|
|
|
|
valuesTuple.add(def)
|
|
|
|
innerTuple.add(arg[0])
|
|
|
|
innerTuple.add(newEmptyNode(), valuesSym)
|
|
|
|
var
|
|
|
|
varSectionOuter = newNimNode(nnkVarSection, handler).add(
|
|
|
|
newIdentDefs(valuesSym, valuesTuple))
|
|
|
|
body = newStmtList(varSectionInner, handler[6])
|
|
|
|
turnSym = ident"turn"
|
|
|
|
handlerSym = genSym(nskProc, "message")
|
|
|
|
quote do:
|
2022-03-12 16:08:22 +00:00
|
|
|
proc `handlerSym`(`turnSym`: var Turn; bindings: Assertion) =
|
2021-10-29 14:55:49 +00:00
|
|
|
`varSectionOuter`
|
|
|
|
if fromPreserve(`valuesSym`, bindings):
|
|
|
|
`body`
|
2021-07-08 09:50:13 +00:00
|
|
|
|
2021-10-29 14:55:49 +00:00
|
|
|
macro onPublish*(turn: Turn; ds: Ref; pattern: Pattern; doHandler: untyped) =
|
2021-07-08 09:50:13 +00:00
|
|
|
let
|
2021-10-29 14:55:49 +00:00
|
|
|
handlerProc = wrapPublishHandler(doHandler)
|
|
|
|
handlerSym = handlerProc[0]
|
2021-06-29 15:18:09 +00:00
|
|
|
result = quote do:
|
2021-10-29 14:55:49 +00:00
|
|
|
`handlerProc`
|
2022-03-12 16:08:22 +00:00
|
|
|
discard observe(`turn`, `ds`, `pattern`, ClosureEntity(publishImpl: `handlerSym`))
|
2021-06-29 15:18:09 +00:00
|
|
|
|
2021-10-29 14:55:49 +00:00
|
|
|
macro onMessage*(turn: Turn; ds: Ref; pattern: Pattern; doHandler: untyped) =
|
|
|
|
let
|
|
|
|
handlerProc = wrapMessageHandler(doHandler)
|
|
|
|
handlerSym = handlerProc[0]
|
|
|
|
result = quote do:
|
|
|
|
`handlerProc`
|
2022-03-12 16:08:22 +00:00
|
|
|
discard observe(`turn`, `ds`, `pattern`, ClosureEntity(messageImpl: `handlerSym`))
|