diff options
| author | 2026-10-15 02:52:09 +0330 | |
|---|---|---|
| committer | 2026-10-15 02:52:09 +0330 | |
| commit | 41d087771b0e90a39299616582d3a1b87192be81 (patch) | |
| tree | 401b962c3b50dbc2b9425cdeda101843ef2241b2 /TODO.md | |
| parent | actor: a declared actor without its own drop gets one that awaits owed replie... (diff) | |
todo: destructors closed with what landed; overnight handoff notes (triage verdict, file and tsc installed, genome 0x70000)
Diffstat (limited to 'TODO.md')
| -rw-r--r-- | TODO.md | 6 |
1 files changed, 5 insertions, 1 deletions
@@ -147,6 +147,10 @@ this section is written so work can resume from the repository alone. the branch is `ccr-0054c02e-dfdvnd`; everything listed as done below is committed and pushed there. +### overnight 2026-10-15 (local only, nothing pushed) +- post-destructor-merge triage: of the seven failures none came from destructors. zc0typed.zc used `.u` on a typed parameter (test fixed); self-hosted run-only images had stopped bounds-checking after a `//:lines` marker since 342538f (fixed: a marker ends `unbounded;`/`unchecked;`). `zcc static` and four lsp javascript-host tests failed only because `file` and `tsc` were missing on the box; both are installed now (apt, npm) and pass. with `tsc` present the lsp section takes about 26 minutes. +- the genome outgrew its 0x68000-word reservation (426181 words): `genmap` now reserves 0x70000 and the rt.zc map block is regenerated. the heap shrank by 32k words, so tests/programs/gc.zc reclaims 937 (threshold now 900). + ### how the work is organized - start with `ONBOARD.md` (reading order and exact commands), then `docs/SPEC.md` (the language reference), then this file. @@ -516,7 +520,7 @@ brief someone without re-reading the code. - [x] (done on work/bounds, see "agent work at the end of the session") bounds checking on by default, `unbounded` to turn it off (function prefix, block, top-level `unbounded;`, mirroring `unchecked`), implied by `o3`. architecture: indexing is compiled in the postfix `[` handling of the expressions part; growable arrays already check (`dat`, `range_jz`, the `outside` enhancement, `proven()` removing checks a loop test already did). fixed arrays `T[n]` with a variable index get the same inline check against the constant `n`. pointers get a runtime call (for example `rt.bchk(p, i)`) that checks only when `p` is the start of a live heap block (header check word `p ^ MAGIC`, `paylen`), skipping constant index 0 and sizes the analyzer knows (`lnsz`). reports go through `oob`. the runtime, core, compiler parts, server, `run.zc` and `build.zc` start with `unbounded;`, which zc0 accepts and ignores (genome bytes unchanged). keep std, icon and actor checked unless a function touches raw memory on purpose. measure interpreter time before and after. - [ ] after the fuzzing work, add more general functionality to the standard library. - [x] (done on work/dtor, docs/design/destructors.md, spec 3.11.6, 4.10.3-4, 6.15) destructors: drop works on any heap value, set once per value with `drop(v, fn(){...this...})`, `v.drop(f)` or `v.drop = f`, and a struct may declare `fn drop()` as its type default (both run: the value's, then the type's). `heap(v)` boxes an int, a string or a struct into a fresh owned block. drops run where the compiler frees an owned value (block end, early exit, explicit `rt.free`/`rt.recycle`, a temporary at statement end with a hint), parent before children, and the collector runs an unreachable value's drop once after the sweep, resurrection included; a freed block forgets its drop, so a reused address runs no old drop. no drops set or ended inside o3, and no collection inside an o3 region (pending until the outermost exit). copying a value with drop into an actor message is an error. tests: `tests/conformance/6-ownership/drop_*.zc`, `tests/actor/reject/drop_*.zc`, `tests/data/drop_hint.zc`. -- [ ] destructors, what is left (docs/design/destructors.md, "not yet"): reassigning an owner that still holds a value frees it with a hint (today still error 6.8.5); the no-move-out-of-a-droppable rule; the spawn hint; memreport's `(drop)` marker; `break`/`continue` out of an `o3 { }` block skip `o3_leave`; o3 methods called from normal code through a method call; a cycle of unreachable droppable values is never finalized. first users: file descriptors in `std.Host`, processes in `actor.zc`. +- [x] (done on work/dtor2, spec 4.10.3, 4.11, 6.8.5, 6.15.2-5, docs/design/destructors.md "since" and "first users") destructors, the rest: reassigning an `m` owner frees the old value with a hint (`u`, `d` and captured owners keep the leak error; a new value made from the old one is an error); `pop` out of a droppable array is refused; the spawn hint (not for actor structs); memreport's `(drop)`; `break`/`continue` leave `o3 { }` blocks; o3 receiver methods enter the region; droppable cycles finalize one per collection. first users: `std.File` from `Host.open` (drop closes the fd, `writefile` uses it) and declared actors (a generated drop awaits owed replies and closes the endpoint). noticed, not fixed: the lsp says `total is never reassigned; make it a const` for a `let` only assigned inside a closure (tests/actor/accept/lifecycle.zc), and suggests a stack buffer for an actor struct or a value with drop. - [x] (done on work/line-tables, see "agent work at the end of the session") runtime source positions. architecture: at each statement start (`stmt()`) record (code address `here`, line); per function a permanent data block [entry, end, name, file, count, pairs...] linked into a runtime list (`rt.line_blocks`), or appended to run-only images by `build_image` like the symbol blob. `lines on;`/`lines off;` like `docs on;`; on for user programs, off for the genome unless the growth is small. a new syscall op returns the return-stack pointer (the return stack is in vm memory, 0x1A4100..0x1B40FF, growing up); implement it in `src/core/core.c`, `src/micro/micro.c`, `src/js/tinyvm.ts` and the wasm port. `rt.trace()` walks the return stack, printing ` at file:line in function` for words inside a known function range. the runtime's fatal reports (`oob`, bad heap pointer, double free, out of memory, frame overflow) print the trace after their unchanged first line. check mode skips all of it. - [ ] borrow returns tied to an argument. inference already works for a callee defined before the call: `char* skip(char* s) { ...; return s + i; }` makes `let r = skip(t); rt.free(t); r[0]` an error. the gap: when the call comes before the callee's definition, nothing is reported and the program reads freed memory. extend the deferred effect requirements (`effect_require`, `effect_finish` at unit end) so a forward-called function whose return turns out to alias a parameter produces the same error. for bodyless declarations, externs and function types, add an unobtrusive spelling, for example a `borrows s` clause after the parameter list (`char* skip(char* s) borrows s;`), checked against the body when one exists. - [ ] variadic arguments and `std.print`. design: a pack is passed as one hidden argument, a caller-built read-only growable-array handle (`fixed T[?]` view: [len, cap, items, element size] in the caller's frame, so `len(a)` and `a[i]` work unchanged and nothing is allocated). `...int a` is a typed pack; several packs per function when their element types differ (`void f(...int a, ...char b)`): each extra argument goes to the pack whose element type matches its static type, an ambiguous match is an error, packs come after the fixed parameters. `...any args` packs each value with a kind code (int, float, char, string, bstr, pointer, ...) and its type record: `any` is a small built-in record { kind, value, type }. `...*any args` makes the call comma-free: after the fixed arguments, the parser reads unary expressions until `)`, commas optional, so `std.print("x = " name ", age " age "\n");` works and binary expressions must be parenthesized. `std.print(...*any args)` prints each argument by its kind (`put_n`, the float printer, `put_s`, `put_bs`, a character for `char`, hex for pointers). |
