Exemple #1
0
 def end_for(self):
     """
     Completa saltos necesarios al final del ciclo for
     """
     if len(self.jumps_stack) >= 2 and self.operands_stack:
         control = self.get_var(self.operands_stack.pop())
         temp = "_temp_" + str(
             self.temp_vars_index
         )  # Pedir dirección de memoria para el resultado
         self.temp_vars_index += 1
         tipo_res = self.semantic_cube.type_match(control.type, VarType.INT,
                                                  Operator.PLUS)
         temp_address = self.add_temp(temp, tipo_res)
         self.quad_list.append(
             Quadruple(Operator('+'), control.address,
                       self.get_const(1, VarType.INT), temp_address))
         self.quad_list.append(
             Quadruple(Operator.ASSIGN, temp_address, None,
                       control.address))
         end = self.jumps_stack.pop()
         ret = self.jumps_stack.pop()
         self.quad_list.append(Quadruple(Operator('goto'), None, None, ret))
         self.finish_jump(end, len(self.quad_list))
     else:
         raise Exception("Operation stack error: Not enough operands")
Exemple #2
0
 def valor_final_for(self):
     """
     Establece valor final del ciclo for con valor de expresion
     """
     if len(self.operands_stack) >= 2:
         exp = self.get_var(self.operands_stack.pop())
         if exp.type == VarType.INT or exp.type == VarType.FLOAT:
             control = self.get_var(self.operands_stack.pop())
             if control.type == VarType.INT or control.type == VarType.FLOAT:
                 final = "_final_" + control.name
                 final_address = self.add_temp(final, exp.type)
                 self.quad_list.append(
                     Quadruple(Operator.ASSIGN, exp.address, None,
                               final_address))
                 temp = "_temp_" + str(self.temp_vars_index)
                 self.temp_vars_index += 1
                 temp_address = self.add_temp(temp, "bool")
                 self.quad_list.append(
                     Quadruple(Operator('<'), control.address,
                               final_address, temp_address))
                 self.jumps_stack.append(len(self.quad_list) - 1)
                 self.quad_list.append(
                     Quadruple(Operator('gotof'), temp_address, None, None))
                 self.jumps_stack.append(len(self.quad_list) - 1)
                 self.operands_stack.append(control.name)
             else:
                 raise TypeError(
                     "Type mismatch: Control variable is not numeric but " +
                     str(control.type))
         else:
             raise TypeError(
                 "Type mismatch: Final expression for for cycle is not numeric but "
                 + str(exp.type))
     else:
         raise Exception("Operation stack error: Not enough operands")
Exemple #3
0
 def valor_inicial_for(self):
     """
     Inicializa variable de control del ciclo for con valor de expresion
     """
     if len(self.operands_stack) >= 2:
         exp = self.get_var(self.operands_stack.pop())
         if exp.type == VarType.INT or exp.type == VarType.FLOAT:
             control = self.get_var(self.operands_stack.pop())
             tipo_res = self.semantic_cube.type_match(
                 control.type, exp.type, Operator.ASSIGN)
             if tipo_res == VarType.INT or tipo_res == VarType.FLOAT:
                 self.quad_list.append(
                     Quadruple(Operator.ASSIGN, exp.address, None,
                               control.address))
                 self.operands_stack.append(control.name)
             else:
                 raise TypeError(
                     "Type mismatch: Cannot perform operation " +
                     str(Operator.ASSIGN) + " between " +
                     str(control.type) + " and " + str(exp.type))
         else:
             raise TypeError(
                 "Type mismatch: Initial expression for for cycle is not numeric but "
                 + str(exp.type))
     else:
         raise Exception("Operation stack error: Not enough operands")
