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") } }