diff --git a/samples/Makefile b/samples/Makefile index 1103cc93c04..4a220a1ef77 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -7,6 +7,7 @@ ASC_FLAGS=-r -t -v SAMPLES:=$(basename $(wildcard *.as)) +SUBDIRS:=$(shell ls -d */) all: rm -f *.txt @@ -14,6 +15,9 @@ all: echo "$(ASC) $(ASC_FLAGS) $$sample.as >$$sample.txt 2>&1"; \ $(ASC) $(ASC_FLAGS) $$sample.as >$$sample.txt 2>&1; \ done + @for dir in $(SUBDIRS); do \ + make -C $$dir ; \ + done clean: rm -f *.txt diff --git a/samples/app/Makefile b/samples/app/Makefile new file mode 100644 index 00000000000..95c3871de0a --- /dev/null +++ b/samples/app/Makefile @@ -0,0 +1,22 @@ +# Makefile for actorscript demos + +# This works with bash + +ASC=../../src/asc +DVM=../../test/dvm.sh +# we need to specify the output if there is more than one .as file +OUT=main.wasm +#ASC_FLAGS=-r -t -v +LIB=list.as types.as server.as client.as + +SAMPLES:= test + +all: + $(ASC) -r -t -v $(LIB) main.as >main.txt 2>&1 + +dvm: + $(ASC) --dfinity -o $(OUT) $(LIB) main.as + $(DVM) $(OUT) + +clean: + rm -f $(OUT) diff --git a/samples/app/README.md b/samples/app/README.md new file mode 100644 index 00000000000..4edaef412f2 --- /dev/null +++ b/samples/app/README.md @@ -0,0 +1,7 @@ +# Compiling multiple-files as a single application + +This sample shows how to interpret/compile an application consisting of multipl e `.as` files by passing several files on the `asc` command-line. + +The application is a version of the single-file [chatpp][../chatpp.as], split into several files. + +See the [Makefile](./Makefile) for more details. \ No newline at end of file diff --git a/samples/app/client.as b/samples/app/client.as new file mode 100644 index 00000000000..d29ab90227b --- /dev/null +++ b/samples/app/client.as @@ -0,0 +1,21 @@ +actor class Client() = this { + // TODO: these should be constructor params once we can compile them + private var name : Text = ""; + private var server : ?Server = null; + + go(n : Text, s : Server) { + name := n; + server := ?s; + ignore(async { + let sub = await s.subscribe(this); + sub.post("hello from " # name); + sub.post("goodbye from " # name); + sub.cancel(); + }) + }; + + send(msg : Text) { + print(name # " received " # msg # "\n"); + }; +}; + diff --git a/samples/app/list.as b/samples/app/list.as new file mode 100644 index 00000000000..b37e2d13f01 --- /dev/null +++ b/samples/app/list.as @@ -0,0 +1,2 @@ +type List = ?{head : T; var tail : List}; + diff --git a/samples/app/main.as b/samples/app/main.as new file mode 100644 index 00000000000..d23e4ee6fb2 --- /dev/null +++ b/samples/app/main.as @@ -0,0 +1,7 @@ +let server = Server(); +let bob = Client(); +let alice = Client(); +let charlie = Client(); +bob.go("bob", server); +alice.go("alice", server); +charlie.go("charlie", server); diff --git a/samples/app/main.txt b/samples/app/main.txt new file mode 100644 index 00000000000..15622ff780c --- /dev/null +++ b/samples/app/main.txt @@ -0,0 +1,200 @@ +-- Checking all: +type Client = actor {go : shared (Text, Server) -> (); send : shared Text -> ()} +type ClientData = {client : Client; id : Nat; revoked : var Bool} +type List = ?{head : T; tail : var List} +type Server = actor {subscribe : shared Client -> async Subscription} +type Subscription = shared {cancel : shared () -> (); post : shared Text -> ()} +let Client : () -> Client +let Server : () -> Server +let alice : actor {go : shared (Text, Server) -> (); send : shared Text -> ()} +let bob : actor {go : shared (Text, Server) -> (); send : shared Text -> ()} +let charlie : actor {go : shared (Text, Server) -> (); send : shared Text -> ()} +let server : actor {subscribe : shared Client -> async Subscription} +-- Interpreting all: +Server() + <= {subscribe = func} +Client() + <= {go = func; send = func} +Client() + <= {go = func; send = func} +Client() + <= {go = func; send = func} +-> message go("bob", {subscribe = func}) +-> message go("alice", {subscribe = func}) +-> message go("charlie", {subscribe = func}) +<- message go("bob", {subscribe = func}) + go("bob", {subscribe = func}) + -> async client.as:9.12-14.6 + ignore(async _) + <= () + <= () +<- message go("alice", {subscribe = func}) + go("alice", {subscribe = func}) + -> async client.as:9.12-14.6 + ignore(async _) + <= () + <= () +<- message go("charlie", {subscribe = func}) + go("charlie", {subscribe = func}) + -> async client.as:9.12-14.6 + ignore(async _) + <= () + <= () +<- async client.as:9.12-14.6 + -> message subscribe({go = func; send = func}) + => await client.as:10.17-10.40 +<- async client.as:9.12-14.6 + -> message subscribe({go = func; send = func}) + => await client.as:10.17-10.40 +<- async client.as:9.12-14.6 + -> message subscribe({go = func; send = func}) + => await client.as:10.17-10.40 +<- message subscribe({go = func; send = func}) + subscribe({go = func; send = func}) + -> async server.as:18.52-29.4 + <= async _ +<- message subscribe({go = func; send = func}) + subscribe({go = func; send = func}) + -> async server.as:18.52-29.4 + <= async _ +<- message subscribe({go = func; send = func}) + subscribe({go = func; send = func}) + -> async server.as:18.52-29.4 + <= async _ +<- async server.as:18.52-29.4 + <= {cancel = func; post = func} +<- async server.as:18.52-29.4 + <= {cancel = func; post = func} +<- async server.as:18.52-29.4 + <= {cancel = func; post = func} +<- await client.as:10.17-10.40({cancel = func; post = func}) + -> message anon-func-24.14("hello from bob") + -> message anon-func-24.14("goodbye from bob") + -> message anon-func-27.16() + <= () +<- await client.as:10.17-10.40({cancel = func; post = func}) + -> message anon-func-24.14("hello from alice") + -> message anon-func-24.14("goodbye from alice") + -> message anon-func-27.16() + <= () +<- await client.as:10.17-10.40({cancel = func; post = func}) + -> message anon-func-24.14("hello from charlie") + -> message anon-func-24.14("goodbye from charlie") + -> message anon-func-27.16() + <= () +<- message anon-func-24.14("hello from bob") + anon-func-24.14("hello from bob") + broadcast(0, "hello from bob") + -> message send("hello from bob") + -> message send("hello from bob") + <= () + <= () +<- message anon-func-24.14("goodbye from bob") + anon-func-24.14("goodbye from bob") + broadcast(0, "goodbye from bob") + -> message send("goodbye from bob") + -> message send("goodbye from bob") + <= () + <= () +<- message anon-func-27.16() + anon-func-27.16() + unsubscribe(0) + print("(unsubscribe ") +(unsubscribe <= () + printInt(0) +0 <= () + print(")\n") +) + <= () + <= () + <= () +<- message anon-func-24.14("hello from alice") + anon-func-24.14("hello from alice") + broadcast(1, "hello from alice") + -> message send("hello from alice") + <= () + <= () +<- message anon-func-24.14("goodbye from alice") + anon-func-24.14("goodbye from alice") + broadcast(1, "goodbye from alice") + -> message send("goodbye from alice") + <= () + <= () +<- message anon-func-27.16() + anon-func-27.16() + unsubscribe(1) + print("(unsubscribe ") +(unsubscribe <= () + printInt(1) +1 <= () + print(")\n") +) + <= () + <= () + <= () +<- message anon-func-24.14("hello from charlie") + anon-func-24.14("hello from charlie") + broadcast(2, "hello from charlie") + <= () + <= () +<- message anon-func-24.14("goodbye from charlie") + anon-func-24.14("goodbye from charlie") + broadcast(2, "goodbye from charlie") + <= () + <= () +<- message anon-func-27.16() + anon-func-27.16() + unsubscribe(2) + print("(unsubscribe ") +(unsubscribe <= () + printInt(2) +2 <= () + print(")\n") +) + <= () + <= () + <= () +<- message send("hello from bob") + send("hello from bob") + print("charlie received hello from bob\n") +charlie received hello from bob + <= () + <= () +<- message send("hello from bob") + send("hello from bob") + print("alice received hello from bob\n") +alice received hello from bob + <= () + <= () +<- message send("goodbye from bob") + send("goodbye from bob") + print("charlie received goodbye from bob\n") +charlie received goodbye from bob + <= () + <= () +<- message send("goodbye from bob") + send("goodbye from bob") + print("alice received goodbye from bob\n") +alice received goodbye from bob + <= () + <= () +<- message send("hello from alice") + send("hello from alice") + print("charlie received hello from alice\n") +charlie received hello from alice + <= () + <= () +<- message send("goodbye from alice") + send("goodbye from alice") + print("charlie received goodbye from alice\n") +charlie received goodbye from alice + <= () + <= () +-- Finished all: +let Client : () -> Client = func +let Server : () -> Server = func +let alice : actor {go : shared (Text, Server) -> (); send : shared Text -> ()} = {go = func; send = func} +let bob : actor {go : shared (Text, Server) -> (); send : shared Text -> ()} = {go = func; send = func} +let charlie : actor {go : shared (Text, Server) -> (); send : shared Text -> ()} = {go = func; send = func} +let server : actor {subscribe : shared Client -> async Subscription} = {subscribe = func} + diff --git a/samples/app/server.as b/samples/app/server.as new file mode 100644 index 00000000000..2dc1368203a --- /dev/null +++ b/samples/app/server.as @@ -0,0 +1,54 @@ +actor class Server() = { + private var nextId : Nat = 0; + private var clients : List = null; + + private broadcast(id : Nat, message : Text) { + var next = clients; + label sends loop { + switch next { + case null { break sends }; + case (?n) { + if (n.head.id != id) n.head.client.send(message); + next := n.tail; + }; + }; + }; + }; + + subscribe(aclient : Client) : async Subscription { + let c = new {id = nextId; client = aclient; var revoked = false}; + nextId += 1; + let cs = new {head = c; var tail = clients}; + clients := ?cs; + return (shared { + post = shared func(message : Text) { + if (not c.revoked) broadcast(c.id, message); + }; + cancel = shared func() { unsubscribe(c.id) }; + }); + }; + + private unsubscribe(id : Nat) { + var prev : List = null; + var next = clients; + loop { + switch next { + case null return; + case (?n) { + if (n.head.id == id) { + switch prev { + case null { clients := n.tail }; + case (?p) { p.tail := n.tail }; + }; + print "(unsubscribe "; printInt id; print ")\n"; + return; + }; + prev := next; + next := n.tail; + }; + }; + }; + }; +}; + + diff --git a/samples/app/types.as b/samples/app/types.as new file mode 100644 index 00000000000..3ff7117f44d --- /dev/null +++ b/samples/app/types.as @@ -0,0 +1,11 @@ +type Subscription = shared { + post : shared Text -> (); // revokable by Server + cancel : shared () -> (); +}; + +type ClientData = { + id : Nat; + client : Client; + var revoked : Bool; +}; +