syndicate-nim/src/syndicate.nim

113 lines
4.0 KiB
Nim
Raw Normal View History

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
2022-03-15 00:48:42 +00:00
import preserves, preserves/jsonhooks
import ./syndicate/[actors, dataspaces, durings, patterns]
from ./syndicate/relays import connectStdio, connectUnix
2022-03-17 15:39:57 +00:00
export Assertion, Facet, Handle, Ref, Turn, TurnAction, bootDataspace, `?`, `$`,
connectStdio, connectUnix, drop, grab, message, publish, replace, run, stop
2021-09-24 19:25:47 +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 =
handler.expectKind nnkDo
2021-10-29 14:55:49 +00:00
var innerProc = newNimNode(nnkProcDef)
handler.copyChildrenTo innerProc
innerProc[0] = genSym(nskProc, "message")
var
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)
var
2021-10-29 14:55:49 +00:00
varSectionOuter = newNimNode(nnkVarSection, handler).add(
newIdentDefs(valuesSym, valuesTuple))
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:
proc `handlerSym`(`turnSym`: var Turn; bindings: Assertion; `handleSym`: Handle) =
2021-10-29 14:55:49 +00:00
`varSectionOuter`
if fromPreserve(`valuesSym`, bindings):
`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:
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`
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`
discard observe(`turn`, `ds`, `pattern`, ClosureEntity(messageImpl: `handlerSym`))