// Package debruijn provides De Bruijn indexed lambda calculus expressions. // De Bruijn indices eliminate the need for variable names by using numeric // indices to refer to bound variables, avoiding capture issues during substitution. package debruijn import "git.maximhutz.com/max/lambda/pkg/expr" // Expression is the interface for all De Bruijn indexed expression types. // It embeds the general expr.Expression interface for cross-mode compatibility. type Expression interface { expr.Expression Accept(Visitor) } /** ------------------------------------------------------------------------- */ // Abstraction represents a lambda abstraction without a named parameter. // In De Bruijn notation, the parameter is implicit and referenced by index 0 // within the body. type Abstraction struct { body Expression } // Body returns the body of the abstraction. func (a *Abstraction) Body() Expression { return a.body } // Accept implements the Visitor pattern. func (a *Abstraction) Accept(v Visitor) { v.VisitAbstraction(a) } // String returns the De Bruijn notation string representation. func (a *Abstraction) String() string { return Stringify(a) } // NewAbstraction creates a new De Bruijn abstraction with the given body. func NewAbstraction(body Expression) *Abstraction { return &Abstraction{body: body} } /** ------------------------------------------------------------------------- */ // Application represents the application of one expression to another. type Application struct { abstraction Expression argument Expression } // Abstraction returns the function expression being applied. func (a *Application) Abstraction() Expression { return a.abstraction } // Argument returns the argument expression. func (a *Application) Argument() Expression { return a.argument } // Accept implements the Visitor pattern. func (a *Application) Accept(v Visitor) { v.VisitApplication(a) } // String returns the De Bruijn notation string representation. func (a *Application) String() string { return Stringify(a) } // NewApplication creates a new application expression. func NewApplication(abstraction Expression, argument Expression) *Application { return &Application{abstraction: abstraction, argument: argument} } /** ------------------------------------------------------------------------- */ // Variable represents a De Bruijn indexed variable. // The index indicates how many binders to skip to find the binding abstraction. // The label is an optional hint for display purposes. type Variable struct { index int label string } // Index returns the De Bruijn index. func (v *Variable) Index() int { return v.index } // Label returns the optional variable label. func (v *Variable) Label() string { return v.label } // Accept implements the Visitor pattern. func (v *Variable) Accept(visitor Visitor) { visitor.VisitVariable(v) } // String returns the De Bruijn notation string representation. func (v *Variable) String() string { return Stringify(v) } // NewVariable creates a new De Bruijn variable with the given index and label. func NewVariable(index int, label string) *Variable { return &Variable{index: index, label: label} } /** ------------------------------------------------------------------------- */ // Visitor interface for traversing De Bruijn expressions. type Visitor interface { VisitAbstraction(*Abstraction) VisitApplication(*Application) VisitVariable(*Variable) }