def visitMethod_decl(self, ctx: DecafParser.Method_declContext): line_num = ctx.start.line method_name = ctx.ID(0).getText() method_type = ctx.return_type().getText() method_params = [] for i in range(len(ctx.data_type())): param_type = ctx.data_type(i).getText() param_name = ctx.ID(i + 1).getText() param_symbol = VarSymbol(id=param_name, type=param_type, line=line_num, size=8, mem=STACK) method_params.append(param_symbol) method_symbol = MethodSymbol(method_name, method_type, line_num, method_params) self.st.addSymbol(method_symbol) self.body += method_name + ':\n' if method_name == 'main': self.body += 'movq %rsp, %rbp\n' self.st.enterScope() for i in range(len(method_params)): self.st.addSymbol(method_params[i]) self.body += 'movq ' + param_registers[i] + ',' + str(method_params[i].getAddr()) + '(%rsp)\n' self.visitChildren(ctx) self.body += 'ret\n' self.st.exitScope()
def visitMethod_decl(self, ctx: DecafParser.Method_declContext): #1. get method return type method_type = ctx.return_type().getText() #2. get method name method_name = ctx.ID(0).getText() #3. get list of method parameter types and names param_types = [] param_names = [] for i in range(len(ctx.data_type())): param_types.append(ctx.data_type(i).getText()) param_names.append(ctx.ID(i + 1).getText()) #4. create a new method symbol method_symbol = SymbolTable.MethodSymbol(method_name, method_type, ctx.start.line, param_types) #5. add method symbol to current scope self.st.addSymbol(method_symbol) #6. enter the method scope self.st.enterScope() #7. add method symbol to method scope (method names hsould exist in two scopes) #8. add the method parameters as individual symbols for i in range(len(param_types)): self.st.addSymbol( SymbolTable.VarSymbol(param_names[i], param_types[i], ctx.start.line)) #9. visit child nodes (all sub trees and nodes) result = self.visitChildren(ctx) #10. exis the method scope (after visiting all sub-trees!) self.st.exitScope() return result
def visitMethod_decl(self, ctx:DecafParser.Method_declContext): method_name = ctx.ID(0).getText() return_type = ctx.TYPE(0) line_number = ctx.start.line # Checks if the method has already been declared. if self.st.probe(method_name) != None: print('[Error]: The method ' + method_name + ' on line: ' + line_number + 'was already declared!') else: self.body += method_name self.body += ':\n' params = [] # Loops through paramaters and creates a var symbol for them and appends them to a list. if len(params) > 1: for param in range(len(ctx.ID())): param_name = ctx.ID(param).getText() params.append(param_name) var_symbol = self.st.probe(param_name) if var_symbol == None: var_symbol = VarSymbol(id=param_name, type='int', line=ctx.start.line, size=8, mem=self.st.stack_pointer) self.st.addSymbol(var_symbol) var_addr = var_symbol.getAddr() self.body += '\tmovq %rax, -' + str(var_addr[0]) + '(%rsp)\n' params.pop(0) method_symbol = MethodSymbol(id=method_name, type=return_type, line=line_number, params=params) self.st.addSymbol(method_symbol) visit = self.visitChildren(ctx) return visit
def visitMethod_decl(self, ctx: DecafParser.Method_declContext): method_name = ctx.ID()[0].getText() method_return_type = ctx.return_type().getText() line_num = ctx.start.line method_params = [] for x in ctx.data_type(): method_params.append(x.getText()) # get data type as a string method_symbol = MethodSymbol( id=method_name, type=method_return_type, line=line_num, params=method_params) # create a method symbol with ctx values self.st.addSymbol( method_symbol ) # push method symbol with params list to global scope return self.visitChildren(ctx)
def visitMethod_decl(self, ctx: DecafParser.Method_declContext): #Makes method have its own scope #self.st.enterScope() line_num = ctx.start.line method_name = ctx.ID().getText() method_args = [] main_check = self.st.probe('main') method_symbol = self.st.probe(method_name) if ctx.data_type() != None: data_type = ctx.data_type().getText() else: data_type = "void" if method_name == "main" and len(ctx.method_arg()) > 0: # 3 print('Error on line', line_num, ', method \'main\' cannot have any parameters') if main_check != None: # 3 print('Warning detected function ' + method_name + ' declared after main, this will not be executed') # Adds space to method arguments for m in ctx.method_arg(): method_args.append(m.data_type().getText() + ' ' + m.ID().getText()) # var_symbol = VarSymbol(id=m.ID().getText(), # type=m.data_type().getText(), # line=line_num, # size=8, # mem=STACK) # # self.st.addSymbol(var_symbol) method_symbol = MethodSymbol(id=method_name, type=data_type, line=line_num, params=method_args) self.st.addSymbol(method_symbol) self.visitChildren(ctx) statements = ctx.block().statement() # 7 and 8 for s in statements: var_type = self.visit(s.expr(0)) #print(ctx.data_literal().bool_literal()) if s.RETURN() != None: if ctx.VOID() != None: print('Error on line ' + str(line_num) + ', method should not have a return statement')
def visitMethod_decl(self, ctx:DecafParser.Method_declContext): data_type = "" line_num = ctx.start.line method_name = ctx.ID().getText() method_args = ctx.method_arg() method_params = [] if ctx.data_type() != None: data_type = ctx.data_type().getText() else: data_type = "void" for i in method_args: arg_type = i.data_type().getText() method_arg = VarSymbol(id=i.ID().getText(), type=arg_type, line=line_num, size=8, mem=STACK) method_params.append(method_arg) method_symbol = MethodSymbol(id=method_name, type=data_type, line=line_num, params=method_params) self.body += method_name + ':\n' if method_name == 'main': self.body += 'movq %rsp, %rbp\n' self.st.enterScope() for i in range(len(method_params)): self.st.addSymbol(method_params[i]) #Saving each method parameter onto a location on the stack(Memory) self.body += 'movq ' + param_registers[i] + ',' + str(method_params[i].getAddr()) + '(%rsp)\n' self.visitChildren(ctx) self.body += 'ret\n' self.st.exitScope()
def visitMethod_decl(self, ctx: DecafParser.Method_declContext): # add the method_decl params to the symbol table one by one i = 1 paramvalues = [] if ctx.ID() and ctx.data_type(1): while i < len(ctx.ID()): val = ctx.ID(i).getText() t = ctx.data_type(1).getText() i += 1 paramvalues.append(val) var_symbol = SymbolTable.VarSymbol( id=val, type=t, line=ctx.start.line, size=8, mem=SymbolTable.STACK ) self.st.addSymbol(var_symbol) if ctx.ID() and ctx.data_type(): #add the method_decl and its type to the symbol table, with also the list of params return_type = ctx.data_type(0).getText() method_name = ctx.ID(0).getText() line_number = ctx.start.line #sets values to be inserted into the symbol table method_symbol = SymbolTable.MethodSymbol( id=method_name, type=return_type, line=line_number, params = paramvalues ) #add var symbol to the stack, you need to add method symbol to global scope and method symbol include param types, enter new scope, #then loop through the param list and add to stack so theyre added to the symbol table #adds the above method to the symbol table for later use! self.st.addSymbol(method_symbol) #Rule 3 check if main has params, which it should not, we also check that method currently being checked is main, otherwise they are allowed to have params if len(self.st.lookup(method_name).params) > 0 and method_name == 'main': print("[Rule 3] error found parameters in main declaration on line", ctx.start.line) # enter the scope for the method scope self.st.enterScope() #add params to table one by one self.visitChildren(ctx) #Rule 7 void method check if contains return in body! as the method we're checking should not have a return since it is VOID if ctx.VOID(): if ctx.block().getText().find('return') != -1: print('[Rule 7] found void method, but return found on line', ctx.start.line , 'for method:', method_name) #catch the method_name if this method is type void self.voidMethods.append(method_name) self.st.exitScope()
def visitMethod_decl(self, ctx: DecafParser.Method_declContext): self.params param_types = [] ctx.method_param_type() #line used for debugging #print(ctx.method_param_type(0).getText()) method_name = ctx.id(0).getText() return_type = ctx.method_type().getText() line_number = ctx.start.line for i in range(len(ctx.method_param_type())): param_types.append(ctx.method_param_type(i).getText()) for i in range(len(ctx.method_Param_names())): self.params.append(ctx.method_Param_names(i).getText()) #line used for debugging #print(ctx.method_Param_names(0).getText()) for i in range(len(param_types)): if self.params == []: method_params = VarSymbol(id=self.params[i], type=param_types[i], line=line_number, size=8, mem=SymbolTable.STACK) self.st.addSymbol(method_params) else: method_params = VarSymbol(id=self.params[i], type=param_types[i], line=line_number, size=8, mem=SymbolTable.STACK) self.st.addSymbol(method_params) method_symbol = MethodSymbol(id=method_name, type=return_type, line=line_number, params=ctx.method_Param_names()) self.st.addSymbol(method_symbol) if self.st.lookup(method_name) != None: for i in range(len(self.st.lookup(method_name).params)): method_params = VarSymbol( id=ctx.method_Param_names(i).getText(), type=ctx.method_param_type(i).getText(), line=line_number, size=8, mem=SymbolTable.STACK) self.st.addSymbol(method_params) """don't add main to code more than once""" if "main" in method_name: pass else: self.body += method_name + ":" + "\n" """get the statment in the return statment""" returnStatment = ctx.block().statement() if returnStatment != None: for item in returnStatment: if "if" in item.getText(): pass elif "return" in item.getText(): if self.st.lookup(item.expr(0)) == None: """if return of method is void then throw and error""" if return_type == "void": print("method on line:", line_number, "should not return anything") elif return_type == "int": """try to int the expr, if that fails throw an error""" try: int(item.expr(0).getText()) except: print( "ERROR: wrong return type found for method on line:", line_number) elif self.st.lookup( item.expr(0).getText()).type != return_type: print( "ERROR: type of retrun statement does not match method return type, line number:", line_number) else: Addr = self.st.lookup( item.expr(0).getText()).getAddr() self.st.stack_pointer[-1] += 8 self.body += 'movq %rax, ' + str( -self.st.stack_pointer[-1]) + '(%rsp)\n' self.body += "movq " + str( Addr) + " (%rbp), " + " %rax" + "\n" "" if return_type == "int" and returnStatment == []: print("ERROR: method missing return statement", line_number) if return_type == "boolean" and returnStatment == []: print("ERROR: method missing return statement", line_number) return self.visitChildren(ctx)