Refactor for Syndicate API update

This commit is contained in:
Emery Hemingway 2023-12-26 01:11:54 +02:00
parent 0d789361d6
commit bba515cdd8
22 changed files with 151 additions and 134 deletions

1
.envrc
View File

@ -1,2 +1 @@
source_env .. source_env ..
use nix

View File

@ -1,5 +1,17 @@
{ {
"depends": [ "depends": [
{
"method": "fetchzip",
"packages": [
"bigints"
],
"path": "/nix/store/jvrm392g8adfsgf36prgwkbyd7vh5jsw-source",
"ref": "20231006",
"rev": "86ea14d31eea9275e1408ca34e6bfe9c99989a96",
"sha256": "15pcpmnk1bnw3k8769rjzcpg00nahyrypwbxs88jnwr4aczp99j4",
"srcDir": "src",
"url": "https://github.com/ehmry/nim-bigints/archive/86ea14d31eea9275e1408ca34e6bfe9c99989a96.tar.gz"
},
{ {
"method": "fetchzip", "method": "fetchzip",
"packages": [ "packages": [
@ -52,24 +64,24 @@
"packages": [ "packages": [
"preserves" "preserves"
], ],
"path": "/nix/store/fmb2yckksz7iv3qdkk5gk1j060kppkq9-source", "path": "/nix/store/fpkhfxnfbdcri6k7mac21r3byg738bs4-source",
"ref": "20231102", "ref": "20240108",
"rev": "4faeb766dc3945bcfacaa1a836ef6ab29b20ceb0", "rev": "a01ba8c96d65f670862ba074bf82b50cbda6ed99",
"sha256": "1a3g5bk1l1h250q3p6sqv6r1lpsplp330qqyp48r0i4a5r0jksq3", "sha256": "0n8pghy2qfywx0psr54yzjvhdhi5av204150jyyzfxhigczd8sr4",
"srcDir": "src", "srcDir": "src",
"url": "https://git.syndicate-lang.org/ehmry/preserves-nim/archive/4faeb766dc3945bcfacaa1a836ef6ab29b20ceb0.tar.gz" "url": "https://git.syndicate-lang.org/ehmry/preserves-nim/archive/a01ba8c96d65f670862ba074bf82b50cbda6ed99.tar.gz"
}, },
{ {
"method": "fetchzip", "method": "fetchzip",
"packages": [ "packages": [
"syndicate" "syndicate"
], ],
"path": "/nix/store/nhpvl223vbzdrlzikw7pgyfxs344w7ma-source", "path": "/nix/store/hma19sff6k2bi6qj01yscbynz6x2zvxj-source",
"ref": "20231108", "ref": "20240108",
"rev": "095418032180e360ea27ec7fcd63193944b68e2c", "rev": "3e11884a916c0452c90128c29940856e2d347cb7",
"sha256": "09pbml2chzz0v5zpz67fs7raj0mfmg8qrih2vz85xxc51h7ncqvw", "sha256": "0n1gbwllwwilz9fp5zyp4054vzcq1p7ddzg02sw8d0vqb1wmpsqm",
"srcDir": "src", "srcDir": "src",
"url": "https://git.syndicate-lang.org/ehmry/syndicate-nim/archive/095418032180e360ea27ec7fcd63193944b68e2c.tar.gz" "url": "https://git.syndicate-lang.org/ehmry/syndicate-nim/archive/3e11884a916c0452c90128c29940856e2d347cb7.tar.gz"
} }
] ]
} }

View File

@ -1,5 +1,5 @@
version 1. version 1.
Mountpoint = <mount @source string @target string @type string @status Status> . Mountpoint = <mount @source string @target string @type string @status Status> .
Status = Failure / #t. Status = Failure / @success #t .
Failure = <failure @msg string> . Failure = <failure @msg string> .

View File

@ -37,19 +37,24 @@ proc isObserve(pat: Pattern): bool =
pat.dcompound.orKind == DCompoundKind.rec and pat.dcompound.orKind == DCompoundKind.rec and
pat.dcompound.rec.label.isSymbol"Observe" pat.dcompound.rec.label.isSymbol"Observe"
runActor("cache_actor") do (turn: var Turn; root: Cap): proc spawnCacheActor*(turn: var Turn; root: Cap): Actor =
spawnTimers(turn, root) spawn("cache_actor", turn) do (turn: var Turn):
connectStdio(turn, root) during(turn, root, ?:BootArgs) do (ds: Cap, lifetime: float64):
during(turn, root, ?BootArgs) do (ds: Cap, lifetime: float64): onPublish(turn, ds, ?:Observe) do (pat: Pattern, obs: Cap):
onPublish(turn, ds, ?Observe) do (pat: Pattern, obs: Cap): var cache: CacheEntity
var cache: CacheEntity if obs.relay != turn.facet and not(pat.isObserve):
if obs.relay != turn.facet and not(pat.isObserve): # Watch pattern if the observer is not us
# Watch pattern if the observer is not us # and if the pattern isn't a recursive observe
# and if the pattern isn't a recursive observe cache = CacheEntity(
cache = CacheEntity( timeouts: root,
timeouts: root, target: ds,
target: ds, pattern: pat,
pattern: pat, lifetime: lifetime,
lifetime: lifetime, )
) discard observe(turn, ds, pat, cache)
discard observe(turn, ds, pat, cache)
when isMainModule:
runActor("cache_actor") do (turn: var Turn; root: Cap):
spawnTimers(turn, root)
connectStdio(turn, root)
discard spawnCacheActor(turn, root)

View File

@ -7,14 +7,11 @@ import std/[asyncdispatch, asyncfile, tables]
import posix, posix/inotify import posix, posix/inotify
import preserves import preserves
import syndicate, syndicate/[bags, relays] import syndicate, syndicate/[bags, relays]
from syndicate/protocols/dataspace import Observe
import ./schema/inotify_actor import ./schema/inotify_actor
var IN_NONBLOCK {.importc, nodecl.}: cint var IN_NONBLOCK {.importc, nodecl.}: cint
type type
Observe = dataspace.Observe[Cap]
# Registry = TableRef[cint, TableRef[Cap, HashSet[string]]]
BootArgs {.preservesDictionary.} = object BootArgs {.preservesDictionary.} = object
dataspace: Cap dataspace: Cap
@ -72,7 +69,7 @@ runActor("inotify_actor") do (root: Cap; turn: var Turn):
let buf = newSeq[byte](8192) let buf = newSeq[byte](8192)
let eventPattern = ?Observe(pattern: !InotifyMessage) ?? { 0: grabLit(), 1: grabLit() } let eventPattern = ?Observe(pattern: !InotifyMessage) ?? { 0: grabLit(), 1: grabLit() }
connectStdio(turn, root) connectStdio(turn, root)
during(turn, root, ?BootArgs) do (ds: Cap): during(turn, root, ?:BootArgs) do (ds: Cap):
let inf = inotify_init1(IN_NONBLOCK) let inf = inotify_init1(IN_NONBLOCK)
doAssert inf != -1, $inf & " - " & $strerror(errno) doAssert inf != -1, $inf & " - " & $strerror(errno)
var var

View File

@ -4,7 +4,7 @@
import std/json import std/json
import preserves, preserves/jsonhooks import preserves, preserves/jsonhooks
export fromPreserveHook, toPreserveHook export fromPreservesHook, toPreservesHook
# re-export the hooks so that conversion "just works" # re-export the hooks so that conversion "just works"
type type

View File

@ -7,28 +7,33 @@ import preserves, preserves/jsonhooks, syndicate, syndicate/relays
import ./schema/config, ./json_messages import ./schema/config, ./json_messages
runActor("main") do (root: Cap; turn: var Turn): proc spawnJsonSocketTranslator*(turn: var Turn; root: Cap): Actor =
connectStdio(turn, root) spawn("json_socket_translator", turn) do (turn: var Turn):
during(turn, root, ?JsonSocketTranslatorArguments) do (ds: Cap, socketPath: string): during(turn, root, ?:JsonSocketTranslatorArguments) do (ds: Cap, socketPath: string):
let socket = newAsyncSocket( let socket = newAsyncSocket(
domain = AF_UNIX, domain = AF_UNIX,
sockType = SOCK_STREAM, sockType = SOCK_STREAM,
protocol = cast[Protocol](0), protocol = cast[Protocol](0),
buffered = false, buffered = false,
) )
addCallback(connectUnix(socket, socketPath), turn) do (turn: var Turn): addCallback(connectUnix(socket, socketPath), turn) do (turn: var Turn):
let a = JsonTranslatorConnected(path: socketPath) let a = JsonTranslatorConnected(path: socketPath)
discard publish(turn, ds, a) discard publish(turn, ds, a)
let socketFacet = turn.facet let socketFacet = turn.facet
proc processOutput(fut: Future[string]) {.gcsafe.} = proc processOutput(fut: Future[string]) {.gcsafe.} =
run(socketFacet) do (turn: var Turn): run(socketFacet) do (turn: var Turn):
var data = fut.read.parseJson var data = fut.read.parseJson
message(turn, ds, RecvJson(data: data)) message(turn, ds, RecvJson(data: data))
socket.recvLine.addCallback(processOutput)
socket.recvLine.addCallback(processOutput) socket.recvLine.addCallback(processOutput)
socket.recvLine.addCallback(processOutput)
onMessage(turn, ds, ?SendJson) do (data: JsonNode): onMessage(turn, ds, ?:SendJson) do (data: JsonNode):
asyncCheck(turn, send(socket, $data & "\n")) asyncCheck(turn, send(socket, $data & "\n"))
do: do:
close(socket) close(socket)
when isMainModule:
runActor("json_socket_translator") do (turn: var Turn; root: Cap):
connectStdio(turn, root)
discard spawnJsonSocketTranslator(turn, root)

View File

@ -5,7 +5,7 @@ import std/[json, os, osproc]
import preserves import preserves
import syndicate, syndicate/relays import syndicate, syndicate/relays
from preserves/jsonhooks import toPreserveHook from preserves/jsonhooks import toPreservesHook
import ./json_messages import ./json_messages

View File

@ -2,7 +2,7 @@
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
from os import commandLineParams from os import commandLineParams
import preserves, syndicate/capabilities import preserves, syndicate/capabilities, syndicate/protocols/sturdy
const usage = """ const usage = """
mintsturdyref OID < SECRET_KEY mintsturdyref OID < SECRET_KEY
@ -19,7 +19,7 @@ See:
""" """
proc main = proc main =
var oids: seq[Preserve[void]] var oids: seq[Value]
for p in commandLineParams(): for p in commandLineParams():
case p case p
of "-h", "--help", "?": of "-h", "--help", "?":
@ -28,7 +28,7 @@ proc main =
add(oids, parsePreserves p) add(oids, parsePreserves p)
if oids.len == 0: if oids.len == 0:
stderr.writeLine """using the "syndicate" OID""" stderr.writeLine """using the "syndicate" OID"""
oids.add(toPreserve "syndicate") oids.add(toPreserves "syndicate")
var key: array[16, byte] var key: array[16, byte]
case readBytes(stdin, key, 0, 16) case readBytes(stdin, key, 0, 16)

View File

@ -25,7 +25,7 @@ runActor("mount_actor") do (turn: var Turn; root: Cap):
targetPat = ?Observe(pattern: !Mountpoint) ?? { 1: grabLit() } targetPat = ?Observe(pattern: !Mountpoint) ?? { 1: grabLit() }
sourcePat = ?Observe(pattern: !Mountpoint) ?? { 0: grabLit(), 2: grabLit() } sourcePat = ?Observe(pattern: !Mountpoint) ?? { 0: grabLit(), 2: grabLit() }
connectStdio(turn, root) connectStdio(turn, root)
during(turn, root, ?BootArgs) do (ds: Cap): during(turn, root, ?:BootArgs) do (ds: Cap):
during(turn, ds, targetPat) do (target: string): during(turn, ds, targetPat) do (target: string):
during(turn, ds, sourcePat) do (source: string, fsType: string): during(turn, ds, sourcePat) do (source: string, fsType: string):
var mountpoint = Mountpoint( var mountpoint = Mountpoint(
@ -35,7 +35,7 @@ runActor("mount_actor") do (turn: var Turn; root: Cap):
) )
var rc = mount(source, target, fsType, 0, nil) var rc = mount(source, target, fsType, 0, nil)
if rc == 0: if rc == 0:
mountpoint.status = Status(orKind: StatusKind.true) mountpoint.status = Status(orKind: StatusKind.success)
else: else:
mountpoint.status = Status(orKind: StatusKind.Failure) mountpoint.status = Status(orKind: StatusKind.Failure)
mountpoint.status.failure.msg = osErrorMsg(osLastError()) mountpoint.status.failure.msg = osErrorMsg(osLastError())

View File

@ -15,9 +15,9 @@ var
IP_TTL {.importc, nodecl, header: "<netinet/in.h>".}: int IP_TTL {.importc, nodecl, header: "<netinet/in.h>".}: int
]# ]#
proc toPreserveHook(address: IpAddress; E: typedesc): Preserve[E] = toPreserve($address, E) proc toPreservesHook(address: IpAddress): Value = toPreserves($address)
proc fromPreserveHook[E](address: var IpAddress; pr: Preserve[E]): bool = proc fromPreservesHook(address: var IpAddress; pr: Value): bool =
try: try:
if pr.isString: if pr.isString:
address = parseIpAddress(pr.string) address = parseIpAddress(pr.string)
@ -27,7 +27,7 @@ proc fromPreserveHook[E](address: var IpAddress; pr: Preserve[E]): bool =
when isMainModule: when isMainModule:
# verify that the hook catches # verify that the hook catches
var ip: IpAddress var ip: IpAddress
assert fromPreserveHook(ip, toPreserveHook(ip, void)) assert fromPreservesHook(ip, toPreservesHook(ip))
type type
IcmpHeader {.packed.} = object IcmpHeader {.packed.} = object
@ -157,7 +157,7 @@ type Args {.preservesDictionary.} = object
runActor("net_mapper") do (root: Cap; turn: var Turn): runActor("net_mapper") do (root: Cap; turn: var Turn):
connectStdio(turn, root) connectStdio(turn, root)
let rttObserver = ?Observe(pattern: !RoundTripTime) ?? {0: grabLit()} let rttObserver = ?Observe(pattern: !RoundTripTime) ?? {0: grabLit()}
during(turn, root, ?Args) do (ds: Cap): during(turn, root, ?:Args) do (ds: Cap):
during(turn, ds, rttObserver) do (address: IpAddress): during(turn, ds, rttObserver) do (address: IpAddress):
var ping: Pinger var ping: Pinger
if address.family == IpAddressFamily.IPv4: if address.family == IpAddressFamily.IPv4:

