示例#1
0
    def get_value(self, virtual_address):
        '''Gets the value of an address depending on its scope range'''
        # Infer scope from address
        scope_range = mh.get_scope_from_address(virtual_address)

        # Address is in main memory
        if scope_range in ['global', 'constant']:
            return self.__main.value(virtual_address)
        # Address could be in main memory or in a stack of memory
        elif scope_range == 'local':
            if len(self.__s_execution) > 0:
                current_context = self.__s_execution[
                    -1]  # Get the current memory context
                # Validate if address is in currenresst context
                if current_context.address_exists(
                        virtual_address) == None:  # Not in current context
                    # Validate if address is in main memory
                    if self.__main.address_exists(
                            virtual_address) == None:  # Not in memory
                        error("This address does not exist in main %s" %
                              virtual_address)
                    else:
                        return self.__main.value(virtual_address)
                # Return value from current context
                else:
                    return current_context.value(virtual_address)
示例#2
0
 def cast(self, value, v_type):
     '''Casts a value to a specific data type'''
     if v_type in [0, 5]:
         return int(value)
     elif v_type == 1:
         return float(value)
     elif v_type in [2, 4]:
         return str(value[1:-1])
     elif v_type == 3:
         return bool(value)
     else:
         error("Invalid casting to %s" % v_type)
示例#3
0
    def is_address_valid(self,
                         virtual_address,
                         data_type,
                         scope,
                         item_type,
                         is_constant=False):
        # Check if address is for a constant
        if is_constant:
            if not CONSTANTS_BASE_ADDRESS[data_type] <= virtual_address < (
                    CONSTANTS_BASE_ADDRESS[data_type] +
                    ranges["constant"]):  # Count exceeded
                error("Too many %s constants" % types[data_type])

        else:  # is variable or temporal
            # Is an int, float, char
            if data_type in [0, 1, 2]:
                if scope == "global":
                    if item_type in ["variable", "temporal"]:
                        if not GLOBALS_BASE_ADDRESS[item_type][
                                data_type] <= virtual_address < (
                                    GLOBALS_BASE_ADDRESS[item_type][data_type]
                                    + ranges[item_type]):
                            error("Too many %s %s %ss" %
                                  (types[data_type], scope, item_type))

                if scope == "local":
                    if item_type in ["variable", "temporal"]:
                        if not LOCALS_BASE_ADDRESS[item_type][
                                data_type] <= virtual_address < (
                                    LOCALS_BASE_ADDRESS[item_type][data_type] +
                                    ranges[item_type]):
                            error("Too many %s %s %ss" %
                                  (types[data_type], scope, item_type))

            elif data_type in [3, 5]:  # bool or pointer
                if scope == "global":
                    if not GLOBALS_BASE_ADDRESS[item_type][
                            data_type] <= virtual_address < (
                                GLOBALS_BASE_ADDRESS[item_type][data_type] +
                                ranges[item_type]):
                        error("Too many '%s' global temporal variables" %
                              types[data_type])
                elif scope == "local":  # local
                    if not LOCALS_BASE_ADDRESS[item_type][
                            data_type] <= virtual_address < (
                                LOCALS_BASE_ADDRESS[item_type][data_type] +
                                ranges[item_type]):
                        error("Too many '%s' local temporal variables" %
                              types[data_type])

        return virtual_address
示例#4
0
def get_scope_from_address(virtual_address):
    if virtual_address in range(GLOBALS_BASE_ADDRESS['variable'][0],
                                LOCALS_BASE_ADDRESS['variable'][0]):
        return 'global'
    elif virtual_address in range(LOCALS_BASE_ADDRESS['variable'][0],
                                  CONSTANTS_BASE_ADDRESS[0]):
        return 'local'
    elif virtual_address in range(CONSTANTS_BASE_ADDRESS[0],
                                  OBJECTS_BASE_ADDRESS):
        return 'constant'
    elif virtual_address in range(OBJECTS_BASE_ADDRESS,
                                  OBJECTS_BASE_ADDRESS + ranges['instance']):
        return 'instance'
    else:
        error("Invalid address")
