コード例 #1
0
    def gosubQuad(self, returnType, numQuad, funcName, returnAddress):
        """
        Generate the GOSUB quad when calling a function

        Args:
            returnType (string): Data type the called functon returns
            numQuad (integer): The number of the quadrupĺe where the called function starts
            funcName (string): Name of the current function to know if the memory address
                               needs to be global or local.
            returnAddress (integer): Memory address of the return value from the called function
        """
        if (returnType == 'void'):
            returnDir = None
        else:
            returnDir = memoryObj.getMemoryAddress(returnType, 1, funcName,
                                                   True)

            self.stkType.append(returnType)
            self.stkOperand.append(returnDir)

        # Store on memory the constant value
        gosubAddr = memoryObj.getMemoryAddressToConstant('int', numQuad)

        # Generate GOSUB Quad to execute a function and update the return data
        self.stkQuadruples.append(Quadruple('GOSUB', None, None, gosubAddr))

        # Generate assignation quad to store the returned value in a termporal value
        if (returnAddress != None):
            self.stkQuadruples.append(
                Quadruple('=', returnAddress, None, returnDir))
コード例 #2
0
    def generateAssignmentSingleQuad(self):
        """
        Generate the quadruple when using the operators ++ and --

        Raises:
            Exception: If the variables are not Integers or Floats
        """

        # Pop the last operands
        lftOperand = self.stkOperand.pop()
        lftOpndType = self.stkType.pop()

        # Pop the operator
        operator = self.stkOperator.pop()

        # Raise exception if it is a invalid operation
        if (lftOpndType not in ['int', 'float']):
            if (operator == '++'):
                actionName = 'increment'
            else:
                actionName = 'decrement'
            raise Exception("Cannot {} a {}".format(actionName, lftOpndType))

        # Get memory address for the constant
        cteAddr = memoryObj.getMemoryAddressToConstant('int', 1)

        if (operator == '++'):
            # Push the quadruple
            self.stkQuadruples.append(
                Quadruple('+', lftOperand, cteAddr, lftOperand))

        elif (operator == '--'):
            # Push the quadruple
            self.stkQuadruples.append(
                Quadruple('-', lftOperand, cteAddr, lftOperand))
コード例 #3
0
    def fillForQuad(self):
        """
        Generate the last quads of the FOR and the GOTO if the condition 
        still does not meet. Also fill the previous GOTOF quad.
        """

        # Pop the memory address
        VControl = self.stkOperand.pop()
        IDMemory = self.stkOperand.pop()
        self.stkType.pop()
        self.stkType.pop()

        # Get memory address for the constant
        cteAddr = memoryObj.getMemoryAddressToConstant('int', 1)

        # Generate the update quad
        self.stkQuadruples.append(Quadruple('+', VControl, cteAddr, VControl))
        self.stkQuadruples.append(Quadruple('=', VControl, None, IDMemory))

        # Get jumps
        endFOR = self.stkJumps.pop()
        returnFOR = self.stkJumps.pop()

        # Generate the GOTO quad
        self.stkQuadruples.append(Quadruple('GOTO', None, None, returnFOR))

        # Store the jump quad
        jumpAddr = memoryObj.getMemoryAddressToConstant(
            'int', len(self.stkQuadruples))

        # Fill the jump quad
        self.stkQuadruples[endFOR].result = jumpAddr
コード例 #4
0
    def argumentQuad(self, varType, argNum):
        """
        Generate the quad per argument sent to a function. Also checks that
        the user do not send more thant the expécted amount.

        Args:
            varType (string): Data type of the expected argument
            argNum (integer): Number of the expected argument

        Raises:
            Exception: If there are more arguments than the called function needs
        """
        # Pop the arg value
        argValue = self.stkOperand.pop()
        argType = self.stkType.pop()

        # Validate the data type
        if (varType != argType):
            raise Exception("The argument is {} but needs to be {}".format(
                argType, varType))

        # Store the constant value
        argNumAddr = memoryObj.getMemoryAddressToConstant('int', argNum)

        # Push the quadruple
        self.stkQuadruples.append(
            Quadruple('PARAM', argValue, None, argNumAddr))
