def visitFunctionDeclaration(self, ctx: BSParser.FunctionDeclarationContext): """ This populates the symbol table with methods. It cannot handle return values. So all records In the symbol table will be empty typed. :param ctx: visitor context :return: nothing """ name = ctx.IDENTIFIER().__str__() function = self.symbol_table.functions[name] self.scope_stack.append(name) # If this case arises, then we know if ChemTypes.UNKNOWN in function.types and len(function.types) == 1: ret = self.visitReturnStatement(ctx.returnStatement()) # If this is a variable, grab the symbol and make the update. # Otherwise it's a function call. if 'method' not in ret.keys(): symbol = self.symbol_table.get_local(ret['name'], name) function.types.update(symbol.types) else: function.types.update(ret['types']) if ChemTypes.UNKNOWN in function.types: #only remove if exists function.types.remove(ChemTypes.UNKNOWN) self.scope_stack.pop()
def visitFunctionDeclaration(self, ctx: BSParser.FunctionDeclarationContext): """ This populates the symbol table with methods. It does not visit statements. :param ctx: visitor context :return: nothing """ name = ctx.IDENTIFIER().__str__() self.symbol_table.new_scope(name) types = {ChemTypes.UNKNOWN} if ctx.functionTyping(): types = self.visitFunctionTyping(ctx.functionTyping()) args = list() if ctx.formalParameters(): temp_args = self.visitFormalParameters(ctx.formalParameters()) args = list() for arg in temp_args: self.symbol_table.add_local( Symbol(arg['name'], name, arg['types'])) args.append(arg['name']) bs_function = Function(name, types, args) if name in self.symbol_table.functions.keys(): raise UndefinedFunction( "Trying to redeclare function: {}.".format(name)) self.symbol_table.functions[name] = bs_function self.symbol_table.end_scope()
def visitFunctionDeclaration(self, ctx: BSParser.FunctionDeclarationContext): name = ctx.IDENTIFIER().__str__() func = self.symbol_table.functions[name] self.functions[name] = dict() # initialize the basic block calling chain. self.bb_calls[name] = list() self.scope_stack.append(name) self.symbol_table.current_scope = self.symbol_table.scope_map[name] self.current_block = BasicBlock() self.functions[name] = { "blocks": dict(), "entry": self.current_block.nid, 'graph': None } label = Label("{}_entry".format(name)) # Build the mapping from label to nid. self.labels[name] = self.current_block.nid self.current_block.add(label) self.graph.add_node(self.current_block.nid, function=self.scope_stack[-1], label=self.current_block.label.label) for statement in ctx.statements(): self.visitStatements(statement) if ctx.returnStatement(): ret_statement = self.visitReturnStatement(ctx.returnStatement()) self.log.info(ret_statement) if ret_statement['function']: ret_val = "{}_return".format(ret_statement['name']) self.current_block.add( Call({ 'name': ret_val, 'offset': -1 }, self.symbol_table.functions[ret_statement['name']], ret_statement['args'])) self.current_block.add(Return({'name': ret_val, 'offset': -1})) self.add_call_to_graph(self.current_block.nid, ret_statement['name']) else: self.current_block.add(Return(ret_statement)) # self.current_block.add(ret_statement) self.functions[self.scope_stack[-1]]['blocks'][ self.current_block.nid] = self.current_block self.functions[name]['graph'] = self.graph self.scope_stack.pop() return None
def visitFunctionDeclaration(self, ctx: BSParser.FunctionDeclarationContext): name = ctx.IDENTIFIER().__str__() func = self.symbol_table.functions[name] smt = "" self.scope_stack.append(name) for statement in ctx.statements(): smt += self.visitStatements(statement) self.scope_stack.pop() return smt
def visitFunctionDeclaration(self, ctx: BSParser.FunctionDeclarationContext): """ This attempts to finish building the method signature. Including typing information. It does visit statements. It cannot handle the case of method chaining. :return: nothing """ name = ctx.IDENTIFIER().__str__() self.symbol_table.current_scope = self.symbol_table.scope_map[name] self.scope_stack.append(name) function = self.symbol_table.functions[name] # You must visit the statements first. Otherwise, # the return statement won't understand what to do. for statement in ctx.statements(): self.visitStatements(statement) function.types.update(self.visitReturnStatement(ctx.returnStatement())) self.symbol_table.functions[name] = function self.scope_stack.pop()