Files
RustAst/docs/binder-refactoring-log.md
T
Michael Schimmel a78e72d074 Refactor Binder to use new scope structure
This commit refactors the Binder implementation to better align with the
updated scope structure.
Key changes include:

- Introducing `ExprContext` to distinguish between statement and
  expression contexts.
- Modifying `define_variable` to handle both global and local scope
  definitions more robustly.
- Updating `resolve_variable` to correctly handle upvalue captures,
  especially for global addresses.
- Adjusting `bind` and related functions to use the new `ExprContext`.
- Updating the refactoring log to reflect completed phases.
2026-03-10 17:20:47 +01:00

2.7 KiB

Development Log: Binder Refactoring & Block Scoping

Status Quo

  • Myc currently uses a flat scope per function.
  • def is treated as a side-effect expression that "leaks" into the function scope regardless of nesting (e.g., inside if or do).
  • This leads to uninitialized variables at runtime if the definition is skipped by control flow.

Goal

Implement strict Block Scoping and distinguish between Statements and Expressions to eliminate undefined variable states.

Rules

  1. Block Scoping: Every (do ...) and if branch creates a new lexical scope.
  2. Statements vs. Expressions:
    • def is a Statement.
    • Statements have no return value (Void).
    • Statements cannot be used as expressions (e.g., as arguments, RHS of assignments, or conditions).
    • Statements cannot be the last element of a block (since the block's value is determined by its last expression).
  3. No Shadowing: Redefining a symbol within the same scope level is an error. Shadowing from outer scopes is allowed (standard lexical scoping).
  4. Self-Reference: A variable is only available in its scope after its definition is complete (RHS of def sees outer scope).

Implementation Plan

Phase 1: Binder Infrastructure (Completed)

  1. Update CompilerScope to support hierarchical nesting via a stack in FunctionCompiler.
  2. Implement push_scope and pop_scope in Binder.
  3. Refactor resolve_variable to traverse the scope stack (inner-to-outer).
  4. Update define_variable to enforce "No Shadowing" at the current scope level.

Phase 2: Statement/Expression Validation (Completed)

  1. Introduce a mechanism to track "Context" (Expression vs. Statement) during binding.
  2. Validate that def is only used in statement positions.
  3. Enforce that the last node in a BoundKind::Block is an expression.

Phase 3: VM Compatibility

  1. Ensure the VM handles "Void" results from statements correctly.
  2. (Optional) Optimize stack allocation based on scope depth.

Log Entries

2024-05-22: Initialization

  • Analyzed design-flaw.myc.
  • Defined the "Statement" concept to solve the uninitialized variable problem.
  • Initialized this log.

Phase 1 & 2 Completed

  • Introduced scope stack into FunctionCompiler.
  • Introduced ExprContext (Expression / Statement) in the Binder.
  • def now acts strictly as a statement.
  • Variables defined inside nested scopes (e.g. inside if or do) do not leak into outer local scopes anymore.
  • Outstanding behavior to discuss: def inside nested scopes at the root level still leaks into globals.