Update call sites to match the new Reducer interface where the expression is passed to the constructor and Reduce() takes no arguments.
50 lines
1.2 KiB
Go
50 lines
1.2 KiB
Go
package lambda
|
|
|
|
import (
|
|
"git.maximhutz.com/max/lambda/pkg/emitter"
|
|
"git.maximhutz.com/max/lambda/pkg/expr"
|
|
"git.maximhutz.com/max/lambda/pkg/reducer"
|
|
)
|
|
|
|
// NormalOrderReducer implements normal order (leftmost-outermost) reduction
|
|
// for lambda calculus expressions.
|
|
type NormalOrderReducer struct {
|
|
emitter.BaseEmitter[reducer.Event]
|
|
expression Expression
|
|
}
|
|
|
|
// NewNormalOrderReducer creates a new normal order reducer.
|
|
func NewNormalOrderReducer(expression Expression) *NormalOrderReducer {
|
|
return &NormalOrderReducer{
|
|
BaseEmitter: *emitter.New[reducer.Event](),
|
|
expression: expression,
|
|
}
|
|
}
|
|
|
|
// Expression returns the current expression state.
|
|
func (r *NormalOrderReducer) Expression() expr.Expression {
|
|
return r.expression
|
|
}
|
|
|
|
// Reduce performs normal order reduction on a lambda expression.
|
|
// The expression must be a lambda.Expression; other types are returned unchanged.
|
|
func (r *NormalOrderReducer) Reduce() {
|
|
r.Emit(reducer.StartEvent)
|
|
it := NewIterator(&r.expression)
|
|
|
|
for !it.Done() {
|
|
if fn, arg, ok := IsViable(it.Current()); !ok {
|
|
it.Next()
|
|
} else {
|
|
it.Swap(Substitute(fn.body, fn.parameter, arg))
|
|
r.Emit(reducer.StepEvent)
|
|
|
|
if _, _, ok := IsViable(it.Parent()); ok {
|
|
it.Back()
|
|
}
|
|
}
|
|
}
|
|
|
|
r.Emit(reducer.StopEvent)
|
|
}
|