feat: added swap to iterator

This commit is contained in:
2026-01-12 19:39:48 -05:00
parent 15c904ccc9
commit 588f4cd521
3 changed files with 25 additions and 81 deletions

View File

@@ -5,13 +5,15 @@ type Iterator struct {
}
func NewIterator(expr *Expression) *Iterator {
return &Iterator{
trace: []*Expression{expr},
return &Iterator{[]*Expression{expr}}
}
func (i *Iterator) Done() bool {
return len(i.trace) == 0
}
func (i *Iterator) Current() *Expression {
if len(i.trace) < 1 {
if i.Done() {
return nil
}
@@ -26,6 +28,22 @@ func (i *Iterator) Parent() *Expression {
return i.trace[len(i.trace)-2]
}
func (i *Iterator) Swap(with Expression) {
current := i.Current()
if current != nil {
*current = with
}
}
func (i *Iterator) Back() bool {
if i.Done() {
return false
}
i.trace = i.trace[:len(i.trace)-1]
return true
}
func (i *Iterator) Next() {
switch typed := (*i.Current()).(type) {
case *Abstraction:
@@ -48,12 +66,3 @@ func (i *Iterator) Next() {
i.trace = []*Expression{}
}
}
func (i *Iterator) Back() bool {
if len(i.trace) == 0 {
return false
}
i.trace = i.trace[:len(i.trace)-1]
return true
}

View File

@@ -1,32 +1,5 @@
package lambda
import (
"git.maximhutz.com/max/lambda/pkg/lifo"
)
func ReduceOnce(e *Expression) bool {
stack := lifo.New(e)
for !stack.Empty() {
top := stack.MustPop()
switch typed := (*top).(type) {
case *Abstraction:
stack.Push(&typed.body)
case *Application:
if fn, fnOk := typed.abstraction.(*Abstraction); fnOk {
*top = Substitute(fn.body, fn.parameter, typed.argument)
return true
}
stack.Push(&typed.argument)
stack.Push(&typed.abstraction)
}
}
return false
}
func IsViable(e *Expression) (*Abstraction, Expression, bool) {
if e == nil {
return nil, nil, false
@@ -42,18 +15,15 @@ func IsViable(e *Expression) (*Abstraction, Expression, bool) {
func ReduceAll(e *Expression, step func()) {
it := NewIterator(e)
for it.Current() != nil {
current := it.Current()
if fn, arg, ok := IsViable(current); !ok {
for !it.Done() {
if fn, arg, ok := IsViable(it.Current()); !ok {
it.Next()
} else {
*current = Substitute(fn.body, fn.parameter, arg)
it.Swap(Substitute(fn.body, fn.parameter, arg))
step()
if _, _, ok := IsViable(it.Parent()); ok {
it.Back()
} else {
}
}
}

View File

@@ -1,35 +0,0 @@
package lifo
import "fmt"
type LIFO[T any] []T
func New[T any](items ...T) *LIFO[T] {
l := LIFO[T](items)
return &l
}
func (l *LIFO[T]) Push(item T) {
*l = append(*l, item)
}
func (l *LIFO[T]) Empty() bool {
return len(*l) == 0
}
func (l *LIFO[T]) MustPop() T {
var item T
*l, item = (*l)[:len(*l)-1], (*l)[len(*l)-1]
return item
}
func (l *LIFO[T]) Pop() (T, error) {
var item T
if l.Empty() {
return item, fmt.Errorf("stack is exhausted")
}
return l.MustPop(), nil
}