def visitStatement(self, ctx: DecafParser.StatementContext): #Rule 17 iterate through the expressions found within a for loop and check if they are digits by using a python built in feature, if not then the for loop is not valid and error displayed if ctx.FOR(): for j, i in enumerate(ctx.expr()): if i.getText().isdigit() != True: #Tell us which expr has the issue 0 = first 1 = second print("[Rule 17] Expected type int for expr", j , "in this for loop but found error on line:", ctx.start.line, "is int?", i.getText().isdigit()) #Rule 11 check if boolean has return in body! if not error out, simple check for a true or false within the statement if ctx.IF(): temp = ctx.getText() if temp.find('true') == -1 and temp.find('false') == -1: print('[Rule 11] error on line', ctx.start.line, 'expected boolean type return value') # rule 2, No identifier is used before it is declared, check if it exists in the symbol table, this rule was provided by Ryan via screencast on moodle if ctx.location(): id = ctx.location().ID().getText() if (self.st.lookup(id) == None): print("[Rule 2] error on line", ctx.start.line,'ID: (', id, ') not declared before use') if ctx.location(): if ctx.location().ID().getText() != None: if self.st.lookup(ctx.location().ID().getText()) == None: print('[Rule 9] error ID (', ctx.location().ID().getText(), ") does not exists in local/global variable or formal parameter, on line", ctx.start.line) #Rule 15 check that location and expr have the same type by doing a lookup in the table if they exist if they do then test to see if types match otherwise #error and error if not in symbol table if ctx.location() and ctx.expr(): lookup = self.st.lookup(ctx.location().getText()) for i in ctx.expr(): res = self.st.lookup(i.getText()) if lookup == None and res == None or lookup and res and lookup.type != res.type: print("[Rule 15] location and expr don't have same type") return self.visitChildren(ctx)
def visitStatement(self, ctx: DecafParser.StatementContext): line_num = ctx.start.line expression = ctx.expr(0) # 11 Expr of an if must have type bool if ctx.IF() != None: expr_type = self.visit(expression) expr_b_type = self.visit(expression.expr(0)) print(expr_b_type) #if (expr_a_type != None and expr_a_type != 'boolean') or (expr_b_type != None and expr_b_type != 'boolean'): #print('Error on line ' + str(line_num) + ', expression in if must be of type boolean') elif ctx.location() != None: loc_type = self.visit(ctx.location()) expr_type = self.visit(ctx.expr(0)) operator = ctx.assign_op().getText() identifier = self.st.probe(ctx.location().getText()) #2 if identifier == None: print('Error on line ' + str(line_num) + ', identifier \'' + ctx.location().getText() + '\' has not been declared') #16 - TODO change error message elif loc_type != None: if (loc_type != 'int' or expr_type != 'int') and (operator == '-=' or operator == '+='): print( 'Error on line ' + str(line_num) + ' variables must be of type int when in an incrementing/decrementing assignment' ) #15 elif loc_type != expr_type: print('Error on line ' + str(line_num) + ' type mismatched in expression') #17 elif ctx.FOR() != None: expr_type_a = self.visit(ctx.expr(0)) expr_type_b = self.visit(ctx.expr(1)) if expr_type_a != 'int' or expr_type_b != 'int': print('Error on line ' + str(line_num) + ' for statement expressions must be of type int') else: self.visitChildren(ctx)
def visitStatement(self, ctx:DecafParser.StatementContext): if ctx.CONTINUE() != None: self.body += '\tjmp main\n' if ctx.BREAK() != None: self.body += '\tjmp main\n' if ctx.IF(): self.st.enterScope() if_label = 'if-label-'+str(self.IF_LABEL_COUNT) self.body += '\tcmp %r11 %r10\n' self.body += '\tjl '+if_label+'l\n' self.body += '\tje '+if_label+'e\n' self.body += '\tjg '+if_label+'g\n' self.body += '\tret\n' self.body += if_label+':\n' self.IF_LABEL_COUNT = self.IF_LABEL_COUNT + 1 ctx.expr() self.st.exitScope() if ctx.RETURN(): if ctx.expr(): return_value = str(ctx.expr(0).getText()) self.body += '\tmovq $'+return_value+', %rax\n' self.body += '\tret\n' else: self.body += '\tret\n' if ctx.FOR(): self.st.enterScope() start_value = ctx.expr(0) end_value = ctx.expr(1) self.body += '\tmovq $1, %rbx\n' self.body += '\tjmp begin-for-'+str(self.LOOP_COUNT)+'\n' self.body += 'begin-for-'+str(self.LOOP_COUNT)+':\n' self.body += '\tcmp $'+str(end_value)+ ', %rbx\n' self.body += '\tjge end-for-'+str(self.LOOP_COUNT)+'\n' visit = self.visitChildren(ctx) self.body += '\taddq $1, %rbx\n' self.body += '\tjmp begin-for-'+str(self.LOOP_COUNT)+'\n' self.body += 'end-for-'+str(self.LOOP_COUNT)+':\n' self.body += '\tret\n' self.LOOP_COUNT = self.LOOP_COUNT + 1 self.st.exitScope() visit = self.visitChildren(ctx) return visit
def visitStatement(self, ctx: DecafParser.StatementContext): line_number = ctx.start.line statmentName = ctx.location() if ctx.expr(): #visit first expression self.visit(ctx.expr(0)) #move the stack pointer and save value of first expression self.st.stack_pointer[-1] += 8 self.body += 'movq %rax, ' + str( -self.st.stack_pointer[-1]) + '(%rsp)\n' #visit second expression self.visit(ctx.expr(0)) self.body += 'movq ' + str( -self.st.stack_pointer[-1]) + '(%rsp), %r10\n' self.st.stack_pointer[-1] -= 8 self.body += 'movq %rax, %r11\n' """if a loction exists then assign the locaton varible to look on the symbol table""" if ctx.location(): location = self.st.lookup(ctx.location().getText()) if ctx.expr(): expr = ctx.expr(0).expr(0) if expr.literal(): if self.st.lookup(location.id).type == "boolean": try: """if the lookup if type returns a boolean then try to int the expression if that is possible throw an error""" int(ctx.expr(0).expr(0).getText()) print( "ERROR: cannot assign boolean to int, line number:", line_number) except: """if that fails it can be assumed that the opertor is wrong""" print( "ERROR cannot use that operator with booleans, line number:", line_number) if ctx.breaknCon() != None: self.breakncon = ctx.breaknCon().getText() if ctx.FOR(): """try and int the item in side of the for loop if that fails error""" for items in ctx.expr(): try: int(items.getText()) except: if items.location() != None: if self.st.lookup( items.location().getText()).type != "int": print("ERROR: type is not int. Line number:", line_number) else: print( "ERROR: type int must be used here in for loop. Line number:", line_number) """ if an if statment exists then check if the expression is an boolean check if you are comparing two things of the same types """ if ctx.IF() != None: if ctx.expr(0).bin_op() == None: if self.st.lookup(ctx.expr(0).getText()).type != "boolean": print( "ERROR", "cannot evaluate type " + self.st.lookup(ctx.expr(0).getText()).type + " to boolean, on line:", line_number) else: """get the eq operator """ self.eq_op = ctx.expr(0).bin_op().eq_op().getText() if ctx.expr(0).bin_op(): """get the bin op """ bin_op = ctx.expr(0).bin_op().getText() ids = ctx.expr(0).getText().replace(bin_op, "") """make a list out of all the ids""" listOfIds = list(ids) """compare the operands of of bin_op and if they are not the same type then error""" if self.st.lookup(listOfIds[0]).type != self.st.lookup( listOfIds[1]).type: print( "cannot compare " + self.st.lookup(listOfIds[0]).type + " with " + self.st.lookup(listOfIds[1]).type + " line number", line_number) else: """if bin op is not found get the type of the expression and if it's not boolean, throw an error""" if self.st.lookup(ctx.expr(0).getText()).type != "boolean": print( "ERROR: " + "cannot evaluate type int line number", line_number) if self.eq_op != None: expression = ctx.expr(0).getText() ids = expression.replace(self.eq_op, "") idList = list(ids) """check if the operands logical and or both boolean""" if self.st.lookup(idList[0]).type and self.st.lookup( idList[1]).type != "boolean": print("ERROR: cannot use logical not here. Line number:", line_number) expr = ctx.expr(0) expArrry = [] if expr != None: if "+ " in expr.getText(): """make an array of the epressions""" expArrry = expr.replace("+", ",") expArrry = expArrry.split(",") var_name = None varnames = None for varnames in expArrry: var_name = self.st.lookup(varnames) if var_name != None: pass else: """error if symbol is on symbol table already""" print( "ERROR: varible referanced but never assinged " + " '" + varnames + "' " + "on line", line_number) if statmentName != None: var_symbol = self.st.lookup(statmentName.getText()) if var_symbol != None: pass else: print("ERROR:", "varible referanced but never assinged", "'", statmentName.getText() + "'", "on line", line_number) return self.visitChildren(ctx)