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()
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 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))
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
def __init__(self, tp, name, size): super().__init__(tp, name) self.value = ArrayList(None, None) self.size = size
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))
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 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
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__())