Files
lambda/pkg/convert/lambda_to_debruijn.go
M.V. Hutz f3b9137d75 feat: add De Bruijn index reduction engine
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>
2026-01-12 21:27:40 -05:00

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
}