package convert import ( "fmt" "git.maximhutz.com/max/lambda/pkg/lambda" "git.maximhutz.com/max/lambda/pkg/saccharine/ast" ) func convertAtom(n *ast.Atom) lambda.Expression { return lambda.NewVariable(n.Name) } func convertAbstraction(n *ast.Abstraction) lambda.Expression { result := SaccharineToLambda(n.Body) parameters := n.Parameters // If the function has no parameters, it is a thunk. Lambda calculus still // requires _some_ parameter exists, so generate one. if len(parameters) == 0 { freeVars := lambda.GetFreeVariables(result) freshName := lambda.GenerateFreshName(freeVars) parameters = append(parameters, freshName) } for i := len(parameters) - 1; i >= 0; i-- { result = lambda.NewAbstraction(parameters[i], result) } return result } func convertApplication(n *ast.Application) lambda.Expression { result := SaccharineToLambda(n.Abstraction) arguments := []lambda.Expression{} for _, argument := range n.Arguments { convertedArgument := SaccharineToLambda(argument) arguments = append(arguments, convertedArgument) } for _, argument := range arguments { result = lambda.NewApplication(result, argument) } return result } func SaccharineToLambda(n ast.Expression) lambda.Expression { switch n := n.(type) { case *ast.Atom: return convertAtom(n) case *ast.Abstraction: return convertAbstraction(n) case *ast.Application: return convertApplication(n) default: panic(fmt.Errorf("unknown expression type: %T", n)) } }