# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense import std/[hashes, tables] import preserves import ./actors, ./patterns, ./protocols/dataspace type DuringProc* = proc (a: Value; h: Handle) DuringActionKind = enum null, dead, act DuringAction = object case kind: DuringActionKind of null, dead: discard of act: action: Cont DuringEntity {.final.}= ref object of Entity cb: DuringProc assertionMap: Table[Handle, DuringAction] method publish(de: DuringEntity; turn: Turn; a: AssertionRef; h: Handle) = let action = de.cb(turn, a.value, h) # assert(not action.isNil "should have put in a no-op action") let g = de.assertionMap.getOrDefault h case g.kind of null: de.assertionMap[h] = DuringAction(kind: act, action: action) of dead: de.assertionMap.del h freshen(turn, action) of act: raiseAssert("during: duplicate handle in publish: " & $h) method retract(de: DuringEntity; turn: Turn; h: Handle) = 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.action.isNil: turn.queue(g.action) proc during*(cb: DuringProc): DuringEntity = DuringEntity(cb: cb) proc observe*(turn: Turn; ds: Cap; pat: Pattern; e: Entity): Handle = publish(turn, ds, Observe(pattern: pat, observer: newCap(turn, e)).toPreserves) proc assertHandle(turn: Turn): Handle = doAssert( turn.event.isSome and turn.event.get.orKind == EventKind.Assert, "operation not valid during this turn") turn.event.get.assert.handle proc awaitRetraction(cont: Cont): Cont {.cpsMagic.} = {.error: "this cannot work".} let h = cont.turn.assertHandle while true: let turn = cont.turn if turn.retracts(h): return c else: turn.facet.actor.qeueue(c)