feat: progress

This commit is contained in:
2026-01-11 20:18:38 -05:00
parent 609fe05250
commit d4f33c1658
7 changed files with 11594 additions and 43 deletions

View File

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

View File

@@ -1,9 +1,11 @@
package lambda
import "git.maximhutz.com/max/lambda/pkg/fifo"
import (
"git.maximhutz.com/max/lambda/pkg/lifo"
)
func ReduceOnce(e *Expression) bool {
stack := fifo.New(e)
stack := lifo.New(e)
for !stack.Empty() {
top := stack.MustPop()
@@ -13,8 +15,7 @@ func ReduceOnce(e *Expression) bool {
stack.Push(&typed.body)
case *Application:
if fn, fnOk := typed.abstraction.(*Abstraction); fnOk {
reduced := Substitute(fn.body, fn.parameter, typed.argument)
*top = reduced
*top = Substitute(fn.body, fn.parameter, typed.argument)
return true
}
@@ -25,3 +26,35 @@ func ReduceOnce(e *Expression) bool {
return false
}
func IsViable(e *Expression) (*Abstraction, Expression, bool) {
if e == nil {
return nil, nil, false
} else if app, appOk := (*e).(*Application); !appOk {
return nil, nil, false
} else if fn, fnOk := app.abstraction.(*Abstraction); !fnOk {
return nil, nil, false
} else {
return fn, app.argument, true
}
}
func ReduceAll(e *Expression, step func()) {
it := NewIterator(e)
for it.Current() != nil {
current := it.Current()
if fn, arg, ok := IsViable(current); !ok {
it.Next()
} else {
*current = Substitute(fn.body, fn.parameter, arg)
step()
if _, _, ok := IsViable(it.Parent()); ok {
it.Back()
} else {
}
}
}
}

35
pkg/lifo/lifo.go Normal file
View File

@@ -0,0 +1,35 @@
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
}