aboutsummaryrefslogtreecommitdiff
path: root/docs/history/10-zc/code/tests
diff options
context:
space:
mode:
Diffstat (limited to 'docs/history/10-zc/code/tests')
-rw-r--r--docs/history/10-zc/code/tests/basics.zc22
-rw-r--r--docs/history/10-zc/code/tests/errors/back_to_m.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/borrow_escape.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/branch_mismatch.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/child_dies.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/child_recast.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/copy_owned.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/d_into_block.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/d_kept.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/discard_u.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/give_m.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/global_store.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/leak_overwrite.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/lend_d.zc4
-rw-r--r--docs/history/10-zc/code/tests/errors/loop_move.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/plain_return.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/proto_needed.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/return_m.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/tag_mismatch.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/u_dropped.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/u_skip_level.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/unchecked_touch.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/untagged_param.zc3
-rw-r--r--docs/history/10-zc/code/tests/errors/unused.zc2
-rw-r--r--docs/history/10-zc/code/tests/errors/use_after_give.zc3
-rw-r--r--docs/history/10-zc/code/tests/gc.zc20
-rw-r--r--docs/history/10-zc/code/tests/meta.zc46
-rw-r--r--docs/history/10-zc/code/tests/misc.zc30
-rwxr-xr-xdocs/history/10-zc/code/tests/runerr.sh9
-rw-r--r--docs/history/10-zc/code/tests/umd.zc52
30 files changed, 241 insertions, 0 deletions
diff --git a/docs/history/10-zc/code/tests/basics.zc b/docs/history/10-zc/code/tests/basics.zc
new file mode 100644
index 0000000..9dfb44e
--- /dev/null
+++ b/docs/history/10-zc/code/tests/basics.zc
@@ -0,0 +1,22 @@
+var table[10];
+var greeting = "hey";
+const N = 10, BIG = 0x100 * 2;
+fn fib(n) { if (n < 2) return n; return fib(n - 1) + fib(n - 2); }
+fn twice(f, x) { return f(f(x)); }
+fn inc(x) { return x + 1; }
+fn main()
+{
+ var i, s = 0, a[5];
+ for (i = 0; i < N; i++) table[i] = i * i;
+ for (var j = 0; j < N; j++) s += table[j];
+ putn(s); putc(' '); putn(fib(15)); putc(' '); putn(twice(inc, 40)); putc(' '); putn(BIG); putc(10);
+ puts(greeting); putc(' '); putn('A'); putc(' '); putn(-17 / 5); putc(' '); putn(-17 % 5); putc(' '); putn(1 << 10); putc(' '); putn(-64 >> 3); putc(10);
+ i = 0; while (1) { i++; if (i == 3) continue; if (i > 6) break; putn(i); } putc(10);
+ a[0] = 5; a[1] = a[0]++; a[2] = ++a[0]; putn(a[0]); putn(a[1]); putn(a[2]); putc(10);
+ var b = { var t = 3; t * t };
+ putn(b); putc(' '); putn(3 > 2 && 2 > 1); putn(0 || 0); putn(!5); putn(~0); putn(5 != 5); putn(4 >= 4); putc(10);
+ var x = asm { 2 3 + };
+ putn(x); putc(10);
+ asm { 'o' . 'k' . 10 . }
+ return 0;
+}
diff --git a/docs/history/10-zc/code/tests/errors/back_to_m.zc b/docs/history/10-zc/code/tests/errors/back_to_m.zc
new file mode 100644
index 0000000..ee25096
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/back_to_m.zc
@@ -0,0 +1,2 @@
+// expect: x: can't be recast back to m
+fn main() { var x = new(3); x as d; x as m; return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/borrow_escape.zc b/docs/history/10-zc/code/tests/errors/borrow_escape.zc
new file mode 100644
index 0000000..725bc61
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/borrow_escape.zc
@@ -0,0 +1,3 @@
+// expect: p: is owned and can't be returned
+fn f(m p) { return p; }
+fn main() { var x = new(1); f(x); return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/branch_mismatch.zc b/docs/history/10-zc/code/tests/errors/branch_mismatch.zc
new file mode 100644
index 0000000..62cb18b
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/branch_mismatch.zc
@@ -0,0 +1,3 @@
+// expect: x: ends the branches of an if in different states
+fn take(d p) { return p[0]; }
+fn main() { var x = new(1); x as d; if (x[0]) take(x); return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/child_dies.zc b/docs/history/10-zc/code/tests/errors/child_dies.zc
new file mode 100644
index 0000000..16e1935
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/child_dies.zc
@@ -0,0 +1,3 @@
+// expect: c: used after it was given away
+fn take(d p) { return p[0]; }
+fn main() { var p = new(2), c = new(1); p[0] = c; take(p as d); return c[0]; }
diff --git a/docs/history/10-zc/code/tests/errors/child_recast.zc b/docs/history/10-zc/code/tests/errors/child_recast.zc
new file mode 100644
index 0000000..f4be23e
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/child_recast.zc
@@ -0,0 +1,2 @@
+// expect: c: belongs to a container; recast the container instead
+fn main() { var p = new(2), c = new(1); p[0] = c; c as d; return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/copy_owned.zc b/docs/history/10-zc/code/tests/errors/copy_owned.zc
new file mode 100644
index 0000000..42d2ab0
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/copy_owned.zc
@@ -0,0 +1,2 @@
+// expect: x: is an owned object and can't be copied
+fn main() { var x = new(1); var y = x; return y[0]; }
diff --git a/docs/history/10-zc/code/tests/errors/d_into_block.zc b/docs/history/10-zc/code/tests/errors/d_into_block.zc
new file mode 100644
index 0000000..02189ab
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/d_into_block.zc
@@ -0,0 +1,2 @@
+// expect: x: used after it was given away
+fn main() { var x = new(1); x as d; { x[0] = 5; } return x[0]; }
diff --git a/docs/history/10-zc/code/tests/errors/d_kept.zc b/docs/history/10-zc/code/tests/errors/d_kept.zc
new file mode 100644
index 0000000..28eaccf
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/d_kept.zc
@@ -0,0 +1,2 @@
+// expect: x: d object was never given away
+fn main() { var x = new(3); x as d; x[0] = 1; return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/discard_u.zc b/docs/history/10-zc/code/tests/errors/discard_u.zc
new file mode 100644
index 0000000..18bc810
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/discard_u.zc
@@ -0,0 +1,3 @@
+// expect: can't be thrown away
+fn mk() -> u { var p = new(1); return p as u; }
+fn main() { mk(); return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/give_m.zc b/docs/history/10-zc/code/tests/errors/give_m.zc
new file mode 100644
index 0000000..537fa0c
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/give_m.zc
@@ -0,0 +1,3 @@
+// expect: x: is m; write 'as d'
+fn take(d p) { return p[0]; }
+fn main() { var x = new(3); take(x); return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/global_store.zc b/docs/history/10-zc/code/tests/errors/global_store.zc
new file mode 100644
index 0000000..13882b9
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/global_store.zc
@@ -0,0 +1,3 @@
+// expect: x: must be d to be stored in a global
+var g;
+fn main() { var x = new(1); g = x; return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/leak_overwrite.zc b/docs/history/10-zc/code/tests/errors/leak_overwrite.zc
new file mode 100644
index 0000000..42773fb
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/leak_overwrite.zc
@@ -0,0 +1,2 @@
+// expect: x: still owns an object
+fn main() { var x = new(1); x = new(2); return x[0]; }
diff --git a/docs/history/10-zc/code/tests/errors/lend_d.zc b/docs/history/10-zc/code/tests/errors/lend_d.zc
new file mode 100644
index 0000000..e1e37d5
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/lend_d.zc
@@ -0,0 +1,4 @@
+// expect: x: is d; pass it to a d parameter
+fn look(m p) { return p[0]; }
+fn take(d p) { return p[0]; }
+fn main() { var x = new(3); x as d; look(x); take(x); return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/loop_move.zc b/docs/history/10-zc/code/tests/errors/loop_move.zc
new file mode 100644
index 0000000..b1a6019
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/loop_move.zc
@@ -0,0 +1,3 @@
+// expect: x: changes state inside a loop
+fn take(d p) { return p[0]; }
+fn main() { var x = new(1); var i = 0; x as d; while (i < 3) { take(x); i++; } return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/plain_return.zc b/docs/history/10-zc/code/tests/errors/plain_return.zc
new file mode 100644
index 0000000..61f546f
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/plain_return.zc
@@ -0,0 +1,3 @@
+// expect: returns a new object; declare the function with -> u
+fn mk() { return new(1); }
+fn main() { return mk(); }
diff --git a/docs/history/10-zc/code/tests/errors/proto_needed.zc b/docs/history/10-zc/code/tests/errors/proto_needed.zc
new file mode 100644
index 0000000..2613b9d
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/proto_needed.zc
@@ -0,0 +1,3 @@
+// expect: f: was called before its tags were declared
+fn main() { var x = new(1); f(1); return x[0]; }
+fn f(d p) { return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/return_m.zc b/docs/history/10-zc/code/tests/errors/return_m.zc
new file mode 100644
index 0000000..c361760
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/return_m.zc
@@ -0,0 +1,3 @@
+// expect: x: has to be u to be returned
+fn mk() -> u { var x = new(1); return x; }
+fn main() { var y = mk(); return y[0]; }
diff --git a/docs/history/10-zc/code/tests/errors/tag_mismatch.zc b/docs/history/10-zc/code/tests/errors/tag_mismatch.zc
new file mode 100644
index 0000000..f9631d6
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/tag_mismatch.zc
@@ -0,0 +1,2 @@
+// expect: c: its tag doesn't match its container's
+fn main() { var p = new(2), c = new(1); p as u; p[0] = c; return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/u_dropped.zc b/docs/history/10-zc/code/tests/errors/u_dropped.zc
new file mode 100644
index 0000000..76b7765
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/u_dropped.zc
@@ -0,0 +1,2 @@
+// expect: x: u object must leave this block
+fn main() { var x = new(3); x as u; return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/u_skip_level.zc b/docs/history/10-zc/code/tests/errors/u_skip_level.zc
new file mode 100644
index 0000000..b8a024f
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/u_skip_level.zc
@@ -0,0 +1,2 @@
+// expect: t: is u; it can only be handed to a variable of the enclosing block
+fn main() { var r; { { var t = new(1); t as u; r = t; } } return r[0]; }
diff --git a/docs/history/10-zc/code/tests/errors/unchecked_touch.zc b/docs/history/10-zc/code/tests/errors/unchecked_touch.zc
new file mode 100644
index 0000000..1f57466
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/unchecked_touch.zc
@@ -0,0 +1,2 @@
+// expect: x: is tracked by the analyzer and can't be used in unchecked code
+fn main() { var x = new(1); unchecked { x[0] = 1; } return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/untagged_param.zc b/docs/history/10-zc/code/tests/errors/untagged_param.zc
new file mode 100644
index 0000000..5a044c6
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/untagged_param.zc
@@ -0,0 +1,3 @@
+// expect: x: is an owned object; it can only be passed to an m or d parameter
+fn f(p) { return 0; }
+fn main() { var x = new(1); f(x); return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/unused.zc b/docs/history/10-zc/code/tests/errors/unused.zc
new file mode 100644
index 0000000..cbc6129
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/unused.zc
@@ -0,0 +1,2 @@
+// expect: x: m object is never used
+fn main() { var x = new(3); return 0; }
diff --git a/docs/history/10-zc/code/tests/errors/use_after_give.zc b/docs/history/10-zc/code/tests/errors/use_after_give.zc
new file mode 100644
index 0000000..5225462
--- /dev/null
+++ b/docs/history/10-zc/code/tests/errors/use_after_give.zc
@@ -0,0 +1,3 @@
+// expect: x: used after it was given away
+fn take(d p) { return p[0]; }
+fn main() { var x = new(3); take(x as d); return x[0]; }
diff --git a/docs/history/10-zc/code/tests/gc.zc b/docs/history/10-zc/code/tests/gc.zc
new file mode 100644
index 0000000..e5ff7f7
--- /dev/null
+++ b/docs/history/10-zc/code/tests/gc.zc
@@ -0,0 +1,20 @@
+var keep;
+unchecked fn churn(n)
+{
+ var i = 0, p;
+ while (i < n) { p = new(10); p[0] = i; if (i % 100 == 0) keep = p; i++; }
+ return 0;
+}
+fn main()
+{
+ var base = live_objects(), f;
+ churn(1000);
+ putn(live_objects() - base); putc(' ');
+ f = gc();
+ putn(f >= 990); putc(' '); // conservative: a stale word or two may keep one alive
+ putn(keep[0]); putc(' '); // the one a global still points at survives
+ churn(200000); // 3.2m words through a 393k word heap: needs the automatic collector
+ putn(gc_runs > 1); putc(' ');
+ putn(keep[0]); putc(10);
+ return 0;
+}
diff --git a/docs/history/10-zc/code/tests/meta.zc b/docs/history/10-zc/code/tests/meta.zc
new file mode 100644
index 0000000..9c81616
--- /dev/null
+++ b/docs/history/10-zc/code/tests/meta.zc
@@ -0,0 +1,46 @@
+fn ipow(a, b) { var r = 1; while (b > 0) { r *= a; b--; } return r; }
+// a parse word that adds an operator to the compiler's tables
+immediate fn pow_op() { next(); add_binop("**", 11, "ipow c"); return 0; }
+pow_op
+
+// unless (cond) stmt: a parse word that emits code itself
+immediate fn unless()
+{
+ var a;
+ next();
+ expect(intern("(")); rval(); plainuse(expr()); rval(); expect(intern(")"));
+ emitseq(useq[0], ulen[0]); // not
+ a = hole(); op(O_JZ); // skip the body when the condition was true
+ substmt();
+ setlit(a, here);
+ return 0;
+}
+// repeat N { body }: a macro, built from token lists
+immediate fn repeat()
+{
+ var n, body, i = 0;
+ next(); n = tv; next();
+ body = grab();
+ while (i < n) { feed(qdup(body)); i++; }
+ free(body as d);
+ return 0;
+}
+fn main()
+{
+ putn(2 ** 10); putc(' '); putn(3 + 2 ** 3 * 2); putc(10);
+ unless (1 > 2) puts("unless ok\n");
+ unless (2 > 1) puts("wrong\n");
+ repeat 3 { putc('r'); }
+ putc(10);
+ var q = quote { putn(40 + 2); putc(10); return 7; };
+ putn(q[0]); putc(' ');
+ putn(eval(q)); putc(10);
+ var f = compile(q);
+ putn(f()); putc(10);
+ free(q as d);
+ var d = quote { fn sq(x) { return x * x; } };
+ load(d);
+ free(d as d);
+ putn(evals("return sq(12);")); putc(10);
+ return 0;
+}
diff --git a/docs/history/10-zc/code/tests/misc.zc b/docs/history/10-zc/code/tests/misc.zc
new file mode 100644
index 0000000..4a8ceef
--- /dev/null
+++ b/docs/history/10-zc/code/tests/misc.zc
@@ -0,0 +1,30 @@
+// ct { ... } runs a block while compiling and leaves its result as a constant
+immediate fn ct()
+{
+ var q, v;
+ next();
+ q = grab();
+ v = eval(q);
+ free(q as d);
+ lit(v);
+ return 0;
+}
+// teach the asm syntax that p means out, like the old repl demo
+immediate fn teach() { next(); mnem[12] = 'p'; return 0; }
+teach
+
+fn countdown()
+{
+ asm { 5 :top 0 $ '0' + p 1 - 0 $ done z top j :done _ 10 p }
+ return 0;
+}
+fn main()
+{
+ putn(ct { var i = 0, s = 0; while (i < 10) { s += i; i++; } return s; }); putc(10);
+ countdown();
+ puts(lazy()); putc(10);
+ return 0;
+}
+// the analyzer is off from here on
+unchecked;
+fn lazy() { var p = new(3); p[0] = 'o'; p[1] = 'k'; return p; }
diff --git a/docs/history/10-zc/code/tests/runerr.sh b/docs/history/10-zc/code/tests/runerr.sh
new file mode 100755
index 0000000..c1d42c5
--- /dev/null
+++ b/docs/history/10-zc/code/tests/runerr.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# runs every tests/errors/*.zc and checks the compiler rejects it with the expected message
+vm=${1:-zy}; pass=0; fail=0
+for f in "$(dirname "$0")"/errors/*.zc; do
+ want=$(head -1 "$f" | sed 's#^// expect: ##')
+ got=$($vm < "$f" 2>&1 | head -1)
+ if [[ "$got" == *"$want"* ]]; then pass=$((pass+1)); else fail=$((fail+1)); echo "FAIL $(basename $f): got [$got]"; fi
+done
+echo "analyzer rejects: $pass passed, $fail failed"
diff --git a/docs/history/10-zc/code/tests/umd.zc b/docs/history/10-zc/code/tests/umd.zc
new file mode 100644
index 0000000..7d1bffc
--- /dev/null
+++ b/docs/history/10-zc/code/tests/umd.zc
@@ -0,0 +1,52 @@
+// lists as [len, items...], items owned by the list
+fn mklist(n) -> u
+{
+ var l = new(n + 1);
+ l[0] = 0;
+ return l as u;
+}
+fn push(m l, d item) { l[l[0] + 1] = item as d; l[0] = l[0] + 1; return 0; }
+fn sum(m l) { var s = 0, i = 1; while (i <= l[0]) { s += l[i][0]; i++; } return s; }
+fn box(v) -> u { var b = new(1); b[0] = v; return b as u; }
+fn consume(d b) { return b[0]; }
+
+fn main()
+{
+ var base = live_objects();
+ {
+ var l = mklist(8); // u from mklist arrives here as m
+ var i = 0;
+ while (i < 5) {
+ var b = box(i * 10); // m in the loop body
+ b as d; // give it down
+ push(l, b);
+ i++;
+ }
+ putn(sum(l)); putc(' ');
+ putn(live_objects() - base); putc(' '); // list + 5 boxes
+ }
+ putn(live_objects() - base); putc(' '); // freed at the block's end, children too
+
+ // u handed up one block by assignment, and as a block value
+ var outer;
+ {
+ var t = box(7);
+ t as u;
+ outer = t;
+ }
+ var v = { var w = box(8); w as u };
+ putn(outer[0] + v[0]); putc(' ');
+
+ // d given away to a callee
+ var g = box(99);
+ putn(consume(g as d)); putc(' ');
+
+ // containers: child takes its parent's tag
+ var p = new(2), c = new(1);
+ c[0] = 5;
+ p[0] = c;
+ p[1] = new(3);
+ putn(p[0][0]); putc(' ');
+ putn(live_objects() - base); putc(10);
+ return 0;
+}