Add a new interpreter option (-i debruijn) that uses De Bruijn indices for variable representation, eliminating the need for variable renaming during substitution. - Add -i flag to select interpreter (lambda or debruijn) - Create debruijn package with Expression types (Variable with index, Abstraction without parameter, Application) - Implement shift and substitute operations for De Bruijn indices - Add conversion functions between lambda and De Bruijn representations - Update CLI to support switching between interpreters - Add De Bruijn tests to verify all samples pass Closes #26
120 lines
3.4 KiB
Go
120 lines
3.4 KiB
Go
// 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)
|
|
}
|