The inspector walks expressions, which is why it cannot see a frame
This commit is contained in:
parent
f4f61ae8c9
commit
b97a3dbbf1
44
DISCUSS.md
44
DISCUSS.md
@ -8,20 +8,42 @@ Settled decisions live in `NEXT.md`. Reasons for what already exists live in `BU
|
||||
|
||||
---
|
||||
|
||||
## 1. What is `i` supposed to inspect in the stack section?
|
||||
## 1. `i`, the inspector, and the frame it cannot see
|
||||
|
||||
Raised as a question about intent, and it deserves one, because the current answer may be wrong rather than merely
|
||||
undocumented.
|
||||
Two things got conflated here and they should be separated.
|
||||
|
||||
`i` on a local passes that local's **name** to the inspector, which evaluates it as an expression inside the running
|
||||
program. That is correct for the innermost frame, where the name is in scope. **It is not obviously correct for any
|
||||
other frame** — evaluating `y` while looking at frame 3 evaluates `y` wherever the evaluator stands, not in frame 3.
|
||||
It may resolve to a global, to a different binding, or fail.
|
||||
**What the inspector already does.** Most of what was asked for is built. `flan-inspect` opens its own buffer, lays a
|
||||
value's fields one per line, `RET` walks into one, `l` comes back, `g` re-reads. The renderer bounds its walk at depth 4
|
||||
and span 8, and entering a field renders *that field* from depth 0 — so the elision moves with you rather than
|
||||
truncating permanently. It is CIDER's inspector adapted, and the file says what the adaptation changed.
|
||||
|
||||
The locals *listing* does not have this problem: it renders from the frame's own slot addresses. So the display is
|
||||
frame-accurate and the inspector may not be. Options: root the inspector at the slot's address the way the listing is
|
||||
rooted; refuse `i` outside the innermost frame; or make the inspector frame-aware. Worth settling before anyone relies
|
||||
on it.
|
||||
**What is actually missing** is detail on the leaves: a number shows in decimal only, with no hex and no binary, and a
|
||||
pointer does not show its address. Purely additive, small, and worth doing.
|
||||
|
||||
**The real problem, and it is sharper than "a bug".** The locals listing renders from each frame's own slot addresses,
|
||||
so it is frame-accurate. The inspector is built on a stack of **expressions** — going into a field means sending a
|
||||
different expression (`(.pos b)` where the last was `b`), and `l` works by popping back to the previous one. That design
|
||||
is forced: a Flan value has no header, the thunk that rendered it is `dlclose`d as soon as it returns, and there is no
|
||||
heap to retain anything in, so nothing can be held server-side the way CIDER holds a JVM object.
|
||||
|
||||
The consequence is that `i` evaluates a name wherever the evaluator stands, **not in the frame being looked at**. On the
|
||||
innermost frame that happens to be right. On any other it may resolve to a global, to a different binding, or fail —
|
||||
with nothing saying so.
|
||||
|
||||
**An earlier suggestion in this conversation — "root the inspector at the slot's address" — does not work**, and the
|
||||
reason is worth keeping: an address is not an expression, so the first `RET` has nothing to build the next expression
|
||||
from and navigation dies at step one. Recorded because it is the obvious fix and it is wrong.
|
||||
|
||||
So the options are genuinely three, and none is free:
|
||||
|
||||
1. **Teach the program to evaluate an expression relative to a frame.** The most useful and the most work: the frame's
|
||||
slots would have to be in scope for a compiled thunk, which means the daemon building a thunk whose free names bind
|
||||
to that frame's addresses. It would also fix `C-x C-e` while stopped, which has the same blindness.
|
||||
2. **Give the inspector a second rooting mode** — an address root that can still walk, by carrying a type alongside the
|
||||
address and stepping to a field's address rather than to a sub-expression. Navigation then works, but the two modes
|
||||
have different capabilities and `l` has to cross between them.
|
||||
3. **Refuse `i` outside the innermost frame**, honestly and by name. Cheapest, and it gives up the feature exactly where
|
||||
it is most wanted, since the innermost frame is the one already fully visible.
|
||||
|
||||
## 2. Annotating the IR and the disassembly with the source
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user