View File

@ -16,6 +16,6 @@ proc main =
info.argv = commandLineParams() info.argv = commandLineParams()
for key, val in envPairs(): info.env[key] = val for key, val in envPairs(): info.env[key] = val
info.dir = getCurrentDir() info.dir = getCurrentDir()
writeLine(stdout, info.toPreserve) writeLine(stdout, info.toPreserves)
main() main()

View File

@ -19,7 +19,7 @@ proc main =
resolve(turn, root, route) do (turn: var Turn; ds: Cap): resolve(turn, root, route) do (turn: var Turn; ds: Cap):
case paramCount() case paramCount()
of 0: of 0:
let pat = ?Options let pat = ?:Options
onPublish(turn, ds, pat) do (options: seq[string]): onPublish(turn, ds, pat) do (options: seq[string]):
stdout.writeLine options.join("\n") stdout.writeLine options.join("\n")
quit() quit()

View File

@ -7,12 +7,12 @@ type
`path`*: string `path`*: string
JsonSocketTranslatorArguments* {.preservesDictionary.} = object JsonSocketTranslatorArguments* {.preservesDictionary.} = object
`dataspace`* {.preservesEmbedded.}: Preserve[void] `dataspace`* {.preservesEmbedded.}: Value
`socket`*: string `socket`*: string
proc `$`*(x: JsonTranslatorConnected | JsonSocketTranslatorArguments): string = proc `$`*(x: JsonTranslatorConnected | JsonSocketTranslatorArguments): string =
`$`(toPreserve(x)) `$`(toPreserves(x))
proc encode*(x: JsonTranslatorConnected | JsonSocketTranslatorArguments): seq[ proc encode*(x: JsonTranslatorConnected | JsonSocketTranslatorArguments): seq[
byte] = byte] =
encode(toPreserve(x)) encode(toPreserves(x))

