Reuse caller turn symbol in DSL macros

This commit is contained in:
Emery Hemingway 2023-06-30 10:05:42 +01:00
parent 219286a84a
commit 170f49693c
1 changed files with 16 additions and 20 deletions

View File

@ -60,7 +60,7 @@ proc argumentCount(handler: NimNode): int =
handler.expectKind {nnkDo, nnkStmtList} handler.expectKind {nnkDo, nnkStmtList}
if handler.kind == nnkDo: result = pred handler[3].len if handler.kind == nnkDo: result = pred handler[3].len
proc wrapPublishHandler(handler: NimNode): NimNode = proc wrapPublishHandler(turn, handler: NimNode): NimNode =
handler.expectKind {nnkDo, nnkStmtList} handler.expectKind {nnkDo, nnkStmtList}
var innerProc = newNimNode(nnkProcDef) var innerProc = newNimNode(nnkProcDef)
handler.copyChildrenTo innerProc handler.copyChildrenTo innerProc
@ -87,16 +87,15 @@ proc wrapPublishHandler(handler: NimNode): NimNode =
publishBody = publishBody =
if handler.kind == nnkStmtList: handler if handler.kind == nnkStmtList: handler
else: newStmtList(varSectionInner, handler[6]) else: newStmtList(varSectionInner, handler[6])
turnSym = ident"turn"
handleSym = ident"handle" handleSym = ident"handle"
handlerSym = genSym(nskProc, "publish") handlerSym = genSym(nskProc, "publish")
quote do: quote do:
proc `handlerSym`(`turnSym`: var Turn; bindings: Assertion; `handleSym`: Handle) = proc `handlerSym`(`turn`: var Turn; bindings: Assertion; `handleSym`: Handle) =
`varSectionOuter` `varSectionOuter`
if fromPreserve(`valuesSym`, bindings): if fromPreserve(`valuesSym`, bindings):
`publishBody` `publishBody`
proc wrapMessageHandler(handler: NimNode): NimNode = proc wrapMessageHandler(turn, handler: NimNode): NimNode =
handler.expectKind {nnkDo, nnkStmtList} handler.expectKind {nnkDo, nnkStmtList}
var innerProc = newNimNode(nnkProcDef) var innerProc = newNimNode(nnkProcDef)
handler.copyChildrenTo innerProc handler.copyChildrenTo innerProc
@ -121,19 +120,18 @@ proc wrapMessageHandler(handler: NimNode): NimNode =
varSectionOuter = newNimNode(nnkVarSection, handler).add( varSectionOuter = newNimNode(nnkVarSection, handler).add(
newIdentDefs(valuesSym, valuesTuple)) newIdentDefs(valuesSym, valuesTuple))
body = newStmtList(varSectionInner, handler[6]) body = newStmtList(varSectionInner, handler[6])
turnSym = ident"turn"
handlerSym = genSym(nskProc, "message") handlerSym = genSym(nskProc, "message")
quote do: quote do:
proc `handlerSym`(`turnSym`: var Turn; bindings: Assertion) = proc `handlerSym`(`turn`: var Turn; bindings: Assertion) =
`varSectionOuter` `varSectionOuter`
if fromPreserve(`valuesSym`, bindings): if fromPreserve(`valuesSym`, bindings):
`body` `body`
macro onPublish*(turn: Turn; ds: Ref; pattern: Pattern; handler: untyped) = macro onPublish*(turn: untyped; ds: Ref; pattern: Pattern; handler: untyped) =
## Call `handler` when an assertion matching `pattern` is published at `ds`. ## Call `handler` when an assertion matching `pattern` is published at `ds`.
let let
argCount = argumentCount(handler) argCount = argumentCount(handler)
handlerProc = wrapPublishHandler(handler) handlerProc = wrapPublishHandler(turn, handler)
handlerSym = handlerProc[0] handlerSym = handlerProc[0]
result = quote do: result = quote do:
if `pattern`.analyse.capturePaths.len != `argCount`: if `pattern`.analyse.capturePaths.len != `argCount`:
@ -141,11 +139,11 @@ macro onPublish*(turn: Turn; ds: Ref; pattern: Pattern; handler: untyped) =
`handlerProc` `handlerProc`
discard observe(`turn`, `ds`, `pattern`, ClosureEntity(publishImpl: `handlerSym`)) discard observe(`turn`, `ds`, `pattern`, ClosureEntity(publishImpl: `handlerSym`))
macro onMessage*(turn: Turn; ds: Ref; pattern: Pattern; handler: untyped) = macro onMessage*(turn: untyped; ds: Ref; pattern: Pattern; handler: untyped) =
## Call `handler` when an message matching `pattern` is broadcasted at `ds`. ## Call `handler` when an message matching `pattern` is broadcasted at `ds`.
let let
argCount = argumentCount(handler) argCount = argumentCount(handler)
handlerProc = wrapMessageHandler(handler) handlerProc = wrapMessageHandler(turn, handler)
handlerSym = handlerProc[0] handlerSym = handlerProc[0]
result = quote do: result = quote do:
if `pattern`.analyse.capturePaths.len != `argCount`: if `pattern`.analyse.capturePaths.len != `argCount`:
@ -153,7 +151,7 @@ macro onMessage*(turn: Turn; ds: Ref; pattern: Pattern; handler: untyped) =
`handlerProc` `handlerProc`
discard observe(`turn`, `ds`, `pattern`, ClosureEntity(messageImpl: `handlerSym`)) discard observe(`turn`, `ds`, `pattern`, ClosureEntity(messageImpl: `handlerSym`))
proc wrapDuringHandler(entryBody, exitBody: NimNode): NimNode = proc wrapDuringHandler(turn, entryBody, exitBody: NimNode): NimNode =
entryBody.expectKind {nnkDo, nnkStmtList} entryBody.expectKind {nnkDo, nnkStmtList}
var innerProc = newNimNode(nnkProcDef) var innerProc = newNimNode(nnkProcDef)
entryBody.copyChildrenTo innerProc entryBody.copyChildrenTo innerProc
@ -180,38 +178,36 @@ proc wrapDuringHandler(entryBody, exitBody: NimNode): NimNode =
publishBody = publishBody =
if entryBody.kind == nnkStmtList: entryBody if entryBody.kind == nnkStmtList: entryBody
else: newStmtList(varSectionInner, entryBody[6]) else: newStmtList(varSectionInner, entryBody[6])
turnSym = ident"turn"
bindingsSym = ident"bindings" bindingsSym = ident"bindings"
handleSym = ident"duringHandle" handleSym = ident"duringHandle"
duringSym = genSym(nskProc, "during") duringSym = genSym(nskProc, "during")
if exitBody.isNil: if exitBody.isNil:
quote do: quote do:
proc `duringSym`(`turnSym`: var Turn; `bindingsSym`: Assertion; `handleSym`: Handle): TurnAction = proc `duringSym`(`turn`: var Turn; `bindingsSym`: Assertion; `handleSym`: Handle): TurnAction =
`varSectionOuter` `varSectionOuter`
if fromPreserve(`valuesSym`, `bindingsSym`): if fromPreserve(`valuesSym`, `bindingsSym`):
`publishBody` `publishBody`
else: else:
quote do: quote do:
proc `duringSym`(`turnSym`: var Turn; `bindingsSym`: Assertion; `handleSym`: Handle): TurnAction = proc `duringSym`(`turn`: var Turn; `bindingsSym`: Assertion; `handleSym`: Handle): TurnAction =
`varSectionOuter` `varSectionOuter`
if fromPreserve(`valuesSym`, `bindingsSym`): if fromPreserve(`valuesSym`, `bindingsSym`):
`publishBody` `publishBody`
proc action(`turnSym`: var Turn) = proc action(`turn`: var Turn) =
`exitBody` `exitBody`
result = action result = action
macro during*(turn: var Turn; ds: Ref; pattern: Pattern; publishBody, retractBody: untyped) = macro during*(turn: untyped; ds: Ref; pattern: Pattern; publishBody, retractBody: untyped) =
## Call `publishBody` when an assertion matching `pattern` is published to `ds` and ## Call `publishBody` when an assertion matching `pattern` is published to `ds` and
## call `retractBody` on retraction. Assertions that match `pattern` but are not ## call `retractBody` on retraction. Assertions that match `pattern` but are not
## convertable to the arguments of `publishBody` are silently discarded. ## convertable to the arguments of `publishBody` are silently discarded.
## ##
## The following symbols are injected into the scope of both bodies: ## The following symbols are injected into the scope of both bodies:
## - `turn` - active turn at entry of `publishBody` and `retractBody`
## - `bindings` - raw Preserves sequence that matched `pattern` ## - `bindings` - raw Preserves sequence that matched `pattern`
## - `duringHandle` - dataspace handle of the assertion that triggered `publishBody` ## - `duringHandle` - dataspace handle of the assertion that triggered `publishBody`
let let
argCount = argumentCount(publishBody) argCount = argumentCount(publishBody)
callbackProc = wrapDuringHandler(publishBody, retractBody) callbackProc = wrapDuringHandler(turn, publishBody, retractBody)
callbackSym = callbackProc[0] callbackSym = callbackProc[0]
result = quote do: result = quote do:
if `pattern`.analyse.capturePaths.len != `argCount`: if `pattern`.analyse.capturePaths.len != `argCount`:
@ -219,11 +215,11 @@ macro during*(turn: var Turn; ds: Ref; pattern: Pattern; publishBody, retractBod
`callbackProc` `callbackProc`
discard observe(`turn`, `ds`, `pattern`, during(`callbackSym`)) discard observe(`turn`, `ds`, `pattern`, during(`callbackSym`))
macro during*(turn: var Turn; ds: Ref; pattern: Pattern; publishBody: untyped) = macro during*(turn: untyped; ds: Ref; pattern: Pattern; publishBody: untyped) =
## Variant of `during` without a retract body. ## Variant of `during` without a retract body.
let let
argCount = argumentCount(publishBody) argCount = argumentCount(publishBody)
callbackProc = wrapDuringHandler(publishBody, nil) callbackProc = wrapDuringHandler(turn, publishBody, nil)
callbackSym = callbackProc[0] callbackSym = callbackProc[0]
result = quote do: result = quote do:
if `pattern`.analyse.capturePaths.len != `argCount`: if `pattern`.analyse.capturePaths.len != `argCount`: