Ported from the author's Clojure watch.el. Three of its decisions survive unchanged — the program decides what is shown, the request is async, and the paint is replace-buffer-contents so point survives every tick. The transport is the part that had to turn round. An eval here compiles a module and dlopens it, so the planned fix of compiling the render thunk once and re-invoking it per tick was still a poll, and a poll has a defect caching does not touch: a thunk runs at a frame boundary and a stopped program has no more of those. So the program writes into a table in flan_dev.c from its own loop and Emacs reads the table, which is memory. The values are then as fresh as the last frame whatever the repaint interval is, and they are still there while the program is stopped. The frame thread's constraints decide the storage: no allocation, so names are fixed arrays rather than strdup'd; no lock, because the reader is the listener thread; and not the result buffer, which is written once per C-x C-e and would be overwritten sixty times a second by watch traffic. One seqlock per slot rather than one for the table, so a reader retries one slot instead of having to catch the gap between two frames' writes; a snapshot from adjacent frames is what a HUD looks like anyway. Sixty-four slots, and past that a name is dropped rather than fatal — killing the program because somebody watched a 65th value is the diagnostic shooting the patient. Reported as a flag and not a count: the only number the write path could keep is of write attempts, which at frame rate says "3847 names" about one name. Nothing writes the table until a watch buffer is open, so a watch call in a program nobody is debugging is a load and a branch that is not taken — the same number in a release build, since flan_dev.c is linked into both. Scalars work today through declare-c against four runtime entry points, which is why this needed no compiler change. A struct or a slice needs a walk over its type, which is one arm in check.ml beside print; BUILT.md writes it out rather than reaching into a file another lane holds. Ghost text turns out to be gated on the same arm, for a different reason: nothing in the table carries a source location, and a hand-written declare-c call cannot supply one that does not drift when the line moves.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%