예제 #1
0
파일: backend.py 프로젝트: hmaarrfk/pythran
    def visit_FunctionDef(self, node):

        self.fname = node.name
        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 function has a call operator to be called
        # and a default constructor to create instances
        fscope = "type{0}::".format(
            "<{0}>".format(", ".join(formal_types)) if formal_types else "")
        ffscope = "{0}::{1}".format(node.name, fscope)

        operator_declaration = [
            templatize(
                make_const_function_declaration(
                    self, node, "typename {0}result_type".format(fscope),
                    "operator()", formal_types, formal_args, dflt_argv),
                formal_types, dflt_argt),
            EmptyStatement()
        ]
        operator_signature = make_const_function_declaration(
            self, node, "typename {0}result_type".format(ffscope),
            "{0}::operator()".format(node.name), formal_types, formal_args)
        ctx = CachedTypeVisitor(self.lctx)
        operator_local_declarations = ([
            Statement("{0} {1}".format(
                self.types[self.local_names[k]].generate(ctx), k))
            for k in self.ldecls
        ])
        dependent_typedefs = ctx.typedefs()
        operator_definition = FunctionBody(
            templatize(operator_signature, formal_types),
            Block(dependent_typedefs + operator_local_declarations +
                  operator_body))

        ctx = CachedTypeVisitor()
        extra_typedefs = ([
            Typedef(Value(t.generate(ctx), t.name))
            for t in self.types[node][1]
        ] + [Typedef(Value(result_type.generate(ctx), "result_type"))])
        extra_typedefs = ctx.typedefs() + extra_typedefs
        return_declaration = [
            templatize(Struct("type", extra_typedefs), formal_types, dflt_argt)
        ]
        topstruct = Struct(node.name, [callable_type, pure_type] +
                           return_declaration + operator_declaration)

        return [topstruct], [operator_definition]
