Example #1
0
 def __init__(self):
     self.scopes = OrderedMap()
     self.currentBlockLabel = None
     self.currentBlock = None
     self.continueLabel = ArrayList(None, None)
     self.breakLabel = ArrayList(None, None)
     self.rootLabel = "0B"
     self.functionStack = ""
     self.currentFunction = ArrayList(None, None)
     self.currentFunctionName = ArrayList(None, None)
     self.returnWasDeclared = ArrayList(None, None)
     self.globalFunctions = OrderedMap()
 def __init__(self, label):
     self.label = label
     self.statements = ArrayList(None, None)
     self.variables = OrderedMap()
     self.functions = OrderedMap()
     self.functionName = None
     self.returnIndex = 0
     self.registers = OrderedMap()
Example #3
0
 def __init__(self,scopes:OrderedMap):
     self.scopes = scopes
     self.stack = ArrayList(None,None)
     self.currentBlock = Scope("0B")
     self.rootLabel = "0B"
     self.callStack = ArrayList(None,None)
     self.usedStackValues = ArrayList(None,None)
     self.globalFunctions = OrderedMap()
     self.executedStatements = ArrayList(None,None)
     self.debug = False
     self.inputBuffer = ArrayList(None,None)
     self.fromBuffer = False
     initialDelay = datetime.datetime.now()
     self.inputDelay = initialDelay-initialDelay
Example #4
0
    def readLanguageDefinition(file):

        file = open(file, 'r')
        array = ArrayList()

        for line in file.readlines():
            if line.__len__() > 1:
                array.append(stringReplace(line, '\n'))
        for line in array:
            arr = line.split(" ")
            Token.keys.append(arr[0])
            Token.tokens.setdefault(arr[0], arr[1])
        for key in Token.keys:
            value = Token.get(key)
            if value[0].isalpha():
                Token.setKeyword(key)

        for tokenKey in Token.keys:
            if not Token.keywords.__contains__(tokenKey):
                Token.other.setdefault(tokenKey, Token.get(tokenKey))
