perf: implement structural sharing for expression trees #10
@@ -30,12 +30,12 @@ func NewAbstraction(parameter string, body Expression) *Abstraction {
|
|||||||
/** ------------------------------------------------------------------------- */
|
/** ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
type Application struct {
|
type Application struct {
|
||||||
function Expression
|
abstraction Expression
|
||||||
argument Expression
|
argument Expression
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Application) Function() Expression {
|
func (a *Application) Abstraction() Expression {
|
||||||
return a.function
|
return a.abstraction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Application) Argument() Expression {
|
func (a *Application) Argument() Expression {
|
||||||
@@ -46,8 +46,8 @@ func (a *Application) Accept(v Visitor) {
|
|||||||
v.VisitApplication(a)
|
v.VisitApplication(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewApplication(function Expression, argument Expression) *Application {
|
func NewApplication(abstraction Expression, argument Expression) *Application {
|
||||||
return &Application{function: function, argument: argument}
|
return &Application{abstraction: abstraction, argument: argument}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ------------------------------------------------------------------------- */
|
/** ------------------------------------------------------------------------- */
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ func GetFreeVariables(e Expression) *set.Set[string] {
|
|||||||
vars.Remove(e.parameter)
|
vars.Remove(e.parameter)
|
||||||
return vars
|
return vars
|
||||||
case *Application:
|
case *Application:
|
||||||
vars := GetFreeVariables(e.function)
|
vars := GetFreeVariables(e.abstraction)
|
||||||
vars.Merge(GetFreeVariables(e.argument))
|
vars.Merge(GetFreeVariables(e.argument))
|
||||||
return vars
|
return vars
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ func IsFreeVariable(n string, e Expression) bool {
|
|||||||
case *Abstraction:
|
case *Abstraction:
|
||||||
return e.parameter != n && IsFreeVariable(n, e.body)
|
return e.parameter != n && IsFreeVariable(n, e.body)
|
||||||
case *Application:
|
case *Application:
|
||||||
return IsFreeVariable(n, e.function) || IsFreeVariable(n, e.argument)
|
return IsFreeVariable(n, e.abstraction) || IsFreeVariable(n, e.argument)
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ func ReduceOnce(e *Expression) bool {
|
|||||||
case *Abstraction:
|
case *Abstraction:
|
||||||
stack.Push(&typed.body)
|
stack.Push(&typed.body)
|
||||||
case *Application:
|
case *Application:
|
||||||
if fn, fnOk := typed.function.(*Abstraction); fnOk {
|
if fn, fnOk := typed.abstraction.(*Abstraction); fnOk {
|
||||||
reduced := Substitute(fn.body, fn.parameter, typed.argument)
|
reduced := Substitute(fn.body, fn.parameter, typed.argument)
|
||||||
*top = reduced
|
*top = reduced
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.Push(&typed.argument)
|
stack.Push(&typed.argument)
|
||||||
stack.Push(&typed.function)
|
stack.Push(&typed.abstraction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ func Rename(expr Expression, target string, newName string) Expression {
|
|||||||
return NewAbstraction(newParam, newBody)
|
return NewAbstraction(newParam, newBody)
|
||||||
|
|
||||||
case *Application:
|
case *Application:
|
||||||
newFunc := Rename(e.function, target, newName)
|
newAbs := Rename(e.abstraction, target, newName)
|
||||||
newArg := Rename(e.argument, target, newName)
|
newArg := Rename(e.argument, target, newName)
|
||||||
|
|
||||||
if newFunc == e.function && newArg == e.argument {
|
if newAbs == e.abstraction && newArg == e.argument {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewApplication(newFunc, newArg)
|
return NewApplication(newAbs, newArg)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return expr
|
return expr
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func (v *stringifyVisitor) VisitAbstraction(f *Abstraction) {
|
|||||||
|
|
||||||
func (v *stringifyVisitor) VisitApplication(c *Application) {
|
func (v *stringifyVisitor) VisitApplication(c *Application) {
|
||||||
v.builder.WriteRune('(')
|
v.builder.WriteRune('(')
|
||||||
c.function.Accept(v)
|
c.abstraction.Accept(v)
|
||||||
v.builder.WriteRune(' ')
|
v.builder.WriteRune(' ')
|
||||||
c.argument.Accept(v)
|
c.argument.Accept(v)
|
||||||
v.builder.WriteRune(')')
|
v.builder.WriteRune(')')
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ func Substitute(expr Expression, target string, replacement Expression) Expressi
|
|||||||
return NewAbstraction(param, newBody)
|
return NewAbstraction(param, newBody)
|
||||||
|
|
||||||
case *Application:
|
case *Application:
|
||||||
newFunc := Substitute(e.function, target, replacement)
|
newAbs := Substitute(e.abstraction, target, replacement)
|
||||||
newArg := Substitute(e.argument, target, replacement)
|
newArg := Substitute(e.argument, target, replacement)
|
||||||
|
|
||||||
if newFunc == e.function && newArg == e.argument {
|
if newAbs == e.abstraction && newArg == e.argument {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewApplication(newFunc, newArg)
|
return NewApplication(newAbs, newArg)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return expr
|
return expr
|
||||||
|
|||||||
Reference in New Issue
Block a user