-
Notifications
You must be signed in to change notification settings - Fork 0
/
quadHelpers.py
278 lines (259 loc) · 12.7 KB
/
quadHelpers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
from semanticCube import SemanticCube
from symbolTable import SymbolTable, Variable
from quad import Quad
import condHelpers
import helpers
quadruple = Quad.instantiate()
symbolTable = SymbolTable.instantiate()
varPointer = None
tempCounter = 0
# getPointingScope
# What: Gets the pointer to either global or class memory
# Parameters: The current Scope (function or class)
# Returns the Scope from the sent function or class
# When is it used: To get the Scope for the quad to be saved
def getPointingScope(currentScope):
if currentScope.getContext() == 'classFunction':
return symbolTable.getGlobalScope().getScopeClasses()[symbolTable.getStack()]
else:
return symbolTable.getGlobalScope()
# check_multdiv_operator
# What: Gets and checks left and right operators for multiplication and division
# Parameters: A quadruple object
# When is it used: When PLY reads a multiplication or division
def check_multdiv_operator(quadruple):
workingStack = quadruple.getWorkingStack()
if workingStack:
if workingStack[-1] == '*' or workingStack[-1] == '/':
right_operand = quadruple.pilaO.pop()
right_type = helpers.getTypeV2(right_operand)
left_operand = quadruple.pilaO.pop()
left_type = helpers.getTypeV2(left_operand)
operator = workingStack.pop()
if quadruple.pOper:
quadruple.pOper.pop()
result_type = SemanticCube[operator][left_type][right_type]
if result_type != 'TYPE MISMATCH':
# get next temp memory depending on type
keyword = ''
if symbolTable.getCurrentScope().getContext() == 'global':
keyword = 'global'
else:
keyword = 'local'
tempAddressPointer = getPointingScope(symbolTable.getCurrentScope()).memory.memSpace[keyword][result_type]['temp']
tempAddress = tempAddressPointer.getInitialAddress() + tempAddressPointer.getOffset()
quadruple.pilaO.append(tempAddress)
symbolTable.getCurrentScope().setLatestExpValue(result_type)
quadruple.saveQuad(operator,left_operand,right_operand, tempAddress)
global tempCounter
symbolTable.getCurrentScope().getScopeTemps()[tempCounter] = (Variable('', result_type, 0, [], tempAddressPointer.getOffset(), False, tempAddressPointer, False))
tempCounter += 1
tempAddressPointer.setOffset()
else:
raise Exception('ERROR! Type Mismatch') #type mismatch
# check_plusminus_operator
# What: Gets and checks left and right operators for addition and subtraction
# Parameters: A quadruple object
# When is it used: When PLY reads a addition or subtraction
def check_plusminus_operator(quadruple):
workingStack = quadruple.getWorkingStack()
if workingStack:
if workingStack[-1] == '+' or workingStack[-1] == '-':
right_operand = quadruple.pilaO.pop()
right_type = helpers.getTypeV2(right_operand)
left_operand = quadruple.pilaO.pop()
left_type = helpers.getTypeV2(left_operand)
operator = workingStack.pop()
if quadruple.pOper:
quadruple.pOper.pop()
result_type = SemanticCube[operator][left_type][right_type]
symbolTable.getCurrentScope().setLatestType(result_type)
if result_type != 'TYPE MISMATCH':
# get next temp memory depending on type
keyword = ''
if symbolTable.getCurrentScope().getContext() == 'global':
keyword = 'global'
else:
keyword = 'local'
tempAddressPointer = getPointingScope(symbolTable.getCurrentScope()).memory.memSpace[keyword][result_type]['temp']
tempAddress = tempAddressPointer.getInitialAddress() + tempAddressPointer.getOffset()
quadruple.pilaO.append(tempAddress)
symbolTable.getCurrentScope().setLatestExpValue(result_type)
quadruple.saveQuad(operator,left_operand,right_operand, tempAddress)
global tempCounter
symbolTable.getCurrentScope().getScopeTemps()[tempCounter] = (Variable('', result_type, 0, [], tempAddressPointer.getOffset(), False, tempAddressPointer, False))
tempCounter += 1
tempAddressPointer.setOffset()
else:
raise Exception('ERROR! Type Mismatch') #type mismatch
# check_relational_operator
# What: Gets and checks left and right operators for relational operators
# Parameters: A quadruple object
# When is it used: When PLY reads a relational operator
def check_relational_operator(quadruple):
workingStack = quadruple.getWorkingStack()
if workingStack:
operatorSet = {'>','<','==','!=','>=','<='}
if workingStack[-1] in operatorSet:
right_operand = quadruple.pilaO.pop()
left_operand = quadruple.pilaO.pop()
right_type = helpers.getTypeV2(right_operand)
left_type = helpers.getTypeV2(left_operand)
operator = workingStack.pop()
if quadruple.pOper:
quadruple.pOper.pop()
result_type = SemanticCube[operator][left_type][right_type]
symbolTable.getCurrentScope().setLatestType(result_type)
if result_type != 'TYPE MISMATCH':
# get next temp memory depending on type
keyword = ''
if symbolTable.getCurrentScope().getContext() == 'global':
keyword = 'global'
else:
keyword = 'local'
tempAddressPointer = getPointingScope(symbolTable.getCurrentScope()).memory.memSpace[keyword][result_type]['temp']
tempAddress = tempAddressPointer.getInitialAddress() + tempAddressPointer.getOffset()
quadruple.pilaO.append(tempAddress)
tempAddressPointer.setOffset()
quadruple.saveQuad(operator,left_operand,right_operand,tempAddress)
global tempCounter
symbolTable.getCurrentScope().getScopeTemps()[tempCounter] = (Variable('', result_type, 0, [], tempAddressPointer.getOffset(), False, tempAddressPointer, False))
tempCounter += 1
symbolTable.getCurrentScope().setLatestExpValue(result_type)
else:
raise Exception('ERROR! Type Mismatch') #type mismatch
# check_and_or_operator
# What: Gets and checks left and right operators for relational operators
# Parameters: A quadruple object
# When is it used: When PLY reads a relational operator
def check_and_or_operator(quadruple):
workingStack = quadruple.getWorkingStack()
if workingStack:
if workingStack[-1] == '&&' or workingStack[-1] == '||':
right_operand = quadruple.pilaO.pop()
right_type = helpers.getTypeV2(right_operand)
left_operand = quadruple.pilaO.pop()
left_type = helpers.getTypeV2(left_operand)
operator = workingStack.pop()
if quadruple.pOper:
quadruple.pOper.pop()
result_type = SemanticCube[operator][left_type][right_type]
if result_type != 'TYPE MISMATCH':
# get next temp memory depending on type
keyword = ''
if symbolTable.getCurrentScope().getContext() == 'global':
keyword = 'global'
else:
keyword = 'local'
tempAddressPointer = getPointingScope(symbolTable.getCurrentScope()).memory.memSpace[keyword][result_type]['temp']
tempAddress = tempAddressPointer.getInitialAddress() + tempAddressPointer.getOffset()
quadruple.pilaO.append(tempAddress)
quadruple.saveQuad(operator,left_operand,right_operand, tempAddress)
global tempCounter
symbolTable.getCurrentScope().getScopeTemps()[tempCounter] = (Variable('', result_type, 0, [], tempAddressPointer.getOffset(), False, tempAddressPointer, False))
tempCounter += 1
tempAddressPointer.setOffset()
symbolTable.getCurrentScope().setLatestExpValue(result_type)
else:
raise Exception('ERROR! Type Mismatch') #type mismatch
# expression_evaluation
# What: Solves expressions when completed
# Parameters: P (what's stored in PLY's syntax)
# When is it used: Everytime an expression ends
def expression_evaluation(p):
if not quadruple.pOper or quadruple.pOper[-1] == '=' or quadruple.pOper[-1] == 'print':
if not quadruple.pOper:
# if it comes from a conditional
if p[-2] == 'if' or p[-3] == 'while':
condHelpers.enterCond()
# regular assignments
elif quadruple.pOper[-1] == '=':
right_operand = quadruple.pilaO.pop() # this should be a value
left_operand = quadruple.pilaO.pop() # this should be an id
right_type = helpers.getTypeV2(right_operand)
left_type = helpers.getTypeV2(left_operand)
if right_type == left_type:
quadruple.saveQuad('=', right_operand, -1 ,left_operand)
else:
raise Exception("ERROR! cannot assign type {} to {}".format(left_type, right_type))
quadruple.pOper.pop()
# print statements
elif quadruple.pOper[-1] == 'print' and not symbolTable.getCurrentScope().getMatchingParams():
print_operand = quadruple.pilaO.pop() # this should be the value to print
quadruple.saveQuad('print', -1, -1, print_operand)
# verifying array dimensions
elif quadruple.pOper[-1] == '$':
lsPointer = quadruple.pilaDim[-1]["id"].getDimensionNodes()
currentDim = quadruple.pilaDim[-1]["dim"]
quadruple.saveQuad("verify", quadruple.pilaO[-1], 0, lsPointer[currentDim-1].getLim()) # -1 because array index
keyword = ''
if symbolTable.getCurrentScope().getContext() == 'global':
keyword = 'global'
else:
keyword = 'local'
currType = helpers.getTypeV2(quadruple.pilaO[-1])
tempAddressPointer = getPointingScope(symbolTable.getCurrentScope()).memory.memSpace[keyword][currType]['temp']
tempAddress = tempAddressPointer.getInitialAddress() + tempAddressPointer.getOffset()
global tempCounter
# if array has another dimension still, multiply S1 by MDim1
if len(lsPointer) > currentDim:
aux = quadruple.pilaO.pop()
quadruple.saveQuad("*a", aux, lsPointer[currentDim-1].getMDim(), tempAddress)
symbolTable.getCurrentScope().getScopeTemps()[tempCounter] = (Variable('', currType, 0, [], tempAddressPointer.getOffset(), False, tempAddressPointer, False))
tempCounter += 1
quadruple.pilaO.append(tempAddress)
tempAddressPointer.setOffset()
# if array has more than 1 dimension, generate quads
if currentDim > 1:
left_operand = quadruple.pilaO.pop()
right_operand = quadruple.pilaO.pop()
tempAddress = tempAddressPointer.getInitialAddress() + tempAddressPointer.getOffset()
quadruple.saveQuad("+", left_operand, right_operand, tempAddress)
symbolTable.getCurrentScope().getScopeTemps()[tempCounter] = (Variable('', currType, 0, [], tempAddressPointer.getOffset(), False, tempAddressPointer, False))
tempCounter += 1
quadruple.pilaO.append(tempAddress)
tempAddressPointer.setOffset()
# check that void functions do not have return values
elif quadruple.pOper[-1] == 'return':
if symbolTable.getCurrentScope().getScopeType() == 'void':
if quadruple.pilaO[-1]:
raise Exception("ERROR! Void functions cannot return values")
expValue = quadruple.pilaO.pop()
expValueType = helpers.getTypeV2(expValue)
if expValueType != symbolTable.getCurrentScope().getScopeType():
raise Exception("ERROR! Type mismatch in returning function")
# if void, return should have no expValue
quadruple.saveQuad('return', -1, -1, expValue)
quadruple.pOper.pop()
# endDim
# What: Creates the quads when an array is finished being called
# Parameters: variable with dimensions
# When is it used: Everytime an array variable is called, not declared
def endDim(var):
current = symbolTable.getCurrentScope()
aux = quadruple.pilaO.pop()
varPointerDimNodes = var.getDimensionNodes()
keyword = ''
if symbolTable.getCurrentScope().getContext() == 'global':
keyword = 'global'
else:
keyword = 'local'
currType = helpers.getTypeV2(quadruple.pilaO[-1])
tempAddressPointer = getPointingScope(symbolTable.getCurrentScope()).memory.memSpace[keyword][currType]['temp']
tempAddress = tempAddressPointer.getInitialAddress() + tempAddressPointer.getOffset()
quadruple.saveQuad("+a", aux, varPointerDimNodes[var.getDimensions()-1].getOffset(), tempAddress)
global tempCounter
symbolTable.getCurrentScope().getScopeTemps()[tempCounter] = (Variable('', currType, 0, [], tempAddressPointer.getOffset(), False, tempAddressPointer, False))
tempCounter += 1
tempAddressPointer.setOffset()
tempAddress2 = tempAddressPointer.getInitialAddress() + tempAddressPointer.getOffset()
quadruple.saveQuad("+a", tempAddress, var.getVirtualAddress(), tempAddress2)
symbolTable.getCurrentScope().getScopeTemps()[tempCounter] = (Variable('', currType, 0, [], tempAddressPointer.getOffset(), False, tempAddressPointer, False))
tempCounter += 1
quadruple.pilaO.pop() # gets rid of dirBase
tempAddressPointer.setOffset()
quadruple.pilaO.append([tempAddress2])
quadruple.pOper.pop() # eliminates fake bottom
quadruple.pilaDim.pop()
current.resetLatestDimension()
return True