From ecc350ca5c2eb50be8309c5f14f8bf0d87db9a02 Mon Sep 17 00:00:00 2001 From: Moon Flower Date: Mon, 12 Oct 2026 08:46:23 +0330 Subject: a --- docs/history/10-zc/code/tests/basics.zc | 22 +++++++++ docs/history/10-zc/code/tests/errors/back_to_m.zc | 2 + .../10-zc/code/tests/errors/borrow_escape.zc | 3 ++ .../10-zc/code/tests/errors/branch_mismatch.zc | 3 ++ docs/history/10-zc/code/tests/errors/child_dies.zc | 3 ++ .../10-zc/code/tests/errors/child_recast.zc | 2 + docs/history/10-zc/code/tests/errors/copy_owned.zc | 2 + .../10-zc/code/tests/errors/d_into_block.zc | 2 + docs/history/10-zc/code/tests/errors/d_kept.zc | 2 + docs/history/10-zc/code/tests/errors/discard_u.zc | 3 ++ docs/history/10-zc/code/tests/errors/give_m.zc | 3 ++ .../10-zc/code/tests/errors/global_store.zc | 3 ++ .../10-zc/code/tests/errors/leak_overwrite.zc | 2 + docs/history/10-zc/code/tests/errors/lend_d.zc | 4 ++ docs/history/10-zc/code/tests/errors/loop_move.zc | 3 ++ .../10-zc/code/tests/errors/plain_return.zc | 3 ++ .../10-zc/code/tests/errors/proto_needed.zc | 3 ++ docs/history/10-zc/code/tests/errors/return_m.zc | 3 ++ .../10-zc/code/tests/errors/tag_mismatch.zc | 2 + docs/history/10-zc/code/tests/errors/u_dropped.zc | 2 + .../10-zc/code/tests/errors/u_skip_level.zc | 2 + .../10-zc/code/tests/errors/unchecked_touch.zc | 2 + .../10-zc/code/tests/errors/untagged_param.zc | 3 ++ docs/history/10-zc/code/tests/errors/unused.zc | 2 + .../10-zc/code/tests/errors/use_after_give.zc | 3 ++ docs/history/10-zc/code/tests/gc.zc | 20 +++++++++ docs/history/10-zc/code/tests/meta.zc | 46 +++++++++++++++++++ docs/history/10-zc/code/tests/misc.zc | 30 +++++++++++++ docs/history/10-zc/code/tests/runerr.sh | 9 ++++ docs/history/10-zc/code/tests/umd.zc | 52 ++++++++++++++++++++++ 30 files changed, 241 insertions(+) create mode 100644 docs/history/10-zc/code/tests/basics.zc create mode 100644 docs/history/10-zc/code/tests/errors/back_to_m.zc create mode 100644 docs/history/10-zc/code/tests/errors/borrow_escape.zc create mode 100644 docs/history/10-zc/code/tests/errors/branch_mismatch.zc create mode 100644 docs/history/10-zc/code/tests/errors/child_dies.zc create mode 100644 docs/history/10-zc/code/tests/errors/child_recast.zc create mode 100644 docs/history/10-zc/code/tests/errors/copy_owned.zc create mode 100644 docs/history/10-zc/code/tests/errors/d_into_block.zc create mode 100644 docs/history/10-zc/code/tests/errors/d_kept.zc create mode 100644 docs/history/10-zc/code/tests/errors/discard_u.zc create mode 100644 docs/history/10-zc/code/tests/errors/give_m.zc create mode 100644 docs/history/10-zc/code/tests/errors/global_store.zc create mode 100644 docs/history/10-zc/code/tests/errors/leak_overwrite.zc create mode 100644 docs/history/10-zc/code/tests/errors/lend_d.zc create mode 100644 docs/history/10-zc/code/tests/errors/loop_move.zc create mode 100644 docs/history/10-zc/code/tests/errors/plain_return.zc create mode 100644 docs/history/10-zc/code/tests/errors/proto_needed.zc create mode 100644 docs/history/10-zc/code/tests/errors/return_m.zc create mode 100644 docs/history/10-zc/code/tests/errors/tag_mismatch.zc create mode 100644 docs/history/10-zc/code/tests/errors/u_dropped.zc create mode 100644 docs/history/10-zc/code/tests/errors/u_skip_level.zc create mode 100644 docs/history/10-zc/code/tests/errors/unchecked_touch.zc create mode 100644 docs/history/10-zc/code/tests/errors/untagged_param.zc create mode 100644 docs/history/10-zc/code/tests/errors/unused.zc create mode 100644 docs/history/10-zc/code/tests/errors/use_after_give.zc create mode 100644 docs/history/10-zc/code/tests/gc.zc create mode 100644 docs/history/10-zc/code/tests/meta.zc create mode 100644 docs/history/10-zc/code/tests/misc.zc create mode 100755 docs/history/10-zc/code/tests/runerr.sh create mode 100644 docs/history/10-zc/code/tests/umd.zc (limited to 'docs/history/10-zc/code/tests') 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; +} -- cgit v1.2.3