172 lines
4.0 KiB
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")
|