Documentation
¶
Overview ¶
Package bind implements name resolution and symbol binding for Lua AST nodes.
The binding phase occurs after parsing and before type checking. It resolves all identifier references in the AST to unique SymbolIDs, establishing the connection between uses of a name and its declaration.
The binder performs lexical scope analysis using a scope stack. Each scope frame tracks local variable declarations. Name lookup searches from innermost to outermost scope, implementing Lua's lexical scoping rules:
- Local variables shadow outer declarations of the same name
- Undeclared variables become implicit globals
- Function parameters create a new scope for the function body
- Loop variables (for statements) are local to the loop body
- repeat-until condition can see variables declared in the loop body
The binding process handles several Lua-specific behaviors:
- Method definitions (function obj:method()) receive an implicit 'self' parameter
- Local function definitions are predeclared to support mutual recursion
- Expressions on the right side of 'local x = expr' see the outer scope
- Generic for loops can declare multiple iteration variables
The result is a BindingTable that maps AST nodes to their resolved symbols, enabling subsequent compiler phases to work with unique symbol identities rather than string names.
Package bind provides name resolution for Lua programs.
The binder traverses AST nodes and resolves identifier references to unique symbols. This establishes the binding between uses and definitions, enabling type checking and CFG construction to work with stable identities.
Symbol Assignment ¶
Symbols are assigned to:
- Local variables at their declaration point
- Function parameters at function entry
- For loop iteration variables at loop entry
- Global references (assumed external)
- Field paths like M.f.g (each qualified access gets a symbol)
Usage ¶
Call Bind with a function AST and optional global names:
bindings := bind.Bind(funcExpr, "print", "error", "assert")
The returned BindingTable provides:
- BindingTable.SymbolOf: Look up symbol for an IdentExpr
- BindingTable.Name: Get the source name for a symbol
- BindingTable.Kind: Get the declaration kind (local/param/global)
- BindingTable.ParamSymbols: Get parameter symbols for a function
Index ¶
- type Binder
- type BindingTable
- func (t *BindingTable) AllSymbols() []cfg.SymbolID
- func (t *BindingTable) Bind(ident *ast.IdentExpr, sym cfg.SymbolID)
- func (t *BindingTable) CapturedSymbols(fn *ast.FunctionExpr) []cfg.SymbolID
- func (t *BindingTable) FieldSymbol(baseSym cfg.SymbolID, path string) (cfg.SymbolID, bool)
- func (t *BindingTable) FuncLitBySymbol(sym cfg.SymbolID) (*ast.FunctionExpr, bool)
- func (t *BindingTable) FuncLitSymbol(fn *ast.FunctionExpr) (cfg.SymbolID, bool)
- func (t *BindingTable) GenericForSymbols(stmt *ast.GenericForStmt) []cfg.SymbolID
- func (t *BindingTable) GetOrCreateFieldSymbol(baseSym cfg.SymbolID, path string) cfg.SymbolID
- func (t *BindingTable) GetOrCreateFuncLitSymbol(fn *ast.FunctionExpr) cfg.SymbolID
- func (t *BindingTable) Globals() []cfg.SymbolID
- func (t *BindingTable) Kind(sym cfg.SymbolID) (cfg.SymbolKind, bool)
- func (t *BindingTable) LocalSymbols(stmt *ast.LocalAssignStmt) []cfg.SymbolID
- func (t *BindingTable) Name(sym cfg.SymbolID) string
- func (t *BindingTable) NumForSymbol(stmt *ast.NumberForStmt) (cfg.SymbolID, bool)
- func (t *BindingTable) ParamSymbols(fn *ast.FunctionExpr) []cfg.SymbolID
- func (t *BindingTable) SetFuncLitSymbol(fn *ast.FunctionExpr, sym cfg.SymbolID)
- func (t *BindingTable) SetGenericForSymbols(stmt *ast.GenericForStmt, syms []cfg.SymbolID)
- func (t *BindingTable) SetKind(sym cfg.SymbolID, k cfg.SymbolKind)
- func (t *BindingTable) SetLocalSymbols(stmt *ast.LocalAssignStmt, syms []cfg.SymbolID)
- func (t *BindingTable) SetName(sym cfg.SymbolID, name string)
- func (t *BindingTable) SetNumForSymbol(stmt *ast.NumberForStmt, sym cfg.SymbolID)
- func (t *BindingTable) SetParamSymbols(fn *ast.FunctionExpr, syms []cfg.SymbolID)
- func (t *BindingTable) SymbolOf(ident *ast.IdentExpr) (cfg.SymbolID, bool)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Binder ¶
type Binder struct {
// contains filtered or unexported fields
}
Binder performs name resolution by walking the AST and assigning unique SymbolIDs to all identifier declarations and references.
The binder maintains a stack of scope frames to implement lexical scoping. The bottom frame (index 0) holds global variables. Each function body, block statement, and loop body pushes a new frame.
Usage:
table := bind.Bind(functionAST, predeclaredGlobals) sym, ok := table.SymbolOf(someIdentifier)
func NewBinder ¶
NewBinder creates a binder initialized with predeclared global names.
The globals parameter specifies names that should be treated as predefined global variables (e.g., "print", "pairs", "ipairs"). These are placed in the bottom scope frame and receive SymbolGlobal kind.
Globals are sorted before processing to ensure deterministic SymbolID assignment across multiple bindings of the same source.
type BindingTable ¶
type BindingTable struct {
// contains filtered or unexported fields
}
BindingTable stores the results of name resolution for a Lua program.
The table provides bidirectional mapping between AST nodes and symbols:
- IdentExpr nodes map to their resolved SymbolID
- FunctionExpr nodes map to their parameter symbols
- LocalAssignStmt nodes map to their declared local symbols
- For loop statements map to their iteration variable symbols
Each symbol has an associated kind (global, local, param) and name. The table also supports field paths (M.f.g) and anonymous function symbols.
BindingTable is the primary output of the binding phase and is consumed by type checking and CFG construction phases.
func Bind ¶
func Bind(fn *ast.FunctionExpr, globals []string) *BindingTable
Bind performs complete name resolution on a function AST.
This is the main entry point for the binding phase. It creates a binder with the specified predeclared globals, processes the entire function (including nested functions), and returns the resulting BindingTable.
The returned table maps all IdentExpr nodes to their resolved symbols and records parameter/local symbol lists for each function and declaration.
func NewBindingTable ¶
func NewBindingTable() *BindingTable
NewBindingTable creates an empty binding table with all maps initialized.
func (*BindingTable) AllSymbols ¶
func (t *BindingTable) AllSymbols() []cfg.SymbolID
AllSymbols returns every symbol in the table without duplicates.
This collects symbols from all sources: bound identifiers, kinds map, parameter lists, local declarations, and for loop variables. Zero symbols are excluded.
func (*BindingTable) Bind ¶
func (t *BindingTable) Bind(ident *ast.IdentExpr, sym cfg.SymbolID)
Bind records that an identifier references a specific symbol.
func (*BindingTable) CapturedSymbols ¶
func (t *BindingTable) CapturedSymbols(fn *ast.FunctionExpr) []cfg.SymbolID
CapturedSymbols identifies free variables in a function.
A captured symbol is one that is referenced inside the function body but declared outside it. This includes both upvalues (locals from enclosing functions) and globals.
The analysis walks the function body to find all referenced symbols, then subtracts symbols declared within the function (parameters and locals).
func (*BindingTable) FieldSymbol ¶
FieldSymbol looks up an existing symbol for a field path. Returns zero and false if no symbol exists for the given base and path.
func (*BindingTable) FuncLitBySymbol ¶
func (t *BindingTable) FuncLitBySymbol(sym cfg.SymbolID) (*ast.FunctionExpr, bool)
FuncLitBySymbol returns the function literal for a symbol if known.
func (*BindingTable) FuncLitSymbol ¶
func (t *BindingTable) FuncLitSymbol(fn *ast.FunctionExpr) (cfg.SymbolID, bool)
FuncLitSymbol returns the symbol for a function literal if one exists.
func (*BindingTable) GenericForSymbols ¶
func (t *BindingTable) GenericForSymbols(stmt *ast.GenericForStmt) []cfg.SymbolID
GenericForSymbols returns the iteration variable symbols for a generic for.
func (*BindingTable) GetOrCreateFieldSymbol ¶
GetOrCreateFieldSymbol returns or creates a symbol for a qualified field path.
Field paths represent nested property access like M.f or M.f.g. The baseSym identifies the root object, and path is the dot-separated field chain.
The created symbol gets a composite name (e.g., "M.f") and SymbolLocal kind. Subsequent calls with the same base and path return the existing symbol.
func (*BindingTable) GetOrCreateFuncLitSymbol ¶
func (t *BindingTable) GetOrCreateFuncLitSymbol(fn *ast.FunctionExpr) cfg.SymbolID
GetOrCreateFuncLitSymbol returns or creates a symbol for an anonymous function.
Anonymous functions (function literals) need symbols for type assignment and reference tracking. Each unique FunctionExpr AST node gets its own symbol.
func (*BindingTable) Globals ¶
func (t *BindingTable) Globals() []cfg.SymbolID
Globals returns all symbols with SymbolGlobal kind. This includes both predeclared globals and implicitly created globals.
func (*BindingTable) Kind ¶
func (t *BindingTable) Kind(sym cfg.SymbolID) (cfg.SymbolKind, bool)
Kind returns the declaration kind of a symbol. Returns false if the symbol has no recorded kind.
func (*BindingTable) LocalSymbols ¶
func (t *BindingTable) LocalSymbols(stmt *ast.LocalAssignStmt) []cfg.SymbolID
LocalSymbols returns the symbols declared by a local assignment.
func (*BindingTable) Name ¶
func (t *BindingTable) Name(sym cfg.SymbolID) string
Name returns the source name of a symbol, or empty if unknown.
func (*BindingTable) NumForSymbol ¶
func (t *BindingTable) NumForSymbol(stmt *ast.NumberForStmt) (cfg.SymbolID, bool)
NumForSymbol returns the iteration variable symbol for a numeric for.
func (*BindingTable) ParamSymbols ¶
func (t *BindingTable) ParamSymbols(fn *ast.FunctionExpr) []cfg.SymbolID
ParamSymbols returns the parameter symbols for a function in declaration order.
func (*BindingTable) SetFuncLitSymbol ¶
func (t *BindingTable) SetFuncLitSymbol(fn *ast.FunctionExpr, sym cfg.SymbolID)
SetFuncLitSymbol assigns a specific symbol to a function literal.
func (*BindingTable) SetGenericForSymbols ¶
func (t *BindingTable) SetGenericForSymbols(stmt *ast.GenericForStmt, syms []cfg.SymbolID)
SetGenericForSymbols records the iteration variables for a generic for loop. For 'for k, v in pairs(t) do ... end', this records symbols for k and v.
func (*BindingTable) SetKind ¶
func (t *BindingTable) SetKind(sym cfg.SymbolID, k cfg.SymbolKind)
SetKind records whether a symbol is a global, local, or parameter.
func (*BindingTable) SetLocalSymbols ¶
func (t *BindingTable) SetLocalSymbols(stmt *ast.LocalAssignStmt, syms []cfg.SymbolID)
SetLocalSymbols records the symbols declared by a local assignment. For 'local a, b, c = ...', the symbols correspond to a, b, c in order.
func (*BindingTable) SetName ¶
func (t *BindingTable) SetName(sym cfg.SymbolID, name string)
SetName records the source name associated with a symbol.
func (*BindingTable) SetNumForSymbol ¶
func (t *BindingTable) SetNumForSymbol(stmt *ast.NumberForStmt, sym cfg.SymbolID)
SetNumForSymbol records the iteration variable for a numeric for loop. For 'for i = 1, 10 do ... end', this records the symbol for 'i'.
func (*BindingTable) SetParamSymbols ¶
func (t *BindingTable) SetParamSymbols(fn *ast.FunctionExpr, syms []cfg.SymbolID)
SetParamSymbols records the ordered parameter symbols for a function. For methods with implicit self, self is the first symbol in the list.