Closes #26 - Added -i flag to select interpreter (lambda or debruijn) - Created debruijn package with Expression interface - Variable contains index and optional label - Abstraction contains only body (no parameter) - Application structure remains similar - Implemented De Bruijn reduction without variable renaming - Shift operation handles index adjustments - Substitute replaces by index instead of name - Abstracted Engine into interface with two implementations - LambdaEngine: original named variable engine - DeBruijnEngine: new index-based engine - Added conversion functions between representations - LambdaToDeBruijn: converts named to indexed - DeBruijnToLambda: converts indexed back to named - SaccharineToDeBruijn: direct saccharine to De Bruijn - Updated main to switch engines based on -i flag - All test samples pass with both engines Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
39 lines
742 B
Go
39 lines
742 B
Go
package debruijn
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type stringifyVisitor struct {
|
|
builder strings.Builder
|
|
}
|
|
|
|
func (v *stringifyVisitor) VisitVariable(a *Variable) {
|
|
if a.label != "" {
|
|
v.builder.WriteString(a.label)
|
|
} else {
|
|
v.builder.WriteString(fmt.Sprintf("%d", a.index))
|
|
}
|
|
}
|
|
|
|
func (v *stringifyVisitor) VisitAbstraction(f *Abstraction) {
|
|
v.builder.WriteRune('\\')
|
|
v.builder.WriteRune('.')
|
|
f.body.Accept(v)
|
|
}
|
|
|
|
func (v *stringifyVisitor) VisitApplication(c *Application) {
|
|
v.builder.WriteRune('(')
|
|
c.abstraction.Accept(v)
|
|
v.builder.WriteRune(' ')
|
|
c.argument.Accept(v)
|
|
v.builder.WriteRune(')')
|
|
}
|
|
|
|
func Stringify(e Expression) string {
|
|
b := &stringifyVisitor{builder: strings.Builder{}}
|
|
e.Accept(b)
|
|
return b.builder.String()
|
|
}
|