Skip to content

Unify scope resolution: walk_scope, resolve_binder, free_vars into single compiler phase #129

@dowdiness

Description

@dowdiness

Problem

Three functions solve overlapping scope resolution problems with different approaches:

Function Location Approach Handles nested blocks?
walk_scope examples/ideal/main/scope_annotation.mbt Recursive walk with scope stack yes
resolve_binder lang/lambda/edits/scope.mbt Ad-hoc FlatProj + source positions no
free_vars lang/lambda/edits/free_vars.mbt Recursive walk with bound-name set yes

walk_scope and free_vars follow the same pattern (recursive descent maintaining scope context) and handle nested blocks correctly. resolve_binder is ad-hoc and broken for nested blocks.

Ideal architecture

A single scope resolution phase in lang/lambda/ that produces a binding map:

Input:  ProjNode tree (or Term)
Output: Map[NodeId, BindingInfo]  — every Var → its binder

This replaces:

  • resolve_binder — just look up the binding map
  • free_vars — vars not in the binding map are free
  • walk_scope in the ideal editor — reads the binding map and adds UI metadata (color, usage_ids)

Dependencies

Scope

  • Move walk_scope's algorithm to lang/lambda/edits/ as a proper compiler phase
  • Replace resolve_binder call sites (scope.mbt, text_edit_refactor.mbt)
  • Replace free_vars with a derived query on the binding map
  • Keep walk_scope in the ideal editor as a thin wrapper that reads the phase output

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions