v3 Semantics: Nested Functions

  • Resolve nested-function references through lexical scopes.
  • Distinguish known declaration arity from dynamically stored callable values.
  • Preserve const and declaration-order rules without inventing type inference.
1 / 6

Readiness

  • Trace v2 scope lookup and v3 postfix ASTs.
2 / 6

Worked reconstruction

Analyze let base=3; fn make(x){ fn add(y){ return base+x+y; } return add; }. Register base, then register make before traversing its body. Push a function scope with parameter x. Register add in that scope before entering its body; inside add, y resolves locally, x resolves in make's scope, and base resolves in the outer scope. Return to make's scope, resolve add as its return value, then pop the function scope.

Moving base's declaration after make changes the result: base is unavailable when make's body is analyzed. There is no global hoisting pass. Self-recursion is allowed because the current function binding is installed before its body. Function bindings are const-like; assigning to their name is rejected.

3 / 6

Diagnose before implementing

An analyzer rejects every f() where f was introduced with let, yet accepts const a=[1]; a=[2];. Explain why its call policy is too strict and its assignment policy too weak.

4 / 6

Independent transfer

Write one nested function whose outer reference is valid, then move the declaration past the use to produce a name error. Compare direct known-function wrong arity with wrong arity through a variable holding that function.

5 / 6

Carry forward

Carry a name-valid AST into closure compilation. Record which decisions remain dynamic so later runtime failures are not misdiagnosed as missing static checks.

6 / 6
←/→ or click edges to navigate · ? help · N notes · F fullscreen