From 7ebb97d3274bccdaecfc824416d8492570728b1c Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sun, 20 Sep 2026 22:25:38 +0700 Subject: [PATCH] FIX.org: the break-loop display pass, dated --- FIX.org | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/FIX.org b/FIX.org index 27b02fd..d75d642 100644 --- a/FIX.org +++ b/FIX.org @@ -4047,3 +4047,48 @@ so an unprintable second argument underlines that argument, not the form — pinned in test_flan.ml. Output pinned by test/programs/println-variadic.flan and its acceptance row (LLVM), spacing exact, "|" markers so a leaked trailing space is a visible red. +* Break-loop display pass, 2026-09-20 + +Off a dogfooding session that hit BoundsError: "can I get a better error +message? I don't see a precise line number anywhere, what is s1 and s3? the +condition field messages are weird, the continue message is weird too, do a +full pass and reword things." + +** Built +- Condition values render. The break loop stashes the condition pointer in + the agent's snapshot (it used to discard it); [flan_agent_condition] hands + it back on the stopped thread; a new daemon op =condition= builds a render + thunk over the struct's fields — render_locals pointed at the condition — + and delivers it at-stop, so resume-and-restop cannot read the old type over + the new pointer. The buffer's headline now reads the fields inline: + "BoundsError — low 648, high 648, length 100", nothing hardcoding any one + condition. Works for user =error= conditions and for the trap-built ones, + on both backends. +- Precise location. The bounds/slice/arith trap sites publish their loc + around the break-hook call ([flan_break_site] in flan_rt.c), the snapshot + copies it, agent verb =site= serves it, and =break= answers =:site= plus + the line's text as =:source=. The buffer draws "at file:line:col" under the + headline with the source line and a caret at the column. +- Compiler temps are hidden from the locals listing rather than refused as + =s4=; a shadowing rebind strips its =~N= except when the outer binding is + on the same list, where both keep their raw spelling ([Session.shown_names]). +- Rewording. Every bracketed implementation note is gone from the buffer + (they were implemented anyway); the refusal table is one short sentence per + section; the abort line says what abort does ("end the program here; the + dev session ends with it" — true: abort is _exit(134) and merged flan dev + is that process). A shadowed restart is now *takeable*: the buffer sends + =restart-at= with the index for every choice, name as receipt, so the + shadowed line just says "same name as N; taken by its number". + +** Deferred, ready to build +- Restart locations. The =%restart= frame is mirrored across emit.ml, x86.ml + and flan_rt.c (fields 0-9 today), so giving =continue= a file:line:col + means: two fields (loc ptr + i64 len, the module's own string, like the + shadow frame's), stores emitted at emit_restart_case in both backends, a + [flan_restart_loc] accessor, the agent snapshot copying it beside each + name, =restarts= growing a loc column, and the buffer printing + "0: [continue] sand.flan:52". Cross-backend ABI change; do it as one lane, + not as a rider. +- A site for user =error= calls. flan_error has no loc parameter; threading + one through means both backends' call emission. Same lane as above if the + frame is being touched anyway.