@@ -2,6 +2,7 @@ package evaluator
2
2
3
3
import (
4
4
"fmt"
5
+ "strings"
5
6
6
7
"github.com/AvicennaJr/Nuru/ast"
7
8
"github.com/AvicennaJr/Nuru/object"
@@ -105,6 +106,57 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
105
106
return evalIndexExpression (left , index )
106
107
case * ast.DictLiteral :
107
108
return evalDictLiteral (node , env )
109
+ case * ast.WhileExpression :
110
+ return evalWhileExpression (node , env )
111
+ case * ast.AssignmentExpression :
112
+ left := Eval (node .Left , env )
113
+ if isError (left ) {
114
+ return left
115
+ }
116
+
117
+ value := Eval (node .Value , env )
118
+ if isError (value ) {
119
+ return value
120
+ }
121
+
122
+ if ident , ok := node .Left .(* ast.Identifier ); ok {
123
+ env .Set (ident .Value , value )
124
+ } else if ie , ok := node .Left .(* ast.IndexExpression ); ok {
125
+ obj := Eval (ie .Left , env )
126
+ if isError (obj ) {
127
+ return obj
128
+ }
129
+
130
+ if array , ok := obj .(* object.Array ); ok {
131
+ index := Eval (ie .Index , env )
132
+ if isError (index ) {
133
+ return index
134
+ }
135
+ if idx , ok := index .(* object.Integer ); ok {
136
+ if int (idx .Value ) > len (array .Elements ) {
137
+ return newError ("Index imezidi idadi ya elements" )
138
+ }
139
+ array .Elements [idx .Value ] = value
140
+ } else {
141
+ return newError ("Hauwezi kufanya opereshen hii na %#v" , index )
142
+ }
143
+ } else if hash , ok := obj .(* object.Dict ); ok {
144
+ key := Eval (ie .Index , env )
145
+ if isError (key ) {
146
+ return key
147
+ }
148
+ if hashKey , ok := key .(object.Hashable ); ok {
149
+ hashed := hashKey .HashKey ()
150
+ hash .Pairs [hashed ] = object.DictPair {Key : key , Value : value }
151
+ } else {
152
+ return newError ("Hauwezi kufanya opereshen hii na %T" , key )
153
+ }
154
+ } else {
155
+ return newError ("%T haifanyi operation hii" , obj )
156
+ }
157
+ } else {
158
+ return newError ("Tumia neno kama variable, sio %T" , left )
159
+ }
108
160
109
161
}
110
162
@@ -173,17 +225,70 @@ func evalInfixExpression(
173
225
left , right object.Object ,
174
226
) object.Object {
175
227
switch {
228
+
229
+ case operator == "+" && left .Type () == object .DICT_OBJ && right .Type () == object .DICT_OBJ :
230
+ leftVal := left .(* object.Dict ).Pairs
231
+ rightVal := right .(* object.Dict ).Pairs
232
+ pairs := make (map [object.HashKey ]object.DictPair )
233
+ for k , v := range leftVal {
234
+ pairs [k ] = v
235
+ }
236
+ for k , v := range rightVal {
237
+ pairs [k ] = v
238
+ }
239
+ return & object.Dict {Pairs : pairs }
240
+
241
+ case operator == "+" && left .Type () == object .ARRAY_OBJ && right .Type () == object .ARRAY_OBJ :
242
+ leftVal := left .(* object.Array ).Elements
243
+ rightVal := right .(* object.Array ).Elements
244
+ elements := make ([]object.Object , len (leftVal )+ len (rightVal ))
245
+ elements = append (leftVal , rightVal ... )
246
+ return & object.Array {Elements : elements }
247
+
248
+ case operator == "*" && left .Type () == object .ARRAY_OBJ && right .Type () == object .INTEGER_OBJ :
249
+ leftVal := left .(* object.Array ).Elements
250
+ rightVal := int (right .(* object.Integer ).Value )
251
+ elements := leftVal
252
+ for i := rightVal ; i > 1 ; i -- {
253
+ elements = append (elements , leftVal ... )
254
+ }
255
+ return & object.Array {Elements : elements }
256
+
257
+ case operator == "*" && left .Type () == object .INTEGER_OBJ && right .Type () == object .ARRAY_OBJ :
258
+ leftVal := int (left .(* object.Integer ).Value )
259
+ rightVal := right .(* object.Array ).Elements
260
+ elements := rightVal
261
+ for i := leftVal ; i > 1 ; i -- {
262
+ elements = append (elements , rightVal ... )
263
+ }
264
+ return & object.Array {Elements : elements }
265
+
266
+ case operator == "*" && left .Type () == object .STRING_OBJ && right .Type () == object .INTEGER_OBJ :
267
+ leftVal := left .(* object.String ).Value
268
+ rightVal := right .(* object.Integer ).Value
269
+ return & object.String {Value : strings .Repeat (leftVal , int (rightVal ))}
270
+
271
+ case operator == "*" && left .Type () == object .INTEGER_OBJ && right .Type () == object .STRING_OBJ :
272
+ leftVal := left .(* object.Integer ).Value
273
+ rightVal := right .(* object.String ).Value
274
+ return & object.String {Value : strings .Repeat (rightVal , int (leftVal ))}
275
+
176
276
case left .Type () == object .INTEGER_OBJ && right .Type () == object .INTEGER_OBJ :
177
277
return evalIntegerInfixExpression (operator , left , right )
278
+
178
279
case operator == "==" :
179
280
return nativeBoolToBooleanObject (left == right )
281
+
180
282
case operator == "!=" :
181
283
return nativeBoolToBooleanObject (left != right )
284
+
182
285
case left .Type () != right .Type ():
183
286
return newError ("Aina Hazilingani: %s %s %s" ,
184
287
left .Type (), operator , right .Type ())
288
+
185
289
case left .Type () == object .STRING_OBJ && right .Type () == object .STRING_OBJ :
186
290
return evalStringInfixExpression (operator , left , right )
291
+
187
292
default :
188
293
return newError ("Operesheni Haielweki: %s %s %s" ,
189
294
left .Type (), operator , right .Type ())
@@ -353,6 +458,8 @@ func evalIndexExpression(left, index object.Object) object.Object {
353
458
switch {
354
459
case left .Type () == object .ARRAY_OBJ && index .Type () == object .INTEGER_OBJ :
355
460
return evalArrayIndexExpression (left , index )
461
+ case left .Type () == object .ARRAY_OBJ && index .Type () != object .INTEGER_OBJ :
462
+ return newError ("Tafadhali tumia number, sio: %s" , index .Type ())
356
463
case left .Type () == object .DICT_OBJ :
357
464
return evalDictIndexExpression (left , index )
358
465
default :
@@ -413,3 +520,25 @@ func evalDictIndexExpression(dict, index object.Object) object.Object {
413
520
414
521
return pair .Value
415
522
}
523
+
524
+ func evalWhileExpression (we * ast.WhileExpression , env * object.Environment ) object.Object {
525
+ var result object.Object
526
+
527
+ for {
528
+ condition := Eval (we .Condition , env )
529
+ if isError (condition ) {
530
+ return condition
531
+ }
532
+
533
+ if isTruthy (condition ) {
534
+ result = Eval (we .Consequence , env )
535
+ } else {
536
+ break
537
+ }
538
+ }
539
+
540
+ if result != nil {
541
+ return result
542
+ }
543
+ return nil
544
+ }
0 commit comments