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])
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]