Exemplo n.º 1
0
    def loop_visitor(self, node):
        """
        New decorate function.

        It push the breaking flag, run the visitor and add "else" statements.
        """
        if not node.orelse:
            with pushpop(self.break_handlers, None):
                res = visit(self, node)
            return res

        break_handler = "__no_breaking{0}".format(id(node))
        with pushpop(self.break_handlers, break_handler):
            res = visit(self, node)

        # handle the body of the for loop
        orelse = [self.visit(stmt) for stmt in node.orelse]
        orelse_label = Label(break_handler)
        return Block([res] + orelse + [orelse_label])
Exemplo n.º 2
0
    def visit_FunctionDef(self, node):
        self.returns = False
        tmp = self.prepare_functiondef_context(node)
        operator_body, formal_types, formal_args = tmp

        tmp = self.prepare_types(node)
        dflt_argv, dflt_argt, result_type, callable_type, pure_type = tmp

        # a generator has a call operator that returns the iterator
        next_name = "__generator__{0}".format(cxxid(node.name))
        instanciated_next_name = "{0}{1}".format(
            next_name,
            "<{0}>".format(", ".join(formal_types)) if formal_types else "")

        if self.returns:
            operator_body.append(Label(CxxGenerator.FinalStatement))
        operator_body.append(Statement("return result_type()"))

        next_declaration = [
            FunctionDeclaration(Value("result_type", "next"), []),
            EmptyStatement()]  # empty statement to force a comma ...

        # the constructors
        next_constructors = [
            FunctionBody(
                FunctionDeclaration(Value("", next_name), []),
                Line(': pythonic::yielder() {}')
                )]
        if formal_types:
            # If all parameters have a default value, we don't need default
            # constructor
            if dflt_argv and all(dflt_argv):
                next_constructors = list()
            next_constructors.append(FunctionBody(
                make_function_declaration(self, node, "", next_name,
                                          formal_types, formal_args,
                                          dflt_argv),
                Line(": {0} {{ }}".format(
                    ", ".join(["pythonic::yielder()"] +
                              ["{0}({0})".format(arg)
                               for arg in formal_args])))
                ))

        next_iterator = [
            FunctionBody(
                FunctionDeclaration(Value("void", "operator++"), []),
                Block([Statement("next()")])),
            FunctionBody(
                FunctionDeclaration(
                    Value("typename {0}::result_type".format(
                        instanciated_next_name),
                        "operator*"),
                    [], "const"),
                Block([
                    ReturnStatement(
                        CxxGenerator.StateValue)])),
            FunctionBody(
                FunctionDeclaration(
                    Value("pythonic::types::generator_iterator<{0}>"
                          .format(next_name),
                          "begin"),
                    []),
                Block([Statement("next()"),
                       ReturnStatement(
                           "pythonic::types::generator_iterator<{0}>"
                           "(*this)".format(next_name))])),
            FunctionBody(
                FunctionDeclaration(
                    Value("pythonic::types::generator_iterator<{0}>"
                          .format(next_name),
                          "end"),
                    []),
                Block([ReturnStatement(
                    "pythonic::types::generator_iterator<{0}>()"
                    .format(next_name))]))
            ]
        next_signature = templatize(
            FunctionDeclaration(
                Value(
                    "typename {0}::result_type".format(
                        instanciated_next_name),
                    "{0}::next".format(instanciated_next_name)),
                []),
            formal_types)

        next_body = operator_body
        # the dispatch table at the entry point
        next_body.insert(0, Statement("switch({0}) {{ {1} }}".format(
            CxxGenerator.StateHolder,
            " ".join("case {0}: goto {1};".format(num, where)
                     for (num, where) in sorted(
                         self.yields.values(),
                         key=lambda x: x[0])))))

        ctx = CachedTypeVisitor(self.lctx)
        next_members = ([Statement("{0} {1}".format(ft, fa))
                         for (ft, fa) in zip(formal_types, formal_args)] +
                        [Statement("{0} {1}".format(
                            self.types[self.local_names[k]].generate(ctx),
                            k))
                         for k in self.ldecls] +
                        [Statement("{0} {1}".format(v, k))
                         for k, v in self.extra_declarations] +
                        [Statement(
                            "typename {0}::result_type {1}".format(
                                instanciated_next_name,
                                CxxGenerator.StateValue))])

        extern_typedefs = [Typedef(Value(t.generate(ctx), t.name))
                           for t in self.types[node][1]]
        iterator_typedef = [
            Typedef(
                Value("pythonic::types::generator_iterator<{0}>".format(
                    "{0}<{1}>".format(next_name, ", ".join(formal_types))
                    if formal_types else next_name),
                    "iterator")),
            Typedef(Value(result_type.generate(ctx),
                          "value_type"))]
        result_typedef = [
            Typedef(Value(result_type.generate(ctx), "result_type"))]
        extra_typedefs = (ctx.typedefs() +
                          extern_typedefs +
                          iterator_typedef +
                          result_typedef)

        next_struct = templatize(
            Struct(next_name,
                   extra_typedefs +
                   next_members +
                   next_constructors +
                   next_iterator +
                   next_declaration, "pythonic::yielder"),
            formal_types)
        next_definition = FunctionBody(next_signature, Block(next_body))

        operator_declaration = [
            templatize(
                make_const_function_declaration(
                    self, node, instanciated_next_name,
                    "operator()",
                    formal_types, formal_args, dflt_argv),
                formal_types,
                dflt_argt),
            EmptyStatement()]
        operator_signature = make_const_function_declaration(
            self, node, instanciated_next_name,
            "{0}::operator()".format(cxxid(node.name)),
            formal_types, formal_args)
        operator_definition = FunctionBody(
            templatize(operator_signature, formal_types),
            Block([ReturnStatement("{0}({1})".format(
                instanciated_next_name,
                ", ".join(formal_args)))])
            )

        topstruct_type = templatize(
            Struct("type", extra_typedefs),
            formal_types)
        topstruct = Struct(
            cxxid(node.name),
            [topstruct_type, callable_type, pure_type] +
            operator_declaration)

        return [next_struct, topstruct], [next_definition, operator_definition]