Documentation
¶
Overview ¶
Package cfg constructs control flow graphs from Lua AST nodes.
This package transforms parsed Lua code into a graph representation suitable for dataflow analysis. The CFG captures control flow through branches, loops, and function calls while preserving variable scope and SSA versioning.
Core Types ¶
Graph is the primary type, holding:
- The underlying CFG structure with entry/exit points
- NodeInfo for each CFG point (assignments, calls, branches, returns)
- SSA versioning for all variables
- Scope visibility maps for lexical scoping
- Nested function references for hierarchical analysis
Builder constructs graphs incrementally from AST traversal. It handles:
- Creating CFG nodes and edges
- Tracking scope entry/exit
- Computing SSA versions via dominance frontiers
- Extracting nested function definitions
ScopeTracker maintains lexical scope during construction:
- Symbol registration at declaration points
- Visibility snapshots at each CFG point
- Global vs local symbol distinction
Node Information Types ¶
Each CFG node carries semantic information via the NodeInfo interface:
- AssignInfo: Local/global assignments with targets and sources
- CallInfo: Function calls with callee, arguments, and receiver
- ReturnInfo: Return statements with expressions
- BranchInfo: Conditional branches with condition analysis
- FuncDefInfo: Function definitions (global, field, method)
- TypeDefInfo: Type alias definitions
SSA Versioning ¶
The package computes SSA (Static Single Assignment) form using the Cytron et al. dominance-frontier algorithm:
- Collect all assigned symbols across the function
- Compute dominance frontiers via immediate dominators
- Place phi nodes at iterated dominance frontiers
- Rename variables during dominator-tree traversal
SSA versioning enables precise dataflow tracking through control flow joins. The Version type identifies a specific definition of a symbol, and PhiInfo represents join points where multiple definitions merge.
Symbol Resolution ¶
Symbols are bound during a separate binder pass that runs before CFG construction. The Builder receives a pre-populated bind.BindingTable mapping AST identifiers to unique SymbolIDs. This ensures consistent symbol identity across the analysis.
Usage ¶
Typical usage involves calling Build or BuildWithBindings:
// Simple case: build with automatic binding graph := cfg.Build(funcExpr, "print", "error") // Module case: share bindings across functions bindings := bind.Bind(moduleFunc, globalNames...) graph := cfg.BuildWithBindings(funcExpr, bindings)
The resulting graph provides iteration methods for processing nodes:
graph.EachAssign(func(p cfg.Point, info *cfg.AssignInfo) {
// Process assignment at point p
})
graph.EachCall(func(p cfg.Point, info *cfg.CallInfo) {
// Process call at point p
})
Nested Functions ¶
Nested function definitions are collected during CFG construction and accessible via Graph.NestedFunctions. Each NestedFunc contains the definition point, AST node, and assigned symbol. Callers typically build separate graphs for nested functions and link them via symbol IDs.
Package cfg provides CFG construction utilities.
Package cfg provides CFG construction utilities.
Index ¶
- Constants
- func ExtractTypeCheckPattern(info *CallInfo)
- func SortedFieldNames[T any](m map[string]T) []string
- func SortedSymbolIDs[T any](m map[basecfg.SymbolID]T) []basecfg.SymbolID
- type AssignInfo
- type AssignTarget
- type BranchInfo
- type Builder
- func (b *Builder) AddCondBranch(expr ast.Expr) basecfg.Point
- func (b *Builder) AddConditionEdges(expr ast.Expr, thenTarget, elseTarget basecfg.Point) basecfg.Point
- func (b *Builder) AddLinearEdge(next basecfg.Point)
- func (b *Builder) AddNodeWithSnapshot(kind basecfg.NodeKind, target basecfg.SymbolID, callee string) basecfg.Point
- func (b *Builder) Assign(s *ast.AssignStmt)
- func (b *Builder) BreakStmt(_ *ast.BreakStmt)
- func (b *Builder) CallStmt(s *ast.FuncCallStmt)
- func (b *Builder) ComputeSSAVersions()
- func (b *Builder) FuncDef(s *ast.FuncDefStmt)
- func (b *Builder) GenericFor(s *ast.GenericForStmt)
- func (b *Builder) GotoStmt(s *ast.GotoStmt)
- func (b *Builder) IfStmt(s *ast.IfStmt)
- func (b *Builder) LabelStmt(s *ast.LabelStmt)
- func (b *Builder) LocalAssign(s *ast.LocalAssignStmt)
- func (b *Builder) NumberFor(s *ast.NumberForStmt)
- func (b *Builder) ParamDefs(fn *ast.FunctionExpr)
- func (b *Builder) ProcessExprs(p basecfg.Point, exprs []ast.Expr) []string
- func (b *Builder) RepeatStmt(s *ast.RepeatStmt)
- func (b *Builder) ResolvePendingGotos()
- func (b *Builder) ReturnStmt(s *ast.ReturnStmt)
- func (b *Builder) ScopedBlock(stmts []ast.Stmt)
- func (b *Builder) StealDeclPoints() map[basecfg.SymbolID]basecfg.Point
- func (b *Builder) StealGlobals() map[string]basecfg.SymbolID
- func (b *Builder) StealScopeVisibility() map[basecfg.Point]map[string]basecfg.SymbolID
- func (b *Builder) StealSymbolKinds() map[basecfg.SymbolID]basecfg.SymbolKind
- func (b *Builder) StealSymbolNames() map[basecfg.SymbolID]string
- func (b *Builder) Stmt(stmt ast.Stmt)
- func (b *Builder) Stmts(stmts []ast.Stmt)
- func (b *Builder) TypeDef(s *ast.TypeDefStmt)
- func (b *Builder) WhileStmt(s *ast.WhileStmt)
- type CFG
- type CallInfo
- type CondCheck
- type CondCheckKind
- type FuncDefInfo
- type FuncDefTargetKind
- type Graph
- func (g *Graph) AllSymbolIDs() map[basecfg.SymbolID]bool
- func (g *Graph) AllSymbolsAt(p Point) map[string]basecfg.SymbolID
- func (g *Graph) AllVisibleVersions(p Point) map[basecfg.SymbolID]Version
- func (g *Graph) Assign(p Point) *AssignInfo
- func (g *Graph) AssignPoints() []Point
- func (g *Graph) Bindings() *bind.BindingTable
- func (g *Graph) Branch(p Point) *BranchInfo
- func (g *Graph) CFG() *basecfg.CFG
- func (g *Graph) Call(p Point) *CallInfo
- func (g *Graph) CalleePathAt(p Point) constraint.Path
- func (g *Graph) DeclarationPoint(sym basecfg.SymbolID) (Point, bool)
- func (g *Graph) DirectAliasSymbol(targetSym basecfg.SymbolID) basecfg.SymbolID
- func (g *Graph) EachAssign(fn func(Point, *AssignInfo))
- func (g *Graph) EachBranch(fn func(Point, *BranchInfo))
- func (g *Graph) EachCall(fn func(Point, *CallInfo))
- func (g *Graph) EachCallSite(fn func(Point, *CallInfo))
- func (g *Graph) EachFuncDef(fn func(Point, *FuncDefInfo))
- func (g *Graph) EachNode(fn func(Point, NodeInfo))
- func (g *Graph) EachReturn(fn func(Point, *ReturnInfo))
- func (g *Graph) EachTypeDef(fn func(Point, *TypeDefInfo))
- func (g *Graph) EdgeCond(from, to Point) (bool, bool)
- func (g *Graph) Edges() []basecfg.Edge
- func (g *Graph) Entry() Point
- func (g *Graph) Exit() Point
- func (g *Graph) Func() *ast.FunctionExpr
- func (g *Graph) FuncDef(p Point) *FuncDefInfo
- func (g *Graph) FuncDefPathAt(p Point) constraint.Path
- func (g *Graph) GlobalSymbol(name string) (basecfg.SymbolID, bool)
- func (g *Graph) HasPhiAt(_ Point, sym basecfg.SymbolID) bool
- func (g *Graph) HasScopeTracking() bool
- func (g *Graph) ID() uint64
- func (g *Graph) Info(p Point) NodeInfo
- func (g *Graph) IsBranch(p Point) bool
- func (g *Graph) IsJoin(p Point) bool
- func (g *Graph) NameOf(sym basecfg.SymbolID) string
- func (g *Graph) NestedFunctions() []NestedFunc
- func (g *Graph) Node(p Point) *basecfg.Node
- func (g *Graph) ParamDeclPoints() []Point
- func (g *Graph) ParamNames() []string
- func (g *Graph) ParamSymbols() []basecfg.SymbolID
- func (g *Graph) PhiNodes() []basecfg.PhiNode
- func (g *Graph) PopulateSymbols(resolve SymbolResolver)
- func (g *Graph) Predecessor(p Point) Point
- func (g *Graph) Predecessors(p Point) []Point
- func (g *Graph) RPO() []Point
- func (g *Graph) Return(p Point) *ReturnInfo
- func (g *Graph) Size() int
- func (g *Graph) Successor(p Point) Point
- func (g *Graph) Successors(p Point) []Point
- func (g *Graph) SymbolAt(p Point, name string) (basecfg.SymbolID, bool)
- func (g *Graph) SymbolKind(sym basecfg.SymbolID) (basecfg.SymbolKind, bool)
- func (g *Graph) TypeDef(p Point) *TypeDefInfo
- func (g *Graph) VisibleVersion(p Point, sym basecfg.SymbolID) Version
- type NestedFunc
- type Node
- type NodeInfo
- type NodeKind
- type NumericForInfo
- type PhiInfo
- type PhiOperand
- type Point
- type ReturnInfo
- type ScopeTracker
- func (t *ScopeTracker) CurrentDepth() int
- func (t *ScopeTracker) DeclarationPoint(sym basecfg.SymbolID) (basecfg.Point, bool)
- func (t *ScopeTracker) EnterScope()
- func (t *ScopeTracker) ExitScope()
- func (t *ScopeTracker) Lookup(name string) (basecfg.SymbolID, bool)
- func (t *ScopeTracker) RegisterGlobal(sym basecfg.SymbolID, name string, declPoint basecfg.Point)
- func (t *ScopeTracker) RegisterSymbol(sym basecfg.SymbolID, name string, kind basecfg.SymbolKind, ...)
- func (t *ScopeTracker) SnapshotVisibility(point basecfg.Point)
- func (t *ScopeTracker) SymbolAt(point basecfg.Point, name string) (basecfg.SymbolID, bool)
- func (t *ScopeTracker) SymbolKind(sym basecfg.SymbolID) (basecfg.SymbolKind, bool)
- func (t *ScopeTracker) VisibleAt(point basecfg.Point) *SymbolMap
- type SymbolID
- type SymbolKind
- type SymbolMap
- type SymbolResolver
- type TargetKind
- type TypeDefInfo
- type TypeParamInfo
- type Version
Constants ¶
const ( SymbolUnknown = basecfg.SymbolUnknown SymbolLocal = basecfg.SymbolLocal SymbolGlobal = basecfg.SymbolGlobal SymbolParam = basecfg.SymbolParam SymbolUpvalue = basecfg.SymbolUpvalue )
Symbol kind constants.
const ( NodeEntry = basecfg.NodeEntry NodeExit = basecfg.NodeExit NodeAssign = basecfg.NodeAssign NodeCall = basecfg.NodeCall NodeBranch = basecfg.NodeBranch NodeJoin = basecfg.NodeJoin NodeReturn = basecfg.NodeReturn NodeScopeEnter = basecfg.NodeScopeEnter NodeScopeExit = basecfg.NodeScopeExit NodeTypeDef = basecfg.NodeTypeDef )
Node kind constants.
const ( CheckNone = basecfg.CheckNone CheckTruthy = basecfg.CheckTruthy CheckFalsy = basecfg.CheckFalsy CheckNil = basecfg.CheckNil CheckNotNil = basecfg.CheckNotNil CheckLimit = basecfg.CheckLimit CheckTypeEqual = basecfg.CheckTypeEqual CheckTypeNot = basecfg.CheckTypeNot )
Condition check kind constants.
Variables ¶
This section is empty.
Functions ¶
func ExtractTypeCheckPattern ¶
func ExtractTypeCheckPattern(info *CallInfo)
ExtractTypeCheckPattern detects Type:is(x) or TypeName(x) patterns.
func SortedFieldNames ¶
SortedFieldNames returns the field names from m in ascending order.
Types ¶
type AssignInfo ¶
type AssignInfo struct {
IsLocal bool // local x = ... vs x = ...
Stmt ast.Stmt // original AST statement (for position info)
Targets []AssignTarget
Sources []ast.Expr
SourceNames []string // Pre-extracted: identifier name or "" if not ident
SourceSymbols []basecfg.SymbolID // Symbol IDs for source expressions (0 if not ident or unresolved)
// Pre-extracted CallInfo for each source that is a function call (nil otherwise)
SourceCalls []*CallInfo
// Type annotations (for local assignments)
TypeAnnotations []ast.TypeExpr
// For generic for: iterator expressions
IterExprs []ast.Expr
// For numeric for
NumericFor *NumericForInfo
// SSA versions assigned by this node (one per target, may be zero if not yet computed)
TargetVersions []Version
}
AssignInfo captures pre-extracted data for assignment nodes.
func (*AssignInfo) Kind ¶
func (*AssignInfo) Kind() basecfg.NodeKind
Kind returns the node kind for AssignInfo.
type AssignTarget ¶
type AssignTarget struct {
Kind TargetKind
// For TargetIdent: the variable name and symbol
Name string // Variable name
Symbol basecfg.SymbolID // Unique symbol ID (0 if unresolved)
// For TargetField: base object and field chain
// For TargetIndex: base object if it is an identifier
BaseName string // "x" in x.y or x[k]
BaseSymbol basecfg.SymbolID // Symbol ID for base variable
FieldPath []string // ["y", "z"] in x.y.z
// For TargetIndex: the base expression and key
Base ast.Expr // x in x[k]
Key ast.Expr // k in x[k]
// Raw LHS expression for complex cases
Expr ast.Expr
}
AssignTarget represents a single assignment target with pre-extracted info.
func ExtractAssignTarget ¶
func ExtractAssignTarget(expr ast.Expr) AssignTarget
ExtractAssignTarget extracts assignment target info from an expression.
type BranchInfo ¶
type BranchInfo struct {
CondVar string // Variable being tested (path string)
CondSymbol SymbolID // Symbol ID of condition variable root (0 if unresolved)
CondCheck CondCheck // Condition check type
Condition ast.Expr // Full condition expression
}
BranchInfo captures pre-extracted data for branch nodes.
func (*BranchInfo) Kind ¶
func (*BranchInfo) Kind() basecfg.NodeKind
Kind returns the node kind for BranchInfo.
type Builder ¶
type Builder struct {
Cfg *basecfg.CFG
Info map[basecfg.Point]NodeInfo
Nested []NestedFunc
Current basecfg.Point
CurrentLive bool
Labels map[string]basecfg.Point
Pending map[string][]basecfg.Point
LoopExits []basecfg.Point
// SSA versioning state (keyed by basecfg.SymbolID for scope-aware versioning)
NextVersionID map[basecfg.SymbolID]int // symbol -> next version ID
VisibleVersion map[basecfg.Point]map[basecfg.SymbolID]Version // (point, symbol) -> visible version
PhiNodes []PhiInfo // Collected phi nodes
// Scope tracking (structural visibility)
ScopeTracker *ScopeTracker
// Binding table (AST ident -> symbol, populated by binder pass)
Bindings *bind.BindingTable
// Function parameters (collected during ParamDefs)
ParamNames []string
ParamSymbols []basecfg.SymbolID
ParamDeclPoints []basecfg.Point
}
Builder constructs CFG Graphs from AST nodes through incremental traversal.
Builder maintains the state needed to transform an AST function body into a control flow graph. It tracks the current program point, pending gotos, loop exits, and scope visibility during traversal.
The build process involves:
- Traversing statements to create CFG nodes
- Connecting nodes with edges (including conditional edges)
- Tracking scope entry/exit for lexical scoping
- Computing SSA versions via dominance frontiers
- Collecting nested function definitions
Usage is internal to the package. External code should use Build or BuildWithBindings to construct graphs.
func NewBuilder ¶
func NewBuilder() *Builder
NewBuilder creates a new Builder with initialized fields.
func (*Builder) AddCondBranch ¶
AddCondBranch creates a branch node for a condition.
func (*Builder) AddConditionEdges ¶
func (b *Builder) AddConditionEdges(expr ast.Expr, thenTarget, elseTarget basecfg.Point) basecfg.Point
AddConditionEdges creates branch nodes for a condition expression.
func (*Builder) AddLinearEdge ¶
AddLinearEdge adds an edge from the current point to next, then updates current.
func (*Builder) AddNodeWithSnapshot ¶
func (b *Builder) AddNodeWithSnapshot(kind basecfg.NodeKind, target basecfg.SymbolID, callee string) basecfg.Point
AddNodeWithSnapshot creates a CFG node and immediately takes a visibility snapshot.
func (*Builder) Assign ¶
func (b *Builder) Assign(s *ast.AssignStmt)
Assign processes a regular assignment statement.
func (*Builder) CallStmt ¶
func (b *Builder) CallStmt(s *ast.FuncCallStmt)
CallStmt processes a function call statement.
func (*Builder) ComputeSSAVersions ¶
func (b *Builder) ComputeSSAVersions()
ComputeSSAVersions computes SSA versions for all variables and inserts phi nodes. Uses Cytron et al. dominance-frontier phi placement + dominator-tree rename.
func (*Builder) FuncDef ¶
func (b *Builder) FuncDef(s *ast.FuncDefStmt)
FuncDef processes a function definition statement.
func (*Builder) GenericFor ¶
func (b *Builder) GenericFor(s *ast.GenericForStmt)
GenericFor processes a generic for statement.
func (*Builder) LocalAssign ¶
func (b *Builder) LocalAssign(s *ast.LocalAssignStmt)
LocalAssign processes a local assignment statement.
func (*Builder) NumberFor ¶
func (b *Builder) NumberFor(s *ast.NumberForStmt)
NumberFor processes a numeric for statement.
func (*Builder) ParamDefs ¶
func (b *Builder) ParamDefs(fn *ast.FunctionExpr)
ParamDefs processes function parameters.
func (*Builder) ProcessExprs ¶
ProcessExprs extracts identifier names and collects nested functions in one pass.
func (*Builder) RepeatStmt ¶
func (b *Builder) RepeatStmt(s *ast.RepeatStmt)
RepeatStmt processes a repeat statement.
func (*Builder) ResolvePendingGotos ¶
func (b *Builder) ResolvePendingGotos()
ResolvePendingGotos resolves forward goto references.
func (*Builder) ReturnStmt ¶
func (b *Builder) ReturnStmt(s *ast.ReturnStmt)
ReturnStmt processes a return statement.
func (*Builder) ScopedBlock ¶
ScopedBlock processes a do block.
func (*Builder) StealDeclPoints ¶
StealDeclPoints transfers ownership of the declaration points map. The Builder must not be used after this call.
func (*Builder) StealGlobals ¶
StealGlobals transfers ownership of the globals map from the ScopeTracker.
func (*Builder) StealScopeVisibility ¶
StealScopeVisibility transfers ownership of the visibility map from the ScopeTracker to the caller. The Builder must not be used after this call.
func (*Builder) StealSymbolKinds ¶
func (b *Builder) StealSymbolKinds() map[basecfg.SymbolID]basecfg.SymbolKind
StealSymbolKinds transfers ownership of the symbol kinds map. The Builder must not be used after this call.
func (*Builder) StealSymbolNames ¶
StealSymbolNames transfers ownership of the symbol names map. The Builder must not be used after this call.
func (*Builder) TypeDef ¶
func (b *Builder) TypeDef(s *ast.TypeDefStmt)
TypeDef processes a type definition statement.
type CallInfo ¶
type CallInfo struct {
Callee ast.Expr // Function expression (for non-method calls)
Args []ast.Expr // Call arguments
Method string // "foo" if x:foo()
Receiver ast.Expr // x if x:foo()
IsStmt bool // Statement vs expression
// Pre-extracted for quick checks
CalleeName string // "error", "assert", "setmetatable" etc
CalleeSymbol basecfg.SymbolID // Symbol ID for callee (0 if unresolved or not ident)
ArgNames []string // Pre-extracted: identifier name or "" if not ident
ArgSymbols []basecfg.SymbolID // Symbol IDs for arguments (0 if not ident or unresolved)
ReceiverName string // Pre-extracted: identifier name or "" if not ident
ReceiverSymbol basecfg.SymbolID // Symbol ID for receiver (0 if unresolved)
// Pre-extracted predicate pattern info (for Type:is(x) or TypeName(x))
IsTypeCheck bool // True if this is Type:is(arg) or TypeName(arg) pattern
TypeCheckName string // Type name for type check (receiver name for :is, callee name otherwise)
TypeCheckPath constraint.Path // Binding-based path for type check argument (identity + display)
// Unified callee path for identity resolution.
// For f() -> {Root: "f", Symbol: sym}
// For obj.f() -> {Root: "obj", Symbol: objSym, Segments: [{Field, "f"}]}
// For obj:f() -> receiver path only: {Root: "obj", Symbol: objSym}
// Method name is in CallInfo.Method field, not in CalleePath
// For a.b.c() -> {Root: "a", Symbol: aSym, Segments: [{Field, "b"}, {Field, "c"}]}
// For a.b:c() -> receiver path: {Root: "a", Symbol: aSym, Segments: [{Field, "b"}]}
// Empty if callee cannot be statically resolved to a path.
CalleePath constraint.Path
}
CallInfo captures pre-extracted data for call nodes.
func BuildCallInfo ¶
func BuildCallInfo(call *ast.FuncCallExpr, isStmt bool) *CallInfo
BuildCallInfo creates a CallInfo from a FuncCallExpr, extracting all needed info.
func ExtractSourceCalls ¶
ExtractSourceCalls pre-extracts CallInfo for each source expression that is a call.
type CondCheckKind ¶
type CondCheckKind = basecfg.CondCheckKind
CondCheckKind is an alias for basecfg.CondCheckKind.
type FuncDefInfo ¶
type FuncDefInfo struct {
TargetKind FuncDefTargetKind
Name string // Function name
Symbol basecfg.SymbolID // Symbol ID for function (0 if unresolved)
Receiver ast.Expr // T in T:bar() or T.baz()
ReceiverName string // Receiver identifier name if available
ReceiverSymbol basecfg.SymbolID // Symbol ID for receiver (0 if unresolved)
IsMethod bool // Uses : syntax
FuncExpr *ast.FunctionExpr
// Unified target path for where the function is stored.
// For function foo() -> {Root: "foo", Symbol: sym}
// For local function foo() -> {Root: "foo", Symbol: sym}
// For function M.foo() -> {Root: "M", Symbol: MSym, Segments: [{Field, "foo"}]}
// For function M:foo() -> same as M.foo (method semantics separate via IsMethod)
TargetPath constraint.Path
}
FuncDefInfo captures pre-extracted data for function definition nodes.
func (*FuncDefInfo) Kind ¶
func (*FuncDefInfo) Kind() basecfg.NodeKind
Kind returns the node kind for FuncDefInfo.
type FuncDefTargetKind ¶
type FuncDefTargetKind uint8
FuncDefTargetKind identifies how the function is being assigned.
const ( FuncDefGlobal FuncDefTargetKind = iota // function foo() FuncDefField // function T.foo() FuncDefMethod // function T:foo() )
Function definition target kind constants.
type Graph ¶
type Graph struct {
// contains filtered or unexported fields
}
Graph holds CFG with pre-extracted node info. Immutable after Build().
func Build ¶
func Build(fn *ast.FunctionExpr, globals ...string) *Graph
Build creates an immutable Graph for a function body. If globals is provided, those names are seeded into the binder's root scope with stable SymbolIDs before traversal, enabling global symbol resolution.
func BuildBlock ¶
BuildBlock creates an immutable Graph for a block of statements. If globals is provided, those names are seeded into the binder's root scope with stable SymbolIDs before traversal, enabling global symbol resolution.
func BuildWithBindings ¶
func BuildWithBindings(fn *ast.FunctionExpr, bindings *bind.BindingTable) *Graph
BuildWithBindings creates an immutable Graph using a pre-computed binding table. This allows sharing SymbolIDs across multiple function graphs within a module.
func (*Graph) AllSymbolIDs ¶
AllSymbolIDs returns a set of all symbols known to this graph. Useful when only symbol identity is needed (avoids AllSymbolsAt merges).
func (*Graph) AllSymbolsAt ¶
AllSymbolsAt returns all visible symbols at a CFG point.
func (*Graph) AllVisibleVersions ¶
AllVisibleVersions returns all symbol versions visible at a point. The returned map should not be modified. Implements cfg.SSAVersioned.
func (*Graph) Assign ¶
func (g *Graph) Assign(p Point) *AssignInfo
Assign returns AssignInfo at p, or nil if not an assign node.
func (*Graph) AssignPoints ¶
AssignPoints returns all assignment points.
func (*Graph) Bindings ¶
func (g *Graph) Bindings() *bind.BindingTable
Bindings returns the binding table populated during binder pass.
func (*Graph) Branch ¶
func (g *Graph) Branch(p Point) *BranchInfo
Branch returns BranchInfo at p, or nil if not a branch node.
func (*Graph) CalleePathAt ¶
func (g *Graph) CalleePathAt(p Point) constraint.Path
CalleePathAt returns the callee path for a call at point p. Returns empty path if p is not a call node.
func (*Graph) DeclarationPoint ¶
DeclarationPoint returns the CFG point where a symbol was declared. Returns (0, false) if the symbol is unknown. Implements cfg.SSAVersioned.
func (*Graph) DirectAliasSymbol ¶
DirectAliasSymbol returns the source symbol for a direct local alias assignment. Handles patterns like `local f = B` in the current graph. Returns 0 if the alias is ambiguous or not a direct ident assignment.
func (*Graph) EachAssign ¶
func (g *Graph) EachAssign(fn func(Point, *AssignInfo))
EachAssign calls fn for each assignment node in point order.
func (*Graph) EachBranch ¶
func (g *Graph) EachBranch(fn func(Point, *BranchInfo))
EachBranch calls fn for each branch node in point order.
func (*Graph) EachCallSite ¶
EachCallSite calls fn for each call site in point order.
A call site includes:
- Call statement nodes (foo())
- Call expressions inside assignment sources (local x = foo())
- Call expressions inside return statements (return foo())
Calls embedded in assignment/return sources are yielded in source order.
func (*Graph) EachFuncDef ¶
func (g *Graph) EachFuncDef(fn func(Point, *FuncDefInfo))
EachFuncDef calls fn for each function definition node in point order.
func (*Graph) EachReturn ¶
func (g *Graph) EachReturn(fn func(Point, *ReturnInfo))
EachReturn calls fn for each return node in point order.
func (*Graph) EachTypeDef ¶
func (g *Graph) EachTypeDef(fn func(Point, *TypeDefInfo))
EachTypeDef calls fn for each type definition node in point order.
func (*Graph) Func ¶
func (g *Graph) Func() *ast.FunctionExpr
Func returns the root function expression for this graph, if any.
func (*Graph) FuncDef ¶
func (g *Graph) FuncDef(p Point) *FuncDefInfo
FuncDef returns FuncDefInfo at p, or nil if not a funcdef node.
func (*Graph) FuncDefPathAt ¶
func (g *Graph) FuncDefPathAt(p Point) constraint.Path
FuncDefPathAt returns the target path for a function definition at point p. Returns empty path if p is not a function definition node.
func (*Graph) GlobalSymbol ¶
GlobalSymbol returns the symbol ID for a global name. Returns (0, false) if the name is not a known global.
func (*Graph) HasPhiAt ¶
HasPhiAt returns true if there's a phi node at point p for the given symbol.
func (*Graph) HasScopeTracking ¶
HasScopeTracking returns true if scope visibility was computed during build.
func (*Graph) NameOf ¶
NameOf returns the variable name for a symbol (for display purposes). Returns empty string if the symbol is unknown.
func (*Graph) NestedFunctions ¶
func (g *Graph) NestedFunctions() []NestedFunc
NestedFunctions returns all nested functions found during build.
func (*Graph) ParamDeclPoints ¶
ParamDeclPoints returns a copy of the CFG points where parameters are declared. Returns nil for block graphs or functions with no parameters.
func (*Graph) ParamNames ¶
ParamNames returns a copy of the function parameter names. Returns nil for block graphs or functions with no parameters.
func (*Graph) ParamSymbols ¶
ParamSymbols returns a copy of the function parameter symbol IDs. Returns nil for block graphs or functions with no parameters.
func (*Graph) PopulateSymbols ¶
func (g *Graph) PopulateSymbols(resolve SymbolResolver)
PopulateSymbols fills in basecfg.SymbolID fields for all node infos using the resolver.
func (*Graph) Predecessor ¶
Predecessor returns single predecessor (for non-join nodes).
func (*Graph) Predecessors ¶
Predecessors returns all predecessors of p.
func (*Graph) Return ¶
func (g *Graph) Return(p Point) *ReturnInfo
Return returns ReturnInfo at p, or nil if not a return node.
func (*Graph) Successors ¶
Successors returns all successors of p.
func (*Graph) SymbolAt ¶
SymbolAt returns the basecfg.SymbolID for a variable name at a specific CFG point. This reflects lexical scoping - the same name may resolve to different symbols at different points due to shadowing. Returns (0, false) if the name is not visible at that point. Implements cfg.SSAVersioned.
func (*Graph) SymbolKind ¶
SymbolKind returns the kind of a symbol (Param, Local, or Global). Returns (SymbolUnknown, false) if the symbol is not known.
func (*Graph) TypeDef ¶
func (g *Graph) TypeDef(p Point) *TypeDefInfo
TypeDef returns TypeDefInfo at p, or nil if not a typedef node.
type NestedFunc ¶
type NestedFunc struct {
Point Point
Func *ast.FunctionExpr
Symbol basecfg.SymbolID // Symbol for the function literal (0 if not yet assigned)
}
NestedFunc records a nested function found during CFG build.
type NumericForInfo ¶
NumericForInfo captures numeric for loop details.
type PhiOperand ¶
type PhiOperand = basecfg.PhiOperand
PhiOperand is an alias for basecfg.PhiOperand.
type ReturnInfo ¶
type ReturnInfo struct {
Exprs []ast.Expr
Names []string // Pre-extracted: identifier name or "" if not ident
Symbols []basecfg.SymbolID // Symbol IDs for returned identifiers (0 if not ident or unresolved)
SourceCalls []*CallInfo // Call info for returned call expressions (parallel to Exprs; nil if not a call)
}
ReturnInfo captures pre-extracted data for return nodes.
func (*ReturnInfo) Kind ¶
func (*ReturnInfo) Kind() basecfg.NodeKind
Kind returns the node kind for ReturnInfo.
type ScopeTracker ¶
type ScopeTracker struct {
// contains filtered or unexported fields
}
ScopeTracker tracks symbol visibility during CFG construction. It does NOT create symbols - it only registers symbols created by the binder. Uses copy-on-write: maps are shared until modification.
func NewScopeTracker ¶
func NewScopeTracker() *ScopeTracker
NewScopeTracker creates a new scope tracker.
func (*ScopeTracker) CurrentDepth ¶
func (t *ScopeTracker) CurrentDepth() int
CurrentDepth returns the current scope nesting depth.
func (*ScopeTracker) DeclarationPoint ¶
DeclarationPoint returns the CFG point where a symbol was declared.
func (*ScopeTracker) EnterScope ¶
func (t *ScopeTracker) EnterScope()
EnterScope pushes a new scope frame onto the stack. Uses copy-on-write: shares parent's map until modification.
func (*ScopeTracker) ExitScope ¶
func (t *ScopeTracker) ExitScope()
ExitScope pops the current scope frame from the stack.
func (*ScopeTracker) Lookup ¶
func (t *ScopeTracker) Lookup(name string) (basecfg.SymbolID, bool)
Lookup returns the symbol for a name in the current scope.
func (*ScopeTracker) RegisterGlobal ¶
RegisterGlobal registers a symbol as a global. Uses lazy overlay - globals are stored separately and merged on lookup.
func (*ScopeTracker) RegisterSymbol ¶
func (t *ScopeTracker) RegisterSymbol( sym basecfg.SymbolID, name string, kind basecfg.SymbolKind, declPoint basecfg.Point, )
RegisterSymbol registers an externally-created symbol in the current scope.
func (*ScopeTracker) SnapshotVisibility ¶
func (t *ScopeTracker) SnapshotVisibility(point basecfg.Point)
SnapshotVisibility records the current visibility state at a CFG point. Uses copy-on-write: the next modification will copy the map.
func (*ScopeTracker) SymbolKind ¶
func (t *ScopeTracker) SymbolKind(sym basecfg.SymbolID) (basecfg.SymbolKind, bool)
SymbolKind returns the kind of a symbol.
type SymbolKind ¶
type SymbolKind = basecfg.SymbolKind
SymbolKind is an alias for basecfg.SymbolKind.
type SymbolMap ¶
type SymbolMap struct {
// contains filtered or unexported fields
}
SymbolMap wraps a map for compatibility with existing code.
type SymbolResolver ¶
SymbolResolver resolves variable names to SymbolIDs at CFG points.
type TargetKind ¶
type TargetKind uint8
TargetKind identifies the kind of assignment target.
const ( TargetIdent TargetKind = iota // Simple identifier: x TargetField // Field access: x.y TargetIndex // Index access: x[k] )
Target kind constants.
type TypeDefInfo ¶
type TypeDefInfo struct {
Name string
TypeParams []TypeParamInfo
TypeExpr ast.TypeExpr
}
TypeDefInfo captures pre-extracted data for type definition nodes.
func (*TypeDefInfo) Kind ¶
func (*TypeDefInfo) Kind() basecfg.NodeKind
Kind returns the node kind for TypeDefInfo.
type TypeParamInfo ¶
TypeParamInfo captures a type parameter definition.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package analysis provides pure graph analysis algorithms for CFGs.
|
Package analysis provides pure graph analysis algorithms for CFGs. |
|
Package extraction provides pure AST extraction functions for CFG construction.
|
Package extraction provides pure AST extraction functions for CFG construction. |