3
3
4
4
from generated .MyParser import MyParser
5
5
from generated .MyParserVisitor import MyParserVisitor
6
- from utils .values import Int , Float , String , Vector
6
+ from utils .memory import MemoryStack
7
+ from utils .values import Value , Int , Float , String , Vector
8
+
9
+
10
+ class Break (Exception ):
11
+ pass
12
+
13
+
14
+ class Continue (Exception ):
15
+ pass
16
+
17
+
18
+ def not_same_type (a : Value , b : Value ):
19
+ return type (a ) is not type (b ) or (
20
+ isinstance (a , Vector )
21
+ and (a .dims != b .dims or a .primitive_type != b .primitive_type )
22
+ )
7
23
8
24
9
25
class Interpreter (MyParserVisitor ):
26
+ def __init__ (self ):
27
+ self .memory_stack = MemoryStack ()
28
+ self .memory_stack .push_memory ()
29
+
10
30
def visitScopeStatement (self , ctx : MyParser .ScopeStatementContext ):
11
- return self .visitChildren (ctx ) # todo
31
+ self .memory_stack .push_memory ()
32
+ self .visitChildren (ctx )
33
+ self .memory_stack .pop_memory ()
12
34
13
35
def visitIfThenElse (self , ctx : MyParser .IfThenElseContext ):
14
36
condition = self .visit (ctx .if_ ())
15
37
if condition :
16
38
return self .visit (ctx .then ())
17
- elif ctx .else_ () is not None :
39
+ elif ctx .else_ ():
18
40
return self .visit (ctx .else_ ())
19
41
20
42
def visitIf (self , ctx : MyParser .IfContext ):
@@ -24,13 +46,32 @@ def visitElse(self, ctx: MyParser.ElseContext):
24
46
return self .visit (ctx .statement ())
25
47
26
48
def visitForLoop (self , ctx : MyParser .ForLoopContext ):
27
- return self .visitChildren (ctx ) # todo
49
+ a , b = self .visit (ctx .range_ ())
50
+ variable = ctx .id_ ().getText ()
51
+ for i in range (a , b + 1 ):
52
+ self .memory_stack .put (variable , Int (i ))
53
+ try :
54
+ self .visit (ctx .statement ())
55
+ except Continue :
56
+ continue
57
+ except Break :
58
+ break
28
59
29
60
def visitRange (self , ctx : MyParser .RangeContext ):
30
- return self .visitChildren (ctx ) # todo
61
+ a = self .visit (ctx .expression (0 ))
62
+ b = self .visit (ctx .expression (1 ))
63
+ if {type (a ), type (b )} != {Int }:
64
+ raise TypeError
65
+ return (a .value , b .value )
31
66
32
67
def visitWhileLoop (self , ctx : MyParser .WhileLoopContext ):
33
- return self .visitChildren (ctx ) # todo
68
+ while self .visit (ctx .comparison ()):
69
+ try :
70
+ self .visit (ctx .statement ())
71
+ except Continue :
72
+ continue
73
+ except Break :
74
+ break
34
75
35
76
def visitComparison (self , ctx : MyParser .ComparisonContext ):
36
77
a = self .visit (ctx .expression (0 ))
@@ -50,17 +91,51 @@ def visitComparison(self, ctx: MyParser.ComparisonContext):
50
91
return a >= b
51
92
52
93
def visitSimpleAssignment (self , ctx : MyParser .SimpleAssignmentContext ):
53
- return self .visitChildren (ctx ) # todo
94
+ if ctx .id_ (): # a = 1
95
+ self .memory_stack .put (ctx .id_ ().getText (), self .visit (ctx .expression ()))
96
+ else : # a[0] = 1
97
+ ref_value = self .visit (ctx .elementReference ())
98
+ new_value = self .visit (ctx .expression ())
99
+ if not_same_type (ref_value , new_value ):
100
+ raise TypeError
101
+ ref_value .value = new_value .value
54
102
55
103
def visitCompoundAssignment (self , ctx : MyParser .CompoundAssignmentContext ):
56
- return self .visitChildren (ctx ) # todo
104
+ if ctx .id_ (): # a += 1
105
+ value = self .memory_stack .get (ctx .id_ ().getText ())
106
+ new_value = self .visit (ctx .expression ())
107
+ match ctx .getChild (1 ).symbol .type :
108
+ case MyParser .ASSIGN_PLUS :
109
+ new_value = value + new_value
110
+ case MyParser .ASSIGN_MINUS :
111
+ new_value = value - new_value
112
+ case MyParser .ASSIGN_MULTIPLY :
113
+ new_value = value * new_value
114
+ case MyParser .ASSIGN_DIVIDE :
115
+ new_value = value / new_value
116
+ self .memory_stack .put (ctx .id_ ().getText (), new_value )
117
+ else : # a[0] += 1
118
+ ref_value = self .visit (ctx .elementReference ())
119
+ new_value = self .visit (ctx .expression ())
120
+ if not_same_type (ref_value , new_value ):
121
+ raise TypeError
122
+ match ctx .getChild (1 ).symbol .type :
123
+ case MyParser .ASSIGN_PLUS :
124
+ new_value = ref_value + new_value
125
+ case MyParser .ASSIGN_MINUS :
126
+ new_value = ref_value - new_value
127
+ case MyParser .ASSIGN_MULTIPLY :
128
+ new_value = ref_value * new_value
129
+ case MyParser .ASSIGN_DIVIDE :
130
+ new_value = ref_value / new_value
131
+ ref_value .value = new_value .value
57
132
58
133
def visitPrint (self , ctx : MyParser .PrintContext ):
59
134
for i in range (ctx .getChildCount () // 2 ):
60
135
print (str (self .visit (ctx .expression (i ))))
61
136
62
137
def visitReturn (self , ctx : MyParser .ReturnContext ):
63
- if ctx .expression () is not None :
138
+ if ctx .expression ():
64
139
return_value = self .visit (ctx .expression ())
65
140
if not isinstance (return_value , Int ):
66
141
raise TypeError
@@ -79,7 +154,14 @@ def visitBinaryExpression(self, ctx: MyParser.BinaryExpressionContext):
79
154
return a * b
80
155
case MyParser .DIVIDE :
81
156
return a / b
82
- # todo: MAT_* operations
157
+ case MyParser .MAT_PLUS :
158
+ return a .mat_add (b )
159
+ case MyParser .MAT_MINUS :
160
+ return a .mat_sub (b )
161
+ case MyParser .MAT_MULTIPLY :
162
+ return a .mat_mul (b )
163
+ case MyParser .MAT_DIVIDE :
164
+ return a .mat_truediv (b )
83
165
84
166
def visitParenthesesExpression (self , ctx : MyParser .ParenthesesExpressionContext ):
85
167
return self .visit (ctx .expression ())
@@ -117,10 +199,10 @@ def visitSpecialMatrixFunction(self, ctx: MyParser.SpecialMatrixFunctionContext)
117
199
return vector
118
200
119
201
def visitBreak (self , ctx : MyParser .BreakContext ):
120
- return self . visitChildren ( ctx ) # todo
202
+ raise Break ()
121
203
122
204
def visitContinue (self , ctx : MyParser .ContinueContext ):
123
- return self . visitChildren ( ctx ) # todo
205
+ raise Continue ()
124
206
125
207
def visitVector (self , ctx : MyParser .VectorContext ):
126
208
elements = [
@@ -129,10 +211,20 @@ def visitVector(self, ctx: MyParser.VectorContext):
129
211
return Vector (elements )
130
212
131
213
def visitElementReference (self , ctx : MyParser .ElementReferenceContext ):
132
- return self .visitChildren (ctx ) # todo
214
+ indices = [
215
+ self .visit (ctx .expression (i )) for i in range (ctx .getChildCount () // 2 - 1 )
216
+ ]
217
+ if {type (idx ) for idx in indices } != {Int }:
218
+ raise TypeError
219
+ result = self .visit (ctx .id_ ())
220
+ for idx in indices :
221
+ if not isinstance (result , Vector ):
222
+ raise TypeError
223
+ result = result .value [idx .value ]
224
+ return result
133
225
134
226
def visitId (self , ctx : MyParser .IdContext ):
135
- return self .visitChildren (ctx ) # todo
227
+ return self .memory_stack . get (ctx . getText ())
136
228
137
229
def visitInt (self , ctx : MyParser .IntContext ):
138
230
return Int (ctx .getText ())
@@ -141,4 +233,4 @@ def visitFloat(self, ctx: MyParser.FloatContext):
141
233
return Float (ctx .getText ())
142
234
143
235
def visitString (self , ctx : MyParser .StringContext ):
144
- return String (ctx .getText ())
236
+ return String (ctx .getText ()[ 1 : - 1 ]) # without quotes
0 commit comments