# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense import min, preserves, syndicate, ./min_preserves const facetType* = "syndicate-facet" dictFacetType = "dict:" & facetType capType* = "syndicate-cap" dictCapType = "dict:" & capType proc discardTurn(turn: var Turn) = discard proc newFacetDict(i: In): MinValue = result = i.scope.newDict result.objType = facetType proc getFacet(q: MinValue): Facet = assert q.objType == facetType cast[Facet](q.obj) proc newCapDict(i: In): MinValue = result = i.scope.newDict result.objType = capType proc getCap(q: MinValue): Cap = assert q.objType == capType cast[Cap](q.obj) proc setCap(q: MinValue; cap: Cap) = q.obj = addr cap[] proc runForObj(q: MinValue) = while q.obj.isNil: syndicate.runOnce() proc syndicate_module*(i: In) = let def = i.define() def.symbol("actor") do (i: In): let vals = i.expect "str" name = vals[0].getString dict = i.newFacetDict bootActor(name) do (turn: var Turn): dict.obj = addr turn.facet[] runForObj dict i.push dict def.symbol("stop-actor") do (i: In): let vals = i.expect("dict:" & facetType) facet = vals[0].getFacet stopActor facet def.symbol("dataspace") do (i: In): let vals = i.expect(dictFacetType) facet = vals[0].getFacet dict = i.newCapDict facet.queueTurn do (turn: var Turn): dict.setCap turn.newDataspace runForObj dict i.push dict def.symbol("assert") do (i: In): let vals = i.expect(dictCapType, "a") var cap = vals[0].getCap pr = i.toPreserves vals[1] h = newVal 0 cap.relay.queueTurn do (turn: var Turn): h.intVal = publish(turn, cap, pr) while h.intVal == 0: syndicate.runOnce() i.push h def.symbol("retract") do (i: In): let vals = i.expect(dictCapType, "int") cap = vals[0].getCap h = Handle vals[1].intVal cap.relay.queueTurn do (turn: var Turn): retract(turn, h) def.symbol("message") do (i: In): let vals = i.expect(dictCapType, "a") var cap = vals[0].getCap pr = i.toPreserves vals[1] cap.relay.queueTurn do (turn: var Turn): message(turn, cap, pr) def.symbol("sync") do (i: In): let vals = i.expect(dictCapType) cap = vals[0].getCap var pending = true cap.relay.queueTurn do (turn: var Turn): sync(turn, cap) do (turn: var Turn): pending = false while pending: if not syndicate.runOnce(): raiseInvalid("failed to make sync progress") def.finalize("syndicate")