# 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, )