Closes #26 - Added -i flag to select interpreter (lambda or debruijn) - Created debruijn package with Expression interface - Variable contains index and optional label - Abstraction contains only body (no parameter) - Application structure remains similar - Implemented De Bruijn reduction without variable renaming - Shift operation handles index adjustments - Substitute replaces by index instead of name - Abstracted Engine into interface with two implementations - LambdaEngine: original named variable engine - DeBruijnEngine: new index-based engine - Added conversion functions between representations - LambdaToDeBruijn: converts named to indexed - DeBruijnToLambda: converts indexed back to named - SaccharineToDeBruijn: direct saccharine to De Bruijn - Updated main to switch engines based on -i flag - All test samples pass with both engines Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
44 lines
1.2 KiB
Go
44 lines
1.2 KiB
Go
package convert
|
|
|
|
import (
|
|
"git.maximhutz.com/max/lambda/pkg/debruijn"
|
|
"git.maximhutz.com/max/lambda/pkg/lambda"
|
|
)
|
|
|
|
// LambdaToDeBruijn converts a lambda expression to De Bruijn index representation.
|
|
func LambdaToDeBruijn(expr lambda.Expression) debruijn.Expression {
|
|
return lambdaToDeBruijn(expr, []string{})
|
|
}
|
|
|
|
func lambdaToDeBruijn(expr lambda.Expression, context []string) debruijn.Expression {
|
|
switch e := expr.(type) {
|
|
case *lambda.Variable:
|
|
index := findIndex(e.Value(), context)
|
|
return debruijn.NewVariable(index, e.Value())
|
|
|
|
case *lambda.Abstraction:
|
|
newContext := append([]string{e.Parameter()}, context...)
|
|
body := lambdaToDeBruijn(e.Body(), newContext)
|
|
return debruijn.NewAbstraction(body)
|
|
|
|
case *lambda.Application:
|
|
abs := lambdaToDeBruijn(e.Abstraction(), context)
|
|
arg := lambdaToDeBruijn(e.Argument(), context)
|
|
return debruijn.NewApplication(abs, arg)
|
|
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// findIndex returns the De Bruijn index for a variable name in the context.
|
|
// Returns the index if found, or -1 if the variable is free.
|
|
func findIndex(name string, context []string) int {
|
|
for i, v := range context {
|
|
if v == name {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|