From 633d4a4d3bc84d824de8cdb303baf5313bdf52b6 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 28 Dec 2025 02:19:48 -0500 Subject: [PATCH] fix: no stringify in hot loop --- Makefile | 3 +++ cmd/lambda/lambda.go | 12 +++++++++--- pkg/lambda/substitute.go | 14 ++++++-------- samples/church.txt | 7 +++++++ 4 files changed, 25 insertions(+), 11 deletions(-) create mode 100644 samples/church.txt diff --git a/Makefile b/Makefile index d7db258..895db60 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,9 @@ thunk: it saccharine: it @ ./lambda.exe - < ./samples/saccharine.txt +church: it + @ ./lambda.exe - < ./samples/church.txt + prof: @ go tool pprof -top profile/cpu.prof diff --git a/cmd/lambda/lambda.go b/cmd/lambda/lambda.go index b593434..be7ced2 100644 --- a/cmd/lambda/lambda.go +++ b/cmd/lambda/lambda.go @@ -41,10 +41,14 @@ func main() { // Turn tokens into syntax tree. expression, err := saccharine.Parse(tokens) cli.HandleError(err) - logger.Info("parsed syntax tree", "tree", saccharine.Stringify(expression)) + if options.Verbose { + logger.Info("parsed syntax tree", "tree", saccharine.Stringify(expression)) + } compiled := convert.SaccharineToLambda(expression) - logger.Info("compiled lambda expression", "tree", lambda.Stringify(compiled)) + if options.Verbose { + logger.Info("compiled lambda expression", "tree", lambda.Stringify(compiled)) + } // Reduce expression. start := time.Now() @@ -56,7 +60,9 @@ func main() { steps := 0 for lambda.ReduceOnce(&compiled) { - logger.Info("reduction", "tree", lambda.Stringify(compiled)) + if options.Verbose { + logger.Info("reduction", "tree", lambda.Stringify(compiled)) + } if options.Explanation { fmt.Println(" =", lambda.Stringify(compiled)) } diff --git a/pkg/lambda/substitute.go b/pkg/lambda/substitute.go index 96d4ec2..8798165 100644 --- a/pkg/lambda/substitute.go +++ b/pkg/lambda/substitute.go @@ -11,16 +11,14 @@ func Substitute(e *Expression, target string, replacement Expression) { return } - if !IsFreeVariable(typed.Parameter, replacement) { - Substitute(&typed.Body, target, replacement) - return + if IsFreeVariable(typed.Parameter, replacement) { + replacementFreeVars := GetFreeVariables(replacement) + used := GetFreeVariables(typed.Body) + used.Merge(replacementFreeVars) + freshVar := GenerateFreshName(used) + Rename(typed, typed.Parameter, freshVar) } - replacementFreeVars := GetFreeVariables(replacement) - used := GetFreeVariables(typed.Body) - used.Merge(replacementFreeVars) - freshVar := GenerateFreshName(used) - Rename(typed, typed.Parameter, freshVar) Substitute(&typed.Body, target, replacement) case *Application: Substitute(&typed.Abstraction, target, replacement) diff --git a/samples/church.txt b/samples/church.txt new file mode 100644 index 0000000..571d394 --- /dev/null +++ b/samples/church.txt @@ -0,0 +1,7 @@ +0 := \f.\x.x +inc n := \f x.(f (n f x)) +exp n m := (m n) + +N := (inc (inc (inc (inc (inc 0))))) + +(exp N N)