package convert import ( "git.maximhutz.com/max/lambda/pkg/lambda" "git.maximhutz.com/max/lambda/pkg/saccharine/ast" ) type compileVisitor struct{} func (v compileVisitor) VisitAtom(n *ast.Atom) lambda.Expression { return lambda.NewVariable(n.Name) } func (v compileVisitor) VisitAbstraction(n *ast.Abstraction) lambda.Expression { result := ast.Visit(v, 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 (v compileVisitor) VisitApplication(n *ast.Application) lambda.Expression { result := ast.Visit(v, n.Abstraction) arguments := []lambda.Expression{} for _, argument := range n.Arguments { convertedArgument := ast.Visit(v, argument) arguments = append(arguments, convertedArgument) } for _, argument := range arguments { result = lambda.NewApplication(result, argument) } return result } func SaccharineToLambda(n ast.Expression) lambda.Expression { return ast.Visit(&compileVisitor{}, n) }