A watch window, an address-rooted inspector, and structural typing that is just layout
This commit is contained in:
parent
7ff6c27964
commit
135a780f3d
48
NEXT.md
48
NEXT.md
@ -653,6 +653,54 @@ exists for the expander, which cannot work that way.
|
||||
`exported` and the refusal machinery already exist and take a second rule in one line, but there is no way for a
|
||||
package to *mark* a name private, and adding one means a parser change.
|
||||
|
||||
## Decided in discussion — three more, all approved and none started
|
||||
|
||||
**A watch window, ported from the author's Clojure one.** `~/Development/siam-farmer/watch.el` is the working
|
||||
original; read it first. Its design, and the parts to keep:
|
||||
|
||||
- **The program defines what is shown.** Emacs polls one function — `(watch/render)` — and paints the string it
|
||||
returns. There is no watch-expression machinery, no per-variable registration, no UI for building a query. The user
|
||||
writes a function in the game.
|
||||
- **Async, not synchronous.** A sync request on a 0.2s timer blocks Emacs's UI thread every tick. The original says so
|
||||
in a comment, having evidently learned it.
|
||||
- **`replace-buffer-contents`, not erase-and-insert.** It diffs, so point and scroll survive every tick; erasing yanks
|
||||
the cursor to the top five times a second.
|
||||
- Nothing is appended — the buffer is always the current snapshot.
|
||||
|
||||
**The one thing that does not port, and it decides the design.** In Clojure an eval is cheap. Here `eval-expr`
|
||||
*compiles a module and `dlopen`s it* — tens of milliseconds and a new `.so` each time, in a directory nothing sweeps.
|
||||
Polling at 5Hz would produce hundreds of shared objects a minute. So **the watch thunk must be compiled once and then
|
||||
called repeatedly**, which makes this a daemon feature rather than something the Emacs side can do alone: a `watch`
|
||||
op that compiles on first use and a cheap re-invoke per tick.
|
||||
|
||||
The author also raised **ghost text** as an alternative or addition to a dedicated buffer — values shown inline at the
|
||||
code they belong to. Not designed; the buffer is the port, ghost text is a further question.
|
||||
|
||||
**The inspector gets a second way to start: an address and a type.** Closes the hole in `DISCUSS.md` item 1, where `i`
|
||||
on a local in any frame but the innermost evaluates a name wherever the evaluator stands rather than in that frame, and
|
||||
may silently inspect something else.
|
||||
|
||||
The inspector navigates by rewriting *expressions* — `(.pos b)` where the last was `b` — and `l` pops back. That is
|
||||
why the obvious fix, rooting it at the slot's address, was rejected: an address is not an expression, so the first
|
||||
`RET` has nothing to build from. **The shadow stack changed this.** The daemon now has a frame's address and every
|
||||
slot's type, so the second rooting mode is cheap: start from an address plus a type, and stepping into a field is
|
||||
address-plus-offset with the field's type. `Render.render` already does exactly that arithmetic for locals, and
|
||||
navigation keeps working, which was the objection.
|
||||
|
||||
**Structural typing requires identical layout — same fields, same types, same order.** Settled by the author, and it
|
||||
makes the feature simple rather than hard: structural compatibility becomes "the same memory", which costs nothing at
|
||||
run time and needs no copy, no reordering and no adaptor. The motivating case is `{.x 1.0 .y 1.0}` and that order is
|
||||
natural anyway.
|
||||
|
||||
**Flexible field order waits for classes, deliberately.** A class has an implementation-defined representation, so the
|
||||
compiler owns the layout and field order stops being observable — any order can match. That is the right place to pay
|
||||
for flexibility, because a class already carries identity and metadata, and a `Vector2` should pay for neither. See the
|
||||
`defclass` entry: `Handle` is the gate.
|
||||
|
||||
Note what this settles from the earlier discussion: writability was the question that decided layout, and requiring
|
||||
identical layout answers it — fields are writable on the ordinary terms, by value a copy and through a `(Ptr T)` the
|
||||
original, with no special case.
|
||||
|
||||
## Blocked and unfinished
|
||||
|
||||
Everything below was found, decided or half-built and then stopped. Each says what blocks it. Nothing here is a
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user