@@ -8,8 +8,10 @@ import (
8
8
"github.com/reilandeubank/golisp/pkg/scanner"
9
9
)
10
10
11
+ // VisitListExpr evaluates a list which could be an operation, keyword and arguments, or a simple list of atoms
11
12
func (i * Interpreter ) VisitListExpr (l parser.ListExpr ) (interface {}, error ) {
12
13
switch head := l .Head .(type ) {
14
+ // adds the tail as the operator's operands and evaluates the operator
13
15
case parser.Operator :
14
16
head .Operands = l .Tail
15
17
result , err := i .evaluate (head )
@@ -20,9 +22,11 @@ func (i *Interpreter) VisitListExpr(l parser.ListExpr) (interface{}, error) {
20
22
return nil , nil
21
23
}
22
24
return result , nil
25
+ // adds the tail as the keyword's arguments and evaluates it
23
26
case parser.Keyword :
24
27
head .Args = l .Tail
25
28
return i .evaluate (head )
29
+ // will simply return a list of atoms
26
30
case parser.Atom :
27
31
returnList := parser.ListExpr {Head : head , Tail : l .Tail }
28
32
return returnList , nil
@@ -31,15 +35,15 @@ func (i *Interpreter) VisitListExpr(l parser.ListExpr) (interface{}, error) {
31
35
return nil , fmt .Errorf ("LISTEXPR not implemented" )
32
36
}
33
37
38
+ // VisitKeywordExpr evaluates a syntax node where the keyword is of one of the
39
+ // below types, and it contains a list of "arguments
34
40
func (i * Interpreter ) VisitKeywordExpr (k parser.Keyword ) (interface {}, error ) {
35
41
switch k .Keyword .Type {
36
- case scanner .TRUE :
42
+ case scanner .TRUE : // TRUE keyword maps to Go's 'true' value
37
43
return true , nil
38
- // case scanner.FALSE:
39
- // return false, nil
40
- case scanner .NIL :
44
+ case scanner .NIL : // NIL keyword maps to Go's 'nil' value (is also treated like a false value)
41
45
return nil , nil
42
- case scanner .CAR :
46
+ case scanner .CAR : // car returns the first element of a list as an atom
43
47
car , err := i .evaluate (k .Args [0 ])
44
48
switch car .(type ) {
45
49
case parser.ListExpr :
@@ -50,7 +54,7 @@ func (i *Interpreter) VisitKeywordExpr(k parser.Keyword) (interface{}, error) {
50
54
return nil , err
51
55
}
52
56
return car , nil
53
- case scanner .CDR :
57
+ case scanner .CDR : // cdr returns the entire list other than the first element
54
58
output , err := i .evaluate (k .Args [0 ])
55
59
if err != nil {
56
60
return nil , err
@@ -65,7 +69,7 @@ func (i *Interpreter) VisitKeywordExpr(k parser.Keyword) (interface{}, error) {
65
69
} else {
66
70
return parser.ListExpr {Head : list .Tail [0 ]}, nil
67
71
}
68
- case scanner .COND :
72
+ case scanner .COND : // cond is of the form (cond c1 r1 c2 r2...), where if c_n is true, r_n will be evaluated
69
73
for j := 0 ; j < len (k .Args ); j += 2 {
70
74
condition , err := i .evaluate (k .Args [j ])
71
75
if err != nil {
@@ -76,7 +80,7 @@ func (i *Interpreter) VisitKeywordExpr(k parser.Keyword) (interface{}, error) {
76
80
}
77
81
}
78
82
return nil , & RuntimeError {Token : k .Keyword , Message : "Lack of true condition" }
79
- case scanner .NUMBERQ :
83
+ case scanner .NUMBERQ : // number? returns true if the argument is of type 'number', else nil
80
84
if len (k .Args ) != 1 {
81
85
return nil , & RuntimeError {Token : k .Keyword , Message : "NUMBER? operation must have 1 operand" }
82
86
}
@@ -85,12 +89,12 @@ func (i *Interpreter) VisitKeywordExpr(k parser.Keyword) (interface{}, error) {
85
89
return nil , err
86
90
}
87
91
return checkNumberOperand (k .Keyword , expr )
88
- case scanner .SYMBOLQ :
92
+ case scanner .SYMBOLQ : // symbol? returns true if the argument is a symbol, else nil
89
93
if len (k .Args ) != 1 {
90
94
return nil , & RuntimeError {Token : k .Keyword , Message : "SYMBOL? operation must have 1 operand" }
91
95
}
92
96
return reflect .TypeOf (k .Args [0 ]) == reflect .TypeOf (parser.Symbol {}), nil
93
- case scanner .LISTQ :
97
+ case scanner .LISTQ : // list? returns true if the argument is a list, else nil
94
98
if len (k .Args ) != 1 {
95
99
return nil , & RuntimeError {Token : k .Keyword , Message : "LIST? operation must have 1 operand" }
96
100
}
@@ -99,7 +103,7 @@ func (i *Interpreter) VisitKeywordExpr(k parser.Keyword) (interface{}, error) {
99
103
return nil , err
100
104
}
101
105
return reflect .TypeOf (expr ) == reflect .TypeOf (parser.ListExpr {}), nil
102
- case scanner .NILQ :
106
+ case scanner .NILQ : // nil? returns true if the argument is nil, else nil
103
107
if len (k .Args ) != 1 {
104
108
return nil , & RuntimeError {Token : k .Keyword , Message : "NIL? operation must have 1 operand" }
105
109
}
@@ -108,7 +112,7 @@ func (i *Interpreter) VisitKeywordExpr(k parser.Keyword) (interface{}, error) {
108
112
return nil , err
109
113
}
110
114
return expr == nil , nil
111
- case scanner .ANDQ :
115
+ case scanner .ANDQ : // and? is the logical AND operation
112
116
if len (k .Args ) != 2 {
113
117
return nil , & RuntimeError {Token : k .Keyword , Message : "AND? operation must have 2 operands" }
114
118
}
@@ -121,7 +125,7 @@ func (i *Interpreter) VisitKeywordExpr(k parser.Keyword) (interface{}, error) {
121
125
return nil , err
122
126
}
123
127
return isTruthy (left ) && isTruthy (right ), nil
124
- case scanner .ORQ :
128
+ case scanner .ORQ : // or? is the logical OR operation
125
129
if len (k .Args ) != 2 {
126
130
return nil , & RuntimeError {Token : k .Keyword , Message : "OR? operation must have 2 operands" }
127
131
}
@@ -138,7 +142,7 @@ func (i *Interpreter) VisitKeywordExpr(k parser.Keyword) (interface{}, error) {
138
142
return nil , nil
139
143
}
140
144
return result , nil
141
- case scanner .NOTQ :
145
+ case scanner .NOTQ : // not? is the logical NOT operator
142
146
if len (k .Args ) != 2 {
143
147
return nil , & RuntimeError {Token : k .Keyword , Message : "NOT? operation must have 1 operand" }
144
148
}
@@ -147,7 +151,7 @@ func (i *Interpreter) VisitKeywordExpr(k parser.Keyword) (interface{}, error) {
147
151
return nil , err
148
152
}
149
153
return ! isTruthy (expr ), nil
150
- case scanner .SET :
154
+ case scanner .SET : // SET will declare and initialize a global variable with the first operand as the name and the second operand as the value
151
155
if len (k .Args ) != 2 {
152
156
return nil , & RuntimeError {Token : k .Keyword , Message : "SET operation must have 2 operands" }
153
157
}
@@ -160,12 +164,13 @@ func (i *Interpreter) VisitKeywordExpr(k parser.Keyword) (interface{}, error) {
160
164
}
161
165
i .environment .define (k .Args [0 ].(parser.Symbol ).Name .Lexeme , value )
162
166
return nil , nil
167
+ default :
168
+ return nil , fmt .Errorf ("KEYWORDEXPR not implemented" )
163
169
}
164
- return nil , fmt .Errorf ("KEYWORDEXPR not implemented" )
165
170
}
166
171
167
172
func (i * Interpreter ) VisitOperatorExpr (o parser.Operator ) (interface {}, error ) {
168
- if len (o .Operands ) != 2 {
173
+ if len (o .Operands ) != 2 { // ensures that binary operators only receive 2 operands
169
174
return nil , & RuntimeError {Token : o .Operator , Message : "Binary operation must only have two operands" }
170
175
}
171
176
left , err := i .evaluate (o .Operands [0 ])
@@ -184,7 +189,7 @@ func (i *Interpreter) VisitOperatorExpr(o parser.Operator) (interface{}, error)
184
189
return nil , err
185
190
}
186
191
return left .(float64 ) - right .(float64 ), nil
187
- case scanner .PLUS :
192
+ case scanner .PLUS : // + can be used with a pair of numbers or a pair of strings
188
193
if reflect .TypeOf (left ) == reflect .TypeOf ("" ) && reflect .TypeOf (right ) == reflect .TypeOf ("" ) {
189
194
return left .(string ) + right .(string ), nil
190
195
}
@@ -218,8 +223,9 @@ func (i *Interpreter) VisitOperatorExpr(o parser.Operator) (interface{}, error)
218
223
return left .(float64 ) < right .(float64 ), nil
219
224
case scanner .EQUAL :
220
225
return isEqual (left , right ), nil
226
+ default :
227
+ return nil , & RuntimeError {Token : o .Operator , Message : "Invalid operator" }
221
228
}
222
- return nil , & RuntimeError {Token : o .Operator , Message : "Invalid operator" }
223
229
}
224
230
225
231
func (i * Interpreter ) VisitAtomExpr (a parser.Atom ) (interface {}, error ) {
@@ -230,7 +236,7 @@ func (i *Interpreter) VisitSymbolExpr(s parser.Symbol) (interface{}, error) {
230
236
return i .environment .get (s .Name )
231
237
}
232
238
233
- func (i * Interpreter ) VisitCallExpr (c parser.Call ) (interface {}, error ) {
239
+ func (i * Interpreter ) VisitCallExpr (c parser.Call ) (interface {}, error ) {
234
240
callee , err := i .evaluate (c .Callee )
235
241
if err != nil {
236
242
return nil , err
0 commit comments