# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense import min, preserves, syndicate, ./min_preserves const capType* = "syndicate-cap" dictCapType = "dict:" & capType patternType* = "syndicate-pattern" dictPatternType* = "dict:" & patternType proc runForObj(q: MinValue) = while q.obj.isNil: syndicate.runOnce() proc discardTurn(turn: Turn) = discard 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 set(q: MinValue; cap: Cap) = assert q.objType == capType q.obj = addr cap[] proc newDict(i: In; cap: Cap): MinValue = result = i.newCapDict result.set cap proc newDict(i: In; pat: Pattern): MinValue = result = i.scope.newDict result.objType = patternType result.obj = addr pat[] type MinEntity = ref object of syndicate.Entity itr: ptr MinInterpreter # unsafe if turns are running while the interpreter is not! handlers: MinValue proc push(me: MinEntity; elems: varargs[MinValue]) = for e in elems: me.itr[].push e method publish(me: MinEntity; turn: Turn; ass: AssertionRef; h: Handle) = var v = me.itr[].toMin ass.value q = me.itr[].dget(me.handlers, "publish") me.push v, h.newVal, q method retract(me: MinEntity; turn: Turn; h: Handle) = var q = me.itr[].dget(me.handlers, "retract") me.push h.newVal, q method message(me: MinEntity; turn: Turn; ass: AssertionRef) = var v = me.itr[].toMin ass.value q = me.itr[].dget(me.handlers, "message") me.push v, q method sync(me: MinEntity; turn: Turn; peer: Cap) = var p = me.itr[].newDict peer q = me.itr[].dget(me.handlers, "sync") me.push p, q echo "MinEntity pushes sync onto stack" proc syndicate_module*(i: In) = let def = i.define() def.symbol("dataspace") do (i: In): let vals = i.expect("dict") dict = i.newCapDict bootActor("dataspace") do (turn: Turn): dict.set 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: 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: 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: 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: Turn): sync(turn, cap) do (turn: Turn): pending = false while pending: echo "run a turn for sync" if not syndicate.runOnce(): raiseInvalid("failed to make sync progress") def.symbol("to-cap") do (i: In): let vals = i.expect("dict") capDict = i.newCapDict entity = MinEntity(itr: addr i, handlers: vals[0]) bootActor("name") do (turn: Turn): capDict.set: turn.newCap entity runForObj capDict i.push capDict #[ def.symbol("pattern-discard") do (i: In): i.push: i.toMin Pattern(orKind: PatternKind.`discard`).toPreserves ]# #[ def.symbol("pattern-bind") do (i: In): let vals = i.expect("'sym", "a") var pr = i.toPreserves vals[1] pat = grab pr i.push: i.toMin pat.toPreserves ]# #[ def.symbol("pattern-any") do (i: In): var rec = i.newRecord("_".newVal) i.push rec def.symbol("pattern-bind") do (i: In): let vals = i.expect("'sym", "a") ]# #[ def.symbol("on-message") do (i: In): let vals = i.expect(dictCapType, "quot") cap = vals[0].getCap ]# def.finalize("syndicate")