示例#1
0
    def cpu(self):
        
        """
        the first main frame should return to the HALT instruction, which is the last
        quadruple
        """
        HALTinstIdx = len(self.code) - 1
        mainMethodFrame = Frame(self.mainMethod, HALTinstIdx)
        mainObject = ObjectSpace(self.mainClass)
        mainMethodFrame.registers[0] = mainObject
        self.callStack.push(mainMethodFrame)

        quadruple = self.code[self.ip]
        toBeInvokedFrame = None
        while (quadruple.opCode != "HALT" and self.ip < len(self.code)):
            registers = self.callStack.peek().registers  #shortcut to current stack registers
            self.ip = self.ip + 1 #almost all the instructions should increment the ip
                                #if not, the instruction should take care of it
                
            if(quadruple.opCode == "+"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] + registers[offset(op2)]
            elif(quadruple.opCode == "-"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] - registers[offset(op2)]
            elif(quadruple.opCode == "*"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] * registers[offset(op2)]
            elif(quadruple.opCode == "/"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] / registers[offset(op2)]
            elif(quadruple.opCode == "or"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] or registers[offset(op2)]
            elif(quadruple.opCode == "and"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] and registers[offset(op2)]
            elif(quadruple.opCode == "=="):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] == registers[offset(op2)]
            elif(quadruple.opCode == "!="):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] != registers[offset(op2)]
            elif(quadruple.opCode == ">="):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] >= registers[offset(op2)]
            elif(quadruple.opCode == ">"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] > registers[offset(op2)]
            elif(quadruple.opCode == "<="):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] <= registers[offset(op2)]
            elif(quadruple.opCode == "<"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op3)] = registers[offset(op1)] < registers[offset(op2)]
            elif(quadruple.opCode == "PRINT"):
                op1 = int(quadruple.op1)
                print(str(registers[offset(op1)]), end = "")
            elif(quadruple.opCode == "PRINTLINE"):
                print()
            elif(quadruple.opCode == "READINT"):
                op1 = int(quadruple.op1)
                read = input()
                try:
                    tmp = int(read)
                except ValueError:
                    exit("ERROR Inesperado: Se leyo una literal no valida en readint(): " + read)
                registers[offset(op1)] = tmp
            elif(quadruple.opCode == "READDOUBLE"):
                op1 = int(quadruple.op1)
                read = input()
                try:
                    tmp = float(read)
                except ValueError:
                    exit("ERROR Inesperado: Se leyo una literal no valida en readdouble(): " + read)
                registers[offset(op1)] = tmp
            elif(quadruple.opCode == "READCHAR"):
                op1 = int(quadruple.op1)
                read = input()
                if(len(read) > 1):
                    exit("ERROR Inesperado: Se leyo mas de un caracter en readchar(): " + read)
                registers[offset(op1)] = read
            elif(quadruple.opCode == "GOTOFALSE"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                if(not registers[offset(op1)]):
                    self.ip = op2
            elif(quadruple.opCode == "GOTO"):
                op1 = int(quadruple.op1)
                self.ip = op1
            elif(quadruple.opCode == "CCONST"):
                op1 = quadruple.op1
                op2 = int(quadruple.op2)
                registers[offset(op2)] = chr(ord(op1))
            elif(quadruple.opCode == "DCONST"):
                op1 = float(quadruple.op1)
                op2 = int(quadruple.op2)
                registers[offset(op2)] = op1
            elif(quadruple.opCode == "ICONST"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                registers[offset(op2)] = op1
            elif(quadruple.opCode == "="):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                registers[offset(op2)] = registers[offset(op1)]
            elif(quadruple.opCode == "ERA"):
                op1 = quadruple.op1
                methodToBeInvoked = self.methodsDirectory[op1]
                toBeInvokedFrame = Frame(methodToBeInvoked, -1) #the return address of the invokedFrame should be set in the GOSUB/GOSUBVOID.
                                                                #here we leave it pending with a -1
            elif(quadruple.opCode == "PARAM"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                toBeInvokedFrame.registers[op2] = registers[offset(op1)]
            elif(quadruple.opCode == "GOSUB"):
                op1 = quadruple.op1
                op2 = int(quadruple.op2)
                invokedMethodSymbol = self.methodsDirectory[op1]
                callerFrame = self.callStack.peek()
                callerFrame.tempReturned = op2  #register that will be used to store the value that invokedFrame will return. No offseted yet
                toBeInvokedFrame.returnAddress = self.ip
                self.callStack.push(toBeInvokedFrame)
                self.ip = invokedMethodSymbol.firstQuadrupleIdx
            elif(quadruple.opCode == "GOSUBVOID"):
                op1 = quadruple.op1
                invokedMethodSymbol = self.methodsDirectory[op1]
                callerFrame = self.callStack.peek()
                toBeInvokedFrame.returnAddress = self.ip
                self.callStack.push(toBeInvokedFrame)
                self.ip = invokedMethodSymbol.firstQuadrupleIdx
            elif(quadruple.opCode == "RETURN"):
                op1 = int(quadruple.op1)
                returnValue = registers[offset(op1)]
                popedFrame = self.callStack.pop()
                callerFrame = self.callStack.peek()
                callerFrame.registers[offset(callerFrame.tempReturned)] = returnValue
                self.ip = popedFrame.returnAddress
            elif(quadruple.opCode == "RETURNVOID"):
                popedFrame = self.callStack.pop()
                self.ip = popedFrame.returnAddress
            elif(quadruple.opCode == "SHOULD_RETURN_SOMETHING_ERROR"):
                op1 = quadruple.op1
                exit("ERROR Inesperado: Metodo " + op1 + " no regreso nada...")
            elif(quadruple.opCode == "OBJECT"):
                op1 = int(quadruple.op1)
                op2 = quadruple.op2.strip()
                clase = self.classesDirectory[op2]
                obj = ObjectSpace(clase)
                registers[offset(op1)] = obj
            elif(quadruple.opCode == "PUTFIELD"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op2)].fields[op3] = registers[offset(op1)]
            elif(quadruple.opCode == "GETFIELD"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                op3 = int(quadruple.op3)
                registers[offset(op1)] = registers[offset(op2)].fields[op3]
            elif(quadruple.opCode == "VERIFYARRAYACCESS"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                if(registers[offset(op1)] < 0 or registers[offset(op1)] >= op2):
                    exit("ERROR Inesperado: Indice " + str(registers[offset(op1)]) + " fuera de rango en acceso a elemento de arreglo.")
            elif(quadruple.opCode == "GETARRAYELEM"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                registers[offset(op2)] = registers[offset(registers[offset(op1)])]
            elif(quadruple.opCode == "PUTARRAYELEM"):
                op1 = int(quadruple.op1)
                op2 = int(quadruple.op2)
                registers[offset(registers[offset(op1)])] = registers[offset(op2)]
            else:
                print("Cuadruplo no reconocido: " + quadruple.opCode)
            quadruple = self.code[self.ip]