View File

@ -10,7 +10,7 @@ type
`name`*: string `name`*: string
proc `$`*(x: InotifyMessage): string = proc `$`*(x: InotifyMessage): string =
`$`(toPreserve(x)) `$`(toPreserves(x))
proc encode*(x: InotifyMessage): seq[byte] = proc encode*(x: InotifyMessage): seq[byte] =
encode(toPreserve(x)) encode(toPreserves(x))

View File

@ -13,18 +13,18 @@ type
`status`*: Status `status`*: Status
StatusKind* {.pure.} = enum StatusKind* {.pure.} = enum
`Failure`, `true` `Failure`, `success`
`Status`* {.preservesOr.} = object `Status`* {.preservesOr.} = object
case orKind*: StatusKind case orKind*: StatusKind
of StatusKind.`Failure`: of StatusKind.`Failure`:
`failure`*: Failure `failure`*: Failure
of StatusKind.`true`: of StatusKind.`success`:
`true`* {.preservesLiteral: "#t".}: bool `success`* {.preservesLiteral: "#t".}: bool
proc `$`*(x: Failure | Mountpoint | Status): string = proc `$`*(x: Failure | Mountpoint | Status): string =
`$`(toPreserve(x)) `$`(toPreserves(x))
proc encode*(x: Failure | Mountpoint | Status): seq[byte] = proc encode*(x: Failure | Mountpoint | Status): seq[byte] =
encode(toPreserve(x)) encode(toPreserves(x))

