def visitMethod_call(self, ctx: DecafParser.Method_callContext): line_num = ctx.start.line method_name = ctx.method_name() method_symbol = self.st.probe(method_name.getText()) # 6 # Check method is of type bool or int if method_symbol != None and method_symbol.type == 'void': # 6 print('Error on line ' + str(line_num) + ' method \'' + method_name.getText() + '\' must return a value') # 5 if method_symbol != None: # Check correct number of args if len(method_symbol.params) != len(ctx.expr()): print('Error on line ' + str(line_num) + ' method ' + method_name.getText() + ' needs ' + str(len(method_symbol.params)) + ' arguments has ' + str(len(ctx.expr()))) else: #Check correct types of args for i in range(len(method_symbol.params)): param_type = method_symbol.params[i].split(' ')[0] if (param_type == 'int' and ctx.expr(i).data_literal().int_literal() == None) or (param_type == 'boolean' and ctx.expr( i).data_literal().bool_literal() == None): print('Error on line ' + str(line_num) + ' type mismatch on method \'' + method_name.getText() + '\' parameters') self.visitChildren(ctx)
def visitMethod_call(self, ctx: DecafParser.Method_callContext): #Rule 5 find out the count of params currently found for a method_call and check if they match the len which is in the symbol table for this method if ctx.method_name() != None and ctx.expr() != None: id = ctx.method_name().getText() if self.st.lookup(id) == None or len(ctx.expr()) < len(self.st.lookup(id).params) or len(ctx.expr()) > len(self.st.lookup(id).params): count = 0 if self.st.lookup(id) != None: count = len(self.st.lookup(id).params) print('[Rule 5] error param length do not match expected for method_call', id,'lookup param count is:', count ,'found params in call_method:', len(ctx.expr())) return self.visitChildren(ctx)
def visitMethod_call(self, ctx:DecafParser.Method_callContext): method_name = ctx.method_name() method_symbol = self.st.lookup(method_name) if not ctx.callout_arg(): if method_symbol == None: print('[Error]: Call to a function that does not exist: ' + str(method_name) + ' on line: ' + str(ctx.start.line)) else: self.body += '\tjmp '+method_name+'\n' visit = self.visitChildren(ctx) return visit
def visitMethod_call(self, ctx:DecafParser.Method_callContext): if ctx.method_name(): for i in range(len(ctx.expr())): self.visit(ctx.expr(i)) self.st.stack_pointer[-1] += 8 ptr = self.st.stack_pointer[-1] self.body += 'movq %rax, ' + str(ptr) + '(%rsp)\n' for z in range(len(ctx.expr())): ptr = self.st.stack_pointer[-1] reg = param_registers[z] self.body += 'movq ' + str(ptr) + '(% rsp), ' + reg + '\n' self.st.stack_pointer[-1] -= 8 #Current pos stored in symbol table #Needs to be 16 byte aligned or we get segmentation errors stack_len = self.st.stack_pointer[-1] stack_len = stack_len + (int(stack_len/8+1) % 2) * 8 self.body += 'subq $' + str(stack_len) + ', %rsp\n' method_name = ctx.method_name().getText() self.body += 'call ' + method_name + '\n' self.body += 'addq $' + str(stack_len) + ', %rsp\n' elif ctx.CALLOUT(): pass else: self.visitChildren(ctx)
def visitMethod_call(self, ctx: DecafParser.Method_callContext): # get method call line_num = ctx.start.line method_name = ctx.method_name().getText() # lookup method call name in symbol table method_symbol = self.st.lookup(method_name) method_symbol_params = method_symbol.params if len(ctx.expr()) != len(method_symbol_params): return print( "Error you passed an incorrect combination of parameters", "on line", line_num, ", the number and types of arguments in a method call must be the same as the number and types of the formals" ) else: for i in range(max(len(method_symbol_params), len(ctx.expr()))): # check out of bound index if i >= len(method_symbol_params): print( "Error you passed an unexpected parameter", ctx.expr()[i].literal().getText(), "on line", line_num, ", the number and types of arguments in a method call must be the same as the number and types of the formals" ) else: if method_symbol_params[i] == 'int': if ctx.expr()[i].literal().int_literal() == None: print( "Error incorrect parameter data type expected", method_symbol.type, "received value", ctx.expr()[i].literal().getText(), "on line", line_num, ", the number and types of arguments in a method call must be the same as the number and types of the formals" ) elif method_symbol_params[i] == 'boolean': if ctx.expr()[i].literal().bool_literal() == None: print( "Error incorrect parameter date type expected", method_symbol.type, "received", ctx.expr()[i].literal(), "on line", line_num, ", the number and types of arguments in a method call must be the same as the number and types of the formals" ) else: print( "missing method_symbol_params with data type classification:", method_symbol_params[i], " on line number", line_num, ", the number and types of arguments in a method call must be the same as the number and types of the formals" ) return self.visitChildren(ctx)
def visitMethod_call(self, ctx: DecafParser.Method_callContext): if ctx.method_name(): for i in range(len(ctx.expr())): self.visit(ctx.expr(i)) self.st.stack_pointer[-1] += 8 self.body += 'movq %rax, ' + str(-self.st.stack_pointer[-1]) + '(%rsp)\n' for i in range(len(ctx.expr())): self.body += 'movq ' + str(-self.st.stack_pointer[-1]) + '(%rsp), ' + param_registers[ len(ctx.expr()) - i - 1] + '\n' self.st.stack_pointer[-1] -= 8 # adjust stack to 16-byte alignment (multiple of 8 that is not divisible by 16) stack_len = self.st.stack_pointer[-1] stack_len = stack_len + (stack_len // 8 + 1 % 2) * 8 self.body += 'subq $' + str(stack_len) + ', %rsp\n' method_name = ctx.method_name().getText() self.body += 'call ' + method_name + '\n' self.body += 'addq $' + str(stack_len) + ', %rsp\n' elif ctx.CALLOUT(): for i in range(len(ctx.callout_arg())): if ctx.callout_arg(i).STRING_LITERAL(): callout_arg = ctx.callout_arg(i).getText() label = 'str' + str(ctx.callout_arg(i).start.start) self.head += label + ': .asciz ' + callout_arg + '\n' self.st.stack_pointer[-1] += 8 self.body += 'movq $' + label + ', ' + str(-self.st.stack_pointer[-1]) + '(%rsp)\n' else: pass
def visitMethod_call(self, ctx: DecafParser.Method_callContext): line_number = ctx.start.line param_names = ctx.expr() if "callout" in ctx.getText(): callout_argument = ctx.callout_arg(0).getText() print(callout_argument) self.body += 'mov edx, len \n' #message length self.body += 'mov ecx, msg \n' #message to to be written self.body += 'mov ebx, 1 \n' #file descriptor self.body += 'mov eax, 4 \n' #system call number (system write) self.body += 'int 0x80 \n' #call the kernel self.body += 'mov eax, 1 \n' #system call number (system exit) self.body += 'int 0x80 \n' #call kernel again self.body += 'section .data \n' self.body += 'msg db ' + callout_argument + ', 0x0' + '\n' #string to be printed self.body += 'len equ $-msg \n' #ength of string else: method_params = self.st.lookup(ctx.id().getText()).params """ if the length of the paramertor lists in the method call and the original method decal are not the same throw an error """ if len(method_params) != len(param_names): print("ERROR: " + "method " + ctx.id().getText() + " epecting", len(method_params), "input params but got", len(param_names), "on line", line_number) else: for i in range(len(param_names)): """ if any of the method params in the original method decal is a boolean check if the types of the oringal params and the types of the called params match """ if self.st.lookup( method_params[i].getText()).type == "boolean": for i in range(len(ctx.expr())): if self.st.lookup( param_names[i].getText()) != None: if self.st.lookup(param_names[i].getText( )).type != self.st.lookup( method_params[i].getText()).type: print( "ERROR: wrong paramertor type found for method call on line:", line_number) try: int(param_names[i].getText()) print( "ERROR: parametor type cannot be boolean for method call", "int", "on line:", line_number) except: pass """ check if a varible inside of method call exists """ if param_names != None: for name in param_names: if name.literal() == None: pass else: if name.literal().bool_literal() or name.literal( ).int_litereal(): pass else: self.params.append(name.getText()) var_symbol = self.st.lookup(name.getText()) if var_symbol != None: pass else: print( "ERROR:", "varible referanced but never assinged " + " '" + name.getText() + "' " + "on line", line_number) return self.params # Visit a parse tree produced by DecafParser#block.""" return self.visitChildren(ctx)