diff --git a/cmd/lambda/lambda.go b/cmd/lambda/lambda.go index 1e232bf..b94c046 100644 --- a/cmd/lambda/lambda.go +++ b/cmd/lambda/lambda.go @@ -30,9 +30,9 @@ func main() { cli.HandleError(err) logger.Info("Parsed syntax tree.", "tree", lambda.Stringify(expression)) - lambda.Normalize(&expression) - cli.HandleError(err) - logger.Info("Evaluated expression.", "tree", expression) + for lambda.ReduceOnce(&expression) { + logger.Info("Reduction.", "tree", lambda.Stringify(expression)) + } fmt.Println(lambda.Stringify(expression)) } diff --git a/pkg/lambda/expression.go b/pkg/lambda/expression.go index 64a8a33..dc0c08b 100644 --- a/pkg/lambda/expression.go +++ b/pkg/lambda/expression.go @@ -2,6 +2,7 @@ package lambda type Expression interface { Accept(Visitor) + Copy() Expression } /** ------------------------------------------------------------------------- */ @@ -11,14 +12,18 @@ type Abstraction struct { Body Expression } -func NewAbstraction(parameter string, body Expression) *Abstraction { - return &Abstraction{Parameter: parameter, Body: body} +func (this *Abstraction) Copy() Expression { + return NewAbstraction(this.Parameter, this.Body.Copy()) } func (this *Abstraction) Accept(v Visitor) { v.VisitAbstraction(this) } +func NewAbstraction(parameter string, body Expression) *Abstraction { + return &Abstraction{Parameter: parameter, Body: body} +} + /** ------------------------------------------------------------------------- */ type Application struct { @@ -26,28 +31,36 @@ type Application struct { Argument Expression } -func NewApplication(function Expression, argument Expression) *Application { - return &Application{Abstraction: function, Argument: argument} +func (this *Application) Copy() Expression { + return NewApplication(this.Abstraction.Copy(), this.Argument.Copy()) } func (this *Application) Accept(v Visitor) { v.VisitApplication(this) } +func NewApplication(function Expression, argument Expression) *Application { + return &Application{Abstraction: function, Argument: argument} +} + /** ------------------------------------------------------------------------- */ type Variable struct { Value string } -func NewVariable(name string) *Variable { - return &Variable{Value: name} +func (this *Variable) Copy() Expression { + return NewVariable(this.Value) } func (this *Variable) Accept(v Visitor) { v.VisitVariable(this) } +func NewVariable(name string) *Variable { + return &Variable{Value: name} +} + /** ------------------------------------------------------------------------- */ type Visitor interface { diff --git a/pkg/lambda/reduce.go b/pkg/lambda/reduce.go index 4410551..b09f624 100644 --- a/pkg/lambda/reduce.go +++ b/pkg/lambda/reduce.go @@ -21,8 +21,3 @@ func ReduceOnce(e *Expression) bool { return false } } - -func Normalize(e *Expression) { - for ReduceOnce(e) { - } -} diff --git a/pkg/lambda/substitute.go b/pkg/lambda/substitute.go index 3b219c5..a8ba42f 100644 --- a/pkg/lambda/substitute.go +++ b/pkg/lambda/substitute.go @@ -4,7 +4,7 @@ func Substitute(e *Expression, target string, replacement Expression) { switch typed := (*e).(type) { case *Variable: if typed.Value == target { - *e = replacement + *e = replacement.Copy() } case *Abstraction: if typed.Parameter == target {