tools/hrw4u/src/visitor.py — 1,208 LoC, 20 visit* methods — does all of this in one pass:
- resolves symbols
- checks hook validity and arguments
- applies sandbox policy
- allocates variable slots
- expands procedures by splicing source text
- and renders
.conf
I'd break it into three: an AST, a semantic-analysis pass (sema), and a .conf emitter. It is a refactor — no C++ changes, no grammar changes, no .conf output changes.
What the split buys
|
Today |
After |
| Where a new check lives |
a visit* method inside a 1,208-line file whose other job is text rendering |
a function over the resolved tree |
| When a check can run |
only while .conf is being produced |
whenever the tree exists |
| What the language server runs |
the whole compiler, .conf emission included, on every keystroke — and reads visitor._proc_registry, a private field |
sema, and stops there |
| Diagnostics |
built from CST contexts inside the emitter |
built from AST spans in sema — one wording for CLI and editor |
| The typed AST from #13126 |
test-only and lossy; nothing consumes it |
the production tree |
.conf emission |
the tail of the compiler |
one consumer of the tree |
What it makes possible later
Because .conf emission becomes a consumer of the resolved tree rather than the compiler's tail,
another consumer can attach at the same point without touching the first — and any check added to
sema lands for both. That is the reason no .conf text appears in any sema_nodes node: the fork
point has to be format-neutral or it is not a fork point.
Tracking
Related but independent
tools/hrw4u/src/visitor.py— 1,208 LoC, 20visit*methods — does all of this in one pass:.confI'd break it into three: an AST, a semantic-analysis pass (
sema), and a.confemitter. It is a refactor — no C++ changes, no grammar changes, no.confoutput changes.What the split buys
visit*method inside a 1,208-line file whose other job is text rendering.confis being produced.confemission included, on every keystroke — and readsvisitor._proc_registry, a private field.confemissionWhat it makes possible later
Because
.confemission becomes a consumer of the resolved tree rather than the compiler's tail,another consumer can attach at the same point without touching the first — and any check added to
sema lands for both. That is the reason no
.conftext appears in anysema_nodesnode: the forkpoint has to be format-neutral or it is not a fork point.
Tracking
Related but independent