Compare commits
1 Commits
feat/debru
...
588f4cd521
| Author | SHA1 | Date | |
|---|---|---|---|
|
588f4cd521
|
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user