Example #5
0
class Interpreter:
    @staticmethod
    def prepateAST(file,debug=False):
        if debug:
            print("Lexer start")
        Token.readLanguageDefinition(HOME_DIR+"/src/param/reserved.txt")
        if debug:
            print("Lexer initialization end")
        lexer = Lexer(file)
        lexer.lexerize()
        if debug:
            print(lexer.tokenList)
        for token in lexer.tokenList:
            if token.type == LexName.LEXER_ERROR:
                raise LexerException(token.__str__())
        parser = Parser(lexer.tokenList)
        beforeParsing = len(parser.tokenList)
        if debug:
            print("Blocks left and right matching: " + str(parser.countBlocks()))
        root = parser.root()

        while parser.needReparse:
            if debug:
                print("Reparsing")
            parser.needReparse = False
            root = parser.root()
        if debug:
            print("Updated token list")
            print(parser.tokenList)

        for token in parser.tokenList:
            if token.value is None:
                parser.mistakesFoundAt.append(token)
        if parser.mistakesFoundAt.__len__()>0:
            print("Before:" + str(beforeParsing) + " After: " + str(parser.tokenList.__len__()))
            print("Mistakes were found at:")
            for mistake in parser.mistakesFoundAt:
                print(mistake)
        else:
            print("No syntax mistakes")
        return root

    @staticmethod
    def prepareTACgen(root:Block)->TACgen:
        t = TACgen()
        Interpreter.addDefaultGlobalFunctions(t)
        t.parseRoot(root)
        return t

    @staticmethod
    def optimizeTest(file,debug=False):
        root = Interpreter.prepateAST(file)
        t = Interpreter.prepareTACgen(root)
        for st in t.getStatementsAsString():
            print(st)
        Optimizer.output = debug
        print("\nOptimize!\n")
        Optimizer.scopes = t.scopes
        t = Optimizer.optimize(t)
        print("\nAfter:\n")

        for st in t.getStatementsAsString():
            print(st)

    @staticmethod
    def simpleTest(file,debug=False,optimize=True,inputBuffer=None)->list:
        prepareForExecution = datetime.datetime.now()
        root = Interpreter.prepateAST(file)
        t = Interpreter.prepareTACgen(root)
        if debug:
            for s in t.getStatementsAsString():
                print(s)

        Optimizer.output = debug
        if optimize:
            t = Optimizer.optimize(t)
        else:
            Optimizer.scopes = t.scopes
            for scope in t.scopes.returnItemsInOrder():
                Optimizer.removeTags(scope)
        if debug:
            print("AFTER:")
            for s in t.getStatementsAsString():
                print(s)

        i = Interpreter(t.scopes)
        i.debug = debug
        i.fromBuffer = inputBuffer is not None
        if i.fromBuffer:
            i.inputBuffer = inputBuffer
        i.globalFunctions = t.globalFunctions
        dateStart = datetime.datetime.now()
        print("Prepared for execution in "+str(dateStart - prepareForExecution))
        if t.scopes.containsKey(t.rootLabel):
            i.interpretBlock(t.rootLabel)
        dateEnd = datetime.datetime.now()
        return [dateStart,dateEnd,dateEnd-dateStart-i.inputDelay,i.inputDelay,i.inputBuffer]



    @staticmethod
    def addDefaultGlobalFunctions(t:TACgen):
        def f1(ob: list):
            eprint(ob[0])
            return [LexName.NULL, ""]

        def f2(ob: list):
            fromBuffer = ob[0]
            bufferizedStack = ob[1]

            if fromBuffer:
                string = bufferizedStack.pop(0)
            else:
                string = input()
                bufferizedStack.append(string)
            return [LexName.STRING, string]

        def f3(ob: list):
            return [LexName.STRING, str(ob[0])]

        def f4(ob: list):
            string = ob[0]
            try:
                i = int(string)
            except ValueError:
                i = 0
            return [LexName.INT, i]

        def f5(ob: list):
            string = ob[0]
            index = ob[1]
            try:
                char = string[index]
            except Exception:
                char = None
            return [LexName.STRING, char]

        t.addGlobalFunction(TFunction([LexName.NULL, False], Token.get(LexName.PRINT),"Global",
                                      [FnParameter(LexName.STRING, "ob")], f1))
        t.addGlobalFunction(TFunction([LexName.STRING, False], Token.get(LexName.INPUT),"Global",
                                      [], f2))
        t.addGlobalFunction(TFunction([LexName.STRING, False], "toStr", "Global",
                                      [FnParameter(LexName.STRING, "ob")], f3))
        t.addGlobalFunction(TFunction([LexName.INT, False], "toInt", "Global",
                                      [FnParameter(LexName.STRING, "ob")], f4))
        t.addGlobalFunction(TFunction([LexName.STRING, False], "charAt", "Global",
                                      [FnParameter(LexName.STRING, "ob"), FnParameter(LexName.INT, "i")], f5))

    def __init__(self,scopes:OrderedMap):
        self.scopes = scopes
        self.stack = ArrayList(None,None)
        self.currentBlock = Scope("0B")
        self.rootLabel = "0B"
        self.callStack = ArrayList(None,None)
        self.usedStackValues = ArrayList(None,None)
        self.globalFunctions = OrderedMap()
        self.executedStatements = ArrayList(None,None)
        self.debug = False
        self.inputBuffer = ArrayList(None,None)
        self.fromBuffer = False
        initialDelay = datetime.datetime.now()
        self.inputDelay = initialDelay-initialDelay

    def setOrGetRegister(self,regName):
        scope = self.callStack.getLast()
        if scope.registers.containsKey(regName):
            return scope.registers.get(regName)
        else:
            scope.registers.put(regName,Reg(regName))
            return scope.registers.get(regName)

    def resolveType(self,t:str):
        if LexName.INT in t:
            return LexName.INT
        if LexName.FLOAT in t:
            return LexName.FLOAT
        if LexName.STRING in t:
            return LexName.STRING
        if LexName.NULL in t:
            return LexName.NULL
        if t in [LexName.TRUE,LexName.FALSE]:
            return LexName.BOOL
        return t

    def fetchValue(self,name:str)->TVariable:
        for scope in self.callStack.getItemsInReverseOrder():
            if scope.variables.containsKey(name):
                return scope.variables.get(name)
        raise SemanticException("Value "+name+" was not found")

    def fetchFunction(self,name:str)->TFunction:
        if self.globalFunctions.containsKey(name):
            return self.globalFunctions.get(name)
        for scope in self.callStack.getItemsInReverseOrder():
            if scope.functions.containsKey(name):
                return scope.functions.get(name)
        raise SemanticException("Function "+name+" was not found")

    def generateScope(self,startingLabel)->Scope:
        return Operation.generateScope(self.scopes.get(startingLabel),"")

    def doFunction(self,startingLabel,functionName)->Scope:
        for scope in self.scopes.returnItemsInOrder():
            if scope.functions.containsKey(functionName):
                fLabel = scope.functions.get(functionName).label
                return Operation.generateScope(self.scopes.get(fLabel))
            if scope.functionName == functionName:
                if scope.label in startingLabel:
                    return Operation.generateScope(self.scopes.get(startingLabel))
        raise Exception("Failed to call "+functionName +" from "+ startingLabel)

    def doJump(self, label):
        for scope in self.callStack.getItemsInReverseOrder():
            if scope is None:
                raise SemanticException("No scopes found at "+label)
            i = 0
            for st in scope.statements:

                if st.tuple[0] == Tnames.LABEL and st.tuple[1] == label:
                    self.currentBlock = scope
                    return i
                i += 1
        raise SemanticException("Failed Jump")

    def doReturn(self,label=None)->int:
        if label is None:
            label = self.currentBlock.label
            self.currentBlock = self.callStack.getLast()
        while True:
            if self.currentBlock.label == label:
                self.usedStackValues.append(self.callStack.pop())
                self.currentBlock = self.callStack.getLast()
                break
            else:
                self.usedStackValues.append(self.callStack.pop())
                self.currentBlock = self.callStack.getLast()
            if self.currentBlock is None:
                self.executedStatements.append("End reached")
                if self.debug:
                    print(self.executedStatements.getLast())
                return -1

        if self.currentBlock is None:
            self.executedStatements.append("End reached")
            if self.debug:
                print(self.executedStatements.getLast())
            return -1

        self.executedStatements.append("Call stack:" + str(self.callStack))
        if self.debug:
            print(self.executedStatements.getLast())
        return self.currentBlock.returnIndex

    def interpretBlock(self, label: str):
        self.callStack.append(self.generateScope(label))
        self.currentBlock = self.callStack.getLast()
        self.executedStatements.append("Call stack:" + str(self.callStack))
        if self.debug:
            print(self.executedStatements.getLast())
        i = -1
        while True:
            i += 1
            if i >= self.currentBlock.statements.__len__():
                # return after CALLBLOCK/CALL to previous spot
                i = self.doReturn()
                if i == -1:
                    break
                i+=1
            # pre-evaluation
            if i >= self.currentBlock.statements.__len__():
                # return after CALLBLOCK/CALL to previous spot
                i = self.doReturn()
                if i == -1:
                    break
                i+=1
            try:
                # found end
                st = self.currentBlock.statements[i]
            except IndexError as e:
                print(e,"at",i)

                break
            string = ""
            for reg in self.currentBlock.registers.returnItemsInOrder():
                string+=str(reg)
            self.executedStatements.append(str(i).zfill(3)+":"+str(st)+string)
            if self.debug:
                print(self.executedStatements.getLast())
            operation = st.operation
            if operation in [Tnames.CALLBLOCK,Tnames.CALL]:
                scope = None
                if operation == Tnames.CALL:
                    argumentCount = self.stack.pop().value
                    fetched = self.fetchFunction(st.tuple[1])
                    if argumentCount != fetched.parameters.__len__():
                        raise SemanticException("Function Parameter amount miss-match")
                    # global function
                    if self.globalFunctions.containsKey(fetched.name):
                        variables = []
                        for var in range(0,fetched.parameters.__len__()):
                            variables.insert(0,self.stack.pop().value)
                        start = datetime.datetime.now()
                        if fetched.name==Token.get(LexName.INPUT):
                            variables.append(self.fromBuffer)
                            variables.append(self.inputBuffer)

                        retVal = fetched.execute(variables)
                        end = datetime.datetime.now()
                        if fetched.name==Token.get(LexName.INPUT):
                            self.inputDelay+= end - start
                        systemReg = Reg("_sysReg")
                        systemReg.t = retVal[0]         # set type
                        systemReg.value = retVal[1]     # set value
                        self.stack.append(systemReg)
                    else:
                        scope = self.doFunction(self.callStack.getLast(), st.tuple[1])
                else:
                    scope = Operation.generateScope(self.scopes.get(st.tuple[1]))
                if scope is not None:
                    self.currentBlock.returnIndex = i
                    self.callStack.append(scope)
                    self.currentBlock = self.callStack.getLast()
                    self.executedStatements.append("Call stack:"+str(self.callStack))
                    if self.debug:
                        print(self.executedStatements.getLast())
                    i = -1
            elif operation in [Tnames.JUMPZ,Tnames.JUMP]:
                boolVal = True
                if operation == Tnames.JUMPZ:
                    reg = self.setOrGetRegister(st.tuple[2])
                    boolVal = reg.booleanValue()
                if (operation==Tnames.JUMP) or (not boolVal):
                    index = self.doJump(st.tuple[1])
                    i = index

            elif operation == Tnames.RETURN:
                fetched = self.fetchFunction(st.tuple[2])
                val = self.stack.getLast()
                if val.tp() != fetched.tp():
                    if val.tp() == LexName.NULL:
                        raise SemanticException("Function " + st.tuple[2] + " " + "returned nothing")
                    raise SemanticException("Function "+st.tuple[2]+" "+"returned different "+val.tp()+" declared"+fetched.tp())
                i = self.doReturn(st.tuple[1])
                if i == -1:
                    break
            else:
                #Non block jumping command
                self.evaluate(st)


    def evaluate(self,st:TAC):
        """Black hole all in one method" for ALL Statements"""
        if st.operation == Tnames.LOAD:
            value = st.tuple[2]
            reg = self.setOrGetRegister(st.tuple[1])
            # resolve if its const or not
            if isinstance(value,list):
                t = self.resolveType(value[0])
                reg.t = t
                # its a simple const value
                if t == LexName.NULL:
                    reg.value = None
                elif t == LexName.BOOL:
                    reg.value = value[0] == LexName.TRUE
                else:
                    reg.value = value[1]
            elif "_" in value:
                # Register call
                reg1 = self.setOrGetRegister(value)
                reg.t = reg1.t
                reg.value = reg1.value
            else:
                # value fetch
                varName = st.tuple[2]
                var = self.fetchValue(varName)
                regName = st.tuple[1]
                reg = self.setOrGetRegister(regName)
                reg.t = var.t
                reg.value = var.value

        elif st.operation == Tnames.INIT:
            name = st.tuple[1][1] # get the name
            regName = st.tuple[2]
            reg = self.setOrGetRegister(regName)
            var = self.currentBlock.variables.get(name)
            var.value = reg.value
            if reg.t == LexName.NULL:
                var.value = None
            elif (var.tp() != reg.tp()) and (reg.tp() is not None):
                raise SemanticException("Type miss match")
            else:
                var.t = reg.t
        elif st.operation == Tnames.INITARR:
            regName = st.tuple[2]
            reg = self.setOrGetRegister(regName)
            name = st.tuple[1][1]
            t = st.tuple[1][0]
            var = self.currentBlock.variables.get(name)
            if reg.tp() != LexName.INT:
                raise SemanticException("Array size must be INT")
            var.value = StaticArray(reg.value,t)
        elif st.operation == Tnames.LOADARR:
            # Load from Array
            regName = st.tuple[1]
            reg = self.setOrGetRegister(regName)
            indexRegName = st.tuple[2][1]
            indexReg = self.setOrGetRegister(indexRegName)
            arrayName = st.tuple[2][0]
            array = self.fetchValue(arrayName)
            reg.value = array.value.get(indexReg).value
            reg.t = array.t

        elif st.operation == Tnames.PUSH:
            regName = st.tuple[1]
            reg = self.setOrGetRegister(regName)
            self.stack.append(reg.toTVariable())

        elif st.operation == Tnames.POP:
            regName = st.tuple[1]
            reg = self.setOrGetRegister(regName)
            val = self.stack.pop()
            reg.t = val.t
            reg.value = val.value

        elif st.operation == LexName.NOT:
            regName = st.tuple[1]
            reg = self.setOrGetRegister(regName)
            booleanValue = reg.booleanValue()
            if reg.tp() == LexName.BOOL:
                reg.value = not booleanValue
            else:
                raise SemanticException("Can't invert non-boolean value")
        elif st.operation in LexName.Operators:
            operation = st.operation
            op1 = st.tuple[1]
            op2 = st.tuple[2]
            src = self.setOrGetRegister(op2)
            dest = None
            if isinstance(op1,list):
            # TODO operation with arrays
                indexReg = self.setOrGetRegister(op1[1])
                if indexReg.tp() != LexName.INT:
                    raise SemanticException("Array index is not INT")
                arrayName = op1[0]
                array = self.fetchValue(arrayName).value
                dest = array[indexReg.value]
            else:
                name = op1
                if "_" in name:
                    dest = self.setOrGetRegister(name)
                else:
                    dest = self.fetchValue(name)
            if not Operation.operationDefined(operation,dest.tp(),src.tp()):
                raise SemanticException(operation+" is not defined to "+dest.tp() + " "+src.tp())
            if operation == LexName.ASSIGN:
                if src.value is None:
                    dest.value = None
                elif src.tp() == LexName.INT and dest.tp() == LexName.FLOAT:
                    dest.value = float(src.value)
                else:
                    dest.value = src.value
            else:
                if (operation in LexName.LogicOperators) or (operation in LexName.CompareOperators):
                    dest.t = LexName.BOOL
                    if operation == LexName.EQUALS:
                        dest.value = dest.value == src.value
                    elif operation == LexName.NOTEQUAL:
                        dest.value = dest.value != src.value
                    elif operation == LexName.GREATER:
                        dest.value = dest.value > src.value
                    elif operation == LexName.GREATEREQUAL:
                        dest.value = dest.value >= src.value
                    elif operation == LexName.LESS:
                        dest.value = dest.value < src.value
                    elif operation == LexName.LESSEQUAL:
                        dest.value = dest.value >= src.value
                    elif operation == LexName.AND:
                        dest.value = dest.booleanValue() and src.booleanValue()
                    elif operation == LexName.OR:
                        dest.value == dest.booleanValue() or src.booleanValue()

                elif operation in [LexName.PLUS,LexName.MINUS,LexName.MULTIPLY,LexName.DIVIDE] or operation in LexName.AdvancedAssign:
                    typePromote = False
                    if src.tp() == LexName.INT and dest.tp() == LexName.FLOAT:
                        typePromote = True
                    if operation in [LexName.PLUS,LexName.ASSIGNPLUS]:
                        dest.value = dest.value + src.value
                    elif operation in [LexName.MINUS,LexName.ASSIGNMINUS]:
                        dest.value = dest.value - src.value
                    elif operation in [LexName.MULTIPLY,LexName.ASSIGNMULTIPLY]:
                        dest.value = dest.value * src.value
                    elif operation in [LexName.DIVIDE,LexName.ASSIGNDIVIDE]:
                        if dest.t == LexName.FLOAT:
                            dest.value = dest.value / src.value
                        else:
                            dest.value = dest.value // src.value
