74 lines
4.3 KiB
Markdown
74 lines
4.3 KiB
Markdown
# Handoff — one buffer for every lowering
|
|
|
|
Branch `dev-loop`, worktree `agent-a9d4028fa5752ba39`, from `f772162`.
|
|
|
|
`spike/x86/dump.sh` landed at `f772162` and prints four lowerings of one function side by side: the LLVM IR
|
|
the frontend emits, what `llc` makes of it at `-O0` and at `-O2`, and what the hand-written x86 backend emits.
|
|
Reading one against another is the only way to check a lowering by eye. A shell script that prints all four
|
|
into a scrollback is not how anyone reads them, though: three of the four are noise on any given day, and the
|
|
one that is not is the one you are elbow-deep in. So the same four go into an Emacs buffer with collapsible
|
|
sections, and the buffer remembers which of them you had open.
|
|
|
|
`M-x flan-lowering`, `C-c C-l` in `flan-mode`.
|
|
|
|
## The three decisions
|
|
|
|
### 1. It compiles the file; it does not ask the daemon
|
|
|
|
`flan-disassemble` (`C-c C-a`) asks the running program what the body it is calling for a name actually came
|
|
out as. This asks a different question — what does this source compile to, through four different lowerings —
|
|
and the two cannot be merged, for a concrete reason rather than a stylistic one: **the daemon has the
|
|
installed body's `.ll` and its `.so`, and neither `llc -O2` nor the hand-written backend has ever been run
|
|
over it.** There is no answer in the daemon to give. `llc -O2` on the installed IR would be a fifth thing,
|
|
built here and never run anywhere, and the backend's output for an installed body does not exist at all
|
|
unless the daemon was started `--x86`.
|
|
|
|
So the two commands sit beside each other and each says which question it answers. `flan-disassemble` keeps
|
|
its header, whose `showing` line is the daemon's own account of how much its answer claims. This buffer's
|
|
header says the opposite thing just as plainly: it names the file and the compiler flags, and says the
|
|
listing is what the source on disk compiles to and not what the program is running. Both docstrings
|
|
cross-reference the other.
|
|
|
|
### 2. `outline-minor-mode`, not `magit-section` and not overlays of my own
|
|
|
|
Nothing under `emacs/` requires a package that is not in Emacs — the whole client is `subr-x`, `seq`,
|
|
`pcase`, `cl-lib`, `xref`, `eldoc`, `comint`, `imenu` and its own files. Taking a dependency on Magit for a
|
|
four-section buffer would be the first, and it would be for folding, which Emacs has had since before Magit
|
|
existed.
|
|
|
|
`outline-minor-mode` on GNU Emacs 30.2.50 is the whole of what was asked for: `outline-cycle` is `TAB` on a
|
|
heading, `outline-hide-body` and `outline-show-all` collapse and expand everything, and
|
|
`outline-next-visible-heading` / `outline-previous-visible-heading` are `n` and `p`. Hand-rolling it would be
|
|
a hundred lines re-implementing that badly.
|
|
|
|
Headings are found by `outline-search-function` keyed to a text property this file puts on the four heading
|
|
lines, **not** by a regexp over the text. That is not fussiness: LLVM IR has `;` comments, assembler output
|
|
has `#` and `;` comments and lines that start with `.`, and `objdump` prints `<flan.step>:` label lines. Any
|
|
regexp loose enough to match four section headers matches inside three of the four bodies, and folding then
|
|
fragments in the middle of a listing.
|
|
|
|
### 3. The open/closed state is a global alist keyed by section, and nothing else
|
|
|
|
One `defvar`, four entries, alive for the Emacs session and no longer. Not persisted to disk: it is four
|
|
booleans, a preference file for it would one day have to be migrated, and nobody has ever wanted yesterday's
|
|
fold state back.
|
|
|
|
Keyed to the **section**, not to the function. The workflow is "I am working on the backend today", which is
|
|
a fact about the section and holds across every function the author looks at while he is doing it. Keyed to
|
|
the function it would forget on every `M-x flan-lowering` of a different name, which is exactly the thing he
|
|
asked not to happen.
|
|
|
|
The alist is the single source of truth. A toggle mutates it and then applies it to the buffer; a refresh
|
|
applies it to the newly drawn buffer. Visibility is never read back out — that would couple this to whether
|
|
outline folds with overlays or with text properties, which is a thing that has changed between Emacs
|
|
versions and is none of this file's business.
|
|
|
|
## Status
|
|
|
|
- [x] Handoff stub, decisions fixed
|
|
- [ ] `emacs/flan-lower.el`
|
|
- [ ] Key in `flan-mode`, autoloads
|
|
- [ ] Tests in `emacs/test-flan-dev.el`
|
|
- [ ] `emacs/MANUAL.md`
|
|
- [ ] `dune test`, `@page`, `@cells`
|