コード例 #5
0
 def performRETURN(self, quad):
     # Parche guadalupano
     asgn_quad = Quadruple(
         Operator.ASGN, self.func_table["global"].var_table[
             self.ctx_stack[-1].ctx].address, quad.res)
     self.performASGN(asgn_quad)
     self.performENDPROC()
コード例 #6
0
    def performREAD(self, quad):
        # Reads std input and writes the value
        addr = quad.op1
        val = input()

        # Check if address is a pointer that needs solving, before writing to mem
        if addr >= 4000:
            quad = Quadruple(Operator.ASGN, self.pointer_mem.getAddress(addr),
                             val)
            self.performASGN(quad, True)
            return

        # Gets datatype and casts accordingly
        data_type = (addr % 1000) // 100

        if data_type == 0:
            val = int(val)
        elif data_type == 1:
            val = float(val)

        # Writes memory
        if addr >= 2000:
            self.ctx_stack[-1].temp_mem.writeAddress(addr, val)
        elif addr >= 1000:
            self.ctx_stack[-1].local_mem.writeAddress(addr, val)
        else:
            self.global_mem.writeAddress(addr, val)
コード例 #7
0
    def performASGN(self, quad, flag=False):
        # If pointer, use op1 as value, otherwise it's an address
        if flag:
            value = quad.op1
        else:
            value = self.resolveMem(quad.op1)

        # Solves data type and casts accordingly
        target_addr = quad.res
        data_type_val = (target_addr % 1000) // 100

        if data_type_val == 0:
            value = int(value)
        elif data_type_val == 1:
            value = float(value)

        # Writes to memory
        if target_addr >= 4000:
            quad = Quadruple(Operator.ASGN,
                             self.pointer_mem.getAddress(target_addr),
                             quad.op1)
            self.performASGN(quad)
        elif target_addr >= 2000:
            self.ctx_stack[-1].temp_mem.writeAddress(target_addr, value)
        elif target_addr >= 1000:
            self.ctx_stack[-1].local_mem.writeAddress(target_addr, value)
        else:
            self.global_mem.writeAddress(target_addr, value)
コード例 #8
0
    def endFunctionQuad(self):
        """
        Generate the ENDFUNC quad
        """
        self.stkQuadruples.append(Quadruple('ENDFUNC', None, None, None))

        # Reset local memory address
        memoryObj.resetLocalCounters()
コード例 #9
0
    def writeQuad(self):
        """
        Generate the quadruple of the WRITE function
        """
        # Get the value to print
        toWriteVal = self.stkOperand.pop()
        self.stkType.pop()

        # Push the quad
        self.stkQuadruples.append(Quadruple('WRITE', None, None, toWriteVal))
コード例 #10
0
    def updateMatrixAddress(self, arrayData):
        """
        Function to make the VERIFY quads and the sum to get the pointer to 
        the real indexed address from a matri

        Args:
            arrayData (Dictionary): A dict with the variable data
        """

        # Get expresion as index
        indexCol = self.stkOperand.pop()
        self.stkType.pop()
        indexRow = self.stkOperand.pop()
        self.stkType.pop()

        # Add the dimension to constant context
        dim1Addr = memoryObj.getMemoryAddressToConstant(
            'int', arrayData['dimensions'][0])
        dim2Addr = memoryObj.getMemoryAddressToConstant(
            'int', arrayData['dimensions'][1])
        baseAddr = memoryObj.getMemoryAddressToConstant(
            'int', arrayData['memoryAddress'])

        # Make the verify quad
        self.stkQuadruples.append(Quadruple('VERIFY', indexRow, dim1Addr,
                                            None))
        self.stkQuadruples.append(Quadruple('VERIFY', indexCol, dim2Addr,
                                            None))

        # Create memory address to store the sum of base address and index
        sumAddr = memoryObj.getMemoryAddress('int', 1, self.currentFunction,
                                             True)
        multAddr = memoryObj.getMemoryAddress('int', 1, self.currentFunction,
                                              True)

        # Make the sum to get the actual memory address
        self.stkQuadruples.append(Quadruple('*', indexRow, dim2Addr, multAddr))
        self.stkQuadruples.append(Quadruple('+', multAddr, dim1Addr, sumAddr))
        self.stkQuadruples.append(Quadruple('+', baseAddr, sumAddr, sumAddr))

        # Append the pointer to the stack
        self.stkOperand.append('->' + str(sumAddr))
        self.stkType.append(arrayData['dataType'])
