aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-14 18:18:11 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-14 18:18:11 +0330
commit0a67504c1715c5865e7fc646980b153ef346e601 (patch)
tree7724b26c7bdda9d73da0334af1ef3039eb7c63ba
parenttodo: correct self-modifying region caveat (diff)
examples: actor demo
-rw-r--r--examples/actors_demo.zc92
1 files changed, 92 insertions, 0 deletions
diff --git a/examples/actors_demo.zc b/examples/actors_demo.zc
new file mode 100644
index 0000000..656e131
--- /dev/null
+++ b/examples/actors_demo.zc
@@ -0,0 +1,92 @@
+namespace;
+include rt, actor;
+typecheck on;
+
+// actors demo: a ring of isolated worker processes passes a token around,
+// then a fan-out of workers crunches collatz ranges in parallel.
+// run: build/bin/zy < examples/actors_demo.zc
+
+const N = 6, LAPS = 3, W = 4;
+
+void color(int c) { rt.put_c(27); rt.put_s("[1;"); rt.put_n(30 + c); rt.put_c('m'); return; }
+void plain() { rt.put_c(27); rt.put_s("[0m"); return; }
+void bar(int n, int c) { color(c); for (int i = 0; i < n; i++) rt.put_s("#"); plain(); return; }
+
+// one stage of the ring: mixes the token and counts its own hops.
+// `seen` lives in the worker, so the caller's copy stays 0.
+actor Hop {
+ int seen;
+ int handle(int tok) {
+ this.seen += 1;
+ return (tok * 31 + this.seen * 7) % 9973;
+ }
+}
+
+// a cruncher: longest collatz chain that starts in [lo, lo + 20000)
+actor Crunch {
+ int handle(int lo) {
+ int best = 0;
+ for (int s = lo; s < lo + 20000; s++) {
+ int n = s, k = 0;
+ while (n != 1) { if (n % 2) n = 3 * n + 1; else n = n / 2; k++; }
+ if (k > best) best = k;
+ }
+ return best;
+ }
+}
+
+fn main() {
+ color(5); rt.put_s("== tinyvm actors: isolated workers, typed channels ==\n"); plain();
+
+ // the ring: the receive callback of stage i forwards to stage i + 1
+ Hop*[6] ring;
+ for (int i = 0; i < N; i++) { ring[i] = rt.new(Hop); ring[i].spawn(); }
+ Hop** rp = &ring[0]; // closures capture a pointer, not the array
+ let hops = 0, last = 0, done = 0;
+ for (int i = 0; i < N; i++) {
+ let me = i;
+ ring[i].recv(fn(int v) {
+ hops++; last = v;
+ color(1 + me % 6); rt.put_s(" stage "); rt.put_n(me); plain();
+ rt.put_s(" -> token "); rt.put_n(v); rt.put_c(' ');
+ bar(v % 40 + 1, 1 + me % 6); rt.put_c(10);
+ if (hops < N * LAPS) {
+ if (me == N - 1) { color(3); rt.put_s(" -- lap "); rt.put_n(hops / N); rt.put_s(" done --\n"); plain(); }
+ rp[(me + 1) % N].send(v);
+ } else done = 1;
+ return 0;
+ });
+ }
+ color(2); rt.put_s("ring of "); rt.put_n(N); rt.put_s(" actors, "); rt.put_n(LAPS); rt.put_s(" laps, seed 42\n"); plain();
+ ring[0].send(42);
+ while (!done) for (int i = 0; i < N; i++) ring[i].poll();
+ for (int i = 0; i < N; i++) ring[i].close();
+
+ // fan-out: W workers in parallel, results arrive as they finish
+ color(2); rt.put_s("\nfan-out: "); rt.put_n(W); rt.put_s(" crunchers, collatz over 80000 starts\n"); plain();
+ Crunch*[4] pool;
+ let answers = 0, best = 0;
+ for (int i = 0; i < W; i++) {
+ pool[i] = rt.new(Crunch); pool[i].spawn();
+ let me = i;
+ pool[i].recv(fn(int k) {
+ answers++; if (k > best) best = k;
+ color(4); rt.put_s(" worker "); rt.put_n(me); plain();
+ rt.put_s(" ["); rt.put_n(me * 20000 + 1); rt.put_s(".."); rt.put_n(me * 20000 + 20000); rt.put_s("] longest chain ");
+ color(6); rt.put_n(k); plain(); rt.put_c(' '); bar(k / 8, 4 + me % 3); rt.put_c(10);
+ return 0;
+ });
+ pool[i].send(i * 20000 + 1);
+ }
+ for (int i = 0; i < W; i++) pool[i].await();
+ for (int i = 0; i < W; i++) pool[i].close();
+
+ color(5); rt.put_s("\n== summary ==\n"); plain();
+ rt.put_s(" ring hops: "); color(3); rt.put_n(hops); plain(); rt.put_c(10);
+ rt.put_s(" final token: "); color(3); rt.put_n(last); plain(); rt.put_c(10);
+ rt.put_s(" worker replies: "); color(3); rt.put_n(answers); plain(); rt.put_c(10);
+ rt.put_s(" longest chain: "); color(3); rt.put_n(best); plain(); rt.put_c(10);
+ rt.put_s(" caller's ring[0].seen: "); color(3); rt.put_n(ring[0].seen); plain();
+ rt.put_s(" (state stayed in the worker)\n");
+ return 0;
+}