diff --git a/NEXT.md b/NEXT.md index b59bf7e..57325ad 100644 --- a/NEXT.md +++ b/NEXT.md @@ -2395,8 +2395,11 @@ plan.org's single line on it (831) names a `for` the language does not have and What is missing is the half only an editor can do — the leverage SBCL lacks. `eval` already compiles and runs an expression inside the live program and the daemon already holds the struct layouts, so "ask the human, type-check the answer, hand it over" is a short hop, and it is the one path the runtime today *refuses*: a restart with - parameters taken from the break loop traps, because `flan_break_resume` and `flan_restart_take` aim the channel at - a frame and have nothing to fill its buffer with. What it needs, end to end: + parameters taken from the break loop traps, because the pair a break loop resumes through — `flan_restart_frame`, + which hands back the frame the human picked, and `flan_restart_take`, which aims the transfer channel at it — + reaches the frame and has nothing to fill its buffer with. (`flan_break_resume` is what this paragraph named + before; there is no such function, and `flan_break_hook` is the unrelated thing that gets the break loop *into* + the agent in the first place.) What it needs, end to end: - the frame already carries the arity and the signature as a string — `flan_restart_arity` and `flan_restart_sig` beside `flan_restart_name`, the same walk, so `restarts` can say what each one takes; - `:restarts` on the wire carries the signature per entry, so the minibuffer can show `use-value (i32)` rather diff --git a/docs/SPIKE-DUPLICITY.md b/docs/SPIKE-DUPLICITY.md index 352c844..0ee3e0a 100644 --- a/docs/SPIKE-DUPLICITY.md +++ b/docs/SPIKE-DUPLICITY.md @@ -425,23 +425,28 @@ and reload semantics are working." Under this reading the gating item changed. C ## 9. Print, hash, sort — one family already duplicated, two not yet -**Printing is duplicated three ways on one side, and it is not the dyn/typed split.** -`runtime/flan_dyn.c:308-313` says so itself: +**Printing was duplicated three ways on one side, and it is not the dyn/typed split. Two of the three are +now one.** This section found three escape tables; the runtime dedupe lane took the two that were on the +same side and made them one function with two framings, which is what this section asked for. What is left +is the split it argued was correct. -> A text inside a structure, quoted and escaped. The same table as `flan_rt.c`'s `flan_escape_bytes` and -> `flan_dev.c`'s `flan_dev_emit_str`... +The table lives once, as `flan_escape_char` (`runtime/flan_rt.c:388`), and both typed-side printers call +it: `flan_escape_bytes` (`:422`), which builds a capped slice for `println`, and `put_str` +(`runtime/flan_dev.c:302`), which streams into the inspector's fixed buffer so the REPL can parse the +printed form back. The framing is each caller's and is the part that is genuinely theirs; the switch is +shared, because two printers disagreeing about what a string looks like is two wire formats. -Three escape tables: `runtime/flan_rt.c:383` (`flan_escape_bytes`, with `:366-372` noting it is already "the -same escape table as `flan_dev_emit_str`"), `runtime/flan_dev.c:237` and again at `:551`, and -`runtime/flan_dyn.c:314` (`emit_escaped`). `SPIKE-DYNAMIC.md:329-332` calls its own "the third copy" and -leaves the instruction "If that table changes, change all three." +The dyn copy stays, as `emit_escaped` (`runtime/flan_dyn.c:472`), and says why at `:465-470`: -Two of those three are on the same side. `flan_rt.c`'s is `println`'s; `flan_dev.c`'s is the inspector's, so -the REPL can parse the printed form back. That pair predates dyn and is same-side duplication that dyn has -now made three-way. The *dyn* copy is the one with a defence, and `SPIKE-DYNAMIC.md:334-338` gives it: a -typed `Vec` prints as `` because the typed printer will not walk storage it does not own, while a dyn -vec's storage belongs to the collector and the printer is inside the runtime that owns it. That is correct -duplicity. Three tables is not. +> This copy is deliberate, and the argument for it is docs/SPIKE-DUPLICITY.md §9's: the dyn printer lives +> inside the runtime that owns the storage it walks, which is why it prints a dyn vec structurally where +> the typed printer answers ``. The whole printer is this side's; the table it shares with the other +> side is the part that must not drift. If that table changes, change this one. + +That is the defence `SPIKE-DYNAMIC.md` gives and this section accepted: a typed `Vec` prints as `` +because the typed printer will not walk storage it does not own, while a dyn vec's storage belongs to the +collector and the printer is inside the runtime that owns it. One copy per *side*, which is the doctrine. +Two tables is the answer; three was not. **Hashing is typed-only.** `flan_hash_fn`, `flan_hash_flat`, `flan_hash_str`, `flan_hash_combine` (`runtime/flan_rt.c:1807, 1911, 1939, 1954`), reached through `Types.keyable` and the checker's `key_pair` diff --git a/docs/SPIKE-DYNAMIC.md b/docs/SPIKE-DYNAMIC.md index f00d960..015c7ac 100644 --- a/docs/SPIKE-DYNAMIC.md +++ b/docs/SPIKE-DYNAMIC.md @@ -326,10 +326,12 @@ running program**, not read off `lib/render.ml` — that file is the REPL's insp | nil | — | `nil` | The leading space before every element is what `lib/render.ml`'s slice loop emits and what a Flan program -prints today; a tidier answer would diverge from an acceptance test. The escape table is the third copy -of the one in `flan_rt.c`'s `flan_escape_bytes` and `flan_dev.c`'s `flan_dev_emit_str` — those two are -already kept identical because the REPL parses the printed form back, and this one joins them. If that -table changes, change all three. +prints today; a tidier answer would diverge from an acceptance test. The escape table is the dyn side's +own copy of the typed side's. The typed side used to have two and now has one — `flan_escape_char` +(`runtime/flan_rt.c:388`), which `flan_escape_bytes` calls for `println` and `flan_dev.c`'s `put_str` +calls for the inspector, each framing the result its own way — so there are two tables in the tree, not +three, and the split that is left is the dyn/typed one argued just below. If that table changes, change +this one too. **A typed `Vec` prints as `` and a dyn vec does not.** That looks like a mismatch and is not. The typed printer's refusal is about walking storage it does not own — `render.ml` says so, and directs you to