Compare commits
1 Commits
main
...
588f4cd521
| Author | SHA1 | Date | |
|---|---|---|---|
|
588f4cd521
|
@@ -5,13 +5,15 @@ type Iterator struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewIterator(expr *Expression) *Iterator {
|
func NewIterator(expr *Expression) *Iterator {
|
||||||
return &Iterator{
|
return &Iterator{[]*Expression{expr}}
|
||||||
trace: []*Expression{expr},
|
}
|
||||||
}
|
|
||||||
|
func (i *Iterator) Done() bool {
|
||||||
|
return len(i.trace) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Iterator) Current() *Expression {
|
func (i *Iterator) Current() *Expression {
|
||||||
if len(i.trace) < 1 {
|
if i.Done() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,6 +28,22 @@ func (i *Iterator) Parent() *Expression {
|
|||||||
return i.trace[len(i.trace)-2]
|
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() {
|
func (i *Iterator) Next() {
|
||||||
switch typed := (*i.Current()).(type) {
|
switch typed := (*i.Current()).(type) {
|
||||||
case *Abstraction:
|
case *Abstraction:
|
||||||
@@ -48,12 +66,3 @@ func (i *Iterator) Next() {
|
|||||||
i.trace = []*Expression{}
|
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
|
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) {
|
func IsViable(e *Expression) (*Abstraction, Expression, bool) {
|
||||||
if e == nil {
|
if e == nil {
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
@@ -42,18 +15,15 @@ func IsViable(e *Expression) (*Abstraction, Expression, bool) {
|
|||||||
func ReduceAll(e *Expression, step func()) {
|
func ReduceAll(e *Expression, step func()) {
|
||||||
it := NewIterator(e)
|
it := NewIterator(e)
|
||||||
|
|
||||||
for it.Current() != nil {
|
for !it.Done() {
|
||||||
current := it.Current()
|
if fn, arg, ok := IsViable(it.Current()); !ok {
|
||||||
|
|
||||||
if fn, arg, ok := IsViable(current); !ok {
|
|
||||||
it.Next()
|
it.Next()
|
||||||
} else {
|
} else {
|
||||||
*current = Substitute(fn.body, fn.parameter, arg)
|
it.Swap(Substitute(fn.body, fn.parameter, arg))
|
||||||
step()
|
step()
|
||||||
|
|
||||||
if _, _, ok := IsViable(it.Parent()); ok {
|
if _, _, ok := IsViable(it.Parent()); ok {
|
||||||
it.Back()
|
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