View File

@ -10,7 +10,7 @@ type
`maximum`*: float32 `maximum`*: float32
proc `$`*(x: RoundTripTime): string = proc `$`*(x: RoundTripTime): string =
`$`(toPreserve(x)) `$`(toPreserves(x))
proc encode*(x: RoundTripTime): seq[byte] = proc encode*(x: RoundTripTime): seq[byte] =
encode(toPreserve(x)) encode(toPreserves(x))

View File

@ -12,7 +12,7 @@ type
`options`*: seq[string] `options`*: seq[string]
proc `$`*(x: Environment | Select | Options): string = proc `$`*(x: Environment | Select | Options): string =
`$`(toPreserve(x)) `$`(toPreserves(x))
proc encode*(x: Environment | Select | Options): seq[byte] = proc encode*(x: Environment | Select | Options): seq[byte] =
encode(toPreserve(x)) encode(toPreserves(x))

View File

@ -3,13 +3,14 @@
## An actor for relaying Webhooks. ## An actor for relaying Webhooks.
import std/[asyncdispatch, asynchttpserver, json, net, sets, strutils, tables, uri] import std/[asyncdispatch, asynchttpserver, net, strutils, tables, uri]
import preserves, preserves/jsonhooks import preserves, preserves/jsonhooks
import syndicate, syndicate/[bags, relays] import syndicate, syndicate/[bags, relays]
import syndicate/protocols/[http, transportAddress] import syndicate/protocols/[http, transportAddress]
type type
CapBag = Bag[Cap]
Endpoints = Table[seq[string], Cap] Endpoints = Table[seq[string], Cap]
WebhookArgs {.preservesDictionary.} = object WebhookArgs {.preservesDictionary.} = object
endpoints: Assertion endpoints: Assertion
@ -19,36 +20,37 @@ type
func splitPath(s: string): seq[string] = s.strip(chars={'/'}).split('/') func splitPath(s: string): seq[string] = s.strip(chars={'/'}).split('/')
proc toRecord(req: Request; seqnum: BiggestInt; path: seq[string]): HttpRequest = proc toRecord(req: Request; seqnum: BiggestInt; path: seq[string]): Value =
## Convert a request value from the std/asynchttpserver module ## Convert a request value from the std/asynchttpserver module
## to a request type from syndicate/protocols/http. ## to a request type from syndicate/protocols/http.
result.sequenceNumber = seqnum var record: HttpRequest
result.host = req.hostname record.sequenceNumber = seqnum
result.`method` = Symbol($req.reqMethod) record.host = req.hostname
result.path = path record.`method` = Symbol($req.reqMethod)
record.path = path
for key, val in req.headers.pairs: for key, val in req.headers.pairs:
result.headers[Symbol key] = val record.headers[Symbol key] = val
for key, val in decodeQuery(req.url.query): for key, val in decodeQuery(req.url.query):
result.query[Symbol key] = record.query[Symbol key] =
@[QueryValue(orKind: QueryValueKind.string, string: val)] @[QueryValue(orKind: QueryValueKind.string, string: val)]
let contentType = req.headers.getOrDefault("content-type") let contentType = req.headers.getOrDefault("content-type")
result = toPreserves record
if req.body.len > 0: if req.body.len > 0:
result.body = RequestBody(orKind: RequestBodyKind.present) result[7] =
case contentType.toString case contentType.toString
of "application/json": of "application/json":
var js = parseJson req.body req.body.parsePreserves
result.body.present = js.toPreserve of "application/octet-stream":
of "application/octet-stream": cast[seq[byte]](req.body).toPreserves
result.body.present = cast[seq[byte]](req.body).toPreserve else:
else: req.body.toPreserves
result.body.present = req.body.toPreserve
proc bootWebhookActor*(turn: var Turn; root: Cap): Actor = proc bootWebhookActor*(turn: var Turn; root: Cap): Actor =
spawn("webhooks", turn) do (turn: var Turn): spawn("webhooks", turn) do (turn: var Turn):
during(turn, root, inject(!BootArgs, {1: grab(), 2: grab()})) do (host: string; port: Port): during(turn, root, inject(!BootArgs, {1: grab(), 2: grab()})) do (host: string; port: Port):
var seqNum: BiggestInt var seqNum: BiggestInt
let facet = turn.facet let facet = turn.facet
let endpoints = newTable[seq[string], Bag[Cap]]() let endpoints = newTable[seq[string], CapBag]()
# use a bag so the same capability registered multiple # use a bag so the same capability registered multiple
# times with the same path does not get duplicate messages # times with the same path does not get duplicate messages
@ -60,10 +62,11 @@ proc bootWebhookActor*(turn: var Turn; root: Cap): Actor =
"no capabilities registered at $1\n" % [req.url.path]) "no capabilities registered at $1\n" % [req.url.path])
else: else:
result = respond(req, Http200, "") result = respond(req, Http200, "")
run(facet) do (turn: var Turn): proc act(turn: var Turn) {.gcsafe.} =
var rec = req.toRecord(seqNum, path) let rec = req.toRecord(seqNum, path)
for cap in endpoints[rec.path]: for cap in endpoints[path]:
message(turn, cap, rec) message(turn, cap, rec)
run(facet, act)
let server = newAsyncHttpServer() let server = newAsyncHttpServer()
if host.isIpAddress: if host.isIpAddress:
@ -80,7 +83,7 @@ proc bootWebhookActor*(turn: var Turn; root: Cap): Actor =
during(turn, root, inject(!BootArgs, {0: grab(), 1: ?host, 2: ?port})) do (eps: Endpoints): during(turn, root, inject(!BootArgs, {0: grab(), 1: ?host, 2: ?port})) do (eps: Endpoints):
for path, cap in eps: for path, cap in eps:
if not endpoints.hasKey path: if not endpoints.hasKey path:
endpoints[path] = Bag[Cap]() endpoints[path] = CapBag()
discard endpoints[path].change(cap, +1) discard endpoints[path].change(cap, +1)
do: do:
for path, cap in eps: for path, cap in eps:
@ -88,5 +91,3 @@ proc bootWebhookActor*(turn: var Turn; root: Cap): Actor =
do: do:
close(server) close(server)
# TODO: JSON payloads

