diff --git a/compiler/src/CODE-LOGIC.md b/compiler/src/CODE-LOGIC.md index 6b11f3a..c1fbd9c 100644 --- a/compiler/src/CODE-LOGIC.md +++ b/compiler/src/CODE-LOGIC.md @@ -10,8 +10,8 @@ the diagnostic codes are catalogued in ## The pipeline ``` -lexer.ml → parser.ml → types.ml → owner.ml → emit.ml → .wob -tokens AST symbols + move/drop/rc bytecode +lexer.ml → parser.ml → types.ml → gcinfer.ml → owner.ml → emit.ml → .wob +tokens AST symbols traced set move/drop bytecode typecheck tables ``` @@ -54,8 +54,12 @@ against `nil` must lower to `EQ` and never `EQS`. ### 3. The owner pass hands the emitter tables, not decisions -`owner.ml` computes moves, scope-end drops, branch-join drops, rc sites and -residual borrow guards, keyed by **node id and label**. `emit.ml` looks them up +`owner.ml` computes moves, scope-end drops, branch-join drops and residual +borrow guards, keyed by **node id and label** (rc sites are gone since +iteration 7b — reference counting no longer exists; `gcinfer.ml` classifies +each class owned/traced first, structurally via SCC over the class-reference +graph plus demand promotion at escape sites, and `Types.is_gc_class` answers +from that set). `emit.ml` looks them up by the same keys. When a construct has arms — `switch`, `if`, `try` — both files must agree on the label strings and on the arm ORDER (`switch_lowering_order` moves `default` last in both). A silent mismatch means a drop that never runs. diff --git a/runtime/src/CODE-LOGIC.md b/runtime/src/CODE-LOGIC.md index 07984ab..109162d 100644 --- a/runtime/src/CODE-LOGIC.md +++ b/runtime/src/CODE-LOGIC.md @@ -13,16 +13,16 @@ the first: constants there and prose there must never disagree. | file | what it owns | | --- | --- | | `wob.h` | every format constant: header offsets, field kinds, opcodes, builtin ids, trap codes, the 16-byte object header, the class descriptor | -| `obj.h/.c` | the per-shard arena, object allocation, `wo_str` (header + length + inline bytes, no NUL) | +| `obj.h/.c` | the per-shard arena, object allocation (traced instances link onto the traced list, born white — black mid-cycle), the per-class may-gcref fixpoint, `wo_str` (header + length + inline bytes, no NUL) | | `cont.h/.c` | `multi` and `map` as native classes: struct heads in the arena, backing arrays malloc'd, map lookup a linear scan over parallel key/value arrays | -| `gc.h/.c` | the kind-directed dispatcher (`wo_drop_kind`/`wo_drop_obj`), refcounting for `@gc`, and the budgeted Bacon–Rajan cycle collector | +| `gc.h/.c` | the kind-directed dispatcher (`wo_drop_kind`/`wo_drop_obj`) for owned values, and the incremental tri-color mark-sweep for traced (inferred-gc) objects: per-shard traced list, snapshot-at-beginning roots, Yuasa deletion barrier (the `wo_drop_kind` GCREF case + `SETF`), budgeted mark and sweep slices (iteration 7b — RC and Bacon–Rajan are gone) | | `borrow.h/.c` | the borrow word: shared counts and the exclusive sentinel | | `loader.h/.c` | parse and **validate** an image; the validation contract in its header comment is exactly what the interpreter may then assume | | `vm.h/.c` | the register interpreter: window-overlap calls, dual-flavor dispatch, traps, unwinding, catch frames | | `builtin.h/.c` | the pure builtins: print, containers, text | | `sysio.c` | the OS half: `fs`, `time`, `env`, `net`, `proc` | | `json.c` | `json.encode` / `json.decode`, driven by class metadata | -| `main.c` | the CLI: find an image (argument or embedded trailer), build argv, call the entry, map its result to an exit code | +| `main.c` | the CLI: find an image (argument or embedded trailer), build argv, call the entry, map its result to an exit code; post-exit gc pump (a rootless cycle frees everything unreachable, in budgeted slices) | `builtin.c`'s `wo_builtin` is the single entry point the interpreter calls; it forwards ids at or above `WO_B_SYS_FIRST` to `sysio.c` and the json pair to