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
|
||||
|
||||
import "git.maximhutz.com/max/lambda/pkg/fifo"
|
||||
|
||||
func ReduceOnce(e *Expression) bool {
|
||||
switch typed := (*e).(type) {
|
||||
case *Abstraction:
|
||||
return ReduceOnce(&typed.Body)
|
||||
case *Application:
|
||||
if fn, fnOk := typed.Abstraction.(*Abstraction); fnOk {
|
||||
Substitute(&fn.Body, fn.Parameter, typed.Argument)
|
||||
*e = fn.Body
|
||||
return true
|
||||
}
|
||||
stack := fifo.New(e)
|
||||
|
||||
if ReduceOnce(&typed.Abstraction) {
|
||||
return true
|
||||
}
|
||||
for !stack.Empty() {
|
||||
top := stack.MustPop()
|
||||
|
||||
return ReduceOnce(&typed.Argument)
|
||||
default:
|
||||
return false
|
||||
switch typed := (*top).(type) {
|
||||
case *Abstraction:
|
||||
stack.Push(&typed.Body)
|
||||
case *Application:
|
||||
if fn, fnOk := typed.Abstraction.(*Abstraction); fnOk {
|
||||
Substitute(&fn.Body, fn.Parameter, typed.Argument)
|
||||
*top = fn.Body
|
||||
return true
|
||||
}
|
||||
|
||||
stack.Push(&typed.Argument)
|
||||
stack.Push(&typed.Abstraction)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user