fix: parameters converted in opposite order

This commit is contained in:
2025-12-27 01:41:00 -05:00
parent 5841023dde
commit df53409887
4 changed files with 71 additions and 14 deletions

View File

@@ -5,4 +5,4 @@ it:
@ chmod +x ${BINARY_NAME}
ex: it
@ ./lambda.exe -v - < ./samples/simple.txt
@ ./lambda.exe - < ./samples/simple.txt

View File

@@ -7,6 +7,8 @@ import (
"git.maximhutz.com/max/lambda/internal/cli"
"git.maximhutz.com/max/lambda/internal/config"
"git.maximhutz.com/max/lambda/pkg/convert"
"git.maximhutz.com/max/lambda/pkg/lambda"
"git.maximhutz.com/max/lambda/pkg/saccharine"
)
@@ -16,8 +18,8 @@ func main() {
cli.HandleError(err)
logger := options.GetLogger()
logger.Info("Using program arguments.", "args", os.Args)
logger.Info("Parsed CLI options.", "options", options)
logger.Info("using program arguments", "args", os.Args)
logger.Info("parsed CLI options", "options", options)
input, err := options.Source.Pull()
cli.HandleError(err)
@@ -25,29 +27,32 @@ func main() {
// Parse tokens.
tokens, err := saccharine.GetTokens([]rune(input))
cli.HandleError(err)
logger.Info("Parsed tokens.", "tokens", tokens)
logger.Info("parsed tokens", "tokens", tokens)
// Turn tokens into syntax tree.
expression, err := saccharine.Parse(tokens)
cli.HandleError(err)
logger.Info("Parsed syntax tree.", "tree", expression)
logger.Info("parsed syntax tree", "tree", saccharine.Stringify(expression))
compiled := convert.SaccharineToLambda(expression)
logger.Info("compiled lambda expression", "tree", lambda.Stringify(compiled))
// Reduce expression.
start := time.Now()
if options.Explanation {
fmt.Println(saccharine.Stringify(expression))
fmt.Println(lambda.Stringify(compiled))
}
// for lambda.ReduceOnce(&expression) {
// logger.Info("Reduction.", "tree", saccharine.Stringify(expression))
// if options.Explanation {
// fmt.Println(" =", saccharine.Stringify(expression))
// }
// }
for lambda.ReduceOnce(&compiled) {
logger.Info("reduction", "tree", lambda.Stringify(compiled))
if options.Explanation {
fmt.Println(" =", lambda.Stringify(compiled))
}
}
elapsed := time.Since(start).Milliseconds()
fmt.Println(saccharine.Stringify(expression))
fmt.Println(lambda.Stringify(compiled))
fmt.Fprintln(os.Stderr, "Time Spent:", elapsed, "ms")
}

View File

@@ -0,0 +1,52 @@
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)
}

View File

@@ -3,7 +3,7 @@
(\add.
(\mult.
(\exp.
(exp (inc (inc (inc (inc (inc 0))))) (inc (inc (inc (inc (inc 0))))))
(exp (inc (inc (inc (inc 0)))) (inc (inc (inc (inc (inc 0))))))
\n m.(m n)
)
\m n f.(m (n f))