diff options
| author | 2026-10-14 08:29:46 +0330 | |
|---|---|---|
| committer | 2026-10-14 08:29:46 +0330 | |
| commit | 1c53304d03414890af0da7432d1aea87e754a14a (patch) | |
| tree | 97190d86cf548c9bc63f68c86a4d2a4f09809713 /tests/spec | |
| parent | a (diff) | |
feat: grow memory limits, add icon/actor libraries, overhaul LSP diagnostics
Compiler and VM
- make every memory map limit dynamic and adjustable at both build time and
runtime, including compiler tables, stacks, and every execution region
- reserve and grow tables, operand and return stacks, frame segments, and
image-building output without relocating live code or globals
- rename i/o and string helpers consistently (puts -> put_s, putn -> put_n,
scat -> cat_s) across compiler, runtime, examples, tests, and docs
- recast and consume values assigned to globals from inside functions
- allow fixed and const together, add typed closure returns (fn:t(...)),
multi-include syntax (include rt, run, core;), and recurse type inference
- never infer string literals as word, anywhere, as argument, variable, or
return type
- draft docs/BORROW.md: a borrow checker less intrusive than Rust's but more
intelligent
LSP and editor integration
- require explicit includes and give every toolchain area its own namespace
(rt, lsp, run, core)
- hover for built-in types, inferred types, values known at hover time, array
and pointer lifetime/size, library names in include statements, and inferred
lifetimes with explanations
- honor /* */ comments as documentation for variables and arguments, and stop
misattributing section headers or trailing comments as variable hints
- stream diagnostics and cancel stale requests on change
- jump to definition and references, including cross-file
- quick fixes with automatic library import, and namespace completion
Hints and diagnostics
- render hints as blue squigglies by default, with hints on/small/off per file
- suppress magic-number hints via a preceding /* */ comment, and say so
- warn on unused arguments; allow multiple _ discards in parameters, pattern
matching, and tagged enums, warning if a _ is actually used
- rewrite hint and comment prose in professional compiler-doc register
Libraries
- add icon.zc: run-time self-modification, find/replace syntax, type and block
edits, and step-through inspection of locals and globals
- add actor.zc: async actors with Actor<I,O>, implicit this, spawn/recv/send,
injected into the compiler machinery at include time rather than built in
Tooling and docs
- reorganize sources, tests, and designs into subdirectories
- unify windows entry points in tinyvm.bat and add a matching tinyvm.sh
- add --help across the toolchain
- polish the learning guide, stdlib docs, and design notes
Tests
- add accept, reject, and regression coverage across the compiler, LSP,
- runtime, icon, actors, threads, formatting, and the toolchain contracts,
plus fuzzers and property tests
Diffstat (limited to 'tests/spec')
| -rw-r--r-- | tests/spec/compiler_contracts.json | 542 |
1 files changed, 542 insertions, 0 deletions
diff --git a/tests/spec/compiler_contracts.json b/tests/spec/compiler_contracts.json new file mode 100644 index 0000000..69b2781 --- /dev/null +++ b/tests/spec/compiler_contracts.json @@ -0,0 +1,542 @@ +[ + { + "group": "modules", + "name": "explicit runtime export", + "accept": true, + "source": "include rt; fn main() { rt.put_n(7); return 0; }" + }, + { + "group": "modules", + "name": "no implicit runtime", + "accept": false, + "source": "fn main() { put_n(7); return 0; }" + }, + { + "group": "modules", + "name": "runtime needs include", + "accept": false, + "source": "fn main() { rt.put_n(7); return 0; }" + }, + { + "group": "modules", + "name": "import does not unqualify runtime", + "accept": false, + "source": "include rt; fn main() { put_n(7); return 0; }" + }, + { + "group": "modules", + "name": "explicit compiler export", + "accept": true, + "source": "include run; fn main() { run.evals(\"return 0;\"); return 0; }" + }, + { + "group": "modules", + "name": "compiler needs include", + "accept": false, + "source": "fn main() { run.evals(\"return 0;\"); return 0; }" + }, + { + "group": "modules", + "name": "no bare compiler exports", + "accept": false, + "source": "include run; fn main() { evals(\"return 0;\"); return 0; }" + }, + { + "group": "modules", + "name": "core reserved for vm", + "accept": false, + "source": "include core; fn main() { core.evals(\"return 0;\"); return 0; }" + }, + { + "group": "modules", + "name": "explicit vm export", + "accept": true, + "source": "include core; fn main() { return core.syscall(9, 0, 0, 0) > 0; }" + }, + { + "group": "modules", + "name": "server needs include", + "accept": false, + "source": "fn main() { return lsp.hid('a'); }" + }, + { + "group": "modules", + "name": "unknown module", + "accept": false, + "source": "include imaginary; fn main() { return 0; }" + }, + { + "group": "modules", + "name": "unknown export", + "accept": false, + "source": "include rt; fn main() { return rt.imaginary(); }" + }, + { + "group": "modules", + "name": "no import bypass with unchecked", + "accept": false, + "source": "unchecked fn main() { put_s(\"hi\"); return 0; }" + }, + { + "group": "modules", + "name": "runtime allocator remains typed", + "accept": true, + "source": "include rt; fn main() { let p = rt.new(int, 3); p[0] = 7; rt.put_n(p[0]); return 0; }" + }, + { + "group": "modules", + "name": "explicit standard library", + "accept": true, + "source": "include std; include rt; fn main() { rt.put_n(std.Text.atoi(\"4\")); return 0; }" + }, + { + "group": "modules", + "name": "dependency imports do not leak", + "accept": false, + "source": "include std; fn main() { rt.put_n(std.Text.atoi(\"4\")); return 0; }" + }, + { + "group": "modules", + "name": "namespace alias does not shadow local", + "accept": true, + "source": "fn main() { int rt = 7; return rt; }" + }, + { + "group": "strings", + "name": "word string parameter", + "accept": true, + "source": "char* echo(char* s) { return s; } fn main() { let s = echo(\"hi\"); return s[0]; }" + }, + { + "group": "strings", + "name": "packed string parameter", + "accept": true, + "source": "bstr echo(bstr s) { return s; } fn main() { let s = echo(b\"hi\"); return s[0]; }" + }, + { + "group": "strings", + "name": "packed and word strings are distinct", + "accept": false, + "source": "typecheck on; char* echo(char* s) { return s; } fn main() { return echo(b\"hi\")[0]; }" + }, + { + "group": "strings", + "name": "word and packed strings are distinct", + "accept": false, + "source": "typecheck on; bstr echo(bstr s) { return s; } fn main() { return echo(\"hi\")[0]; }" + }, + { + "group": "strings", + "name": "string is not raw word", + "accept": false, + "source": "typecheck on; word identity(word n) { return n; } fn main() { return identity(b\"hi\"); }" + }, + { + "group": "strings", + "name": "grouped string inference", + "accept": true, + "source": "fn main() { let a = \"hi\", b = b\"hi\"; return a[0] + b[0]; }" + }, + { + "group": "strings", + "name": "inferred word string remains assignable", + "accept": true, + "source": "include rt; typecheck on; fn main() { let s = \"hi\"; s = \"ok\"; rt.put_n(s[1]); return 0; }", + "output": "107" + }, + { + "group": "strings", + "name": "inferred packed string remains assignable", + "accept": true, + "source": "include rt; typecheck on; fn main() { let s = b\"hi\"; s = b\"ok\"; rt.put_n(s[1]); return 0; }", + "output": "107" + }, + { + "group": "strings", + "name": "inferred string types reject cross-assignment", + "accept": false, + "source": "typecheck on; fn main() { let s = \"hi\"; s = b\"ok\"; return 0; }" + }, + { + "group": "ownership", + "name": "global receives local owner", + "accept": true, + "source": "include rt; int* saved; fn main() { let p = rt.new(int); p[0] = 7; saved = p; return saved[0]; }" + }, + { + "group": "ownership", + "name": "global source is consumed", + "accept": false, + "source": "include rt; int* saved; fn main() { let p = rt.new(int); saved = p; return p[0]; }" + }, + { + "group": "ownership", + "name": "borrowed source cannot transfer", + "accept": false, + "source": "int* saved; fn store(int*.m p) { saved = p; } fn main() { return 0; }" + }, + { + "group": "ownership", + "name": "consumed source cannot transfer twice", + "accept": false, + "source": "include rt; int* a, b; fn main() { let p = rt.new(int); a = p; b = p; return 0; }" + }, + { + "group": "ownership", + "name": "temporary borrowed result cleanup", + "accept": true, + "source": "include rt; char*.u make() { let p = rt.new(char, 2); p[0] = 120; p[1] = 0; return p; } fn main() { rt.put_s(make()); return 0; }" + }, + { + "group": "closure", + "name": "explicit integer result", + "accept": true, + "source": "fn main() { let double = fn:int(int a) { return a * 2; }; return double(4); }" + }, + { + "group": "closure", + "name": "incompatible explicit result", + "accept": false, + "source": "typecheck on; fn main() { let f = fn:int() { return \"hi\"; }; return f(); }" + }, + { + "group": "closure", + "name": "captured state is shared", + "accept": true, + "source": "include rt; fn main() { int n = 0; let f = fn:int() { n++; return n; }; rt.put_n(f()); rt.put_n(f()); rt.put_n(n); return 0; }", + "output": "122" + }, + { + "group": "stdlib", + "name": "word string search", + "accept": true, + "source": "include std; fn main() { return std.Text.ends(\"abcd\", \"cd\"); }" + }, + { + "group": "stdlib", + "name": "packed string search", + "accept": true, + "source": "include std; fn main() { return std.Bytes.ends(b\"abcd\", b\"cd\"); }" + }, + { + "group": "stdlib", + "name": "word string trimming", + "accept": true, + "source": "include std; include rt; fn main() { rt.put_s(std.Text.trim(\" hi \")); return 0; }", + "output": "hi" + }, + { + "group": "stdlib", + "name": "word string substring", + "accept": true, + "source": "include std; include rt; fn main() { rt.put_s(std.Text.substr(\"abcd\", 1, 2)); return 0; }", + "output": "bc" + }, + { + "group": "stdlib", + "name": "negative substring bounds", + "accept": true, + "source": "include std; fn main() { return std.Text.substr(\"abcd\", -1, 2) == 0; }" + }, + { + "group": "runtime", + "name": "word copying borrowed buffers", + "accept": true, + "source": "include rt; fn main() { int a[2] = {1, 2}, b[2]; rt.copy_w(b, a, 2); return b[1]; }" + }, + { + "group": "runtime", + "name": "explicit free consumes owner", + "accept": false, + "source": "include rt; fn main() { let p = rt.new(int); rt.free(p); return p[0]; }" + }, + { + "group": "runtime", + "name": "borrow cannot free owner", + "accept": false, + "source": "include rt; fn f(int*.m p) { rt.free(p); } fn main() { return 0; }" + }, + { + "group": "runtime", + "name": "growable array owns transferred child", + "accept": true, + "source": "include rt; fn main() { let a = rt.new(int*[?]); let p = rt.new(int); p[0] = 7; push(a, p); return a[0][0]; }" + }, + { + "group": "runtime", + "name": "transferred child cannot outlive array", + "accept": false, + "source": "include rt; int* saved; fn main() { let a = rt.new(int*[?]); let p = rt.new(int); push(a, p); saved = p; return 0; }" + }, + { + "group": "runtime", + "name": "collection retains reachable objects", + "accept": true, + "source": "include rt; fn main() { let p = rt.new(int); p[0] = 7; rt.gc(); return p[0]; }" + }, + { + "group": "runtime", + "name": "zero-sized copy is safe", + "accept": true, + "source": "include rt; fn main() { return rt.copy_w(0, 0, 0); }" + }, + { + "group": "arguments", + "name": "explicit discard owns cleanup", + "accept": true, + "source": "include rt; fn ignore(int*.d _) { return 0; } fn main() { let before = rt.live_objects(); ignore(rt.new(int)); rt.put_n(rt.live_objects() - before); return 0; }", + "output": "0" + }, + { + "group": "arguments", + "name": "discard does not disable arity checking", + "accept": false, + "source": "fn ignore(int _, int _) { return 0; } fn main() { return ignore(1); }" + }, + { + "group": "arguments", + "name": "duplicate discard names are permitted", + "accept": true, + "source": "fn ignore(int _, int _) { return 0; } fn main() { return ignore(1, 2); }" + }, + { + "group": "modules", + "name": "multiple explicit imports", + "accept": true, + "source": "include rt, run, core; fn main() { rt.put_n(core.syscall(9, 0, 0, 0) > 0); run.evals(\"return 0;\"); return 0; }" + }, + { + "group": "modules", + "name": "repeated imports are idempotent", + "accept": true, + "source": "include rt, rt, run; include rt; fn main() { rt.put_n(1); return 0; }" + }, + { + "group": "modules", + "name": "unknown import within list", + "accept": false, + "source": "include rt, imaginary, run; fn main() { return 0; }" + }, + { + "group": "modules", + "name": "missing entry within list", + "accept": false, + "source": "include rt,,run; fn main() { return 0; }" + }, + { + "group": "callbacks", + "name": "explicit borrowed callback parameter", + "accept": true, + "source": "include rt; int first(int*.m p) { return p[0]; } fn main() { int(int*.m) f = first; return f(rt.new(1)); }" + }, + { + "group": "callbacks", + "name": "borrowed callback cannot consume source", + "accept": false, + "source": "include rt; fn bad(int*.m p) { rt.free(p); } fn main() { int(int*.m) f = bad; return 0; }" + }, + { + "group": "modules", + "name": "local struct shadows module name", + "accept": true, + "source": "struct point { int x; }; fn main() { point rt; rt.x = 7; return rt.x; }" + }, + { + "group": "strings", + "name": "capture returns a char string", + "accept": true, + "source": "include rt, std; typecheck on; fn main() { char* s = std.capture.start(); rt.put_s(\"hi\"); s = std.capture.end(s); rt.put_s(s); return 0; }", + "output": "hi" + }, + { + "group": "modules", + "name": "boot export needs its namespace", + "accept": false, + "source": "fn main() { return start; }" + }, + { + "group": "strings", + "name": "inferred packed result stays indexable", + "accept": true, + "source": "include rt; fn text() { return b\"hi\"; } fn main() { let s = text(); rt.put_n(s[0]); return 0; }", + "output": "104" + }, + { + "group": "strings", + "name": "typed argument with inferred packed return", + "accept": true, + "source": "include rt; typecheck on; fn echo(bstr s) { return s; } fn main() { let s = echo(b\"hi\"); rt.put_n(s[1]); return 0; }", + "output": "105" + }, + { + "group": "strings", + "name": "inferred word string result stays indexable", + "accept": true, + "source": "include rt; fn text() { return \"hi\"; } fn main() { let s = text(); rt.put_n(s[0]); return 0; }", + "output": "104" + }, + { + "group": "enums", + "name": "tagged enum constructors and repeated discard fields", + "accept": true, + "source": "include rt; enum pair { item { int x; int y; }, other }; fn main() { let p = pair.item(1, 2); switch(p) { case item(_, _): rt.put_n(p.item_x + p.item_y); case _: rt.put_n(0); } rt.free(d*p); return 0; }", + "output": "3" + }, + { + "group": "modules", + "name": "icon exports are loaded by explicit include", + "accept": true, + "source": "include rt, run, icon; fn main() { let q = run.tokens(\"return 7;\"); let frame = icon.begin(q); icon.resume(frame, 4); int result = icon.result(frame); rt.put_n(result); icon.close(d*frame); return 0; }", + "output": "7" + }, + { + "group": "modules", + "name": "icon access requires include", + "accept": false, + "source": "include rt, run; fn main() { return icon.error(); }" + }, + { + "group": "modules", + "name": "icon implementation names remain private", + "accept": false, + "source": "include rt, run, icon; fn main() { return icon_value(0, 0); }" + }, + { + "group": "modules", + "name": "repeated icon include is idempotent", + "accept": true, + "source": "include rt, run, icon, icon; fn main() { let q = run.tokens(\"return 1;\"); rt.put_n(icon.validate(q)); return 0; }", + "output": "1" + }, + { + "group": "qualifiers", + "name": "fixed const array", + "accept": true, + "source": "include rt; fn main() { fixed const int[3] a = {2,3,4}; rt.put_n(a[1]); }", + "output": "3" + }, + { + "group": "qualifiers", + "name": "const fixed array", + "accept": true, + "source": "include rt; fn main() { const fixed int[3] a = {2,3,4}; rt.put_n(a[1]); }", + "output": "3" + }, + { + "group": "qualifiers", + "name": "fixed const global array", + "accept": true, + "source": "include rt; fixed const int[2] data = {8,9}; fn main() { rt.put_n(data[1]); }", + "output": "9" + }, + { + "group": "qualifiers", + "name": "fixed const array rejects element write", + "accept": false, + "source": "fn main() { fixed const int[2] a = {1,2}; a[0] = 3; }" + }, + { + "group": "qualifiers", + "name": "const fixed rejects resize", + "accept": false, + "source": "include rt; fn main() { const fixed int[?] a = rt.new(fixed int[?],2); a.resize(3); }" + }, + { + "group": "qualifiers", + "name": "const fixed cannot be rebound", + "accept": false, + "source": "include rt; fn main() { const fixed int[?] a = rt.new(fixed int[?],2); a = rt.new(fixed int[?],3); }" + }, + { + "group": "qualifiers", + "name": "fixed mutable remains writable", + "accept": true, + "source": "include rt; fn main() { fixed int[2] a = {1,2}; a[0] = 3; rt.put_n(a[0]); }", + "output": "3" + }, + { + "group": "qualifiers", + "name": "const fixed borrow cannot mutate storage", + "accept": false, + "source": "fn mutate(int* p) { p[0] = 9; } fn main() { const fixed int[2] a = {1,2}; mutate(a); }" + }, + { + "group": "qualifiers", + "name": "readonly parameter accepts const fixed", + "accept": true, + "source": "include rt; int first(const fixed int[2] a) { return a[0]; } fn main() { const fixed int[2] a = {7,8}; rt.put_n(first(a)); }", + "output": "7" + }, + { + "group": "inference", + "name": "typed callee constrains untyped caller", + "accept": true, + "source": "include rt; int seed(int n) { return n + 1; } fn caller(n) { let result = seed(n); return result; } fn main() { rt.put_n(caller(4)); }", + "output": "5" + }, + { + "group": "inference", + "name": "recursive anchored return", + "accept": true, + "source": "include rt; int seed(int n) { return n; } fn recursive(n) { if (n <= 0) return seed(n); return recursive(n - 1); } fn main() { rt.put_n(recursive(3)); }", + "output": "0" + }, + { + "group": "qualifiers", + "name": "readonly array alias cannot remove qualifier", + "accept": false, + "source": "fn main() { fixed const int[2] a = {1,2}; int* alias = a; alias[0] = 8; }" + }, + { + "group": "qualifiers", + "name": "readonly array alias preserves qualifier", + "accept": true, + "source": "include rt; fn main() { fixed const int[2] a = {1,2}; let alias = a; rt.put_n(alias[0]); }", + "output": "1" + }, + { + "group": "qualifiers", + "name": "readonly inferred alias cannot write", + "accept": false, + "source": "fn main() { fixed const int[2] a = {1,2}; let alias = a; alias[0] = 8; }" + }, + { + "group": "qualifiers", + "name": "fixed const compound write rejected without typecheck", + "accept": false, + "source": "typecheck off; fn main() { fixed const int[2] a = {1,2}; a[0] += 2; }" + }, + { + "group": "qualifiers", + "name": "fixed const increment rejected", + "accept": false, + "source": "fn main() { fixed const int[2] a = {1,2}; a[0]++; }" + }, + { + "group": "qualifiers", + "name": "readonly packed fixed array", + "accept": true, + "source": "include rt; fn main() { fixed const u8[] a = {2,3}; rt.put_n(a[1]); }", + "output": "3" + }, + { + "group": "runtime", + "name": "owned readfile grows and returns exact character data", + "accept": true, + "source": "include rt; fn main() { char* text = rt.readfile(\"tests/data/readfile_growth.txt\"); rt.put_n(rt.len_w(text)); rt.put_c(32); rt.put_n(text[1029]); rt.put_c(32); rt.put_n(text[1030]); }", + "output": "1031 57 10" + }, + { + "group": "runtime", + "name": "readfile missing path returns null", + "accept": true, + "source": "include rt; fn main() { char* text = rt.readfile(\"tests/data/missing-readfile-contract.txt\"); rt.put_n(text == 0); }", + "output": "1" + }, + { + "group": "runtime", + "name": "owned file contents cannot be used after release", + "accept": false, + "source": "include rt; fn main() { char* text = rt.readfile(\"tests/data/readfile_growth.txt\"); rt.free(text); return text[0]; }" + } +] |