示例#5
0
    def binary_operation(self, quadruple):
        """Executes a binary operation"""
        operator, l_address, r_operand, res_address = quadruple

        l_type = mh.get_type_from_address(
            l_address)  # Check for operands data types infered from address

        # Get operand_address values
        l_value = self.get_value(l_address)

        if type(r_operand) == tuple:  # We want the literal
            r_value = r_operand[0]
            r_type = 0
        else:  # We want the value
            r_value = self.get_value(r_operand)
            r_type = mh.get_type_from_address(r_operand)

        if l_type == 5:
            l_value = self.get_value(l_value)

        if r_type == 5:
            r_value = self.get_value(r_value)

        if l_value == None:
            error("Uninitialized left variable")

        if r_value == None:
            error("Uninitialized right variable")

        if operator == '+':
            return l_value + r_value
        elif operator == '-':
            return l_value - r_value
        elif operator == '*':
            return l_value * r_value
        elif operator == '/':
            if r_value == 0:
                error("Division by zero")
            else:
                if l_type == 0 and r_type == l_type:
                    return floor(l_value / r_value)
                else:
                    return l_value / r_value
        elif operator == '&':
            return l_value and r_value
        elif operator == '|':
            return l_value or r_value
        elif operator == '<':
            return l_value < r_value
        elif operator == '>':
            return l_value > r_value
        elif operator == '<>':
            return l_value != r_value
        elif operator == '==':
            return l_value == r_value
