-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunctionDirectory.py
313 lines (246 loc) · 8.56 KB
/
functionDirectory.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
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
import config
from collections import defaultdict
## -- CONSTANT
class Constant():
def __init__(self, value, vartype, vAddr):
self.value = value
self.vartype = vartype
self.vAddr = vAddr
## -- VARIABLE
class Var():
def __init__(self, name, vartype, vAddr):
self.name = name
self.vartype = vartype
self.dims = []
self.vAddr = vAddr
## -- FUNCTION
class Function():
def __init__(self, name, returnType):
self.debug = config.debugParser
self.name = name
self.returnType = returnType
self.returnAddr = None
self.returnDims = []
self.quadStart = None
self.varTable = None
self.paramTable = []
self.era = []
## GETTERS
# Get variable
def getVar(self, name):
return self.varTable[name]
# Get dimensions of a specified variable
def getDimensionsOfVar(self, name):
return self.varTable[name].dims
# Get return address for function
def getReturnAddr(self):
return self.returnAddr
# Get return dimensions for function
def getReturnDims(self):
return self.returnDims
## SETTERS
# Set return address for function
def setReturnAddr(self, addr):
self.returnAddr = addr
# Set return dimensions for function
def setReturnDims(self, dims):
self.returnDims = dims
# Set start of quad for function
def setQuadStart(self, qs):
self.quadStart = qs
def setVarDims(self, var, dims):
self.varTable[var].dims = dims
if self.debug:
v = self.varTable[var]
space = 1
for i in v.dims:
space *= i
space += v.vAddr - 1
print(f'\t\t\t\t\t>> VAR: {v.name} - {v.vartype}{v.dims} -> {v.vAddr} - {space}')
# Set "era" (local and temporary counters)
def setEra(self, era):
self.era = era
## PUSH/ADD
# Add variable
def addVar(self, name, vartype, vAddr):
self.varTable[name] = Var(name, vartype, vAddr)
if self.debug:
v = self.varTable[name]
print(f'\t\t\t\t\t> VAR: {v.name} - {v.vartype} -> {v.vAddr}')
# Add parameter
def addParam(self, vartype, vAddr):
self.paramTable.append((vartype, vAddr, []))
# Add dimensions to latest parameter
def addParamDims(self, dims):
param = self.paramTable[-1]
self.paramTable[-1] = (param[0], param[1], dims)
# Create var table
def createVarTable(self):
self.varTable = dict()
# Delete var table
def deleteVarTable(self):
self.varTable = None
## -- FUNCTION DIRECTORY
class FunctionDirectory():
def __init__(self):
self.debug = config.debugParser
self.directory = dict()
self.cteTable = dict()
self.globalFunc = None
self.currentFunc = None
self.currentType = "void"
self.paramCount = 0
self.varHelper = None
## SETTERS
# NOTE: `currentFunc` is set in addFunction()
# Set name for global function
def setGlobalFunction(self):
self.globalFunc = self.currentFunc
# Set name for current function
def setCurrentFunction(self, currentFunc):
self.currentFunc = currentFunc
# Set current type used in parser
def setCurrentType(self, t):
self.currentType = t
# Set var helper used in parser
def setVarHelper(self, var):
self.varHelper = var
# Set dimensions for current var
def setVarDims(self, dims):
self.directory[self.currentFunc].setVarDims(self.varHelper, dims)
# Set return address for current function
def setReturnAddr(self, addr):
self.directory[self.currentFunc].setReturnAddr(addr)
# Set return dims for current function
def setReturnDims(self, dims):
self.directory[self.currentFunc].setReturnDims(dims)
# Set start of quad for current function
def setQuadStart(self, qs):
self.directory[self.currentFunc].setQuadStart(qs)
# Set "era" for current function
def setEra(self, era):
self.directory[self.currentFunc].setEra(era)
# Increment param count of function by 1
def incrementParamCount(self):
self.paramCount += 1
# Reset param count to 0
def resetParamCount(self):
self.paramCount = 0
## GETTERS
# Returns desired variable
def getVar(self, name):
ret = None
# Priority: Local -> Global
if name in self.directory[self.currentFunc].varTable:
ret = self.directory[self.currentFunc].getVar(name)
elif name in self.directory[self.globalFunc].varTable:
ret = self.directory[self.globalFunc].getVar(name)
else: # Else, raise an error
raise Exception(f'Variable {name} does not exist!')
return ret
# Returns virtual address of desired variable
def getVAddr(self, name):
try: # Get vAddr of variables
return self.getVar(name).vAddr
except: # If it reaches here, that means it's already an address
return name
# Get constant
def getCte(self, value, vartype):
return self.cteTable[(value, vartype)]
# Get dimensions of a specified variable
def getDimensionsOfVar(self, name):
try:
return self.getVar(name).dims
except:
raise Exception(f'Variable {name} does not exist!')
# Get parameter of function
def getParamOfFunc(self, func):
return self.directory[func].paramTable[self.paramCount]
# Get quadStart of function
def getQuadStartOfFunc(self, func):
return self.directory[func].quadStart
# Get a function's return type
def getReturnTypeOfFunc(self, func):
return self.directory[func].returnType
# Get a function's return dimensions
def getReturnDimsOfFunc(self, func):
return self.directory[func].returnDims
# Get a function's return dimension size
def getReturnSizeOfFunc(self, func):
space = 1
for d in self.directory[func].returnDims:
space *= d
return space
# Get a function's return address
def getReturnAddrOfFunc(self, func):
return self.directory[func].returnAddr
# Get the current function's return type
def getCurrentFuncReturnType(self):
return self.getReturnTypeOfFunc(self.currentFunc)
# Get the current function's return dims
def getCurrentFuncReturnDims(self):
return self.getReturnDimsOfFunc(self.currentFunc)
# Get the current function's return dimension size
def getCurrentFuncReturnSize(self):
return self.getReturnSizeOfFunc(self.currentFunc)
# Get the current function's return address
def getCurrentFuncReturnAddr(self):
return self.getReturnAddrOfFunc(self.currentFunc)
# Get ERA of function
def getEra(self, func):
return self.directory[func].era
## PUSH/ADD
# Adds function to the directory
def addFunction(self, name):
self.directory[name] = Function(name, self.currentType)
self.currentFunc = name
if self.debug:
print(f'-- {self.currentFunc} - {self.currentType}')
# Add parameters to current function
def addFuncParam(self, vAddr):
self.directory[self.currentFunc].addParam(self.currentType, vAddr)
# Add dimensions to parameter of a current function
def addFuncParamDims(self, dims):
self.directory[self.currentFunc].addParamDims(dims)
# Add variable to the current function's var table
def addVar(self, name, vAddr):
self.directory[self.currentFunc].addVar(name, self.currentType, vAddr)
# Add constant
def addCte(self, value, vartype, vAddr):
self.cteTable[(value, vartype)] = Constant(value, vartype, vAddr)
if self.debug:
c = self.cteTable[(value, vartype)]
print(f'\t\t\t\t\t> CTE: {c.value} - {c.vartype} -> {c.vAddr}')
# Add dimension to a specified variable in the current scope
def addDimensionToVar(self, var, dim):
self.directory[self.currentFunc].addDimensionToVar(var, dim)
## FUNCTIONS
# Creates var table for current function
def createVarTable(self):
if self.directory[self.currentFunc].varTable is None:
self.directory[self.currentFunc].createVarTable()
# Deletes var table for current function
def deleteVarTable(self):
self.directory[self.currentFunc].deleteVarTable()
self.currentFunc = self.globalFunc
# Verify number of parameters of function
def verifyParamCount(self, func):
return (self.paramCount == len(self.directory[func].paramTable))
# Return boolean if function exists
def functionExists(self, func):
if func in self.directory:
return True
return False
# Returns a boolean if variable exists in local or global scope
def varExists(self, var):
if var in self.directory[self.currentFunc].varTable or var in self.directory[self.globalFunc].varTable:
return True
return False
# Returns a boolean if a constant exists
def cteExists(self, cte, vartype):
return (cte, vartype) in self.cteTable
# Returns a boolean if variable is available to declare in current context
def varAvailable(self, var):
if var not in self.directory[self.currentFunc].varTable:
return True
return False