View File

@ -15,17 +15,17 @@ proc exitProc() {.noconv.} =
setControlCHook(exitProc) setControlCHook(exitProc)
proc parsePattern(pr: Assertion): Pattern = proc parsePattern(pr: Value): Pattern =
let let
dropSigil = initRecord("lit", "_".toSymbol(Cap)) dropSigil = initRecord("lit", "_".toSymbol)
grabSigil = initRecord("lit", "?".toSymbol(Cap)) grabSigil = initRecord("lit", "?".toSymbol)
var pr = grab(pr).toPreserve(Cap) var pr = grab(pr).toPreserves
apply(pr) do (pr: var Assertion): apply(pr) do (pr: var Value):
if pr == dropSigil: if pr == dropSigil:
pr = initRecord[Cap]("_") pr = initRecord("_")
elif pr == grabSigil: elif pr == grabSigil:
pr = initRecord("bind", initRecord[Cap]("_")) pr = initRecord("bind", initRecord("_"))
doAssert result.fromPreserve(pr) doAssert result.fromPreserves(pr)
proc inputPattern: Pattern = proc inputPattern: Pattern =
var args = commandLineParams() var args = commandLineParams()
@ -36,10 +36,10 @@ proc inputPattern: Pattern =
if input == "": if input == "":
quit "expected Preserves Pattern on stdin" quit "expected Preserves Pattern on stdin"
else: else:
var pr: Assertion var pr: Value
try: pr = decodePreserves(input, Cap) try: pr = decodePreserves(input)
except ValueError: discard except ValueError: discard
try: pr = parsePreserves(input, Cap) try: pr = parsePreserves(input)
except ValueError: discard except ValueError: discard
if pr.isFalse: if pr.isFalse:
quit "failed to parse Preserves argument" quit "failed to parse Preserves argument"
@ -47,7 +47,7 @@ proc inputPattern: Pattern =
type TermEntity {.final.} = ref object of Entity type TermEntity {.final.} = ref object of Entity
pattern: Pattern pattern: Pattern
value: Assertion value: Value
method publish(te: TermEntity; turn: var Turn; v: AssertionRef; h: Handle) = method publish(te: TermEntity; turn: var Turn; v: AssertionRef; h: Handle) =
te.value = v.value te.value = v.value

