diff --git a/.gitignore b/.gitignore index 0b209db..9d1f418 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore # # Binaries for programs and plugins -lambda +/lambda *.exe *.exe~ *.dll diff --git a/pkg/lambda/iterator.go b/pkg/lambda/iterator.go new file mode 100644 index 0000000..76b711a --- /dev/null +++ b/pkg/lambda/iterator.go @@ -0,0 +1,59 @@ +package lambda + +type Iterator struct { + trace []*Expression +} + +func NewIterator(expr *Expression) *Iterator { + return &Iterator{ + trace: []*Expression{expr}, + } +} + +func (i *Iterator) Current() *Expression { + if len(i.trace) < 1 { + return nil + } + + return i.trace[len(i.trace)-1] +} + +func (i *Iterator) Parent() *Expression { + if len(i.trace) < 2 { + return nil + } + + return i.trace[len(i.trace)-2] +} + +func (i *Iterator) Next() { + switch typed := (*i.Current()).(type) { + case *Abstraction: + i.trace = append(i.trace, &typed.body) + case *Application: + i.trace = append(i.trace, &typed.abstraction) + case *Variable: + for len(i.trace) > 1 { + if app, ok := (*i.Parent()).(*Application); ok { + if app.abstraction == *i.Current() { + i.Back() + i.trace = append(i.trace, &app.argument) + return + } + } + + i.Back() + } + + 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 +}