def registerFunc(self, functionName, functionType, line): if self.functionsDir.get(functionName) is not None: exception.fatalError("Función '%s' fue definida anteriormente." % (functionName)) function = { functionName: { 'type': functionType, 'params': [], 'vars': {}, 'goto': line, 'paramAddr': [] }, } self.functionsDir.update(function) self.scope = functionName if functionType != 'void': # agrega una var global para retorno, prefix & para evitar conflictos returnVar = '&' + functionName address = self.memory.assignAddress('global', functionType) self.functionsDir['global']['vars'].update({ returnVar: { 'type': functionType, 'address': address, 'dim1': None, 'dim2': None } }) return True
def getReturnVariable(self, func_id): func = self.functionsDir[func_id] if func['type'] == 'void': exception.fatalError( "Función '%s' no tiene un tipo de retorno válido en expresión." % (func_id)) return self.getVariable('&' + func_id)
def verParamCounter(self, func_id, paramCounter): parCount = len(self.functionsDir[func_id]['paramAddr']) if parCount != paramCounter: exception.fatalError( "Número de parámetros incorrecto para la función '%s'. Se esperaban %s, recibió %s" % (func_id, parCount, paramCounter)) return True
def verify(self, op1, op2, op3): idx = self.memGet(op1) limInf = int(op2) limSup = int(op3) if (idx < limInf or idx >= limSup): exceptions.fatalError("Indice fuera de rango.") self.ip += 1
def div(self, op1, op2, op3): temp1 = self.memGet(op1) temp2 = self.memGet(op2) if (temp2 == 0): exceptions.fatalError("División entre 0") self.memSet(op3, temp1 / temp2) self.ip += 1
def getVariable(self, varId): var = self.functionsDir[self.scope]['vars'].get(varId) if var is not None: return var var = self.functionsDir['global']['vars'].get(varId) if var is not None: return var exception.fatalError("Variable '%s' no ha sido declarada en '%s'." % (varId, self.scope))
def ifStart(self): cond, condType, condMemScope = self.popVar() if condType not in ['bool']: exceptions.fatalError( "Se esperaba bool en condicional se leyó %s" % (condType)) condAddr = self.funcDir.getAddress(cond, condType, condMemScope) buf = "GOTOF %s" % (condAddr) self.pendingLines.append(buf) self.gotoStack.append(self.line) self.writeQuad('if', 'gotof', 'temp', '0') # temporal quadruple
def retorna(self): ret, retType, retMem = self.popVar() retAddr = self.funcDir.getAddress(ret, retType, retMem) globalRetVar = self.funcDir.getReturnVariable(self.funcDir.scope) if globalRetVar['type'] != retType: exceptions.fatalError( "No se puede retornar '%s' en funcion '%s', se esparaba tipo '%s'" % (retType, self.funcDir.scope, globalRetVar['type'])) self.writeQuad("=", retAddr, "0", globalRetVar['address']) self.writeQuad('return', 'goto', 'pending', '0') self.retStack.append(self.line - 1)
def buildAssign(self): op = '=' val, valType, valMem = self.popVar() var, varType, varMem = self.popVar() matches = semantics.match(op, varType, valType) if matches is None: exceptions.fatalError( "No se puede asignar tipo %s a variable de tipo %s" % (valType, varType)) valAddr = self.funcDir.getAddress(val, valType, valMem) varAddr = self.funcDir.getAddress(var, varType, varMem) self.writeQuad('=', valAddr, '0', varAddr)
def whileDo(self): cond, condType, condMemScope = self.popVar( ) # TODO Checar que sea bool (int tambien?) if condType not in ['bool']: exceptions.fatalError( "Se esperaba bool en ciclo mientras, se recibió %s" % (condType)) condAddr = self.funcDir.getAddress(cond, condType, condMemScope) buf = "GOTOF %s" % (condAddr) self.pendingLines.append(buf) self.gotoStack.append(self.line) self.writeQuad('while', 'goto', 'temp', '0')
def validateParam(self, func_id, paramNum, paramType): parCount = len(self.functionsDir[func_id]['params']) if paramNum >= parCount: exception.fatalError( "Número de parámetros incorrecto para la función '%s'. Se esperaban %s, recibió %s." % (func_id, parCount, paramNum + 1)) expected = self.functionsDir[func_id]['params'][ paramNum] # deberia regresar tipo de la variable local if expected != paramType: exception.fatalError( "Se esperaba parámetro de tipo %s. Se recibió %s." % (expected, paramType)) return True
def forDo(self): _limit, limitType, _limitMem = self.peekVar() if limitType != 'int': exceptions.fatalError( "Se esperaba expresion int como limite para iterar en 'desde', se recibió %s" % (limitType)) self.opStack.append("<=") self.buildExp() cond, condType, condMemScope = self.popVar() condAddr = self.funcDir.getAddress(cond, condType, condMemScope) self.gotoStack.append(self.line) buf = "GOTOF %s" % (condAddr) self.pendingLines.append(buf) self.writeQuad('loop', 'gotof', 'temp', '0')
def forStart(self): val, valType, valMem = self.popVar() inc, incType, incMem = self.popVar() if valType != 'int': exceptions.fatalError( "Se esperaba variable int para iterar en 'desde', se recibió %s" % (valType)) valAddr = self.funcDir.getAddress(val, valType, valMem) incAddr = self.funcDir.getAddress(inc, incType, incMem) self.writeQuad("=", valAddr, "0", incAddr) self.idStack.append(inc) self.tpStack.append(incType) self.memStack.append(incMem) self.forIds.append(incAddr) self.gotoStack.append(self.line)
def buildExp(self): op = self.opStack.pop() # pop ids from stack der, derType, derMemScope = self.popVar() izq, izqType, izqMemScope = self.popVar() # get next temp var aux = "t" + str(self.temp) auxType = semantics.match(op, izqType, derType) if auxType is None: exceptions.fatalError("Operador inválido %s para tipos %s y %s" % (op, izqType, derType)) izqAddr = self.funcDir.getAddress(izq, izqType, izqMemScope) derAddr = self.funcDir.getAddress(der, derType, derMemScope) auxAddr = self.funcDir.getAddress(aux, auxType, 'temp') self.writeQuad(op, izqAddr, derAddr, auxAddr) self.idStack.append(aux) self.tpStack.append(auxType) self.memStack.append('temp') self.temp += 1
def accessArray(self): idx, idxType, idxMem = self.peekVar( ) # expresion que se leyo entre brackets [idx][] if idxType != 'int': exceptions.fatalError( "Se esperaba int para indexar arreglo, se recibió %s" % (idxType)) idxAddr = self.funcDir.getAddress(idx, idxType, idxMem) # variable presuntamente dimensionada arrId = self.peek(self.arrStack) arrVar = self.funcDir.getVariable(arrId) # verificacion de limites dim = self.dimStack.pop() + 1 if dim == 1: limit = arrVar['dim1'] if limit is None: exceptions.fatalError( "Variable '%s' no es un arreglo dimensionado" % (arrId)) else: # dim == 2 limit = arrVar['dim2'] if limit is None: exceptions.fatalError( "Variable '%s' no es un arreglo de dos dimensiones" % (arrId)) # checar si esta en rango self.writeQuad('VER', idxAddr, 0, limit) # vuelve a meter al stack para las siguientes operaciones o para self.dimStack.append(dim) if dim == 1 and arrVar['dim2'] is not None: self.idStack.append(arrVar['dim2']) self.tpStack.append('int') self.memStack.append('const') self.opStack.append('*') self.buildExp()
def registerVariable(self, varId, varType, dim1=None, dim2=None): if varType is None: # Si no se manda tipo usar el anterior varType = self.lastType else: # Si se manda tipo guardarlo para siguientes vars self.lastType = varType if self.functionsDir[self.scope]['vars'].get(varId) is not None: exception.fatalError("Variable '%s' duplicada en función '%s'" % (varId, self.scope)) if dim1 == 0 or dim2 == 0: exception.fatalError( "Variable dimensionada %s no puede tener tamaño 0" % (varId)) memoryScope = "local" if self.scope != "global" else "global" address = self.memory.assignAddress(memoryScope, varType, dim1, dim2) self.functionsDir[self.scope]['vars'].update({ varId: { 'type': varType, 'address': address, 'dim1': dim1, 'dim2': dim2 } }) return address
def p_error(p): exceptions.fatalError("Error de sintáxtis en línea %d cerca de '%s'" %(patitoLexer.lexer.lineno, p.value))
def t_error(t): lexer.skip(1) exceptions.fatalError("Caracter ilegal '%s' en línea '%d'" % (t.value[0], lexer.lineno))
def callFunction(self, functionName): if self.functionsDir.get(functionName) is None: exception.fatalError("Función '%s' no existe" % (functionName)) return True