Compare commits

...

3 Commits

7 changed files with 151 additions and 52 deletions

View File

@ -3,7 +3,7 @@
import std/macros
import preserves
import syndicate/[actors, patterns]
import syndicate/[actors, dataspaces, patterns]
export patterns
proc wrapPublishHandler(handler: NimNode): NimNode =
@ -30,15 +30,20 @@ proc wrapPublishHandler(handler: NimNode): NimNode =
var
varSectionOuter = newNimNode(nnkVarSection, handler).add(
newIdentDefs(valuesSym, valuesTuple))
body = newStmtList(varSectionInner, handler[6])
publishBody = newStmtList(varSectionInner, handler[6])
turnSym = ident"turn"
handleSym = ident"handle"
handlerSym = genSym(nskProc, "publish")
onRetractIdent = ident"onRetract"
quote do:
proc `handlerSym`(_: Entity; `turnSym`: var Turn; bindings: Assertion; `handleSym`: Handle) =
proc `handlerSym`(entity: Entity; `turnSym`: var Turn; bindings: Assertion; `handleSym`: Handle) =
`varSectionOuter`
if fromPreserve(`valuesSym`, bindings):
`body`
template `onRetractIdent`(retractBody: untyped): untyped =
proc callback(e: Entity; turn: var Turn; h: Handle) =
retractBody
entity.retractImpl = callback # TODO: fine to clobber previous callback?
`publishBody`
proc wrapMessageHandler(handler: NimNode): NimNode =
handler.expectKind nnkDo

View File

@ -3,13 +3,11 @@
import std/[hashes, macros, tables]
import preserves
import ../syndicate/protocols/[dataspace, dataspacePatterns]
import ./actors, ./bags
import ./actors, ./bags, ./patterns, ./protocols/dataspace
from ../syndicate/protocols/protocol import Handle
from ./protocols/protocol import Handle
type
Pattern* = dataspacePatterns.Pattern[Ref]
Observe = dataspace.Observe[Ref]
Turn = actors.Turn

View File

@ -4,7 +4,7 @@
import std/[macros, tables]
import preserves
import ../syndicate/protocols/dataspacePatterns
import ./protocols/dataspacePatterns
from ./actors import Ref
export dataspacePatterns.`$`
@ -17,9 +17,6 @@ type
DCompound* = dataspacePatterns.DCompound[Ref]
Pattern* = dataspacePatterns.Pattern[Ref]
proc `?`*(): Pattern =
Pattern(orKind: PatternKind.DDiscard)
proc `?`*(d: DBind): Pattern =
Pattern(orKind: PatternKind.DBind, dbind: d)
@ -29,20 +26,33 @@ proc `?`*(d: DLit): Pattern =
proc `?`*(d: DCompound): Pattern =
Pattern(orKind: PatternKind.DCompound, dcompound: d)
proc `?`*(s: string): Pattern =
?DLit(value: toPreserve(s, Ref))
proc arity(T: typedesc): int =
var t: ptr T # a hack to iterate the fields of a non-existent instance
for _ in fields(t[]): inc result
var t: T # a hack to iterate the fields of a non-existent instance
for _ in fields(t): inc result
proc `?_`*(): Pattern = Pattern(orKind: PatternKind.DDiscard)
proc `?*`*(): Pattern = ?DBind(pattern: `?_`())
proc `?`*(T: typedesc; bindings: openArray[(int, Pattern)]): Pattern =
## Pattern constructor operator.
when T.hasCustomPragma(preservesRecord):
var
label = tosymbol(T.getCustomPragmaVal(preservesRecord), Ref)
members: Table[BiggestInt, Pattern]
for (i, p) in bindings:
members[BiggestInt i] = ?DBind(pattern: p)
var label = tosymbol(T.getCustomPragmaVal(preservesRecord), Ref)
result = ?DCompound(
orKind: DCompoundKind.rec,
rec: DCompoundRec(
ctor: CRec(label: label, arity: T.arity),
members: members))
members: toTable bindings))
else:
{.error: "no custom pragma on " & $T.}
proc observe*(pat: Pattern): Pattern =
# TODO: why doesn't Observe from ./protocols/dataspace.nim work?
?DCompound(
orKind: DCompoundKind.rec,
rec: DCompoundRec(
ctor: CRec(label: toSymbol("Observe", Ref), arity: 2),
members: toTable {0 : pat}))

View File

@ -5,7 +5,7 @@ import
type
CRec*[E] {.preservesRecord: "rec".} = ref object
`label`*: Preserve[E]
`arity`*: BiggestInt
`arity`*: int
DLit*[E] {.preservesRecord: "lit".} = ref object
`value`*: Preserve[E]
@ -14,19 +14,19 @@ type
`pattern`*: Pattern[E]
DDiscard* {.preservesRecord: "_".} = object
CArr* {.preservesRecord: "arr".} = object
`arity`*: BiggestInt
`arity`*: int
DCompoundKind* {.pure.} = enum
`rec`, `arr`, `dict`
DCompoundRec*[E] {.preservesRecord: "compound".} = ref object
`ctor`*: CRec[E]
`members`*: Table[BiggestInt, Pattern[E]]
`members`*: Table[int, Pattern[E]]
DCompoundArr*[E] {.preservesRecord: "compound".} = ref object
`ctor`*: CArr
`members`*: Table[BiggestInt, Pattern[E]]
`members`*: Table[int, Pattern[E]]
DCompoundDict*[E] {.preservesRecord: "compound".} = ref object
`ctor`*: CDict

View File

