A let-bound local printed as s0 under lldb. Parameters were fine, because the driver recovered their names from the AST and handed them down in pnames; everything else was a slot index, since Check knew the name in its scope list and dropped it at allocation. Tast.fn now carries snames beside slots, Check fills it in at bind, and Emit prefers it over pnames. A slot the compiler invented keeps s<index>: fresh_slot takes the name as an optional argument, so dotimes' hidden bound and the pair min and max evaluate into say nothing and get None without any of their call sites changing. Naming those something plausible would put a variable in the debugger that is not in the file. Shadowing needed deciding rather than assuming. Every DILocalVariable is scoped to the subprogram — the typed IR has no block structure to build a DILexicalBlock from — so two slots called v landed in one flat scope, and lldb answered p v with the outer one while the body computed with the inner, which it did not list at all. A debugger confident and wrong is the one outcome worse than s0, so a repeat of a name already bound in this function gets a ~2 suffix: ~ is the reader's delimiter and cannot occur in a source symbol, so v~2 is unambiguous and visibly the compiler's. It is a way of not lying, not a way of being right; scoping properly means a lexical block per Let and the declares moved out of the entry block. (lldb) breakpoint set --file debug.flan --line 20 (lldb) frame variable (Cell *) c = 0x00007fffffffd970 (int) n = 41 (int) bump = 42 The test breaks after the binding on purpose. A name breakpoint stops on the function's first line, before the let has stored anything, and a variable is nominally in scope from entry — so the name is checked there and the value only where it means something.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%