@@ -23,34 +23,61 @@ func intToLetter(num int) string {
2323 return "x" + strconv .Itoa (num - 25 )
2424}
2525
26+ func getFreeVariables (t Term ) []Free {
27+ switch t := t .(type ) {
28+ case Free :
29+ return []Free {t }
30+
31+ case Appl :
32+ return append (getFreeVariables (t [0 ]), getFreeVariables (t [1 ])... )
33+
34+ case Abst :
35+ return getFreeVariables (t [0 ])
36+
37+ default :
38+ return []Free {}
39+ }
40+ }
41+
42+ func in (t Free , f * []Free ) bool {
43+ for _ , v := range * f {
44+ if t == v {
45+ return true
46+ }
47+ }
48+
49+ return false
50+ }
51+
2652// String returns the Lambda Expression as a string
2753func (lx Appl ) String () string {
2854 builder := strings.Builder {}
29- lx .deDeBruijn (& builder , new ([]string ), new (int ))
55+ freeVars := getFreeVariables (lx )
56+ lx .deDeBruijn (& builder , new ([]string ), new (int ), & freeVars )
3057
3158 return builder .String ()
3259}
3360
34- func (lx Appl ) deDeBruijn (builder * strings.Builder , boundLetters * []string , nextletter * int ) {
61+ func (lx Appl ) deDeBruijn (builder * strings.Builder , boundLetters * []string , nextletter * int , freeVars * [] Free ) {
3562 for i , part := range lx {
3663 switch part := part .(type ) {
3764 case Abst :
3865 builder .WriteByte ('(' )
39- part .deDeBruijn (builder , boundLetters , nextletter )
66+ part .deDeBruijn (builder , boundLetters , nextletter , freeVars )
4067 builder .WriteByte (')' )
4168
4269 case Appl :
4370 if i == 0 {
44- part .deDeBruijn (builder , boundLetters , nextletter )
71+ part .deDeBruijn (builder , boundLetters , nextletter , freeVars )
4572
4673 } else {
4774 builder .WriteByte ('(' )
48- part .deDeBruijn (builder , boundLetters , nextletter )
75+ part .deDeBruijn (builder , boundLetters , nextletter , freeVars )
4976 builder .WriteByte (')' )
5077 }
5178
5279 default :
53- part .deDeBruijn (builder , boundLetters , nextletter )
80+ part .deDeBruijn (builder , boundLetters , nextletter , freeVars )
5481 }
5582
5683 // Put space between first and second part
@@ -63,25 +90,33 @@ func (lx Appl) deDeBruijn(builder *strings.Builder, boundLetters *[]string, next
6390// String returns the lambda abstraction as a string
6491func (la Abst ) String () string {
6592 builder := strings.Builder {}
66- la .deDeBruijn (& builder , new ([]string ), new (int ))
93+ freeVars := getFreeVariables (la )
94+ la .deDeBruijn (& builder , new ([]string ), new (int ), & freeVars )
6795
6896 return builder .String ()
6997}
7098
71- func (la Abst ) deDeBruijn (builder * strings.Builder , boundLetters * []string , nextletter * int ) {
99+ func (la Abst ) deDeBruijn (builder * strings.Builder , boundLetters * []string , nextletter * int , freeVars * [] Free ) {
72100 // Remember at which character we were
73101 oldNextLetter := * nextletter
74102
75- // Add the localy bound letter to the list
103+ // Search for a free name
76104 newLetter := intToLetter (* nextletter )
77105 * nextletter ++
106+
107+ for in (Free (newLetter ), freeVars ) {
108+ newLetter = intToLetter (* nextletter )
109+ * nextletter ++
110+ }
111+
112+ // Add the localy bound letter to the list
78113 * boundLetters = append ([]string {newLetter }, * boundLetters ... )
79114
80115 builder .WriteRune ('λ' )
81116 builder .WriteString (newLetter )
82117 builder .WriteByte ('.' )
83118
84- la [0 ].deDeBruijn (builder , boundLetters , nextletter )
119+ la [0 ].deDeBruijn (builder , boundLetters , nextletter , freeVars )
85120
86121 // Remove our local naming
87122 * boundLetters = (* boundLetters )[1 :]
@@ -94,20 +129,29 @@ func (lv Var) String() string {
94129 return intToLetter (0 )
95130}
96131
97- func (lv Var ) deDeBruijn (builder * strings.Builder , boundLetters * []string , nextletter * int ) {
132+ func (lv Var ) deDeBruijn (builder * strings.Builder , boundLetters * []string , nextletter * int , freeVars * [] Free ) {
98133 if int (lv ) < len (* boundLetters ) && (* boundLetters )[lv ] != "" {
99134 builder .WriteString ((* boundLetters )[lv ])
100135 return
101136 }
102137
138+ // Search for a free name
103139 newLetter := intToLetter (* nextletter )
104140 * nextletter ++
105141
142+ for in (Free (newLetter ), freeVars ) {
143+ newLetter = intToLetter (* nextletter )
144+ * nextletter ++
145+ }
146+
147+ // Add it to the boundletters table
106148 for i := len (* boundLetters ); i < int (lv ); i ++ {
107149 * boundLetters = append (* boundLetters , "" )
108150 }
109151
110152 * boundLetters = append (* boundLetters , newLetter )
153+
154+ // And finaly write it to output
111155 builder .WriteString (newLetter )
112156}
113157
@@ -117,6 +161,6 @@ func (lf Free) String() string {
117161 return string (lf )
118162}
119163
120- func (lf Free ) deDeBruijn (builder * strings.Builder , boundLetters * []string , nextletter * int ) {
164+ func (lf Free ) deDeBruijn (builder * strings.Builder , boundLetters * []string , nextletter * int , freeVars * [] Free ) {
121165 builder .WriteString (string (lf ))
122166}
0 commit comments