示例#1
0
    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()
示例#2
0
    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()
示例#3
0
    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
示例#4
0
    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
示例#5
0
    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()