refactor: convert Substitute and Rename to standalone functions
Remove Substitute and Rename methods from Expression interface. Refactor receiver methods into standalone functions using type switching. Update call sites to use new function signatures. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,8 +3,6 @@ package lambda
|
|||||||
// Expression represents an immutable lambda calculus expression.
|
// Expression represents an immutable lambda calculus expression.
|
||||||
type Expression interface {
|
type Expression interface {
|
||||||
Accept(Visitor)
|
Accept(Visitor)
|
||||||
Substitute(target string, replacement Expression) Expression
|
|
||||||
Rename(target string, newName string) Expression
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ------------------------------------------------------------------------- */
|
/** ------------------------------------------------------------------------- */
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ func ReduceOnce(e *Expression) bool {
|
|||||||
stack.Push(&typed.body)
|
stack.Push(&typed.body)
|
||||||
case *Application:
|
case *Application:
|
||||||
if fn, fnOk := typed.function.(*Abstraction); fnOk {
|
if fn, fnOk := typed.function.(*Abstraction); fnOk {
|
||||||
reduced := fn.body.Substitute(fn.parameter, typed.argument)
|
reduced := Substitute(fn.body, fn.parameter, typed.argument)
|
||||||
*top = reduced
|
*top = reduced
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,39 @@
|
|||||||
package lambda
|
package lambda
|
||||||
|
|
||||||
// Rename replaces all occurrences of target variable with newName.
|
// Rename replaces all occurrences of target variable with newName.
|
||||||
func (v *Variable) Rename(target string, newName string) Expression {
|
func Rename(expr Expression, target string, newName string) Expression {
|
||||||
if v.value == target {
|
switch e := expr.(type) {
|
||||||
|
case *Variable:
|
||||||
|
if e.value == target {
|
||||||
return NewVariable(newName)
|
return NewVariable(newName)
|
||||||
}
|
}
|
||||||
return v
|
return e
|
||||||
}
|
|
||||||
|
|
||||||
// Rename replaces all occurrences of target variable with newName.
|
case *Abstraction:
|
||||||
func (a *Abstraction) Rename(target string, newName string) Expression {
|
newParam := e.parameter
|
||||||
newParam := a.parameter
|
if e.parameter == target {
|
||||||
if a.parameter == target {
|
|
||||||
newParam = newName
|
newParam = newName
|
||||||
}
|
}
|
||||||
|
|
||||||
newBody := a.body.Rename(target, newName)
|
newBody := Rename(e.body, target, newName)
|
||||||
|
|
||||||
if newParam == a.parameter && newBody == a.body {
|
if newParam == e.parameter && newBody == e.body {
|
||||||
return a
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewAbstraction(newParam, newBody)
|
return NewAbstraction(newParam, newBody)
|
||||||
}
|
|
||||||
|
|
||||||
// Rename replaces all occurrences of target variable with newName.
|
case *Application:
|
||||||
func (a *Application) Rename(target string, newName string) Expression {
|
newFunc := Rename(e.function, target, newName)
|
||||||
newFunc := a.function.Rename(target, newName)
|
newArg := Rename(e.argument, target, newName)
|
||||||
newArg := a.argument.Rename(target, newName)
|
|
||||||
|
|
||||||
if newFunc == a.function && newArg == a.argument {
|
if newFunc == e.function && newArg == e.argument {
|
||||||
return a
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewApplication(newFunc, newArg)
|
return NewApplication(newFunc, newArg)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return expr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1,47 @@
|
|||||||
package lambda
|
package lambda
|
||||||
|
|
||||||
// Substitute replaces all free occurrences of target with replacement.
|
// Substitute replaces all free occurrences of target with replacement.
|
||||||
func (v *Variable) Substitute(target string, replacement Expression) Expression {
|
func Substitute(expr Expression, target string, replacement Expression) Expression {
|
||||||
if v.value == target {
|
switch e := expr.(type) {
|
||||||
|
case *Variable:
|
||||||
|
if e.value == target {
|
||||||
return replacement
|
return replacement
|
||||||
}
|
}
|
||||||
return v
|
return e
|
||||||
}
|
|
||||||
|
|
||||||
// Substitute replaces all free occurrences of target with replacement.
|
case *Abstraction:
|
||||||
func (a *Abstraction) Substitute(target string, replacement Expression) Expression {
|
if e.parameter == target {
|
||||||
if a.parameter == target {
|
return e
|
||||||
return a
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body := a.body
|
body := e.body
|
||||||
param := a.parameter
|
param := e.parameter
|
||||||
if IsFreeVariable(param, replacement) {
|
if IsFreeVariable(param, replacement) {
|
||||||
freeVars := GetFreeVariables(replacement)
|
freeVars := GetFreeVariables(replacement)
|
||||||
freeVars.Merge(GetFreeVariables(body))
|
freeVars.Merge(GetFreeVariables(body))
|
||||||
freshVar := GenerateFreshName(freeVars)
|
freshVar := GenerateFreshName(freeVars)
|
||||||
body = body.Rename(param, freshVar)
|
body = Rename(body, param, freshVar)
|
||||||
param = freshVar
|
param = freshVar
|
||||||
}
|
}
|
||||||
|
|
||||||
newBody := body.Substitute(target, replacement)
|
newBody := Substitute(body, target, replacement)
|
||||||
if newBody == body && param == a.parameter {
|
if newBody == body && param == e.parameter {
|
||||||
return a
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewAbstraction(param, newBody)
|
return NewAbstraction(param, newBody)
|
||||||
}
|
|
||||||
|
|
||||||
// Substitute replaces all free occurrences of target with replacement.
|
case *Application:
|
||||||
func (a *Application) Substitute(target string, replacement Expression) Expression {
|
newFunc := Substitute(e.function, target, replacement)
|
||||||
newFunc := a.function.Substitute(target, replacement)
|
newArg := Substitute(e.argument, target, replacement)
|
||||||
newArg := a.argument.Substitute(target, replacement)
|
|
||||||
|
|
||||||
if newFunc == a.function && newArg == a.argument {
|
if newFunc == e.function && newArg == e.argument {
|
||||||
return a
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewApplication(newFunc, newArg)
|
return NewApplication(newFunc, newArg)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return expr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user