refactor: extract Reducer interface and update engine to use abstractions

Introduce reducer.Reducer interface and update the engine to use abstract
expr.Expression and reducer.Reducer types, enabling pluggable reduction
strategies.

- Add pkg/reducer/reducer.go with Reducer interface.
- Add pkg/lambda/reducer.go with NormalOrderReducer implementation.
- Update engine to accept expr.Expression and reducer.Reducer.
- Update plugins to use expr.Expression directly (no pointer dereference).
- Update main and tests to pass reducer to engine.

Closes #30
This commit is contained in:
2026-01-16 18:40:17 -05:00
parent e0114c736d
commit a61809ad1d
7 changed files with 71 additions and 16 deletions

View File

@@ -5,30 +5,34 @@ package engine
import (
"git.maximhutz.com/max/lambda/internal/config"
"git.maximhutz.com/max/lambda/pkg/emitter"
"git.maximhutz.com/max/lambda/pkg/lambda"
"git.maximhutz.com/max/lambda/pkg/expr"
"git.maximhutz.com/max/lambda/pkg/reducer"
)
// A process for reducing one expression.
// Engine is a process for reducing one expression.
type Engine struct {
Config *config.Config
Expression *lambda.Expression
Expression expr.Expression
Reducer reducer.Reducer
emitter.BaseEmitter[Event]
}
// Create a new engine, given an unreduced λ-expression.
func New(config *config.Config, expression *lambda.Expression) *Engine {
// New creates a new engine with the given expression and reducer.
func New(config *config.Config, expression expr.Expression, reducer reducer.Reducer) *Engine {
return &Engine{
Config: config,
Expression: expression,
Reducer: reducer,
BaseEmitter: *emitter.New[Event](),
}
}
// Begin the reduction process.
// Run begins the reduction process.
func (e *Engine) Run() {
e.Emit(StartEvent)
lambda.ReduceAll(e.Expression, func() {
e.Expression = e.Reducer.Reduce(e.Expression, func(reduced expr.Expression) {
e.Expression = reduced
e.Emit(StepEvent)
})