Example #6
0
 def __init__(self, tp, name, size):
     super().__init__(tp, name)
     self.value = ArrayList(None, None)
     self.size = size
Example #7
0
class TACgen:
    def __init__(self):
        self.scopes = OrderedMap()
        self.currentBlockLabel = None
        self.currentBlock = None
        self.continueLabel = ArrayList(None, None)
        self.breakLabel = ArrayList(None, None)
        self.rootLabel = "0B"
        self.functionStack = ""
        self.currentFunction = ArrayList(None, None)
        self.currentFunctionName = ArrayList(None, None)
        self.returnWasDeclared = ArrayList(None, None)
        self.globalFunctions = OrderedMap()

    def makeTmp(self, index: int):
        return "_r" + str(index)

    def nameIsDefined(self,
                      startingLabel: str,
                      name: str,
                      function=False,
                      checkOnlyLocal=False):
        if function and self.globalFunctions.containsKey(name):
            return True
        childScope = self.scopes.get(startingLabel)
        if checkOnlyLocal:
            if function is True:
                return childScope.functions.containsKey(name)
            else:
                return childScope.variables.containsKey(name)
        if childScope is not None:

            if function is True:
                if childScope.functions.containsKey(name):
                    return True
                else:
                    return self.nameIsDefined(childScope.getParentLabel(),
                                              name, True)
            else:
                if childScope.variables.containsKey(name):
                    return True
                else:
                    return self.nameIsDefined(childScope.getParentLabel(),
                                              name, function)
        else:
            return False

    def getOrderedListOfStatements(self, scopeLabel):

        statements = []
        scope = self.scopes.get(scopeLabel)
        if scope is None:
            print(scopeLabel + "is none")
            return statements
        i = 0
        for st in scope.statements:
            if st.operation == Tnames.LABEL:
                if i == 0:
                    statements.append(st)
                elif st.tuple[1] != scope.label:
                    if str.startswith(st.tuple[1], "E"):
                        statements.append(st)
                    else:
                        statements.extend(
                            self.getOrderedListOfStatements(st.tuple[1]))
                else:
                    statements.append(st)
            else:
                statements.append(st)
            i += 1
        return statements

    @staticmethod
    def getTabbedStatements(statements):
        printable = []
        tabLimit = 0
        for statement in statements:
            line = statement.__str__()
            for i in range(0, tabLimit):
                line = "\t" + line
            if statement.tuple[0] == Tnames.LABEL:
                if str.startswith(statement.tuple[1], "E"):
                    tabLimit -= 1
                else:
                    tabLimit += 1
                    line = "\t" + line

            printable.append(line)
        return printable

    def getStatementsAsString(self):
        statements = []
        for key in self.scopes.keyOrder:

            scope = self.scopes.get(key)
            string = "Block:" + scope.label
            if scope.functionName:
                string += " def " + scope.functionName
            statements.append(string)
            i = 0
            for statement in scope.statements:
                statements.append(str(i).zfill(3) + ":" + statement.__str__())
                i += 1
            statements.append("")
        return statements

    def getCurrentBlockEndLabel(self):
        return "E" + self.currentBlockLabel

    def scopeIsPresent(self, label):
        return self.scopes.containsKey(label)

    def updateCurrentBlock(self, label):
        self.currentBlockLabel = label
        self.currentBlock = self.scopes.get(label)

    def addGlobalFunction(self, function: TFunction):
        """add global functions inside this method"""
        self.globalFunctions.put(function.name, function)

    def parseRoot(self, block: Block):
        scope = Scope(block.label)
        self.scopes.put(block.label, scope)
        self.parseBlock(block)

    def parseBlock(self, block: Block, putLabel=True):
        scope = Scope(block.label)
        self.updateCurrentBlock(block.label)
        if self.scopes.containsKey(block.label):
            scope = self.scopes.get(scope.label)
        else:
            self.scopes.put(scope.label, scope)
        if putLabel:
            scope.statements.append(TAC(Tnames.LABEL, scope.label))
        for st in block.statements:
            self.currentBlockLabel = scope.label
            scope.statements.extend(self.parseStatement(st))
        if putLabel:
            scope.statements.append(TAC(Tnames.LABEL, block.exitLabel()))
        self.scopes.put(scope.label, scope)

    def parseStatement(self, statement: Statement):
        statements = list()
        scope = self.scopes.get(self.currentBlockLabel)
        if isinstance(statement, Statement):
            node = statement.node

            if isinstance(node, VariableAssign):
                statements.append(TAC(Tnames.BEGINMODIFY, ""))
                if not self.nameIsDefined(scope.label, node.name):
                    raise SemanticException(node.name +
                                            " Was not yet defined in " +
                                            scope.label)
                if isinstance(node, ArrayElementAssign):
                    statements.extend(self.parseArrayElementAssign(node))
                else:
                    statements.extend(self.untangleExpression(node.value))
                    statements.append(
                        TAC(node.operator.type, node.name, self.makeTmp(0)))
                statements.append(TAC(Tnames.ENDMODIFY, ""))
            elif isinstance(node, VariableDeclaration):
                if isinstance(node, FunctionDeclaration):
                    label = scope.label
                    self.parseDefineFunction(node)
                    self.updateCurrentBlock(label)
                else:
                    statements.append(TAC(Tnames.BEGININIT, ""))
                    if isinstance(node, VariableInitialization):

                        if self.nameIsDefined(scope.label,
                                              node.name,
                                              checkOnlyLocal=True):
                            raise SemanticException(
                                node.name +
                                " Is allready defined in this scope")
                        else:
                            scope.variables.put(
                                node.name,
                                TVariable([node.tp, False], node.name))

                        statements.extend(self.untangleExpression(node.value))
                        statements.append(
                            TAC(Tnames.INIT, [node.tp, node.name],
                                self.makeTmp(0)))
                    elif isinstance(node, ArrayDeclaration):
                        if self.nameIsDefined(scope.label,
                                              node.name,
                                              checkOnlyLocal=True):
                            raise SemanticException(
                                node.name +
                                " Is allready defined in this scope")
                        else:
                            scope.variables.put(
                                node.name, TVariable([node.tp, True],
                                                     node.name))
                        statements.extend(self.untangleExpression(node.size))
                        statements.append(
                            TAC(Tnames.INITARR, [node.tp, node.name],
                                self.makeTmp(0)))
                    else:
                        statements.append(
                            TAC(Tnames.INIT, node.name,
                                Null(Token(LexName.NULL, None))))
                    statements.append(TAC(Tnames.ENDINIT, ""))
            elif isinstance(node, WhileLoop):
                statements.append(TAC(Tnames.CALLBLOCK, node.node.label))
                if isinstance(node, ForLoop):
                    self.parseFor(node)
                else:
                    self.parseWhile(node)
            elif isinstance(node, Block):
                statements.append(TAC(Tnames.CALLBLOCK, node.label))
                self.parseBlock(node)
            elif isinstance(node, ReturnStatement):
                statements.extend(self.untangleExpression(node.node))
                statements.append(TAC(Tnames.PUSH, self.makeTmp(0)))
                statements.append(
                    TAC(Tnames.RETURN, self.currentFunction.getLast(),
                        self.currentFunctionName.getLast()))
                try:
                    self.returnWasDeclared.pop()
                    self.returnWasDeclared.append(True)
                except:
                    raise SemanticException(
                        "Return declared outside a function")
            elif isinstance(node, BreakStatement):
                if self.breakLabel is not None:
                    statements.append(
                        TAC(Tnames.JUMP, self.breakLabel.getLast()))
            elif isinstance(node, ContinueStatement):
                if self.continueLabel is not None:
                    statements.append(
                        TAC(Tnames.JUMP, self.continueLabel.getLast()))
            elif isinstance(node, IfStatement):
                statements.append(TAC(Tnames.CALLBLOCK, node.blocks[0].label))
                self.parseIf(node)
            elif isinstance(node, EXP):
                statements.extend(self.untangleExpression(node,
                                                          eliminate=True))
        return statements

    def parseDefineFunction(self, node: FunctionDeclaration):

        functionScope = Scope(node.body.label)
        functionScope.functionName = node.name
        function = TFunction([node.tp, node.isArray], node.name,
                             node.body.label, node.parameters)
        self.scopes.put(functionScope.label, functionScope)
        # self.updateCurrentBlock(functionScope.label)
        if self.nameIsDefined(functionScope.label,
                              functionScope.functionName,
                              function=True):
            raise SemanticException("Function name " +
                                    functionScope.functionName +
                                    "is already defined")
        else:

            parentScope = self.scopes.get(functionScope.getParentLabel())
            parentScope.functions.put(functionScope.functionName, function)
            functionScope.functions.put(functionScope.functionName, function)
            #parentScope.statements.append(TAC(Tnames.,functionScope.label))

        for p in node.parameters:
            if self.nameIsDefined(functionScope.label,
                                  p.name,
                                  checkOnlyLocal=True):
                raise SemanticException(p.name + " Is allready defined in " +
                                        functionScope.label + " scope")
            else:
                functionScope.variables.put(
                    p.name, TVariable([p.tp, p.isArray], p.name))
        self.updateCurrentBlock(functionScope.getParentLabel())
        self.functionStack += "f"
        self.currentFunction.append(functionScope.label)
        self.currentFunctionName.append(functionScope.functionName)
        self.returnWasDeclared.append(False)
        self.parseBlock(node.body)

        #popping variables from stack
        for p in node.parameters:
            functionScope.statements.insert(1, TAC("POP", self.makeTmp(0)))
            functionScope.statements.insert(
                2, TAC(LexName.ASSIGN, p.name, self.makeTmp(0)))
        functionScope.statements.append(
            TAC(Tnames.LOAD, self.makeTmp(0), [LexName.NULL, ""]))
        functionScope.statements.append(TAC(Tnames.PUSH, self.makeTmp(0)))
        functionScope.statements.append(
            TAC(Tnames.RETURN, self.currentFunction.getLast(),
                self.currentFunctionName.getLast()))
        self.currentFunction.pop()
        self.currentFunctionName.pop()
        if not self.returnWasDeclared.pop():
            raise SemanticException("Return was not declared in function " +
                                    function.name)
        self.functionStack = self.functionStack[:-1]

    def parseArrayElementAssign(self, node: ArrayElementAssign):
        statements = []
        statements.extend(self.untangleExpression(node.value))
        statements.append(TAC(Tnames.PUSH, self.makeTmp(0)))
        #_r1 = index, _r0 = value
        statements.extend(self.untangleExpression(node.index))
        statements.append(TAC(Tnames.LOAD, self.makeTmp(1), self.makeTmp(0)))
        statements.append(TAC(Tnames.POP, self.makeTmp(0)))
        statements.append(
            TAC(node.operator.type, [node.name, self.makeTmp(1)],
                self.makeTmp(0)))
        return statements

    def parseFor(self, loop: ForLoop):
        label = loop.node.label

        scope = Scope(label)
        self.scopes.put(label, scope)
        self.updateCurrentBlock(label)
        statsBefore = ArrayList()
        statsBefore.extend(self.parseStatement(loop.var))
        statsAfter = ArrayList()
        statsAfter.append(TAC(Tnames.LABEL, "C" + scope.label))
        statsAfter.extend(self.parseStatement(loop.incrementStatement))

        self.parseWhile(loop, False)
        scope = self.scopes.get(label)
        statsBefore.extend(scope.statements)
        statsBefore.extendAt(statsAfter, -2)
        scope.statements = statsBefore

    def parseWhile(self, loop: WhileLoop, addContinue=True):
        stats = ArrayList()
        exitLabel = loop.node.exitLabel()
        label = loop.node.label
        continueLabel = "C" + label
        self.continueLabel.append(continueLabel)
        self.breakLabel.append(exitLabel)
        self.parseBlock(loop.node, False)
        scope = self.scopes.get(label)
        stats.append(TAC(Tnames.LABEL, label))
        if addContinue:
            stats.append(TAC(Tnames.LABEL, continueLabel))
        stats.extend(self.untangleExpression(loop.condition))
        stats.append(TAC(Tnames.JUMPZ, exitLabel, self.makeTmp(0)))
        stats.extend(scope.statements)
        stats.append(TAC(Tnames.JUMP, label))
        stats.append(TAC(Tnames.LABEL, exitLabel))
        scope.statements = stats
        #self.scopes.put(scope.label,scope)
        self.breakLabel.pop()
        self.continueLabel.pop()

    def parseIf(self, st: IfStatement):

        for i in range(0, st.condition.__len__()):
            statements = []
            notLabel = "N" + st.blocks[i].label
            self.parseBlock(st.blocks[i])
            statements.extend(
                self.untangleExpression(st.condition[i], eliminate=True))
            statements.append(TAC(Tnames.JUMPZ, notLabel, self.makeTmp(0)))

            scope = self.scopes.get(st.blocks[i].label)
            scope.statements.extendAt(statements, 0)
            scope.statements.insert(-1,
                                    TAC(Tnames.JUMP, st.blocks[i].exitLabel()))
            scope.statements.insert(-1, TAC(Tnames.LABEL, notLabel))
            try:
                scope.statements.insert(
                    -1, TAC(Tnames.CALLBLOCK, st.blocks[i + 1].label))
            except Exception:
                pass

        if st.containsElse:
            self.parseBlock(st.blocks[-1])

    def untangleExpression(self, exp: AST, index=0, eliminate=False):
        statements = []

        class Info:
            def __init__(self):
                self.eliminate = False

        info = Info()
        info.eliminate = eliminate

        def untangleExp(exp: AST, index: int):
            if isinstance(exp, EXP):
                if isinstance(exp, BinaryOperator):
                    untangleExp(exp.left, index)
                    untangleExp(exp.right, index + 1)
                    statements.append(
                        self.generateArithmetic(exp.op.type, index, index + 1))

                if isinstance(exp, Literall):
                    statements.append(
                        TAC(Tnames.LOAD, self.makeTmp(index),
                            [exp.token.type, exp.token.value]))
            if isinstance(exp, ValueCall):
                info.eliminate = False
                if isinstance(exp, FunctionCall):
                    if not self.nameIsDefined(self.currentBlockLabel,
                                              exp.name,
                                              function=True,
                                              checkOnlyLocal=False):
                        raise SemanticException("Function " + exp.name +
                                                " is not defined in " +
                                                self.currentBlockLabel)
                    for par in exp.parameters:
                        statements.extend(self.untangleExpression(par, index))
                        statements.append(TAC(Tnames.PUSH,
                                              self.makeTmp(index)))
                    amount = exp.parameters.__len__()
                    statements.append(
                        TAC(Tnames.LOAD, self.makeTmp(index),
                            [LexName.INTEGER_CONST, amount]))
                    statements.append(TAC(Tnames.PUSH, self.makeTmp(index)))
                    statements.append(TAC(Tnames.CALL, exp.name))
                    statements.append(TAC(Tnames.POP, self.makeTmp(index)))
                elif isinstance(exp, ArrayCall):
                    if not self.nameIsDefined(self.currentBlockLabel, exp.name,
                                              False):
                        raise SemanticException("Array " + exp.name +
                                                " is not defined")
                    untangleExp(exp.index, index + 1)
                    statements.append(
                        TAC(Tnames.LOADARR, self.makeTmp(index),
                            [exp.name, self.makeTmp(index + 1)]))
                else:
                    if not self.nameIsDefined(self.currentBlockLabel, exp.name,
                                              False):
                        raise SemanticException("Variable " + exp.name +
                                                " is not defined")
                    statements.append(
                        TAC(Tnames.LOAD, self.makeTmp(index), exp.name))
            if exp.negation:
                statements.append(TAC(LexName.NOT, self.makeTmp(index)))

        untangleExp(exp, index)
        if info.eliminate:
            statements.insert(0, TAC(Tnames.BEGINEXP, ""))
            statements.append(TAC(Tnames.ENDEXP, ""))
        return statements

    def generateArithmetic(self, operation, reg1: int, reg2: int) -> TAC:
        return TAC(operation, self.makeTmp(reg1), self.makeTmp(reg2))
