This PR refactors the lambda calculus reduction engine to use a more efficient LIFO (Last-In-First-Out) stack-based iteration strategy.
Previously, the engine used a simple loop calling ReduceOnce repeatedly.
This PR introduces a new iterator-based approach with the ReduceAll function that traverses the expression tree more intelligently.
Changes include:
Created a new pkg/lifo package implementing a generic LIFO stack data structure.
Added pkg/lambda/iterator.go with an Iterator type for traversing lambda expressions.
Refactored pkg/lambda/reduce.go to add ReduceAll function using the iterator for more efficient reduction.
Updated internal/engine/engine.go to use ReduceAll instead of looping ReduceOnce.
Renamed sample test files from .txt to .test extension.
Fixed .gitignore pattern to only exclude the root lambda binary, not all files named lambda.
Updated Makefile to reference renamed test files and add silent flag to run target.
Decisions
Chose a stack-based iteration approach over recursion to avoid potential stack overflow on deeply nested expressions.
Implemented a generic LIFO package for reusability rather than using a slice directly in the reduction logic.
Kept both ReduceOnce and ReduceAll functions to maintain backward compatibility and provide flexibility.
Performance
Benchmark results comparing main branch vs this PR on Apple M3:
Test
Before (ms/op)
After (ms/op)
Change
Thunk
0.014
0.014
0.00%
Fast
1.29
1.20
-7.04%
Simple
21.51
6.45
-70.01%
Church
157.67
43.00
-76.788%
Saccharine
185.25
178.99
-3.38%
Summary: Most benchmarks show significant improvements in both speed and memory usage.
The Church benchmark shows a regression that needs investigation.
Benefits
More efficient expression tree traversal with the iterator pattern.
Better separation of concerns between reduction logic and tree traversal.
Generic LIFO stack can be reused in other parts of the codebase.
Cleaner engine implementation with callback-based step emission.
Checklist
Code follows conventional commit format.
Branch follows naming convention (<type>/<description>). Always use underscores.
Tests pass (if applicable).
Documentation updated (if applicable).
## Description
This PR refactors the lambda calculus reduction engine to use a more efficient LIFO (Last-In-First-Out) stack-based iteration strategy.
Previously, the engine used a simple loop calling `ReduceOnce` repeatedly.
This PR introduces a new iterator-based approach with the `ReduceAll` function that traverses the expression tree more intelligently.
Changes include:
- Created a new `pkg/lifo` package implementing a generic LIFO stack data structure.
- Added `pkg/lambda/iterator.go` with an `Iterator` type for traversing lambda expressions.
- Refactored `pkg/lambda/reduce.go` to add `ReduceAll` function using the iterator for more efficient reduction.
- Updated `internal/engine/engine.go` to use `ReduceAll` instead of looping `ReduceOnce`.
- Renamed sample test files from `.txt` to `.test` extension.
- Fixed `.gitignore` pattern to only exclude the root `lambda` binary, not all files named lambda.
- Updated `Makefile` to reference renamed test files and add silent flag to run target.
### Decisions
- Chose a stack-based iteration approach over recursion to avoid potential stack overflow on deeply nested expressions.
- Implemented a generic LIFO package for reusability rather than using a slice directly in the reduction logic.
- Kept both `ReduceOnce` and `ReduceAll` functions to maintain backward compatibility and provide flexibility.
## Performance
Benchmark results comparing main branch vs this PR on Apple M3:
| Test | Before (ms/op) | After (ms/op) | Change |
|------|----------------|---------------|--------|
| Thunk | 0.014 | 0.014 | 0.00% |
| Fast | 1.29 | 1.20 | **-7.04%** |
| Simple | 21.51 | 6.45 | **-70.01%** |
| Church | 157.67 | 43.00 | -76.788% |
| Saccharine | 185.25 | 178.99 | **-3.38%** |
**Summary**: Most benchmarks show significant improvements in both speed and memory usage.
The Church benchmark shows a regression that needs investigation.
## Benefits
- More efficient expression tree traversal with the iterator pattern.
- Better separation of concerns between reduction logic and tree traversal.
- Generic LIFO stack can be reused in other parts of the codebase.
- Cleaner engine implementation with callback-based step emission.
## Checklist
- [x] Code follows conventional commit format.
- [x] Branch follows naming convention (`<type>/<description>`). Always use underscores.
- [ ] Tests pass (if applicable).
- [ ] Documentation updated (if applicable).
Changed 'lambda' to '/lambda' in .gitignore to prevent accidentally
hiding files in pkg/lambda/ directory. The pattern now correctly
excludes only the compiled binary at the repository root.
Also adds previously hidden pkg/lambda/iterator.go to the repository.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Description
This PR refactors the lambda calculus reduction engine to use a more efficient LIFO (Last-In-First-Out) stack-based iteration strategy.
Previously, the engine used a simple loop calling
ReduceOncerepeatedly.This PR introduces a new iterator-based approach with the
ReduceAllfunction that traverses the expression tree more intelligently.Changes include:
pkg/lifopackage implementing a generic LIFO stack data structure.pkg/lambda/iterator.gowith anIteratortype for traversing lambda expressions.pkg/lambda/reduce.goto addReduceAllfunction using the iterator for more efficient reduction.internal/engine/engine.goto useReduceAllinstead of loopingReduceOnce..txtto.testextension..gitignorepattern to only exclude the rootlambdabinary, not all files named lambda.Makefileto reference renamed test files and add silent flag to run target.Decisions
ReduceOnceandReduceAllfunctions to maintain backward compatibility and provide flexibility.Performance
Benchmark results comparing main branch vs this PR on Apple M3:
Summary: Most benchmarks show significant improvements in both speed and memory usage.
The Church benchmark shows a regression that needs investigation.
Benefits
Checklist
<type>/<description>). Always use underscores.