@ -3,8 +3,7 @@
import std/[asyncdispatch, options, tables]
import preserves, preserves/parse
import ../syndicate/protocols/[protocol, sturdy]
import ./actors, ./dataspaces
import ./actors, ./dataspaces, ./protocols/[protocol, sturdy]
type Oid = sturdy.Oid
@ -280,13 +279,13 @@ proc dispatch(relay: Relay; v: Preserve[WireRef]) =
close relay
proc recv(relay: Relay; buf: seq[byte]) =
proc recv(relay: Relay; buf: string) =
# var pkt = decodePreserves(buf, WireRef)
echo "S: ", buf
var pkt = cast[Preserve[WireRef]](
parsePreserves(cast[string](buf), sturdy.WireRef[void]))
parsePreserves(buf, sturdy.WireRef[void]))
# the compiler cannot convert `Preserve[void]` to `Preserve[WireRef[Ref]]`
# so convert to `Preserve[WireRef[void]]` and cast.
echo "S: ", pkt
dispatch(relay, pkt)
type
@ -361,13 +360,16 @@ proc connectUnix*(turn: var Turn; path: string; cap: SturdyRef; bootProc: During
proc setup(turn: var Turn; relay: Relay) =
let facet = turn.activeFacet
proc recvCb(pktFut: Future[string]) {.gcsafe.} =
let buf = cast[seq[byte]](pktFut.read)
if buf.len == 0:
if pktFut.failed:
run(facet) do (turn: var Turn): stopActor(turn)
else:
relay.recv(buf )
socket.recv(recvSize).addCallback(recvCb)
# TODO: should this need be callSoon?
let buf = pktFut.read
if buf.len == 0:
run(facet) do (turn: var Turn): stopActor(turn)
else:
relay.recv(buf)
socket.recv(recvSize).addCallback(recvCb)
# TODO: should this need be callSoon?
socket.recv(recvSize).addCallback(recvCb)
turn.activeFacet.actor.atExit do (turn: var Turn): close(socket)
discard publish(turn, connectionClosedRef, true)

View File

@ -3,24 +3,16 @@
import std/[asyncdispatch, strutils]
import preserves, preserves/parse
import syndicate, syndicate/protocols/[simpleChatProtocol]
import syndicate/[actors, capabilities, dataspaces, patterns, relay]
import syndicate,
syndicate/[actors, capabilities, dataspaces, patterns, relay],
syndicate/protocols/[simpleChatProtocol]
from syndicate/protocols/protocol import Handle
from os import getCurrentProcessId
when defined(linux):
proc getentropy(buf: pointer; bufLen: csize_t): cint {.
importc, header: "sys/random.h".}
proc mint(): SturdyRef =
#var key: array[32, byte]
#doAssert getEntropy(addr key[0], csize_t key.len) == 0
#mint(key, "syndicate")
let pr = parsePreserves("""<ref "syndicate" [] #x"a6480df5306611ddd0d3882b546e1977">""", Ref)
doAssert fromPreserve(result, pr)
var key: array[16, byte]
mint(key, "syndicate")
waitFor runActor("chat") do (turn: var Turn):
@ -40,12 +32,12 @@ waitFor runActor("chat") do (turn: var Turn):
updateUsername(turn, "user" & $getCurrentProcessId())
onPublish(turn, ds, Present ? {0: `?`()}) do (username: string):
onPublish(turn, ds, Present ? {0: `?*`()}) do (username: string):
echo username, " arrived"
#onRetract:
# echo username, " left"
onRetract:
echo username, " left"
onMessage(turn, ds, Says ? {0: `?`(), 1: `?`()}) do (who: string; what: string):
onMessage(turn, ds, Says ? {0: `?*`(), 1: `?*`()}) do (who: string; what: string):
echo who, ": ", what
message(turn, ds, Says(who: username, what: "hello"))

92
tests/simple_chat.sy Executable file
View File

@ -0,0 +1,92 @@
#!/usr/bin/env spry
title = "Simple Chat Demo"
# Initialize libui
uiInit
username = "user"
menu = newMenu "Menu"
# menu addItem: "Username" onClicked: [
# dialog = newWindow: "Username" width: 200 height: 40 hasBar: false
# entry = newEntryText: username onChanged: []
# quitit = newButton: "Quit" onClicked: [
# destroy dialog
# true
# ]
# layout = newHorizontalBox
# #layout add: entry stretch: true
# layout.add: quitit stretch: false
# group = newGroup "Username"
# group setChild: layout
# dialog setChild: quitit
# dialog show
# ]
menu menuAppendAboutItem
menu addQuitItemShouldClose: [
win destroy
uiQuit
true
]
# Create a new Window
win = newWindow: title width: 640 height: 400 hasBar: true
win margined: true
# create text boxes
scrollback = newMultilineEntryText
scrollback readonly: true
sendEntry = newMultilineEntryText
# create layouts
layout = newVerticalBox
sendBox = newHorizontalBox
# Some buttons and their handlers
sendButton = newButton: "Send" onClicked: [
msg = (sendEntry text)
msg != "" then: [
scrollback addText: (msg, "\x0a")
sendEntry text: ""
]
]
# Group
group = newGroup "Workspace"
group margined: false
group setChild: layout
sendBox add: sendEntry stretch: true
sendBox add: sendButton stretch: false
# Put things in the boxes
layout padded: true
layout add: scrollback stretch: true
layout add: sendBox stretch: false
# Add box to window
win setChild: group
# Set initial text
sendEntry text: "compose a message here"
# Close handler
closeHandler = [
win destroy
uiQuit
true
]
# Set a handler on closing window
win onClosingShouldClose: [ true ]
# Show the window
win show
# Enter libui's event loop
uiMain