View File

@ -2,34 +2,32 @@
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
import std/[os, tables] import std/[os, tables]
import preserves import preserves, syndicate, syndicate/[durings, relays]
import syndicate,
syndicate/[durings, relays]
proc parsePattern(pr: Assertion): Pattern = proc parsePattern(pr: Value): Pattern =
let let
dropSigil = initRecord("lit", "_".toSymbol(Cap)) dropSigil = initRecord("lit", "_".toSymbol)
grabSigil = initRecord("lit", "?".toSymbol(Cap)) grabSigil = initRecord("lit", "?".toSymbol)
var pr = grab(pr).toPreserve(Cap) var pr = grab(pr).toPreserves
apply(pr) do (pr: var Assertion): apply(pr) do (pr: var Value):
if pr == dropSigil: if pr == dropSigil:
pr = initRecord[Cap]("_") pr = initRecord("_")
elif pr == grabSigil: elif pr == grabSigil:
pr = initRecord("bind", initRecord[Cap]("_")) pr = initRecord("bind", initRecord("_"))
doAssert result.fromPreserve(pr) doAssert result.fromPreserves(pr)
proc inputPatterns: seq[Pattern] = proc inputPatterns: seq[Pattern] =
var args = commandLineParams() var args = commandLineParams()
result.setLen(args.len) result.setLen(args.len)
for i, input in args: for i, input in args:
try: result[i] = input.parsePreserves(Cap).parsePattern try: result[i] = input.parsePreserves.parsePattern
except ValueError: except ValueError:
quit "failed to parse Preserves argument" quit "failed to parse Preserves argument"
type DumpEntity {.final.} = ref object of Entity type DumpEntity {.final.} = ref object of Entity
assertions: Table[Handle, seq[Assertion]] assertions: Table[Handle, seq[Value]]
proc toLine(values: seq[Assertion]; prefix: char): string = proc toLine(values: seq[Value]; prefix: char): string =
result = newStringOfCap(1024) result = newStringOfCap(1024)
let sep = getEnv("FS", " ") let sep = getEnv("FS", " ")
result.add(prefix) result.add(prefix)
@ -45,7 +43,7 @@ method publish(dump: DumpEntity; turn: var Turn; ass: AssertionRef; h: Handle) =
dump.assertions[h] = values dump.assertions[h] = values
method retract(dump: DumpEntity; turn: var Turn; h: Handle) = method retract(dump: DumpEntity; turn: var Turn; h: Handle) =
var values: seq[Assertion] var values: seq[Value]
if dump.assertions.pop(h, values): if dump.assertions.pop(h, values):
stdout.write(values.toLine('-')) stdout.write(values.toLine('-'))
stdout.flushFile() stdout.flushFile()

View File

@ -1,6 +1,6 @@
# Package # Package
version = "20231226" version = "20240108"
author = "Emery Hemingway" author = "Emery Hemingway"
description = "Utilites for Syndicated Actors and Synit" description = "Utilites for Syndicated Actors and Synit"
license = "unlicense" license = "unlicense"
@ -10,4 +10,4 @@ bin = @["cache_actor", "json_socket_translator", "json_translator", "m
# Dependencies # Dependencies
requires "nim >= 1.6.6", "illwill", "syndicate >= 20231108" requires "nim >= 2.0.0", "illwill", "syndicate >= 20240108"