50 lines
1.4 KiB
Nim
50 lines
1.4 KiB
Nim
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
|
# SPDX-License-Identifier: Unlicense
|
|
|
|
import std/[hashes, tables]
|
|
import preserves
|
|
import pkg/cps
|
|
import ./[actors, patterns]
|
|
|
|
type
|
|
DuringProc* = proc (f: Facet; a: Value; h: Handle): FacetProc {.gcsafe.}
|
|
DuringActionKind = enum null, dead, act
|
|
DuringAction = object
|
|
case kind: DuringActionKind
|
|
of null, dead: discard
|
|
of act:
|
|
retractProc: FacetProc
|
|
DuringEntity {.final.}= ref object of Entity
|
|
publishProc: DuringProc
|
|
assertionMap: Table[Handle, DuringAction]
|
|
|
|
proc duringPublish(e: Entity; v: Value; h: Handle) {.cps: Cont.} =
|
|
var de = DuringEntity(e)
|
|
let g = de.assertionMap.getOrDefault h
|
|
case g.kind
|
|
of null, dead:
|
|
var cb = de.publishProc(e.facet, v, h)
|
|
de.assertionMap[h] = DuringAction(kind: act, retractProc: cb)
|
|
of act:
|
|
raiseAssert("during: duplicate handle in publish: " & $h)
|
|
|
|
proc duringRetract(e: Entity; h: Handle) {.cps: Cont.} =
|
|
var de = DuringEntity(e)
|
|
let g = de.assertionMap.getOrDefault h
|
|
case g.kind
|
|
of null:
|
|
de.assertionMap[h] = DuringAction(kind: dead)
|
|
of dead:
|
|
raiseAssert("during: duplicate handle in retract: " & $h)
|
|
of act:
|
|
de.assertionMap.del h
|
|
if not g.retractProc.isNil:
|
|
g.retractProc(de.facet)
|
|
|
|
proc during*(cb: DuringProc): Entity =
|
|
## TODO: this doesn't follow Nim idom well.
|
|
DuringEntity(publishProc: cb).setActions(
|
|
publish = whelp duringPublish,
|
|
retract = whelp duringRetract,
|
|
)
|