예제 #2
0
파일: backend.py 프로젝트: hmaarrfk/pythran
    def visit_FunctionDef(self, node):
        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(node.name)
        instanciated_next_name = "{0}{1}".format(
            next_name,
            "<{0}>".format(", ".join(formal_types)) if formal_types else "")

        operator_body.append(
            Statement("{}: return result_type()".format(
                CxxGenerator.FinalStatement)))

        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(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(node.name,
                           [topstruct_type, callable_type, pure_type] +
                           operator_declaration)

        return [next_struct, topstruct], [next_definition, operator_definition]
예제 #3
0
파일: backend.py 프로젝트: Flajt/pythran
    def visit_FunctionDef(self, node):
        class CachedTypeVisitor:
            class CachedType:
                def __init__(self, s):
                    self.s = s

                def generate(self, _):
                    return self.s

            def __init__(self, other=None):
                if other:
                    self.cache = other.cache.copy()
                    self.rcache = other.rcache.copy()
                    self.mapping = other.mapping.copy()
                else:
                    self.cache = dict()
                    self.rcache = dict()
                    self.mapping = dict()

            def __call__(self, node):
                if node not in self.mapping:
                    t = node.generate(self)
                    if t in self.rcache:
                        self.mapping[node] = self.mapping[self.rcache[t]]
                        self.cache[node] = self.cache[self.rcache[t]]
                    else:
                        self.rcache[t] = node
                        self.mapping[node] = len(self.mapping)
                        self.cache[node] = t
                return CachedTypeVisitor.CachedType("__type{0}".format(
                    self.mapping[node]))

            def typedefs(self):
                l = sorted(self.mapping.items(), key=lambda x: x[1])
                L = list()
                visited = set()  # the same value must not be typedefed twice
                for k, v in l:
                    if v not in visited:
                        typename = "__type" + str(v)
                        L.append(Typedef(Value(self.cache[k], typename)))
                        visited.add(v)
                return L

        self.fname = node.name

        # prepare context and visit function body
        fargs = node.args.args

        formal_args = [arg.id for arg in fargs]
        formal_types = ["argument_type" + str(i) for i in range(len(fargs))]

        self.ldecls = set(self.passmanager.gather(LocalNodeDeclarations, node))

        self.local_names = {sym.id: sym for sym in self.ldecls}
        self.local_names.update({arg.id: arg for arg in fargs})
        self.extra_declarations = []

        self.lctx = CachedTypeVisitor()

        # choose one node among all the ones with the same name for each name
        self.ldecls = set({n.id: n for n in self.ldecls}.values())

        # 0 is used as initial_state, thus the +1
        self.yields = {
            k: (1 + v, "yield_point{0}".format(1 + v))
            for (v, k) in enumerate(self.passmanager.gather(YieldPoints, node))
        }

        # gather body dump
        operator_body = [self.visit(stmt) for stmt in node.body]

        # compute arg dump
        default_arg_values = ([None] *
                              (len(node.args.args) - len(node.args.defaults)) +
                              [self.visit(n) for n in node.args.defaults])
        default_arg_types = ([None] *
                             (len(node.args.args) - len(node.args.defaults)) +
                             [self.types[n] for n in node.args.defaults])

        # compute type dump
        result_type = self.types[node][0]

        callable_type = Typedef(Value("void", "callable"))
        pure_type = (Typedef(Value("void", "pure"))
                     if node in self.pure_expressions else EmptyStatement())

        def make_function_declaration(rtype,
                                      name,
                                      ftypes,
                                      fargs,
                                      defaults=None,
                                      attributes=None):
            if defaults is None:
                defaults = [None] * len(ftypes)
            if attributes is None:
                attributes = []
            arguments = list()
            for i, (t, a, d) in enumerate(zip(ftypes, fargs, defaults)):
                if self.yields:
                    rvalue_ref = ""
                elif self.argument_effects[node][i]:
                    rvalue_ref = "&&"
                else:
                    rvalue_ref = " const &"
                argument = Value(
                    t + rvalue_ref,
                    "{0}{1}".format(a, "= {0}".format(d) if d else ""))
                arguments.append(argument)
            return FunctionDeclaration(Value(rtype, name), arguments,
                                       *attributes)

        def make_const_function_declaration(rtype,
                                            name,
                                            ftypes,
                                            fargs,
                                            defaults=None):
            return make_function_declaration(rtype, name, ftypes, fargs,
                                             defaults, ["const"])

        if self.yields:  # generator case
            # a generator has a call operator that returns the iterator

            next_name = "__generator__{0}".format(node.name)
            instanciated_next_name = "{0}{1}".format(
                next_name, "<{0}>".format(", ".join(formal_types))
                if formal_types else "")

            operator_body.append(
                Statement("{0}: return result_type();".format(
                    Cxx.final_statement)))

            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 default_arg_values and all(default_arg_values):
                    next_constructors = list()
                next_constructors.append(
                    FunctionBody(
                        make_function_declaration("", next_name, formal_types,
                                                  formal_args,
                                                  default_arg_values),
                        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(Cxx.generator_state_value)])),
                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(
                    Cxx.generator_state_holder,
                    " ".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[k].generate(ctx), k.id))
                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, Cxx.generator_state_value))
            ])

            extern_typedefs = [
                Typedef(Value(t.generate(ctx), t.name))
                for t in self.types[node][1] if not t.isweak()
            ]
            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(instanciated_next_name,
                                                    "operator()", formal_types,
                                                    formal_args,
                                                    default_arg_values),
                    formal_types, default_arg_types),
                EmptyStatement()
            ]
            operator_signature = make_const_function_declaration(
                instanciated_next_name, "{0}::operator()".format(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(node.name,
                               [topstruct_type, callable_type, pure_type] +
                               operator_declaration)

            self.declarations.append(next_struct)
            self.definitions.append(next_definition)

        else:  # regular function case
            # a function has a call operator to be called
            # and a default constructor to create instances
            fscope = "type{0}::".format("<{0}>".format(", ".join(formal_types))
                                        if formal_types else "")
            ffscope = "{0}::{1}".format(node.name, fscope)

            operator_declaration = [
                templatize(
                    make_const_function_declaration(
                        "typename {0}result_type".format(fscope), "operator()",
                        formal_types, formal_args, default_arg_values),
                    formal_types, default_arg_types),
                EmptyStatement()
            ]
            operator_signature = make_const_function_declaration(
                "typename {0}result_type".format(ffscope),
                "{0}::operator()".format(node.name), formal_types, formal_args)
            ctx = CachedTypeVisitor(self.lctx)
            operator_local_declarations = ([
                Statement("{0} {1}".format(self.types[k].generate(ctx), k.id))
                for k in self.ldecls
            ] + [
                Statement("{0} {1}".format(v, k))
                for k, v in self.extra_declarations
            ])
            dependent_typedefs = ctx.typedefs()
            operator_definition = FunctionBody(
                templatize(operator_signature, formal_types),
                Block(dependent_typedefs + operator_local_declarations +
                      operator_body))

            ctx = CachedTypeVisitor()
            extra_typedefs = ([
                Typedef(Value(t.generate(ctx), t.name))
                for t in self.types[node][1] if not t.isweak()
            ] + [Typedef(Value(result_type.generate(ctx), "result_type"))])
            extra_typedefs = ctx.typedefs() + extra_typedefs
            return_declaration = [
                templatize(Struct("type", extra_typedefs), formal_types,
                           default_arg_types)
            ]
            topstruct = Struct(node.name, [callable_type, pure_type] +
                               return_declaration + operator_declaration)

        self.declarations.append(topstruct)
        self.definitions.append(operator_definition)

        return EmptyStatement()