Exemple #4
0
    def generate_quad_assign(self, name_var="", array=False):
        """
        Función para generar un cuadruplo de asignación utilizando la pila de operandos

        :param name_var: nombre de la variable donde se va a asignar el valor
        """
        if self.operands_stack:
            right_operand = self.get_var(self.operands_stack.pop())
            if array:
                left_operand = self.get_var(self.operands_stack.pop())
            else:
                left_operand = self.get_var(name_var)
            result_type = self.semantic_cube.type_match(
                left_operand.type, right_operand.type, Operator.ASSIGN)
            if result_type != "error":
                self.quad_list.append(
                    Quadruple(Operator.ASSIGN, right_operand.address, None,
                              left_operand.address))
            else:
                raise TypeError("Type mismatch: Cannot perform operation " +
                                str(Operator.ASSIGN) + " between " +
                                str(left_operand.type) + " and " +
                                str(right_operand.type))
        else:
            raise Exception("Operation stack error: not enough operands")
Exemple #5
0
 def generate_quad(self):
     """
     Función para generar un cuadruplo utilizando las pilas de operadores, operandos y tipos
     """
     if len(self.operands_stack) >= 2 and len(
             self.operators_stack) >= 1 and self.operators_stack[-1] != '(':
         right_operand = self.get_var(self.operands_stack.pop())
         left_operand = self.get_var(self.operands_stack.pop())
         operator = Operator(self.operators_stack.pop())
         result_type = self.semantic_cube.type_match(
             left_operand.type, right_operand.type, operator)
         if result_type != "error":
             result_id = "_temp_" + str(self.temp_vars_index)
             result_addr = self.add_temp(result_id, result_type)
             self.temp_vars_index += 1
             self.quad_list.append(
                 Quadruple(Operator(operator), left_operand.address,
                           right_operand.address, result_addr))
             self.operands_stack.append(result_id)
         else:
             raise TypeError("Type mismatch: Cannot perform operation " +
                             str(operator) + " between " +
                             str(left_operand.type) + " and " +
                             str(right_operand.type))
     else:
         raise Exception("Operation stack error: not enough operands")
Exemple #6
0
    def generar_lectura(self, var_name):
        """
        Genera cuadruplo con operando de read y direccion de la variable que recibe el valor

        :var_name: Variable donde se guardara el valor a leer
        """
        var = self.get_var(var_name)
        self.quad_list.append(Quadruple(Operator.READ, None, None,
                                        var.address))
Exemple #7
0
    def fun_call(self, fun_name, arg_list, needs_return=False):
        """
        Genera las acciones necesarias para llamar a una función.
        Verifica coherencia en tipos y número de argumentos.

        :param fun_name: Nombre o identificador de la función a llamar.
        :param arg_list: Lista de argumentos de la llamada a función.
        """
        arg_list.reverse()
        # Verify that the function exists into the DirFunc
        fun = self.get_fun(fun_name)
        if needs_return and fun.return_type == ReturnType.VOID:
            raise Exception('Semantic Error: ' + fun.name +
                            " is void but a return is requested.")
        # Verify coherence in number of parameters
        if len(fun.param_table) != len(arg_list):
            raise Exception(
                'Incorrect number of arguments in function call: ' + fun.name)
        # Generate action ERA size
        self.quad_list.append(Quadruple(Operator.ERA, None, None, fun.name))
        for index, (param,
                    arg_name) in enumerate(zip(fun.param_table, arg_list)):
            arg = self.get_var(arg_name)
            # Verify coherence in types
            if param[1] == arg.type:
                self.quad_list.append(
                    Quadruple(Operator.PARAMETER, arg.address, None, param[0]))
            else:
                raise TypeError('Type mismatch: ' + str(fun_name) +
                                ' requires argument to be ' + str(param[1]) +
                                " but got " + str(arg.type))
        # Generate action GOSUB
        self.quad_list.append(
            Quadruple(Operator.GOSUB, fun.name, None, fun.start_addr))

        # Save return value in a temp value
        if fun.return_type != ReturnType.VOID:
            fun_var = self.get_var("_fun_" + fun_name)
            temp_id = "_temp_" + str(self.temp_vars_index)
            temp_addr = self.add_temp(temp_id, fun_var.type)
            self.temp_vars_index += 1
            self.quad_list.append(
                Quadruple(Operator.ASSIGN, fun_var.address, None, temp_addr))
            self.operands_stack.append(temp_id)
