## 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).
Reviewed-on: #15
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
## Description
This PR refactors the Makefile to improve usability, maintainability, and cross-platform compatibility.
The changes modernize the Makefile structure and make it more user-friendly.
Changes made:
- Renamed the `it` target to `build` for better clarity and conventional naming.
- Added a `help` target as the default goal to display available targets and their descriptions.
- Moved the TEST variable to the top with other configuration variables for better organization.
- Updated binary name from `lambda.exe` to `lambda` and used `${BINARY_NAME}` variable consistently throughout.
- Replaced all `@` prefixes with the `.SILENT:` directive for cleaner syntax.
- Added a `clean` target to remove all build artifacts (binary, program.out, profile directory).
- Made the `graph` target cross-platform by replacing macOS-specific `open` command with file:// URL echo.
- Updated .gitignore to include the `lambda` binary.
### Decisions
- Used `.SILENT:` directive instead of individual `@` prefixes for a cleaner, more maintainable Makefile.
- Made `help` the default target so users can run `make` without arguments to see available commands.
- Removed platform-specific commands (like `open`) in favor of cross-platform alternatives.
## Benefits
- Improved discoverability: Users can run `make` to see all available targets.
- Better maintainability: Using `${BINARY_NAME}` variable consistently makes future changes easier.
- Cross-platform compatibility: Removed macOS-specific commands.
- Cleaner syntax: `.SILENT:` directive eliminates repetitive `@` prefixes.
- More conventional: Renamed `it` to `build` follows standard Makefile conventions.
## Checklist
- [x] Code follows conventional commit format.
- [x] Branch follows naming convention (\`<type>/<description>\`). Always use underscores.
- [x] Tests pass (if applicable).
- [x] Documentation updated (if applicable).
Reviewed-on: #11
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>