def p_draw_line(p): ''' DRAW_LINE : ''' global operandsList global quadruples y2 = operandsList.pop() x2 = operandsList.pop() y1 = operandsList.pop() x1 = operandsList.pop() point1 = Operand("point1", (x1.value, y1.value), (x1.type, y1.type), (x1.vAddress, y1.vAddress)) point2 = Operand("point2", (x2.value, y2.value), (x2.type, y2.type), (x2.vAddress, y2.vAddress)) if ((y2.type != "int") and (y2.type != "float")) or ( (x2.type != "int") and (x2.type != "float")) or ( (y1.type != "int") and (y1.type != "float")) or ((x1.type != "int") and (x1.type != "float")): errorQueue.append( "Error: " + "Failed operation, int or float type parameters expected.") print("Error: " + "Failed operation, int or float type parameters expected. ") else: quadruples.addDrawLineCuadruple(point1, point2)
def validate_function_call(self): if self.param_count != self.AT.funcs[ self.current_function_call].num_params: raise NameError( f"Wrong number of parameters passed. Expected {self.AT.funcs[self.current_function_call].num_params}. {self.param_count} were given." ) else: self.generate_quadruple( Operator.GOSUB, self.current_function_call, None, self.AT.funcs[self.current_function_call].first_quadruple) func = self.AT.get_func(self.current_function_call) func_return_type = func.get_return_type() if func_return_type is not Type.VOID: tmp_address = self.memory_manager.set_temp_address( func_return_type) temp = Operand(address=tmp_address) func_address = self.AT.get_global_var( self.current_function_call).get_address() self.generate_quadruple(Operator.ASSIGN, func_address, None, tmp_address) self.operands.append(temp) self.types.append(func_return_type) self.operators.pop()
def maybe_solve_operation(self, operations): operator = self.get_top_operator() if operator in operations: r_operand = self.operands.pop() r_type = self.types.pop() l_operand = self.operands.pop() l_type = self.types.pop() operator = self.operators.pop() result_type = semantic_cube[l_type][r_type][operator] if result_type == Type.ERROR: raise NameError(f"Type mismatch {l_type} {operator} {r_type}") temp = Operand() temp.set_type(result_type) address = self.memory_manager.set_temp_address(result_type) temp.set_address(address) self.curr_t_count += 1 self.operands.append(temp) self.types.append(result_type) self.generate_quadruple(operator, l_operand.get_address(), r_operand.get_address(), address)
def p_cte(p): ''' CTE : cte_i | cte_f | cte_c | null ''' global cteValue global cteType global operandsList global dirAddresses global funcName cteValue = p[1] if isinstance(p[1], int): cteType = "int" elif isinstance(p[1], float): cteType = "float" elif p[1] == "null": cteType = "string" elif isinstance(p[1], str): cteType = "char" addressTableKey = determineTypeAddressTable(None, cteType, cteValue, None) vAddress = dirAddresses[addressTableKey].getAnAddress() dirAddresses[addressTableKey].saveAddressData(vAddress, cteValue, cteType) #print (str(vAddress) + " : " + str(dirAddresses[addressTableKey].getAddressData(vAddress)["value"])) if p[1] == "null": cteType = "null" consOperand = Operand(None, cteValue, cteType, vAddress) operandsList.append(consOperand)
def randomOperand(self): operand = Operand() for digit in self.digits.keys(): operand.addDigit(digit, self.digits[digit].randomInt()) if (self.explicitRange == []): return operand elif (self.explicitRange != [] and operand.value() in self.explicitRange): return operand else: return self.randomOperand()
def addExpressionCuadruple(self, operator, leftOperand, rightOperand, dirAddresses): result_type = SC[leftOperand.type][rightOperand.type][operator] if result_type == "error": return "Failed operation. type missmatch: cannot do " + operator + " operation between " + leftOperand.type + " and " + rightOperand.type else: self.resultsCounter += 1 resultName = "result" + str(self.resultsCounter) addressTableKey = determineTypeAddressTable(None,result_type,None,True) vAddress = dirAddresses[addressTableKey].getAnAddress() resultOperand = Operand(resultName, None, result_type, vAddress) self.quadruples.append( (operator, leftOperand, rightOperand, resultOperand) ) return resultOperand
def p_sem_add_gosub(p): ''' SEM_ADD_GOSUB : ''' global funcCall global quadruples global operandsList global funcDirec quadruples.addGosubFuncQuadruple(funcCall) funcCallType = funcDirec.getFuncReturnType(funcCall) if not funcCallType == "void": operandsList.append(Operand(funcCall, None, funcCallType, funcCall))
def p_do_color(p): ''' DO_COLOR : cte_s ''' global dirAddresses global operandsList global quadruples cteValue = p[1] cteType = "string" addressTableKey = determineTypeAddressTable(None, cteType, cteValue, None) vAddress = dirAddresses[addressTableKey].getAnAddress() colorOperand = Operand(None, cteValue, cteType, vAddress) dirAddresses[addressTableKey].saveAddressData(vAddress, cteValue, cteType) quadruples.addColorQuadruple(colorOperand)
def get_array_dir(self): operand = self.operands.pop() var, _ = self.arrays.pop() self.types.pop() # To make things easy, our tp are normal temporary address but with negative address value tmp_address = self.memory_manager.set_temp_address(Type.INT) * -1 t = Operand(address=tmp_address) # Add base address base_address = var.get_address() const_address = self.AT.get_constant_address(base_address, Type.INT) if const_address == -1: # It doesn't exist. const_address = self.memory_manager.set_constant_address(Type.INT) self.AT.add_constant_address(base_address, Type.INT, const_address) self.generate_quadruple(Operator.PLUS, operand.get_address(), const_address, tmp_address * -1) self.operands.append(t) self.types.append(Type.INT)
def p_sem_add_print_cte_s(p): ''' SEM_ADD_PRINT_CTE_S : cte_s ''' global operandsList global quadruples global dirAddresses global funcName cteValue = p[1] cteType = "string" addressTableKey = determineTypeAddressTable(None, cteType, cteValue, None) vAddress = dirAddresses[addressTableKey].getAnAddress() consOperand = Operand(None, cteValue, cteType, vAddress) dirAddresses[addressTableKey].saveAddressData(vAddress, cteValue, cteType) quadruples.addPrintCuadruple(consOperand)
def ver_index(self): var, dim_num = self.arrays.pop() if dim_num == 0: self.current_array_address = 0 self.current_array_dim_number = var.get_dim_count() if self.current_dim == self.current_array_dim_number: raise NameError(f'Trying to access a non-existent dimension') s_address = self.operands.pop().get_address() self.types.pop() dim = var.get_dim(dim_num) lim_inf = self.AT.get_constant_address(dim.get_lim_inf(), Type.INT) lim_sup = self.AT.get_constant_address(dim.get_lim_sup(), Type.INT) self.generate_quadruple(Operator.VER, s_address, lim_inf, lim_sup) # Following the formula s1*m1 + s2 + (-k).... tmp_address = self.memory_manager.set_temp_address(Type.INT) t = Operand(address=tmp_address, op_type=Type.INT) m = dim.get_m() m_address = self.AT.get_constant_address(m, Type.INT) # If it doesn't exist, create a new constant address for it. if m_address == -1: m_address = self.memory_manager.set_constant_address(Type.INT) self.AT.add_constant_address(m, Type.INT, m_address) # Multiply m of the current Dim node if it's not the last dim if dim_num < self.current_array_dim_number - 1: self.generate_quadruple(Operator.TIMES, s_address, m_address, tmp_address) # Add (-k) if it's the last Dim node else: k_address = m_address self.generate_quadruple(Operator.PLUS, s_address, k_address, tmp_address) if dim_num != 0: aux = self.operands.pop() self.types.pop() tmp_address_2 = self.memory_manager.set_temp_address(Type.INT) self.generate_quadruple(Operator.PLUS, aux.get_address(), tmp_address, tmp_address_2) t.set_address(tmp_address_2) self.operands.append(t) self.types.append(Type.INT) self.arrays.append((var, dim_num + 1))
def maybe_solve_sign(self): operator = self.get_top_operator() if operator in (Operator.POSITIVE_SIGN, Operator.NEGATIVE_SIGN, Operator.NOT): operand = self.operands.pop() operand_type = self.types.pop() operator = self.operators.pop() result_type = semantic_cube[operand_type][operator] if result_type == Type.ERROR: raise NameError(f'Type mismatch {operand_type} {operator}') temp = Operand(op_type=result_type) address = self.memory_manager.set_temp_address(result_type) temp.set_address(address) self.curr_t_count += 1 self.generate_quadruple(operator, operand.get_address(), None, temp.get_address()) self.operands.append(temp) self.types.append(result_type)
def build_operand_object(self, name, is_function_call=False): t = type(name) operand = Operand(name, is_function_call=is_function_call) if t == int: operand.set_type(Type.INT) address = self.AT.get_constant_address(name, Type.INT) if address == -1: # It doesn't exist. address = self.memory_manager.set_constant_address(Type.INT) self.AT.add_constant_address(name, Type.INT, address) operand.set_address(address) elif t == float: operand.set_type(Type.FLOAT) address = self.AT.get_constant_address(name, Type.FLOAT) if address == -1: # It doesn't exist. address = self.memory_manager.set_constant_address(Type.FLOAT) self.AT.add_constant_address(name, Type.FLOAT, address) operand.set_address(address) elif t == str: # if constant if name[0] == "\"" and name[-1] == "\"": operand.set_type(Type.STRING) address = self.AT.get_constant_address(name, Type.STRING) if address == -1: # It doesn't exist. address = self.memory_manager.set_constant_address( Type.STRING) self.AT.add_constant_address(name, Type.STRING, address) operand.set_address(address) else: # Variable var = self.find_var_in_address_table(name) if var == -1: raise NameError(f'Undeclared variable {name}') operand.set_address(var.get_address()) operand_type = self.get_type_from_address(var.get_address()) operand.set_type(operand_type) return operand
def add_var(self, var_name, is_param=False, is_array=False): func = None operand = Operand(name=var_name, op_type=types[self.last_var_type], is_array=is_array) if self.is_global: self.AT.add_global_address(operand) else: func = self.get_current_func() func.add_var(operand) if is_param: func.num_params += 1 func.param_names.append(var_name) if is_array: func.current_var_name = var_name self.r = 1 else: # Address is only set for non-arrays for now. Address for arrays should be set after knowing the total needed memory space for the array. scope = Scope.GLOBAL if self.is_global else Scope.LOCAL var_address = self.memory_manager.set_address( scope=scope, var_type=types[self.last_var_type]) var = self.find_var_in_address_table(var_name) var.set_address(var_address)
def p_variable(p): ''' VARIABLE : SEM_ID_FOR_ARRAY '[' EXPRESION SEM_CHECK_ARRAY ']' | id ''' global varName global funcDirec global operandsList global funcDirec global dirAddresses global funcName #es una variable en una expresion, no un arreglo if len(p) < 3: varName = p[1] retrievedVar = funcDirec.getVariableInFunc(funcName, varName) if isinstance(retrievedVar, str): errorQueue.append("Error: " + retrievedVar) print("Error: ", retrievedVar) else: operandsList.append( Operand(varName, None, retrievedVar["varType"], retrievedVar["vAddress"]))
def parse(self) -> RecordList: record_list = RecordList() with open(self.src) as fd: for line in fd.readlines(): line = line.replace('=>', ' ') line = line.replace(',', ' ') operator, *operand = line.split() if operator.startswith("//"): # this is comment line continue # remove inline comment i = 0 for i, _ in enumerate(operand): op = operand[i] if op == '//': break operand = operand[:i + 1] if operator in Operator.NOP_OPERATOR: record_list.append(Record(Operator(operator))) elif operator in Operator.UNARY_OPERATOR: record_list.append( Record(Operator(operator), Operand(operand[0]))) elif operator in Operator.BINARY_OPERATOR: if len(operand) != 2: raise ValueError("invalid operand: {}".format(operand)) record_list.append( Record(Operator(operator), operand_one=Operand(operand[0]), operand_three=Operand(operand[1]))) elif operator in Operator.TRIPLE_OPERATOR: record_list.append( Record(Operator(operator), Operand(operand[0]), Operand(operand[1]), Operand(operand[2]))) else: raise ValueError("invalid operator: {}".format(operator)) return record_list
def addReturnCuadruple(self,funcName, operand, dirAddresses): #addressTableKey = determineTypeAddressTable("global",operand.type,None,None) #vAddress = dirAddresses[addressTableKey].getAnAddress() resultOperand = Operand(funcName, None, operand.type, funcName) self.quadruples.append( ("return", operand, None, resultOperand) ) return resultOperand
def addParamFuncQuadruple(self, param, paramsCounter): resultName = "param" + str(paramsCounter) resultOperand = Operand(resultName, None, param.type, param.vAddress) self.quadruples.append( ("parameter", param, None, resultOperand) )
def p_sem_check_array(p): ''' SEM_CHECK_ARRAY : ''' global idForArray global funcDirec global operandsList global operatorsList global funcDirec global dirAddresses global funcName global quadruples #checa si existe el arreglo retrievedArrayData = funcDirec.getVariableInFunc(funcName, idForArray) if isinstance(retrievedArrayData, str): errorQueue.append("Error: " + retrievedArrayData) print("Error: ", retrievedArrayData) elif not retrievedArrayData["isArray"]: errorQueue.append("Error: Failed operation. " + "variable " + idForArray + " is not an array") print("Error: Failed operation. " + "variable " + idForArray + " is not an array") else: arrayIndexExpression = operandsList.pop() #print (arrayIndexExpression.value) #print (arrayIndexExpression.type) #checa que el index del arreglo sea tipo int if arrayIndexExpression.type != "int": errorQueue.append( "Error: Failed operation. Int type index expected for array " + idForArray + ". " + arrayIndexExpression.type + "type was received instead.") print("Error: ", retrievedVar) #si ya recibi un index que es una constante if isinstance(arrayIndexExpression.value, int): actualAddress = retrievedArrayData[ "vAddress"] + arrayIndexExpression.value #checa que el index tipo int del arreglo se encuentre en el rango de direcciones validas para el arreglo if (actualAddress < retrievedArrayData["vAddress"]) or ( actualAddress > retrievedArrayData["sLimit"]): errorQueue.append("Error: Failed operation. Index " + arrayIndexExpression.value + " is out of bounds for array " + idForArray) print("Error: ", retrievedVar) else: operandsList.append( Operand(idForArray, None, retrievedArrayData["varType"], actualAddress)) #oh sorpresa, el index es una expresion cuyo valor solo se puede conocer en ejecucion, por lo tanto no sabemos el address del arreglo else: #Guarda la direccion base del arreglo en una direccion temporal addressTableKey = determineTypeAddressTable( None, "int", retrievedArrayData["vAddress"], None) vAddress = dirAddresses[addressTableKey].getAnAddress() dirAddresses[addressTableKey].saveAddressData( vAddress, retrievedArrayData["vAddress"], "int") #Crea un operando que represente la direccion base del arreglo baseAddressOperand = Operand(None, retrievedArrayData["vAddress"], "int", vAddress) #Suma el operando de la direccion base con el operando del indicie del arreglo para obtener la verdadera direccion realAdressOperand = quadruples.addExpressionCuadruple( "+", baseAddressOperand, arrayIndexExpression, dirAddresses) funcDirec.addTempVarCountInFunc(funcName, realAdressOperand.type) #baseArrayInfo = Operand(idForArray, None, retrievedArrayData["varType"],retrievedArrayData["vAddress"]) #resultOperand = quadruples.addArrayIndexCuadruple(baseArrayInfo,realAdressOperand) #Crea un operando de resultado con la informacion basica del arreglo (nombre, funcion, direccion base) resultOperand = Operand(idForArray, funcName, retrievedArrayData["varType"], realAdressOperand.vAddress) #y ademas, agregale al operando de resultado la info del operando tipo apuntador que tiene guardada su verdadera direccion (la migaja de pan para encontrar al operando del arreglo en los cuadruplos siguientes y resolver su address correcta en ejecucion) resultOperand.fakeAddress = realAdressOperand.vAddress quadruples.addArrayIndexCuadruple(resultOperand) copyResultOperand = Operand(resultOperand.name, resultOperand.value, resultOperand.type, resultOperand.vAddress) copyResultOperand.fakeAddress = realAdressOperand.vAddress operandsList.append(copyResultOperand)
from Composite import Composite from Operand import Operand from Add import Add from Multiply import Multiply #(10 + 25) * 4 + 52 * (3 + 6) expression = Composite(0) first_brackets = Add(Operand(10), Operand(25)) mul = Multiply(first_brackets, Operand(4)) second_brackets = Add(Operand(3), Operand(6)) mul2 = Multiply(second_brackets, Operand(52)) add = Add(mul, mul2) expression.add(add) print(expression.operation())
def __instructions_operands_init__(self): self.loopSize = self.xmldoc.getElementsByTagName( 'loopSize')[0].attributes['value'].value print("loop Size: " + self.loopSize) self.percentage_clue = self.xmldoc.getElementsByTagName( 'instruction_percentage_clue')[0].attributes['value'].value print("Percentage clue? :" + self.percentage_clue) self.instruction_types = {} #a dictionary of instruction type and the amount of each instruction in loop.. Note useful only when percentage clue is True self.instructions = {} #a dictionay that has for keeps an array of instructions for every instruction type self.allInstructionArray = [] #An array which hold all instructions self.operands = {} self.toggleInstructionsList = {} itemList = self.xmldoc.getElementsByTagName("instruction_type") for instruction_type in itemList: name = instruction_type.attributes["id"].value perc = instruction_type.attributes["perc"].value self.instruction_types[name] = int( float(perc) * float(self.loopSize)) '''calculate how many of these instructions will be in the loop''' if (self.percentage_clue == "True"): print("amount per instruction type in the loop:") print(self.instruction_types) sum = 0 for value in list(self.instruction_types.values()): sum += value self.loopSize = sum print("actual loop size is " + str(self.loopSize)) itemList = self.xmldoc.getElementsByTagName("operand") print("Available operands\n") for operandDesc in itemList: ins_type = operandDesc.attributes["type"].value if (ins_type == "immediate" or ins_type == "constant" or ins_type == "automatically_incremented_operand"): anOperand = Operand( id=operandDesc.attributes["id"].value, type=operandDesc.attributes["type"].value, values=[], min=operandDesc.attributes["min"].value, max=operandDesc.attributes["max"].value, stride=operandDesc.attributes["stride"].value, toggleable=operandDesc.attributes["toggle"].value) #elif ins_type=="branch_label": # anOperand = BranchLabel(id=operandDesc.attributes["id"].value,ins_type=operandDesc.attributes["type"].value,values=operandDesc.attributes["values"].value.split(),min=operandDesc.attributes["min"].value,max=operandDesc.attributes["max"].value,stride=operandDesc.attributes["stride"].value,toggleable=operandDesc.attributes["toggle"].value); else: anOperand = Operand( id=operandDesc.attributes["id"].value, type=operandDesc.attributes["type"].value, values=operandDesc.attributes["values"].value.split(), toggleable=operandDesc.attributes["toggle"].value) print("id " + anOperand.id.__str__()) print("values ") print(anOperand.values) print("max " + anOperand.max.__str__()) print("min " + anOperand.min.__str__()) print("stride " + anOperand.stride.__str__() + "\n") self.operands[anOperand.id] = anOperand print("End of available operands\n") itemList = self.xmldoc.getElementsByTagName("instruction") print("Available instructions\n") for instructionDesc in itemList: name = instructionDesc.attributes["name"].value ins_type = instructionDesc.attributes["type"].value numOfOperands = instructionDesc.attributes["num_of_operands"].value if "format" in instructionDesc.attributes: anInstruction = Instruction( name, ins_type, numOfOperands, format=instructionDesc.attributes["format"].value, toggleable=instructionDesc.attributes["toggle"].value) else: print( "Instruction " + name + "doesnt have format specified.. All instructions must have format... Exitting" ) sys.exit() #anInstruction = Instruction(name,ins_type,numOfOperands,toggleable=instructionDesc.attributes["toggle"].value); if (instructionDesc.attributes["toggle"].value == "True"): self.toggleInstructionsList[ instructionDesc.attributes["name"].value] = 1 operands = [] #TODO fix this source of bugs.. It's irritating when the num of operands does not match the operands specified in the xml file. and in general is stupid to how the operands specified and the number of operands at the same time.. this redundancy leads to bugs for i in range(1, int(anInstruction.numOfOperands) + 1): operands.append(self.operands[( instructionDesc.attributes["operand" + i.__str__()].value)].copy()) anInstruction.setOperands(operands) print(anInstruction) ##for debugging self.instructions.setdefault(anInstruction.ins_type, []).append(anInstruction) #print (self.instructions); print("End of available instructions\n") for array in list(self.instructions.values()): for ins in array: self.allInstructionArray.append(ins) print("register initialization")