Purpose
First milestone of the sema rearch under #640. Build a forward scope-building pass in src/semantic/ that mirrors what variable-allocator does today for variable typing, but runs pre-codegen. Annotator queries it; codegen consumers later migrate to `ctx.typeOf(expr)`.
Scope (~200-400 LOC)
New file: `src/semantic/scope-builder.ts`.
- Walks AST in forward order
- Maintains `scopes: Array<Map<name, ResolvedType>>` stack (enter/exit on blocks, function bodies, class methods)
- Handles:
- `variable_declaration` — binds name → declared or inferred type
- `variable` reference — resolves name from scope stack
- function parameters (bind on entry)
- class method `this` binding
- Exposes `resolveVariable(name, scopeAt: Expression): ResolvedType | null`
- Feeds a new sink method `TypeAnnotator` can call when visiting `variable` / `variable_declaration` nodes.
Out of scope
- Member access, index access, call, method_call — next milestone.
- Class field inheritance, inference for untyped vars with complex initializers — later.
- Error reporting — this pilot is type-tracking only; sema diagnostics come later.
Success
- Stage 2 self-hosting green.
- `ctx.typeOf(variableRef)` returns correct type for basic cases WITHOUT falling back to live resolver.
- Unit test showing `typeOf` hits annotator cache (not fallback) for a simple variable expression.
Risks
- Async / closure / lifted-function variable rebinding — pilot may need to defer. If so, note in code + issue comment.
- Parallel-array cache in BaseGenerator may not be the right shape for scope-builder; fine to add a separate `typeOfVariable` backend.
Closes part of #640.
Purpose
First milestone of the sema rearch under #640. Build a forward scope-building pass in
src/semantic/that mirrors what variable-allocator does today for variable typing, but runs pre-codegen. Annotator queries it; codegen consumers later migrate to `ctx.typeOf(expr)`.Scope (~200-400 LOC)
New file: `src/semantic/scope-builder.ts`.
Out of scope
Success
Risks
Closes part of #640.