Branch resolve-check (off generics-inc1 / 6639c19).
Suite 193/193; fixpoint OK (3,491,608 bytes); tree clean.
Tags: v3-resolve-check-step1 … step4d,
v3-two-phase-parse-plan.
Split semantic analysis out of the grammar's parse-time actions into a
post-parse pass (Check), so that identifier binding happens after a
unit's declarations are known — which is what the forward-reference
machinery (FwdVar*, IsFwdVar, the Design forward branch) exists to
work around.
| Step | Commit | What |
|---|---|---|
| 1 | 50df067 |
Check.def/.mod scaffold (Resolve), called by the driver between Parse and Lower, gated by -noresolve. No-op; byte-identical. |
| 2 | f34ca98 |
Forward resolution moved into Check (NoteForward/FlushForward); made scope-independent (SymTab.fwdVarScope + FindScope) so it can run post-parse. FwdVarType deleted. |
| 3 | 7ca434b |
The forward operand is now InvalidType, so the generic "skip checks on an unknown type" rule replaces the purpose-built leniency. Deleted SymTab.IsFwdVar, the fwdVarT table and all five guards; FwdVarRef no longer allocates a placeholder. |
| 4a | 5703b27 |
Expression nodes now store their type (SetTy at the Expr/SimExpr/Term/Fact levels). |
| 4b | 192ad55 |
Check resolves a forward designator's full type (base symbol + selectors via SelType) and stores it on the node. |
| 4c | 9dc2ed7 |
Resolved types propagate up the expression tree (PropNode/EvalExpr); Lower reads the stored type for string/set literals (removes a duplicate construction). |
| 4d | 8efae2e |
A forward-tainted assignment is now type-checked — n := "abc" with a later VAR n : INTEGER was silently accepted. |
New tests: t_fwdsel.mod, t_fwdprop.mod, t_bad_fwd.mod (expect_fail).
NkArray/NkRecord/NkPointer/
NkEnum/NkTypeIdent/NkProcType are never built; constructed types
live only in SymTab. So the original plan's "walk the type AST" had
nothing to walk — type-constructor checks stay parse-time.Lower constructs types while emitting and NewDesc does not
dedup, so a type must be constructed once and cached on the node (the
parser already does, and Lower now reads it for literals).t_fwdvar,
t_fwdsel, t_fwdprop, Showcase22), including through an
array-index selector.FwdVar* cannot be deleted by moving checks. Even with every
check in the walk, Design must still bind a not-yet-declared name —
impossible in one pass. That needs a genuinely two-phase parse
(declarations before bodies). See docs/plan-two-phase-parse.md.Get, sym is the
token just scanned but pos/len describe the previous one
(LexString vs LookAheadName), and Reset does not reset
pos/len/nextPos/nextLen/line/col, so stale values leak
across files. Any mid-file restart must reproduce that state exactly.SymTab: FwdVarRef/FwdVarName/FwdVarResolve — record (name,
kind, scope) and resolve by name; no placeholder, no leniency.Check: NoteForward/FlushForward (resolve + store the designator
type), SelType, EvalExpr/PropNode (propagate), CheckAssign
(forward-tainted assignments).Design's forward branch (FwdVarRef + Check.NoteForward,
Op=1 marker on the node).Lower: unchanged type computation except the literal cases.docs/plan-two-phase-parse.md),
then delete FwdVar*/NoteForward/FlushForward and the Design
forward branch. Recommended start: do the restart at the
driver level using the exported Reset + repeated Get (not new
scanner internals), add a small grammar body-entry production, and
calibrate the stop point empirically (encode observed pos/len
into the error channel). Largest piece in the thread; spans sessions.201) and update the four tests that rely on it. Deletes the whole
mechanism for near-zero work, but is a language-semantics change.RETURN, call arity) — the same safe pattern as step 4d; more
forward-reference diagnostics, no parser change.FwdVar* is a small, self-contained path.cd .../m2compiler-V3
git checkout resolve-check
./bootstrap/fixpoint.sh # FIXPOINT OK
cd compiler && ./build.sh && ./run_tests.sh # 193/193
Key docs: docs/plan-resolve-check.md (running record),
docs/plan-two-phase-parse.md (design for step 1 above).