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
45 lines
1.5 KiB
Go
45 lines
1.5 KiB
Go
package convert
|
|
|
|
import (
|
|
"git.maximhutz.com/max/lambda/pkg/debruijn"
|
|
"git.maximhutz.com/max/lambda/pkg/lambda"
|
|
)
|
|
|
|
// LambdaToDeBruijn converts a lambda calculus expression to De Bruijn indexed form.
|
|
// The context parameter tracks bound variables from outer abstractions.
|
|
func LambdaToDeBruijn(expr lambda.Expression) debruijn.Expression {
|
|
return lambdaToDeBruijnWithContext(expr, []string{})
|
|
}
|
|
|
|
func lambdaToDeBruijnWithContext(expr lambda.Expression, context []string) debruijn.Expression {
|
|
switch e := expr.(type) {
|
|
case *lambda.Variable:
|
|
name := e.Value()
|
|
// Search for the variable in the context (innermost to outermost).
|
|
for i := len(context) - 1; i >= 0; i-- {
|
|
if context[i] == name {
|
|
index := len(context) - 1 - i
|
|
return debruijn.NewVariable(index, name)
|
|
}
|
|
}
|
|
// Free variable: use a negative index to mark it.
|
|
// We encode free variables with index = len(context) + position.
|
|
// For simplicity, we use a large index that won't conflict.
|
|
return debruijn.NewVariable(len(context), name)
|
|
|
|
case *lambda.Abstraction:
|
|
// Add the parameter to the context.
|
|
newContext := append(context, e.Parameter())
|
|
body := lambdaToDeBruijnWithContext(e.Body(), newContext)
|
|
return debruijn.NewAbstraction(body)
|
|
|
|
case *lambda.Application:
|
|
abs := lambdaToDeBruijnWithContext(e.Abstraction(), context)
|
|
arg := lambdaToDeBruijnWithContext(e.Argument(), context)
|
|
return debruijn.NewApplication(abs, arg)
|
|
|
|
default:
|
|
panic("unknown expression type")
|
|
}
|
|
}
|