This repository has been archived on 2024-05-22. You can view files and clone it, but cannot push or open issues or pull requests.
syndicate-min/pkg/min_syndicate.nim

172 lines
4.0 KiB
Nim

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