feat: use iterative approach for reduce once
This commit is contained in:
35
pkg/fifo/fifo.go
Normal file
35
pkg/fifo/fifo.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
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,22 +1,27 @@
|
|||||||
package lambda
|
package lambda
|
||||||
|
|
||||||
|
import "git.maximhutz.com/max/lambda/pkg/fifo"
|
||||||
|
|
||||||
func ReduceOnce(e *Expression) bool {
|
func ReduceOnce(e *Expression) bool {
|
||||||
switch typed := (*e).(type) {
|
stack := fifo.New(e)
|
||||||
|
|
||||||
|
for !stack.Empty() {
|
||||||
|
top := stack.MustPop()
|
||||||
|
|
||||||
|
switch typed := (*top).(type) {
|
||||||
case *Abstraction:
|
case *Abstraction:
|
||||||
return ReduceOnce(&typed.Body)
|
stack.Push(&typed.Body)
|
||||||
case *Application:
|
case *Application:
|
||||||
if fn, fnOk := typed.Abstraction.(*Abstraction); fnOk {
|
if fn, fnOk := typed.Abstraction.(*Abstraction); fnOk {
|
||||||
Substitute(&fn.Body, fn.Parameter, typed.Argument)
|
Substitute(&fn.Body, fn.Parameter, typed.Argument)
|
||||||
*e = fn.Body
|
*top = fn.Body
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if ReduceOnce(&typed.Abstraction) {
|
stack.Push(&typed.Argument)
|
||||||
return true
|
stack.Push(&typed.Abstraction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReduceOnce(&typed.Argument)
|
|
||||||
default:
|
|
||||||
return false
|
return false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,5 +12,5 @@
|
|||||||
)
|
)
|
||||||
\n f x.(f (n f x))
|
\n f x.(f (n f x))
|
||||||
)
|
)
|
||||||
\f x.((((((x))))))
|
\f x.x
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user