diff --git a/pkg/convert/saccharine_to_lambda.go b/pkg/convert/saccharine_to_lambda.go index c441e8e..a76a968 100644 --- a/pkg/convert/saccharine_to_lambda.go +++ b/pkg/convert/saccharine_to_lambda.go @@ -10,7 +10,7 @@ import ( ) func encodeAtom(n *saccharine.Atom) lambda.Expression { - return lambda.NewVariable(n.Name) + return lambda.Variable{Name: n.Name} } func encodeAbstraction(n *saccharine.Abstraction) lambda.Expression { @@ -27,7 +27,7 @@ func encodeAbstraction(n *saccharine.Abstraction) lambda.Expression { } for i := len(parameters) - 1; i >= 0; i-- { - result = lambda.NewAbstraction(parameters[i], result) + result = lambda.Abstraction{Parameter: parameters[i], Body: result} } return result @@ -43,7 +43,7 @@ func encodeApplication(n *saccharine.Application) lambda.Expression { } for _, argument := range arguments { - result = lambda.NewApplication(result, argument) + result = lambda.Application{Abstraction: result, Argument: argument} } return result @@ -58,19 +58,19 @@ func reduceLet(s *saccharine.LetStatement, e lambda.Expression) lambda.Expressio value = encodeAbstraction(&saccharine.Abstraction{Parameters: s.Parameters, Body: s.Body}) } - return lambda.NewApplication( - lambda.NewAbstraction(s.Name, e), - value, - ) + return lambda.Application{ + Abstraction: lambda.Abstraction{Parameter: s.Name, Body: e}, + Argument: value, + } } func reduceDeclare(s *saccharine.DeclareStatement, e lambda.Expression) lambda.Expression { freshVar := lambda.GenerateFreshName(e.GetFree()) - return lambda.NewApplication( - lambda.NewAbstraction(freshVar, e), - encodeExpression(s.Value), - ) + return lambda.Application{ + Abstraction: lambda.Abstraction{Parameter: freshVar, Body: e}, + Argument: encodeExpression(s.Value), + } } func reduceStatement(s saccharine.Statement, e lambda.Expression) lambda.Expression { @@ -112,15 +112,15 @@ func encodeExpression(s saccharine.Expression) lambda.Expression { func decodeExression(l lambda.Expression) saccharine.Expression { switch l := l.(type) { case lambda.Variable: - return &saccharine.Atom{Name: l.Name()} + return &saccharine.Atom{Name: l.Name} case lambda.Abstraction: return &saccharine.Abstraction{ - Parameters: []string{l.Parameter()}, - Body: decodeExression(l.Body())} + Parameters: []string{l.Parameter}, + Body: decodeExression(l.Body)} case lambda.Application: return &saccharine.Application{ - Abstraction: decodeExression(l.Abstraction()), - Arguments: []saccharine.Expression{decodeExression(l.Argument())}} + Abstraction: decodeExression(l.Abstraction), + Arguments: []saccharine.Expression{decodeExression(l.Argument)}} default: panic(fmt.Errorf("unknown expression type: %T", l)) } diff --git a/pkg/engine/normalorder/reduce_once.go b/pkg/engine/normalorder/reduce_once.go index 734d6a5..50d4d5a 100644 --- a/pkg/engine/normalorder/reduce_once.go +++ b/pkg/engine/normalorder/reduce_once.go @@ -10,25 +10,25 @@ import "git.maximhutz.com/max/lambda/pkg/lambda" func ReduceOnce(e lambda.Expression) (lambda.Expression, bool) { switch e := e.(type) { case lambda.Abstraction: - body, reduced := ReduceOnce(e.Body()) + body, reduced := ReduceOnce(e.Body) if reduced { - return lambda.NewAbstraction(e.Parameter(), body), true + return lambda.Abstraction{Parameter: e.Parameter, Body: body}, true } return e, false case lambda.Application: - if fn, fnOk := e.Abstraction().(lambda.Abstraction); fnOk { - return fn.Body().Substitute(fn.Parameter(), e.Argument()), true + if fn, fnOk := e.Abstraction.(lambda.Abstraction); fnOk { + return fn.Body.Substitute(fn.Parameter, e.Argument), true } - abs, reduced := ReduceOnce(e.Abstraction()) + abs, reduced := ReduceOnce(e.Abstraction) if reduced { - return lambda.NewApplication(abs, e.Argument()), true + return lambda.Application{Abstraction: abs, Argument: e.Argument}, true } - arg, reduced := ReduceOnce(e.Argument()) + arg, reduced := ReduceOnce(e.Argument) if reduced { - return lambda.NewApplication(e.Abstraction(), arg), true + return lambda.Application{Abstraction: e.Abstraction, Argument: arg}, true } return e, false diff --git a/pkg/lambda/get_free_variables.go b/pkg/lambda/get_free_variables.go index 1c2bf91..dbed3e5 100644 --- a/pkg/lambda/get_free_variables.go +++ b/pkg/lambda/get_free_variables.go @@ -3,17 +3,17 @@ package lambda import "git.maximhutz.com/max/lambda/pkg/set" func (e Variable) GetFree() set.Set[string] { - return set.New(e.Name()) + return set.New(e.Name) } func (e Abstraction) GetFree() set.Set[string] { - vars := e.Body().GetFree() - vars.Remove(e.Parameter()) + vars := e.Body.GetFree() + vars.Remove(e.Parameter) return vars } func (e Application) GetFree() set.Set[string] { - vars := e.Abstraction().GetFree() - vars.Merge(e.Argument().GetFree()) + vars := e.Abstraction.GetFree() + vars.Merge(e.Argument.GetFree()) return vars } diff --git a/pkg/lambda/is_free_variable.go b/pkg/lambda/is_free_variable.go index 09d77a6..5db42a6 100644 --- a/pkg/lambda/is_free_variable.go +++ b/pkg/lambda/is_free_variable.go @@ -1,12 +1,12 @@ package lambda func (e Variable) IsFree(n string) bool { - return e.Name() == n + return e.Name == n } func (e Abstraction) IsFree(n string) bool { - return e.Parameter() != n && e.Body().IsFree(n) + return e.Parameter != n && e.Body.IsFree(n) } func (e Application) IsFree(n string) bool { - return e.Abstraction().IsFree(n) || e.Argument().IsFree(n) + return e.Abstraction.IsFree(n) || e.Argument.IsFree(n) } diff --git a/pkg/lambda/lambda.go b/pkg/lambda/lambda.go index b979a09..b3680c5 100644 --- a/pkg/lambda/lambda.go +++ b/pkg/lambda/lambda.go @@ -32,69 +32,25 @@ type Expression interface { /** ------------------------------------------------------------------------- */ type Abstraction struct { - parameter string - body Expression + Parameter string + Body Expression } var _ Expression = Abstraction{} -func (a Abstraction) Parameter() string { - return a.parameter -} - -func (a Abstraction) Body() Expression { - return a.body -} - -func (a Abstraction) String() string { - return "\\" + a.parameter + "." + a.body.String() -} - -func NewAbstraction(parameter string, body Expression) Abstraction { - return Abstraction{parameter, body} -} - /** ------------------------------------------------------------------------- */ type Application struct { - abstraction Expression - argument Expression + Abstraction Expression + Argument Expression } var _ Expression = Application{} -func (a Application) Abstraction() Expression { - return a.abstraction -} - -func (a Application) Argument() Expression { - return a.argument -} - -func (a Application) String() string { - return "(" + a.abstraction.String() + " " + a.argument.String() + ")" -} - -func NewApplication(abstraction Expression, argument Expression) Application { - return Application{abstraction, argument} -} - /** ------------------------------------------------------------------------- */ type Variable struct { - name string + Name string } var _ Expression = Variable{} - -func (v Variable) Name() string { - return v.name -} - -func (v Variable) String() string { - return v.name -} - -func NewVariable(name string) Variable { - return Variable{name} -} diff --git a/pkg/lambda/rename.go b/pkg/lambda/rename.go index 2c39237..10e438d 100644 --- a/pkg/lambda/rename.go +++ b/pkg/lambda/rename.go @@ -2,27 +2,27 @@ package lambda // Rename replaces all occurrences of the target variable name with the new name. func (e Variable) Rename(target string, newName string) Expression { - if e.Name() == target { - return NewVariable(newName) + if e.Name == target { + return Variable{Name: newName} } return e } func (e Abstraction) Rename(target string, newName string) Expression { - newParam := e.Parameter() - if e.Parameter() == target { + newParam := e.Parameter + if e.Parameter == target { newParam = newName } - newBody := e.Body().Rename(target, newName) + newBody := e.Body.Rename(target, newName) - return NewAbstraction(newParam, newBody) + return Abstraction{Parameter: newParam, Body: newBody} } func (e Application) Rename(target string, newName string) Expression { - newAbs := e.Abstraction().Rename(target, newName) - newArg := e.Argument().Rename(target, newName) + newAbs := e.Abstraction.Rename(target, newName) + newArg := e.Argument.Rename(target, newName) - return NewApplication(newAbs, newArg) + return Application{Abstraction: newAbs, Argument: newArg} } diff --git a/pkg/lambda/stringify.go b/pkg/lambda/stringify.go new file mode 100644 index 0000000..a83ff48 --- /dev/null +++ b/pkg/lambda/stringify.go @@ -0,0 +1,13 @@ +package lambda + +func (a Abstraction) String() string { + return "\\" + a.Parameter + "." + a.Body.String() +} + +func (a Application) String() string { + return "(" + a.Abstraction.String() + " " + a.Argument.String() + ")" +} + +func (v Variable) String() string { + return v.Name +} diff --git a/pkg/lambda/substitute.go b/pkg/lambda/substitute.go index 1f6b38e..238b77b 100644 --- a/pkg/lambda/substitute.go +++ b/pkg/lambda/substitute.go @@ -1,7 +1,7 @@ package lambda func (e Variable) Substitute(target string, replacement Expression) Expression { - if e.Name() == target { + if e.Name == target { return replacement } @@ -9,12 +9,12 @@ func (e Variable) Substitute(target string, replacement Expression) Expression { } func (e Abstraction) Substitute(target string, replacement Expression) Expression { - if e.Parameter() == target { + if e.Parameter == target { return e } - body := e.Body() - param := e.Parameter() + body := e.Body + param := e.Parameter if replacement.IsFree(param) { freeVars := replacement.GetFree() freeVars.Merge(body.GetFree()) @@ -24,12 +24,12 @@ func (e Abstraction) Substitute(target string, replacement Expression) Expressio } newBody := body.Substitute(target, replacement) - return NewAbstraction(param, newBody) + return Abstraction{Parameter: param, Body: newBody} } func (e Application) Substitute(target string, replacement Expression) Expression { - abs := e.Abstraction().Substitute(target, replacement) - arg := e.Argument().Substitute(target, replacement) + abs := e.Abstraction.Substitute(target, replacement) + arg := e.Argument.Substitute(target, replacement) - return NewApplication(abs, arg) + return Application{Abstraction: abs, Argument: arg} }