def visitExpr(self, ctx: DecafParser.ExprContext): #1. if expression contains location then check symbol table (global scope) for identifier if ctx.location(): id = ctx.location().ID().getText() #2. if identifier not in symbol table then report error if (self.st.lookup(id) == None): print("Error: Found on line", ctx.start.line, ": ID(", id, ") not declared before use.") #hint ctx.location() returns None if not part of expression #hint ctx.location() returns location rule context (e.g. ctx.location().ID().getText() gets identifier name) return self.visitChildren(ctx)
def visitExpr(self, ctx: DecafParser.ExprContext): if ctx.literal(): int_literal = ctx.getText() self.body += 'movq $' + int_literal + ', %rax\n' elif ctx.location(): loc_name = ctx.getText() location = self.st.lookup(loc_name) addr = str(location.getAddr()) if location.mem == HEAP: self.body += 'movq ' + addr + '(%rbp), %rax\n' else: self.body += 'movq ' + addr + '(%rsp), %rax\n' else: self.visitChildren(ctx)
def visitExpr(self, ctx: DecafParser.ExprContext): if ctx.expr(): #Rule 12 check that expr is type int for arith or rel op and check if exists in table before comparing if ctx.ADD() or ctx.MODULOS() or ctx.MINUS() or ctx.MULTIPLY() or ctx.DIVISION() or ctx.GREATER() or ctx.GREATEREQUALS or ctx.LESS() or ctx.LESSEQUALS(): for index, _ in enumerate(ctx.expr()): id = ctx.expr(index).getText() check = self.st.lookup(id) if check != 'int' and id.isdigit() != True and check == None: print("[Rule 12] error doesn't have type int for: (", id, ") on line:", ctx.start.line) #Rule 14 check that logical and cond op have type boolean, if not None check symbol table else return error if ctx.NOT(): temp = ctx.expr(0).getText().replace('!','') lookup = self.st.lookup(temp) if lookup == None or lookup.type != 'boolean': print("[Rule 14] error type boolean not found for not expression, on line:", ctx.start.line) if ctx.ANDAND() or ctx.OROR(): temp = ctx.expr(0).getText().replace('!','') temp1 = ctx.expr(1).getText().replace('!','') lookup = self.st.lookup(temp) lookup1 = self.st.lookup(temp1) if lookup == None and lookup1 == None or lookup.type != 'boolean' and lookup1.type != 'boolean' : print("[Rule 14] error type boolean not found for not expression, on line:", ctx.start.line) #Rule 13 check that eq op have type boolean or int, if not None check symbol table else return error if ctx.EQUALSEQUALS() or ctx.NOTEQUAL(): temp = ctx.expr(0).getText() temp1 = ctx.expr(1).getText() lookup = self.st.lookup(temp) lookup1 = self.st.lookup(temp1) if lookup != None and lookup1 != None and lookup.type != lookup1.type or lookup == None and lookup1 == None: print("[Rule 13] error operands type do not match, on line:", ctx.start.line) # 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') return self.visitChildren(ctx)
def visitExpr(self, ctx: DecafParser.ExprContext): line_num = ctx.start.line expr_type = "" if len(ctx.expr()) == 2: type_a = self.visit(ctx.expr(0)) type_b = self.visit(ctx.expr(1)) op = ctx.bin_op() if type_a == type_b: expr_type = type_a else: expr_type = None #print('Error on line', line_num, 'type mismatched in expression') #12 if (op.rel_op() != None or op.arith_op() != None ) and type_a != 'int' and type_b != 'int': print('Error on line ' + str(line_num) + ' operands must be of type int') #13 elif op.eq_op() != None and type_a != type_b: print('Error on line ' + str(line_num) + ' operands must be of same type') #14 elif op.cond_op() != None and (type_a != 'boolean' or type_b != 'boolean'): print('Error on line ' + str(line_num) + ' operands must be of type boolean') elif ctx.location() != None: var_name = ctx.location().ID().getText() var_symbol = self.st.lookup(var_name) if var_symbol != None: expr_type = var_symbol.type else: #2 expr_type = None print('Error on line ' + str(line_num) + ', ' + var_name + ' has not been declared') elif ctx.data_literal() != None: if ctx.data_literal().int_literal() != None: expr_type = 'int' elif ctx.data_literal().bool_literal() != None: expr_type = 'boolean' else: expr_type = None elif ctx.method_call() != None: method_name = ctx.method_call().method_name().getText() method_symbol = self.st.lookup(method_name) if method_symbol != None: expr_type = method_symbol.type self.visit(ctx.method_call()) else: method_symbol = None elif ctx.EXCLAMATION() != None: expr_type = self.visit(ctx.expr(0)) #14 if expr_type != 'boolean': print('Error on line ' + str(line_num) + ' operand must be of type boolean') else: self.visitChildren(ctx) return expr_type
def visitExpr(self, ctx: DecafParser.ExprContext): line_number = ctx.start.line method_call = ctx.method_call() bin_oper = "" if ctx.expr(0) != None: if ctx.expr(0).bin_op() != None: bin_oper = ctx.expr(0).bin_op().getText() if self.eq_op: pass else: expressions = ctx.expr(0) if expressions != None: if ctx.expr(0).location() and bin_oper != None: for items in ctx.expr(): locatons = items.getText() """ check that the operands of bin_op are ints """ if self.st.lookup(locatons).type != "int": print( "ERROR: can only use a airthmetic operation on ints", line_number) if ctx.expr(0) and bin_oper != None: if ctx.expr(0).location: pass else: airth_op = ctx.expr(0).bin_op().airth_op().getText() if airth_op in expressions.getText(): operands = ctx.expr(0).getText().replace( airth_op, "") listOfoperands = list(operands) """ if operands are not loctions (meaning not varibles), try to chnage the type to int, if that fails throw error """ for i in range(len(listOfoperands)): try: int(listOfoperands[i]) except: print( "ERROR: can only use a airthmetic operation on ints", line_number) """ check if a method call in side of an expression is not void as it must be a type to be evaluated to something for it to be used in an expression, void is anon type """ method_expr_params = [] if method_call != None: method_params = method_call.expr() if self.st.lookup(method_call.ID().getText()).type == "void": print( "ERROR: for method to be used here, method must return something" + " line numnber", line_number) if "()" in method_call.getText(): name = method_call.getText() name = name.replace("()", "") for names in method_params: method_expr_params = method_expr_params.append[names] if len(method_expr_params) < len( self.st.lookup(name).params): print( "ERROR: " + "method " + self.st.lookup(name).id + " epecting", len(self.st.lookup(name).params), "but got", len(method_expr_params), "on line", line_number) return self.visitChildren(ctx)
def visitExpr(self, ctx:DecafParser.ExprContext): # Expression is a variable. if ctx.location(): var_name = ctx.location().getText() var_symbol = self.st.lookup(var_name) if "[" in var_name: split_var = var_name.split('[', 1)[0] var_symbol = self.st.lookup(split_var) if var_symbol == None: print('[Error]: Variable', var_name, 'has not been declared. Found on line', ctx.start.line) else: var_addr = var_symbol.getAddr() self.body += '\tmovq -' + str(var_addr[0]) + '(%rsp), %rax\n' # Expression is a literal (number or string/char) elif ctx.literal(): number = ctx.literal().getText() if number == 'false': number = '0' if number == 'true': number = '1' self.body += '\tmovq $' + number + ', %rax\n' # Expression length is more than 1 (more expressions present such as an operation) elif len(ctx.expr()) > 1: # Visit the first expression. self.visit(ctx.expr(0)) # Move stack pointer 1 place and save value of first expression. self.st.stack_pointer[-1] += 8 self.body += '\tmovq %rax, ' + str(-self.st.stack_pointer[-1]) + '(%rsp)\n' # Visit the second expression. self.visit(ctx.expr(1)) self.body += '\tmovq ' + str(-self.st.stack_pointer[-1]) + '(%rsp), %r10\n' self.st.stack_pointer[-1] -= 8 self.body += '\tmovq %rax, %r11\n' # If a binary operator is present, check the operator and add appropriate code. if ctx.BIN_OP(): if str(ctx.BIN_OP()) == '+': self.body += '\taddq %r10, %r11\n' if str(ctx.BIN_OP()) == '*': self.body += '\timul %r10, %r11\n' if str(ctx.BIN_OP()) == '-': self.body += '\tsubq %r10, %r11\n' if str(ctx.BIN_OP()) == '/': self.body += '\tmovq $0, rdx\n' self.body += '\tmovq %r11, rbx\n' self.body += '\tmovq %r10, rax\n' self.body += '\tidiv %rbx\n' self.body += '\tmovq %r11, %rax\n'
def visitExpr(self, ctx:DecafParser.ExprContext): if ctx.data_literal(): if ctx.data_literal().int_literal() != None: int_literal = ctx.data_literal().getText() self.body += 'movq $' + int_literal + ', %rax\n' elif ctx.location(): loc_name = ctx.location().getText() location = self.st.lookup(loc_name) addr = location.getAddr() if location.mem == HEAP: self.body += 'movq ' + str(addr) + '(%rbp), %rax\n' else: self.body += 'movq ' + str(addr) + '(%rsp), %rax\n' elif len(ctx.expr()) == 2: self.visit(ctx.expr(0)) self.body += 'movq %rax, %r10\n' self.st.stack_pointer[-1] += 8 self.body += 'movq %r10, ' + str(-self.st.stack_pointer[-1]) + '(%rsp)\n' self.visit(ctx.expr(1)) self.body += 'movq %rax, %r11\n' self.body += 'movq ' + str(-self.st.stack_pointer[-1]) + '(%rsp), %r10\n' self.st.stack_pointer[-1] -= 8 if ctx.bin_op().arith_op().ADD(): self.body += 'addq %r10, %r11\n' elif ctx.bin_op().arith_op().SUB(): self.body += 'subq %r11, %r10\n' self.body += 'movq %r10, %r11\n' elif ctx.bin_op().arith_op().MUL(): self.body += 'imul %r10, %r11\n' elif ctx.bin_op().arith_op().DIV(): self.body += 'movq $0, %rdx\n' self.body += 'movq %r11, %rbx\n' self.body += 'movq %r10, %rax\n' self.body += 'idiv %rbx\n' self.body += 'movq %rax, %r11\n' self.body += 'movq %r11, %rax\n' else: self.visitChildren(ctx)