Exemple #8
0
 def end_while(self):
     """
     Completa saltos necesarios al final del ciclo while
     """
     if len(self.jumps_stack) >= 2:
         end = self.jumps_stack.pop()
         ret = self.jumps_stack.pop()
         self.quad_list.append(Quadruple(Operator.GOTO, None, None, ret))
         self.finish_jump(end, len(self.quad_list))
     else:
         raise Exception("Jump stack error")
Exemple #9
0
 def start_else(self):
     """
     Genera cuadruplos necesarios al principio de un else
     """
     self.quad_list.append(Quadruple(Operator.GOTO, None, None, None))
     if self.jumps_stack:
         false = self.jumps_stack.pop()
         self.jumps_stack.append(len(self.quad_list) - 1)
         self.finish_jump(false, len(self.quad_list))
     else:
         raise Exception("Jump stack error")
Exemple #10
0
 def generar_escritura(self):
     """
     Genera cuadruplo con operando de write y el valor a escribir
     """
     addr: int
     if self.operands_stack:
         var_name = self.operands_stack.pop()
         var = self.get_var(var_name)
         self.quad_list.append(
             Quadruple(Operator.WRITE, None, None, var.address))
     else:
         raise Exception("Operation stack error: Not enough operands")
Exemple #11
0
 def end_fun(self):
     """
     Guarda los tamaños de las particiones de la memoria local (necesarios para ejecutar la instucción ERA en VM).
     Genera el cuadruplo con la instrucción ENDFUN.
     """
     # Save partition sizes for ERA instruction.
     fun = self.get_fun(self.current_scope)
     fun.local_partition_sizes = self.v_memory_manager.local_addr.get_partition_sizes(
     )
     fun.temp_partition_sizes = self.v_memory_manager.temp_addr.get_partition_sizes(
     )
     self.quad_list.append(Quadruple(Operator.ENDFUN, None, None, None))
     self.set_global_scope()
Exemple #12
0
 def expresion_while(self):
     """
     Genera cuadruplos necesarios al final de la expresion del while
     """
     if self.operands_stack:
         res = self.get_var(self.operands_stack.pop())
         if res.type == VarType.BOOL:
             self.quad_list.append(
                 Quadruple(Operator.GOTOF, res.address, None, None))
             self.jumps_stack.append(len(self.quad_list) - 1)
         else:
             raise TypeError(
                 "Type mismatch: Needed BOOL type for while conditional")
     else:
         raise Exception("Operation stack error: Not enough operands")
Exemple #13
0
 def return_stmt(self):
     """
     Metodo para añadir el indice del cuadruplo equivalente a la primera instrucción de una función.
     """
     if self.operands_stack:
         return_exp = self.operands_stack.pop()
         return_var = self.get_var(return_exp)
         fun_var = self.get_var("_fun_" + self.current_scope)
         result_type = self.semantic_cube.type_match(
             fun_var.type, return_var.type, Operator.ASSIGN)
         if result_type != "error":
             self.quad_list.append(
                 Quadruple(Operator.ASSIGN, return_var.address, None,
                           fun_var.address))
         else:
             raise TypeError("Type mismatch: Function " +
                             str(self.current_scope) + " returns " +
                             str(fun_var.type) + " but got " +
                             str(return_var.type))
     else:
         raise Exception("Operation stack error: Not enough operands")