コード例 #11
0
    def readQuad(self):
        """
        Generate the quadruple of the READ function
        """
        # Get were to store the data
        toReadDir = self.stkOperand.pop()
        self.stkType.pop()

        # Push the quad
        self.stkQuadruples.append(Quadruple('READ', None, None, toReadDir))
コード例 #12
0
    def eraQuad(self, callingFunc):
        """
        Generate the ERA quad when calling a function

        Args:
            callingFunc (string): Name of the called function
        """
        # Store the function name
        nameAddr = memoryObj.getMemoryAddressToConstant("str", callingFunc)
        self.stkQuadruples.append(Quadruple('ERA', None, None, nameAddr))
コード例 #13
0
    def generateVCVFComparisonQuad(self, funcName):
        """
        Generate the quads where the VControl and VFinal are compared

        Args:
            funcName (string): Name of the current function to know if the memory address
                               needs to be global or local.

        Raises:
            Exception: If the goal expression is not an integer
        """

        # Checks that the goal expresion is a integer
        expType = self.stkType.pop()
        if (expType != 'int'):
            raise Exception("The final expression on a FOR must be an integer")

        # Pop the fianl expresion
        expOperand = self.stkOperand.pop()

        # Generate the memory address of the VFinal
        VFinal = memoryObj.getMemoryAddress('int', 1, self.currentFunction,
                                            True)

        # Generate memory for the temporal boolean
        tempBoolean = memoryObj.getMemoryAddress('int', 1,
                                                 self.currentFunction, True)

        # Generate quads
        self.stkQuadruples.append(Quadruple('=', expOperand, None, VFinal))
        self.stkQuadruples.append(
            Quadruple('<', self.stkOperand[-1], VFinal, tempBoolean))

        # Push the jump quad
        self.stkJumps.append(len(self.stkQuadruples) - 1)

        # Generate the GOTOF quad
        self.stkQuadruples.append(Quadruple('GOTOF', tempBoolean, None, None))

        # Push the jump quad
        self.stkJumps.append(len(self.stkQuadruples) - 1)
コード例 #14
0
    def updateArrayAddress(self, arrayData, varName):
        """
        Make the needed quads to get the real indexed memory address from an array

        Args:
            arrayData (Dictionary): A dict with the data from a variable
            varName (string): String with the variable name

        Raises:
            Exception: If the variable is actually a matrix
        """

        # Check if the var is actually a matrix
        if (arrayData['numDimensions'] == 2):
            raise Exception('Variable {} is a matrix'.format(varName))

        # Get expresion as index
        index = self.stkOperand.pop()
        self.stkType.pop()

        # Add the dimension to constant context
        dimAddr = memoryObj.getMemoryAddressToConstant('int',
                                                       arrayData['dimensions'])
        baseAddr = memoryObj.getMemoryAddressToConstant(
            'int', arrayData['memoryAddress'])

        # Make the verify quad
        self.stkQuadruples.append(Quadruple('VERIFY', index, dimAddr, None))

        # Create memory address to store the sum of base address and index
        sumAddr = memoryObj.getMemoryAddress('int', 1, self.currentFunction,
                                             True)

        # Make the sum to get the actual memory address
        self.stkQuadruples.append(Quadruple('+', index, baseAddr, sumAddr))

        # Append the pointer to the stack
        self.stkOperand.append('->' + str(sumAddr))
        self.stkType.append(arrayData['dataType'])