示例#6
0
    def run(self):
        '''Simulates a virtual machine executing all quadruples'''
        print("-----Start program execution-----")
        # Execute quadruples
        while True:
            quadruple = self.current_process()
            operator = quadruple[0]

            if operator == 'GOTO':
                # print("execute GOTO: ", quadruple[3])
                self.__quadruple_iterator = quadruple[3]

            elif operator == 'GOTOV':
                # print("execute GOTOV: ", quadruple[1], quadruple[3])
                condition = self.get_value(quadruple[1])
                if condition:
                    self.__quadruple_iterator = quadruple[3]
                else:
                    self.proceed()

            elif operator == 'GOTOF':
                # print("execute GOTOF: ", quadruple[1], quadruple[3])
                condition = self.get_value(quadruple[1])
                # print("condition",condition)
                if not condition:
                    self.__quadruple_iterator = quadruple[3]
                else:
                    self.proceed()

            elif operator == 'ERA':
                self.__s_execution.append(Memory())

                self.proceed()
                # print("\nExecute ERA")

            elif operator == 'PARAMETER':
                # print('START PARAMETER')
                argument_address = quadruple[1]
                argument_index = quadruple[3]
                argument_type = quadruple[2]

                # Function/method call was made inside another function/method
                if len(self.__s_execution) > 1:
                    # Take out current execution so you can get argument value from previous execution
                    current_context = self.__s_execution.pop()
                    argument_value = self.get_value(argument_address)

                    # Put back current execution
                    self.__s_execution.append(current_context)
                else:
                    # Function call was made on main
                    current_context = self.__s_execution[-1]
                    argument_value = self.get_value(argument_address)

                # Create variable on new memory to save the argument value from call
                local_address = current_context.get_handler().new_variable(
                    argument_type, 'local', 'variable')

                current_context.push(local_address, argument_value)
                # print("Execute PARAMETER: address: %s value: %s" % (argument_address, argument_value))
                self.proceed()

            elif operator == 'GOSUB':
                function_name = quadruple[1]

                if quadruple[2] == None:  # GOSUB to a function
                    scope = self.function_directory.get_scope(function_name)
                else:  # GOSUB to a method
                    class_name = quadruple[2]
                    scope = self.class_directory.get_class(
                        class_name).get_scope(function_name)

                function_instruction_pointer = scope.get_initial_address()
                self.__s_jumps.append(self.__quadruple_iterator + 1)

                self.__quadruple_iterator = function_instruction_pointer
                # print("Execute GOSUB")

            elif operator == 'RETURN':
                # print("Execute RETURN")
                function_return_address = quadruple[1]
                function_var_address = quadruple[3]

                function_return = self.get_value(function_return_address)

                if self.class_context == None:
                    self.__main.push(function_var_address, function_return)
                else:
                    self.class_context.push(function_var_address,
                                            function_return)

                self.proceed()

            elif operator == 'ENDPROC':
                # Delete last activation record
                endproc = self.__s_execution.pop()
                del endproc

                # Continue with next process
                self.__quadruple_iterator = self.__s_jumps.pop()

                # print("Execute ENDPROC")

            elif operator == 'PRINT':
                # print("execute PRINT")
                res = ""
                value_type = mh.get_type_from_address(quadruple[3])

                value = self.get_value(quadruple[3])

                if value_type == 5:
                    value = self.get_value(value)

                res += str(self.cast(value, value_type))

                while True:
                    next_process = self.next_process()

                    if next_process[0] == 'PRINT2':
                        next_type = mh.get_type_from_address(next_process[3])
                        next_value = self.get_value(next_process[3])

                        if next_type == 5:
                            next_value = self.get_value(next_value)

                        if next_type == 2:
                            res = res + next_value
                        else:
                            res = res + str(self.cast(next_value, next_type))

                        self.proceed()
                    else:
                        break

                print(res)
                self.proceed()

            elif operator == 'READ':
                # Get information from quadruple
                assignTo = quadruple[3]
                data_type = mh.get_type_from_address(assignTo)

                # Ask for user input
                read_input = input()

                # Save user input in the address of the value of the pointer (array or matrix)
                if data_type == 5:
                    assignTo = self.get_value(assignTo)
                    data_type = mh.get_type_from_address(assignTo)

                size = len(read_input)
                # Catch possible errors of different value type
                try:
                    # Cast char to string
                    if data_type == 2 and size == 1:
                        read_input = str(read_input)
                    # Cast to other types
                    elif data_type != 2:
                        read_input = self.cast(read_input, data_type)
                    else:
                        error("Expected a %s type value on read" %
                              types[data_type])
                except (ValueError):
                    error("Expected a %s type value on read." %
                          types[data_type])

                # Put value in memory
                self.assign(assignTo, read_input)
                self.proceed()

            elif operator in [
                    '+', '-', '*', '/', '&', '|', '<', '>', '<>', '=='
            ]:
                # Execute binary operation and send temporal result to memory
                value = self.binary_operation(quadruple)
                assignTo = quadruple[3]
                self.assign(assignTo, value)
                self.proceed()

            elif operator == '=':
                l_type = mh.get_type_from_address(quadruple[1])
                l_value = self.get_value(quadruple[1])
                # print(l_value)

                if l_type == 5:  # Check if it is a pointer
                    l_value = self.get_value(l_value)

                assignTo_type = mh.get_type_from_address(quadruple[3])
                assignTo = quadruple[3]
                if assignTo_type == 5:  # Check if it is a pointer
                    assignTo = self.get_value(assignTo)

                if l_value == None:
                    error("Trying to assign empty address %s" % l_value)

                self.assign(assignTo, l_value)
                self.proceed()

            elif operator == 'VER':
                # Verify correct indexation for array and matrix
                index_address = quadruple[1]
                index_value = self.get_value(index_address)

                upper_limit_address = quadruple[3]
                upper_limit = self.get_value(upper_limit_address)

                if not index_value >= 0 and index_value < upper_limit:
                    error("Invalid indexation of %s" % quadruple[2])
                self.proceed()

            elif operator == 'END':
                print("")
                break