feat: progress
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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
35
pkg/lifo/lifo.go
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user