Exemple #14
0
 def array_usage(self, var_id, dims):
     """
     Metodo adquirir direccion real de arreglo indexado y agregarlo al stack de operandos
     """
     var = self.get_var(var_id)
     if dims == 1:
         # Una dimension
         if var.dims[0] > 0:
             if self.operands_stack:
                 dim = self.operands_stack.pop()
                 dim_var = self.get_var(dim)
                 if dim_var.type == VarType.INT:
                     self.quad_list.append(
                         Quadruple(Operator.VERIFY, dim_var.address,
                                   self.get_const(0, VarType.INT),
                                   self.get_const(var.dims[0],
                                                  VarType.INT)))
                     temp_id = "_temp_" + str(self.temp_vars_index)
                     temp_addr = self.add_temp(temp_id, var.type)
                     self.temp_vars_index += 1
                     self.quad_list.append(
                         Quadruple(Operator.PLUS, dim_var.address,
                                   self.get_const(var.address, VarType.INT),
                                   temp_addr))
                     # pointer_id tiene la direccion del arreglo indexado
                     pointer_id = "_pointer_" + str(self.temp_vars_index)
                     pointer_addr = self.add_pointer(pointer_id, var.type)
                     self.temp_vars_index += 1
                     self.quad_list.append(
                         Quadruple(Operator.ASSIGNPTR, temp_addr, '',
                                   pointer_addr))
                     self.operands_stack.append(pointer_id)
                 else:
                     raise Exception(
                         "Index type error: Needed var type INT")
             else:
                 raise Exception(
                     "Operation stack error: Not enough operands")
         else:
             raise Exception("Var " + str(var_id) +
                             " is not an array of 1 dimension")
     else:
         # Dos dimensiones
         if var.dims[0] > 0 and var.dims[1] > 0:
             if self.operands_stack:
                 dim2 = self.operands_stack.pop()
                 dim2_var = self.get_var(dim2)
                 dim1 = self.operands_stack.pop()
                 dim1_var = self.get_var(dim1)
                 if dim1_var.type == VarType.INT and dim2_var.type == VarType.INT:
                     self.quad_list.append(
                         Quadruple(Operator.VERIFY, dim1_var.address,
                                   self.get_const(0, VarType.INT),
                                   self.get_const(var.dims[0],
                                                  VarType.INT)))
                     temp1_id = "_temp_" + str(self.temp_vars_index)
                     temp1_addr = self.add_temp(temp1_id, VarType.INT)
                     self.temp_vars_index += 1
                     self.quad_list.append(
                         Quadruple(Operator.TIMES, dim1_var.address,
                                   self.get_const(var.dims[1], VarType.INT),
                                   temp1_addr))
                     temp2_id = "_temp_" + str(self.temp_vars_index)
                     temp2_addr = self.add_temp(temp2_id, VarType.INT)
                     self.temp_vars_index += 1
                     self.quad_list.append(
                         Quadruple(Operator.PLUS, temp1_addr,
                                   self.get_const(var.address, VarType.INT),
                                   temp2_addr))
                     self.quad_list.append(
                         Quadruple(Operator.VERIFY, dim2_var.address,
                                   self.get_const(0, VarType.INT),
                                   self.get_const(var.dims[1],
                                                  VarType.INT)))
                     temp3_id = "_temp_" + str(self.temp_vars_index)
                     temp3_addr = self.add_temp(temp3_id, VarType.INT)
                     self.temp_vars_index += 1
                     self.quad_list.append(
                         Quadruple(Operator.PLUS, temp2_addr,
                                   dim2_var.address, temp3_addr))
                     # pointer_id tiene la direccion del arreglo indexado
                     pointer_id = "_pointer_" + str(self.temp_vars_index)
                     pointer_addr = self.add_pointer(pointer_id, var.type)
                     self.temp_vars_index += 1
                     self.quad_list.append(
                         Quadruple(Operator.ASSIGNPTR, temp3_addr, '',
                                   pointer_addr))
                     self.operands_stack.append(pointer_id)
                 else:
                     raise Exception(
                         "Index type error: Needed var type INT")
             else:
                 raise Exception(
                     "Operation stack error: Not enough operands")
         else:
             raise Exception("Var " + str(var_id) +
                             " is not an array of 2 dimensions")
Exemple #15
0
 def set_jump_main(self):
     """
     Genera quad de salto a main al inicio del programa
     """
     self.quad_list.append(Quadruple(Operator('goto'), None, None, None))
     self.jumps_stack.append(len(self.quad_list) - 1)
Exemple #16
0
 def append(self, operator, left_operand, right_operand, result=None):
     # print(operator, left_operand, right_operand, result)
     quadruple = Quadruple(operator, left_operand, right_operand, result)
     self.quads.append(quadruple)