Example #1
0
    def complete_method_call(self, method_scope: MethodScope, instance: str):
        """ Creates a GOSUB quad to the instruction address of the method to be
            called. Aditionally if the method has a return type generates quads
            to take the return value of the method from the global memory and
            store it in a temporal. Finally set the __current_param_index to
            0 since by this point we are done assigning the parameters of
            the method.

            Arguments:
                - method_scope [MethodScope]: The method scope of the function
                    to be called.
                - instance [str]: The name of the instance of the method to be called.
        """
        # Handle weird case when the instance is detected as an operand.
        if instance != None and instance != "self":
            self.__operands.pop()
        self.__quads.append((Operations.GOSUB, method_scope.name,
                             method_scope.instruction_pointer))

        if method_scope.return_type != "void":
            next_address = CompilationMemory.next_temp_memory_space(
                method_scope.return_type)
            temp = Variable(next_address, method_scope.return_type,
                            next_address)
            self.__quads.append(
                (Operations.ASSIGN, temp, method_scope.return_memory_address))
            self.__operands.push(temp)

        if len(method_scope.ordered_arguments) != self.__current_param_index:
            raise Exception(
                f"Number of parameters do not match on {method_scope.name}")
        self.__current_param_index = 0
Example #2
0
 def read_quad(self):
     """ Generates a quad for the read operation.
     """
     memory_address = CompilationMemory.next_temp_memory_space(Types.STRING)
     temp = Variable(memory_address, Types.STRING, memory_address)
     self.__quads.append((Operations.READ, temp))
     self.__operands.push(temp)
Example #3
0
    def push_constant(self, type_: str, memory_space: int):
        """Adds a constant to the operands stack.

        Arguments:
            - type_ [str]: The type of the constant.
            - memory_space [int]: The memory address for the constant.
        """
        new_variable = Variable(memory_space, type_, memory_space)
        self.__operands.push(new_variable)
Example #4
0
    def maybe_gen_not_quad(self) -> bool:
        """ Check if there is a pending not operation in the operators stack.
        """
        if not self.__operators.isEmpty() and Operations.is_not_op(
                self.__operators.top()):
            op = self.__operators.pop()
            operand = self.__operands.pop()

            memory_address = CompilationMemory.next_temp_memory_space(operand)
            self.__quads.append((op, operand, memory_address))
            self.__operands.push(
                Variable(memory_address, operand.var_type, memory_address))
Example #5
0
    def get_value_from_memory(self, variable: Variable, memory: MethodMemory):
        """ Retrieves the value of the variable from the provided memory.

            Arguments:
                - variable [Variable]: The variable to be retrieved.
                - memory [MethodMemory]: The memory to be used to retireved the variable.

            Returns:
                - The value in memory of the provieded variable.
        """
        if variable.is_array_pointer():
            address = memory.get_value(variable.memory_space)
            return memory.get_value(address)
        return memory.get_value(variable.memory_space)
Example #6
0
    def complete_dimension_access(self):
        """ Generates the quad to add the base memory of the dimensional address.
        """
        dim_variable, dimension = self.__dim_operands.pop()
        memory_address = CompilationMemory.next_temp_memory_space(
            Types.ARRAY_POINTER)
        var_pointer = Variable(memory_address, Types.ARRAY_POINTER,
                               memory_address)
        var_pointer.pointer_type = dim_variable.var_type

        if dimension > 1:
            index = self.__operands.pop()
            add_memory_address = CompilationMemory.next_temp_memory_space(
                Types.INT)
            self.__quads.append((Operations.ADD, index, self.__operands.pop(),
                                 add_memory_address))
            self.__operands.push(
                Variable(add_memory_address, Types.INT, add_memory_address))

        var = self.__operands.pop()
        self.__quads.append(
            (Operations.ADD_LIT, var, dim_variable.memory_space, var_pointer))
        self.__operands.push(var_pointer)
Example #7
0
    def maybe_multiply_for_m(self, dim_tuple: Tuple[Variable, int]):
        """ Generate a quad to multipluy the current index to the corresponding
            dimensional variable.

            Arguments:
                - dim_tuple [Tuple[Variable, int]]: The tuple with the dimension variable.
        """
        variable = dim_tuple[0]

        index = self.__operands.pop()
        memory_address = CompilationMemory.next_temp_memory_space(Types.INT)
        new_temp = Variable(memory_address, Types.INT, memory_address)
        self.__quads.append(
            (Operations.PROD_LIT, index,
             variable.getDimensionNumber(dim_tuple[1]).m, new_temp))
        self.__operands.push(new_temp)
Example #8
0
    def gen_quad_for_next_op(self) -> bool:
        """ Perform the type check for the two next operands and creates the quads corresponding to
            the next operand.

            Raises:
                - Exception: If the two operands are not type compatible.
        """
        r_op = self.__operands.pop()
        l_op = self.__operands.pop()
        op = self.__operators.pop()

        result = OperationsCube.verify(r_op.var_type, l_op.var_type, op)
        if result == Types.ERROR:
            raise ValueError(
                f'Cannot perform {op} operation with {r_op.var_type} {l_op.var_type} operands.'
            )

        memory_address = CompilationMemory.next_temp_memory_space(result)
        self.__quads.append((op, l_op, r_op, memory_address))
        self.__operands.push(Variable(memory_address, result, memory_address))