From 1c53304d03414890af0da7432d1aea87e754a14a Mon Sep 17 00:00:00 2001 From: Moon Flower Date: Wed, 14 Oct 2026 08:29:46 +0330 Subject: 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, 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 --- tests/actor/accept/declaration.zc | 11 +++++++++++ tests/actor/accept/failed_worker.zc | 11 +++++++++++ tests/actor/accept/functions.zc | 12 ++++++++++++ tests/actor/accept/generic_declaration.zc | 15 +++++++++++++++ tests/actor/accept/graphs.zc | 14 ++++++++++++++ tests/actor/accept/lifecycle.zc | 10 ++++++++++ tests/actor/accept/parallel.zc | 18 ++++++++++++++++++ tests/actor/accept/pointer_scalar.zc | 13 +++++++++++++ tests/actor/accept/results.zc | 9 +++++++++ tests/actor/accept/safepoint.zc | 10 ++++++++++ tests/actor/accept/state.zc | 15 +++++++++++++++ tests/actor/accept/values.zc | 12 ++++++++++++ 12 files changed, 150 insertions(+) create mode 100644 tests/actor/accept/declaration.zc create mode 100644 tests/actor/accept/failed_worker.zc create mode 100644 tests/actor/accept/functions.zc create mode 100644 tests/actor/accept/generic_declaration.zc create mode 100644 tests/actor/accept/graphs.zc create mode 100644 tests/actor/accept/lifecycle.zc create mode 100644 tests/actor/accept/parallel.zc create mode 100644 tests/actor/accept/pointer_scalar.zc create mode 100644 tests/actor/accept/results.zc create mode 100644 tests/actor/accept/safepoint.zc create mode 100644 tests/actor/accept/state.zc create mode 100644 tests/actor/accept/values.zc (limited to 'tests/actor/accept') diff --git a/tests/actor/accept/declaration.zc b/tests/actor/accept/declaration.zc new file mode 100644 index 0000000..099c0eb --- /dev/null +++ b/tests/actor/accept/declaration.zc @@ -0,0 +1,11 @@ +namespace; +include rt, actor; +typecheck on; +actor Counter { int total; int handle(int value) { this.total += value; return this.total; } } +fn main() { + Counter* a = rt.new(Counter), b = rt.new(Counter); let left = 0, right = 0; + a.spawn(); b.spawn(); a.recv(fn(int n) { left = n; return 0; }); b.recv(fn(int n) { right = n; return 0; }); + a.send(2); a.send(3); b.send(7); a.await(); b.await(); + rt.put_n(left); rt.put_c(' '); rt.put_n(right); rt.put_c(' '); rt.put_n(a.total); rt.put_c(' '); rt.put_n(b.total); rt.put_c(10); + a.close(); b.close(); return 0; +} diff --git a/tests/actor/accept/failed_worker.zc b/tests/actor/accept/failed_worker.zc new file mode 100644 index 0000000..056a6b6 --- /dev/null +++ b/tests/actor/accept/failed_worker.zc @@ -0,0 +1,11 @@ +namespace; +include rt, actor; +typecheck on; +int fail(int n) { rt.syscall(7, 2, 0, 0); return n; } +int healthy(int n) { return n + 1; } +fn main() { + actor.Actor* a = rt.new(actor.Actor); a.spawn(fail); a.recv(fn(int n) { return 0; }); a.send(1); + rt.put_n(a.await()); rt.put_c(' '); rt.put_n(a.send(2)); rt.put_c(' '); a.close(); + actor.Actor* b = rt.new(actor.Actor); let result = 0; b.spawn(healthy); b.recv(fn(int n) { result = n; return 0; }); b.send(2); b.await(); + rt.put_n(result); rt.put_c(10); b.close(); return 0; +} diff --git a/tests/actor/accept/functions.zc b/tests/actor/accept/functions.zc new file mode 100644 index 0000000..f869789 --- /dev/null +++ b/tests/actor/accept/functions.zc @@ -0,0 +1,12 @@ +namespace; +include rt, actor; +typecheck on; +type Operation = int(int); +int handle(Operation operation) { return operation(3); } +fn main() { + actor.Actor* a = rt.new(actor.Actor); + a.spawn(handle); let result = 0; a.recv(fn(int n) { result = n; return 0; }); + char* text = rt.new(char, 3); text[0] = 'a'; text[1] = 'b'; let offset = 7; float scale = 2.0; + Operation operation = fn:int(int n) { if (scale == 2.0) return n + offset + rt.len_w(text); return -1; }; + a.send(operation); a.await(); rt.put_n(result); rt.put_c(10); a.close(); return 0; +} diff --git a/tests/actor/accept/generic_declaration.zc b/tests/actor/accept/generic_declaration.zc new file mode 100644 index 0000000..a5e5e77 --- /dev/null +++ b/tests/actor/accept/generic_declaration.zc @@ -0,0 +1,15 @@ +namespace; +include rt, actor; +typecheck on; +actor Counter { T total; T handle(T input) { this.total += input; return this.total; } } +fn main() { + Counter* a = rt.new(Counter), b = rt.new(Counter); + Counter* c = rt.new(Counter); int left = 0, right = 0, floating = 0; + a.spawn(); b.spawn(); c.spawn(); + a.recv(fn(int n) { left = n; return 0; }); b.recv(fn(int n) { right = n; return 0; }); + c.recv(fn(float n) { floating = n; return 0; }); + a.send(2); a.send(3); b.send(7); c.send(1.5); c.send(2.5); + a.await(); b.await(); c.await(); + rt.put_n(left); rt.put_c(' '); rt.put_n(right); rt.put_c(' '); rt.put_n(floating); rt.put_c(' '); rt.put_n(a.total); rt.put_c(10); + a.close(); b.close(); c.close(); return 0; +} diff --git a/tests/actor/accept/graphs.zc b/tests/actor/accept/graphs.zc new file mode 100644 index 0000000..f90469c --- /dev/null +++ b/tests/actor/accept/graphs.zc @@ -0,0 +1,14 @@ +namespace; +include rt, actor; +typecheck on; +struct Node { int value; Node* next; } +struct Message { char* text; int[?] numbers; Node* node; } +int handle(Message* m) { m.text[0] = 'X'; m.numbers[0] += 10; return rt.len_w(m.text) + m.numbers[0] + m.node.next.value; } +fn main() { + actor.Actor* a = rt.new(actor.Actor); + a.spawn(handle); let result = 0; a.recv(fn(int n) { result = n; return 0; }); + Message* m = rt.new(Message); m.text = rt.new(char, 4); m.text[0] = 'a'; m.text[1] = 'b'; m.text[2] = 'c'; + m.numbers = rt.new(int[?]); push(m.numbers, 5); m.node = rt.new(Node); m.node.value = 7; m.node.next = m.node; + a.send(m); a.await(); + rt.put_n(result); rt.put_c(' '); rt.put_c(m.text[0]); rt.put_c(' '); rt.put_n(m.numbers[0]); rt.put_c(10); a.close(); return 0; +} diff --git a/tests/actor/accept/lifecycle.zc b/tests/actor/accept/lifecycle.zc new file mode 100644 index 0000000..0c953e4 --- /dev/null +++ b/tests/actor/accept/lifecycle.zc @@ -0,0 +1,10 @@ +namespace; +include rt, actor; +typecheck on; +int handle(int n) { return n; } +fn main() { + let total = 0; + { actor.Actor* a = rt.new(actor.Actor); a.spawn(handle); a.recv(fn(int n) { total += n; return 0; }); a.send(1); a.await(); a.close(); rt.put_n(a.send(3)); rt.put_c(' '); a.close(); } + { actor.Actor* b = rt.new(actor.Actor); b.spawn(handle); b.recv(fn(int n) { total += n; return 0; }); b.send(2); b.await(); b.close(); } + rt.put_n(total); rt.put_c(10); return 0; +} diff --git a/tests/actor/accept/parallel.zc b/tests/actor/accept/parallel.zc new file mode 100644 index 0000000..3d47f34 --- /dev/null +++ b/tests/actor/accept/parallel.zc @@ -0,0 +1,18 @@ +namespace; +include rt, actor; +typecheck on; +int delayed(int n) { rt.syscall(48, 300, 0, 0); return n + 1; } +fn main() { + actor.Actor* a = rt.new(actor.Actor), b = rt.new(actor.Actor); + let first = 0, second = 0; + a.spawn(delayed); b.spawn(delayed); + a.recv(fn(int value) { first = value; return 0; }); + b.recv(fn(int value) { second = value; return 0; }); + let started = rt.syscall(50, 0, 0, 0); + a.send(10); b.send(20); + rt.put_n(first); rt.put_c(' '); rt.put_n(second); rt.put_c(10); + a.await(); b.await(); + rt.put_n(first); rt.put_c(' '); rt.put_n(second); rt.put_c(10); + rt.put_n(rt.syscall(50, 0, 0, 0) - started); rt.put_c(10); + a.close(); b.close(); return 0; +} diff --git a/tests/actor/accept/pointer_scalar.zc b/tests/actor/accept/pointer_scalar.zc new file mode 100644 index 0000000..219129a --- /dev/null +++ b/tests/actor/accept/pointer_scalar.zc @@ -0,0 +1,13 @@ +namespace; +include rt, actor; +typecheck on; +struct Node { int value; } +struct Message { int marker; Node* node; } +fn main() { + Node* original = rt.new(Node); original.value = 4; let marker = (original as int) + 0; + actor.Actor* a = rt.new(actor.Actor); + a.spawn(fn:int(Message* m) { return m.marker == marker && m.node as int != m.marker && m.node.value == 4; }); + let result = 0; a.recv(fn(int n) { result = n; return 0; }); + Message* message = rt.new(Message); message.marker = marker; message.node = original; + a.send(message); a.await(); rt.put_n(result); rt.put_c(10); a.close(); return 0; +} diff --git a/tests/actor/accept/results.zc b/tests/actor/accept/results.zc new file mode 100644 index 0000000..9cc557e --- /dev/null +++ b/tests/actor/accept/results.zc @@ -0,0 +1,9 @@ +namespace; +include rt, actor; +typecheck on; +char*.u respond(int n) { char* p = rt.new(char, 3); p[0] = 'o'; p[1] = 'k'; return u*p; } +fn main() { + actor.Actor* a = rt.new(actor.Actor); + a.spawn(respond); a.recv(fn(char* value) { rt.put_s(value); rt.put_c(10); return 0; }); + a.send(1); a.await(); a.close(); return 0; +} diff --git a/tests/actor/accept/safepoint.zc b/tests/actor/accept/safepoint.zc new file mode 100644 index 0000000..23c8eca --- /dev/null +++ b/tests/actor/accept/safepoint.zc @@ -0,0 +1,10 @@ +namespace; +include rt, actor; +typecheck on; +int handle(int n) { return n * 2; } +fn main() { + actor.Actor* a = rt.new(actor.Actor); + let result = 0; a.spawn(handle); a.recv(fn(int n) { result = n; return 0; }); + a.send(4); rt.syscall(48, 50, 0, 0); + rt.put_n(result); rt.put_c(10); a.close(); return 0; +} diff --git a/tests/actor/accept/state.zc b/tests/actor/accept/state.zc new file mode 100644 index 0000000..e53a12a --- /dev/null +++ b/tests/actor/accept/state.zc @@ -0,0 +1,15 @@ +namespace; +include rt, actor; +typecheck on; +actor Counter { int value; fn add(int n) { this.value += n; return this.value; } int handle(int n) { return this.add(n); } } +fn main() { + actor.Actor* a = rt.new(actor.Actor), b = rt.new(actor.Actor); + let state = 0, aresult = 0, bresult = 0; + a.spawn(fn(int n) { state += n; return state; }); + b.spawn(fn(int n) { state += n; return state; }); + a.recv(fn(int n) { aresult = n; return 0; }); b.recv(fn(int n) { bresult = n; return 0; }); + a.send(2); a.send(3); b.send(7); a.await(); b.await(); + rt.put_n(state); rt.put_c(' '); rt.put_n(aresult); rt.put_c(' '); rt.put_n(bresult); rt.put_c(10); + Counter c; c.value = 0; c.add(4); rt.put_n(c.value); rt.put_c(10); + a.close(); b.close(); return 0; +} diff --git a/tests/actor/accept/values.zc b/tests/actor/accept/values.zc new file mode 100644 index 0000000..2f6c103 --- /dev/null +++ b/tests/actor/accept/values.zc @@ -0,0 +1,12 @@ +namespace; +include rt, actor; +typecheck on; +struct Payload { i16 small; u32 large; float fraction; bstr text; } +float handle(Payload* p) { return p.small + p.large + p.fraction + rt.len_s(p.text); } +fn main() { + actor.Actor* a = rt.new(actor.Actor); + a.spawn(handle); let answer = 0; + a.recv(fn(float n) { answer = n == 6.5; return 0; }); + Payload p; p.small = -2; p.large = 4; p.fraction = 1.5; p.text = b"abc"; + a.send(&p); a.await(); rt.put_n(answer); rt.put_c(10); a.close(); return 0; +} -- cgit v1.2.3