コード例 #15
0
    def generateAssignmentQuad(self):
        """
        Function to generate the quadruplo of assignments

        Raises:
            Exception: If the operands types are different
        """
        # Pop the last operands
        rgtOperand = self.stkOperand.pop()
        rgtOpndType = self.stkType.pop()
        lftOperand = self.stkOperand.pop()
        lftOpndType = self.stkType.pop()

        # Pop the operator
        operator = self.stkOperator.pop()

        # Raise exception if it is a invalid operation
        if (lftOpndType != rgtOpndType):
            if (not (lftOpndType == 'int' or rgtOpndType == 'float')):
                raise Exception("Cannot asign a {} to a {}".format(
                    rgtOpndType, lftOpndType))

        if (operator == '='):
            # Push the quadruple
            self.stkQuadruples.append(
                Quadruple(operator, rgtOperand, None, lftOperand))

        elif (operator == '+='):
            # Push the quadruple
            self.stkQuadruples.append(
                Quadruple('+', lftOperand, rgtOperand, lftOperand))

        elif (operator == '-='):
            # Push the quadruple
            self.stkQuadruples.append(
                Quadruple('-', lftOperand, rgtOperand, lftOperand))
コード例 #16
0
    def performPARAM(self, quad):
        # Writes a value for a parameter, given an argument
        from_address = quad.op1

        # Out of bounds (deprecated, but won't touch)
        if from_address >= 5000:
            return

        # Get the type of the argument, param number and param data
        from_type = getDataType(from_address)

        param_num = int(quad.res[3:])
        dest_addr, dest_type = self.func_table[
            self.call_stack[-1].ctx].params[param_num]

        # Get value of parameter
        if from_address >= 4000:
            quad = Quadruple(Operator.PARAM, quad.res,
                             self.pointer_mem.getAddress(from_address))
            self.performPARAM(quad)
            return
        elif from_address >= 3000:
            val = self.cte_mem.getConstant(from_address)
        elif from_address >= 2000:
            val = self.ctx_stack[-1].temp_mem.getValue(from_address)
        elif from_address >= 1000:
            val = self.ctx_stack[-1].local_mem.getValue(from_address)
        else:
            val = self.global_mem.getValue(from_address)

        # Check if it is valid
        result_type = semantic_cube[dest_type][from_type][Operator.ASGN]

        if result_type != None:
            if result_type == Type.INT:
                val = int(val)
            elif result_type == Type.FLOAT:
                val = float(val)

            self.call_stack[-1].local_mem.writeAddress(dest_addr, val)
        else:
            print("[Error]: Argument type does not match parameter type")
            sys.exit()
コード例 #17
0
    def elseConditionQuad(self):
        """
        Function to generate the GOTO quad when uing a else statement
        Also, filling the past GOTOF quad
        """
        # Push the Goto quad
        self.stkQuadruples.append(Quadruple('GOTO', None, None, None))

        # Pop the jump quad
        falseLine = self.stkJumps.pop()

        # Append the new jump
        self.stkJumps.append(len(self.stkQuadruples) - 1)

        # Store the jump quad
        gotoAddr = memoryObj.getMemoryAddressToConstant(
            'int', len(self.stkQuadruples))

        # Fill the GotoF
        self.stkQuadruples[falseLine].result = gotoAddr
コード例 #18
0
    def returnFunctionQuad(self, funcName, funcTable):
        """
        Generate the RETURN Quad of the return statement.
        Making the needed validation.

        Args:
            funcName (string): Name of the function the return is inside
            returnType (string): Data type of the returned value
            varAddr(integer | None): Memory address where is store the returned value
                                     if the function is not void

        Raises:
            Exception: If the function is void and has a return
            Exception: If the returned data type is different than the expected
        """
        varAddr = None
        actualType = self.stkType.pop()

        # Search the function data
        funcData = funcTable.searchFunction(self.currentFunction)

        # If the function is void and have a return raise error
        if (funcData['returnType'] == 'void'):
            raise Exception(
                'Function "{}" is void and does not need a return'.format(
                    funcName))

        # If not, get the global memory address
        else:
            varAddr = funcTable.searchVariable(
                'global', self.currentFunction)['memoryAddress']

        # If the returned value is different from the function return type
        if (funcData['returnType'] != actualType):
            raise Exception(
                'Error trying to return a {} when function "{}" returns a {}'.
                format(actualType, funcName, funcData['returnType']))

        # Push the returned value
        self.stkQuadruples.append(
            Quadruple('RETURN', self.stkOperand.pop(), None, varAddr))