Example #8
0
 def parseWhile(self, loop: WhileLoop, addContinue=True):
     stats = ArrayList()
     exitLabel = loop.node.exitLabel()
     label = loop.node.label
     continueLabel = "C" + label
     self.continueLabel.append(continueLabel)
     self.breakLabel.append(exitLabel)
     self.parseBlock(loop.node, False)
     scope = self.scopes.get(label)
     stats.append(TAC(Tnames.LABEL, label))
     if addContinue:
         stats.append(TAC(Tnames.LABEL, continueLabel))
     stats.extend(self.untangleExpression(loop.condition))
     stats.append(TAC(Tnames.JUMPZ, exitLabel, self.makeTmp(0)))
     stats.extend(scope.statements)
     stats.append(TAC(Tnames.JUMP, label))
     stats.append(TAC(Tnames.LABEL, exitLabel))
     scope.statements = stats
     #self.scopes.put(scope.label,scope)
     self.breakLabel.pop()
     self.continueLabel.pop()
Example #9
0
    def parseFor(self, loop: ForLoop):
        label = loop.node.label

        scope = Scope(label)
        self.scopes.put(label, scope)
        self.updateCurrentBlock(label)
        statsBefore = ArrayList()
        statsBefore.extend(self.parseStatement(loop.var))
        statsAfter = ArrayList()
        statsAfter.append(TAC(Tnames.LABEL, "C" + scope.label))
        statsAfter.extend(self.parseStatement(loop.incrementStatement))

        self.parseWhile(loop, False)
        scope = self.scopes.get(label)
        statsBefore.extend(scope.statements)
        statsBefore.extendAt(statsAfter, -2)
        scope.statements = statsBefore
Example #10
0
from src.TAC import TAC, Tnames
from src.lib import OrderedMap, ArrayList

m = OrderedMap()
m.put("1", 1)
m.put("2", 2)
m.put("4", 4)
m.put("3", 3)

print(m.returnItemsInOrder())

a = ArrayList()
a.append(2)
a.append(3)
a.extendAt([0, 1], 0)
print(a)

stack = list()
stack.append(0)
stack.append(1)
stack.append(2)
print(stack.pop())
print(stack.pop())

print("ab" > "ba")

t = TAC(Tnames.LOAD, "_t0", ['INTEGER_CONST', 10])
print(t.__copy__())