コード例 #19
0
    def generateConditionQuad(self):
        """
        Generate the GOTOF quadruple when start a IF/Then statement

        Raises:
            Exception: If the expression inside the parenthesis is not a bool
        """
        # Pop the last operands
        resultValue = self.stkOperand.pop()
        resultType = self.stkType.pop()

        # Check the result data type
        if (resultType != 'bool'):
            raise Exception(
                "Invalid operation, the condition need to result on a bool.")

        # Push the quadruple
        self.stkQuadruples.append(Quadruple('GOTOF', resultValue, None, None))

        # Add the jump quad to come back later
        self.stkJumps.append(len(self.stkQuadruples) - 1)
コード例 #20
0
    def endWhileQuad(self):
        """
        Generate the GOTO Quad when starting a While
        """
        # Get the jump
        endLine = self.stkJumps.pop()

        # Get the return jump
        returnLine = self.stkJumps.pop()

        # Store on memory the constant value
        gotoAddr = memoryObj.getMemoryAddressToConstant('int', returnLine)

        # Push the return quad
        self.stkQuadruples.append(Quadruple('GOTO', None, None, gotoAddr))

        # Store the jump quad
        gotoAddr = memoryObj.getMemoryAddressToConstant(
            'int', len(self.stkQuadruples))

        # Fill the end line
        self.stkQuadruples[endLine].result = gotoAddr
コード例 #21
0
    def generateVControlQuad(self, funcName):
        """
        Generate the Quadruple where the VControl get the value

        Args:
            funcName (string): Name of the current function to know if the memory address
                               needs to be global or local.
        """

        # Pop the memory address of the ID
        expOperand = self.stkOperand[-1]

        # Generate the memory address of the VControl
        VControl = memoryObj.getMemoryAddress('int', 1, self.currentFunction,
                                              True)

        # Generate the quad
        self.stkQuadruples.append(Quadruple('=', expOperand, None, VControl))

        # Push the VC memory address
        self.stkOperand.append(VControl)
        self.stkType.append('int')
コード例 #22
0
 def endQuad(self):
     """
     Generate the END Quad
     """
     self.stkQuadruples.append(Quadruple('END', None, None, None))
コード例 #23
0
    def generateOperatorQuadruple(self,
                                  funcName,
                                  groupOperators=None,
                                  flgArithmetic=True):
        """
        Function to generate the operation quadruples

        Args:
            funcName (string): The name of the function (To generate the temporal memory space)
            groupOperators (list, optional): List with the arithmetic operators to look for
            flgArithmetic (bool, optional): If the quadruple is going to be a arithmetic operation or not

        Raises:
            Exception: If the operation is invalid
        """

        # Flag to know if is time to push a quadruple
        insertQuad = False

        # If it is a arithmetic operator, make the validations...
        if (flgArithmetic):
            # Check that there are operands and if the
            # if the las operator is on the searched operators group
            if (self.stkOperator):
                if (self.stkOperator[-1] in groupOperators):
                    insertQuad = True

        # Or just push the quad if it is a logical
        # or relational operator
        else:
            insertQuad = True

        if (insertQuad):
            # Pop the last operands
            rgtOperand = self.stkOperand.pop()
            rgtOpndType = self.stkType.pop()
            lftOperand = self.stkOperand.pop()
            lftOpndType = self.stkType.pop()

            # Pop the operator
            operator = self.stkOperator.pop()

            # Validate the operation
            resultType = semanticCube.verifyOperations(operator, lftOpndType,
                                                       rgtOpndType)

            # Raise exception if it is a invalid operation
            if (resultType == "error"):
                raise Exception(
                    "Invalid operation {} between {} and {}".format(
                        operator, lftOpndType, rgtOpndType))

            # Calculate the memory address
            resultAddress = memoryObj.getMemoryAddress(resultType, 1,
                                                       self.currentFunction,
                                                       True)

            # Push the result and it's type
            self.stkOperand.append(resultAddress)
            self.stkType.append(resultType)

            # Push the quadruple
            self.stkQuadruples.append(
                Quadruple(operator, lftOperand, rgtOperand, resultAddress))
コード例 #24
0
 def generateGOTOMain(self):
     """
     Generate the quad to go to the main
     """
     self.stkQuadruples.append(Quadruple('GOTO', None, None, None))