Пример #1
0
    def visit_AnyComp(self, node, comp_type, *path):
        node.elt = self.visit(node.elt)
        name = "{0}_comprehension{1}".format(comp_type, self.count)
        self.count += 1
        args = self.passmanager.gather(ImportedIds, node, self.ctx)
        self.count_iter = 0

        starget = "__target"
        body = reduce(
            self.nest_reducer, reversed(node.generators),
            ast.Expr(
                ast.Call(
                    reduce(lambda x, y: ast.Attribute(x, y, ast.Load()),
                           path[1:], ast.Name(path[0], ast.Load())),
                    [ast.Name(starget, ast.Load()), node.elt], [], None,
                    None)))
        # add extra metadata to this node
        metadata.add(body, metadata.Comprehension(starget))
        init = ast.Assign([ast.Name(starget, ast.Store())],
                          ast.Call(
                              ast.Attribute(
                                  ast.Name('__builtin__', ast.Load()),
                                  comp_type, ast.Load()), [], [], None, None))
        result = ast.Return(ast.Name(starget, ast.Load()))
        sargs = sorted(ast.Name(arg, ast.Param()) for arg in args)
        fd = ast.FunctionDef(name, ast.arguments(sargs, None, None, []),
                             [init, body, result], [])
        self.ctx.module.body.append(fd)
        return ast.Call(ast.Name(name, ast.Load()),
                        [ast.Name(arg.id, ast.Load()) for arg in sargs], [],
                        None, None)  # no sharing !
Пример #2
0
    def attach_data(self, node):
        '''Generic method called for visit_XXXX() with XXXX in
        GatherOMPData.statements list

        '''
        if self.current:
            for curr in self.current:
                md = OMPDirective(curr)
                metadata.add(node, md)
            self.current = list()
        # add a Pass to hold some directives
        for field_name, field in ast.iter_fields(node):
            if field_name in GatherOMPData.statement_lists:
                if(field and
                   isinstance(field[-1], ast.Expr) and
                   self.isompdirective(field[-1].value)):
                    field.append(ast.Pass())
        self.generic_visit(node)

        # add an If to hold scoping OpenMP directives
        directives = metadata.get(node, OMPDirective)
        field_names = {n for n, _ in ast.iter_fields(node)}
        has_no_scope = field_names.isdisjoint(GatherOMPData.statement_lists)
        if directives and has_no_scope:
            # some directives create a scope, but the holding stmt may not
            # artificially create one here if needed
            sdirective = ''.join(d.s for d in directives)
            scoping = ('parallel', 'task', 'section')
            if any(s in sdirective for s in scoping):
                node = ast.If(ast.Num(1), [node], [])
        return node
Пример #3
0
    def visit_Module(self, node):
        """Turn globals assignement to functionDef and visit function defs. """
        module_body = list()
        # Gather top level assigned variables.
        for stmt in node.body:
            if not isinstance(stmt, ast.Assign):
                continue
            for target in stmt.targets:
                assert isinstance(target, ast.Name)
                if target.id in self.to_expand:
                    raise PythranSyntaxError(
                        "Multiple top-level definition of %s." % target.id,
                        target)
                self.to_expand.add(target.id)

        for stmt in node.body:
            if isinstance(stmt, ast.Assign):
                self.local_decl = set()
                cst_value = self.visit(stmt.value)
                for target in stmt.targets:
                    assert isinstance(target, ast.Name)
                    module_body.append(
                        ast.FunctionDef(target.id,
                                        ast.arguments([], None, None, []),
                                        [ast.Return(value=cst_value)], []))
                    metadata.add(module_body[-1].body[0],
                                 metadata.StaticReturn())
            else:
                self.local_decl = self.passmanager.gather(
                    LocalNameDeclarations, stmt, self.ctx)
                module_body.append(self.visit(stmt))

        node.body = module_body
        return node
Пример #4
0
    def attach_data(self, node):
        '''Generic method called for visit_XXXX() with XXXX in
        GatherOMPData.statements list

        '''
        if self.current:
            for curr in self.current:
                md = OMPDirective(curr)
                metadata.add(node, md)
            self.current = list()
        # add a Pass to hold some directives
        for field_name, field in ast.iter_fields(node):
            if field_name in GatherOMPData.statement_lists:
                if(field and
                   isinstance(field[-1], ast.Expr) and
                   self.isompdirective(field[-1].value)):
                    field.append(ast.Pass())
        self.generic_visit(node)

        # add an If to hold scoping OpenMP directives
        directives = metadata.get(node, OMPDirective)
        field_names = {n for n, _ in ast.iter_fields(node)}
        has_no_scope = field_names.isdisjoint(GatherOMPData.statement_lists)
        if directives and has_no_scope:
            # some directives create a scope, but the holding stmt may not
            # artificially create one here if needed
            sdirective = ''.join(d.s for d in directives)
            scoping = ('parallel', 'task', 'section')
            if any(s in sdirective for s in scoping):
                metadata.clear(node, OMPDirective)
                node = ast.If(ast.Num(1), [node], [])
                for directive in directives:
                    metadata.add(node, directive)

        return node
Пример #5
0
    def visit_FunctionDef(self, node):
        self.update = True
        if MODULES['functools'] not in self.global_declarations.values():
            import_ = ast.Import([ast.alias('functools', mangle('functools'))])
            self.ctx.module.body.insert(0, import_)
            functools_module = MODULES['functools']
            self.global_declarations[mangle('functools')] = functools_module

        self.ctx.module.body.append(node)

        former_name = node.name
        seed = 0
        new_name = "pythran_{}{}"

        while new_name.format(former_name, seed) in self.identifiers:
            seed += 1

        new_name = new_name.format(former_name, seed)
        self.identifiers.add(new_name)

        ii = self.gather(ImportedIds, node)
        binded_args = [
            ast.Name(iin, ast.Load(), None, None) for iin in sorted(ii)
        ]
        node.args.args = (
            [ast.Name(iin, ast.Param(), None, None)
             for iin in sorted(ii)] + node.args.args)

        metadata.add(node, metadata.Local())

        class Renamer(ast.NodeTransformer):
            def visit_Call(self, node):
                self.generic_visit(node)
                if (isinstance(node.func, ast.Name)
                        and node.func.id == former_name):
                    node.func.id = new_name
                    node.args = ([
                        ast.Name(iin, ast.Load(), None, None)
                        for iin in sorted(ii)
                    ] + node.args)
                return node

        Renamer().visit(node)

        node.name = new_name
        self.global_declarations[node.name] = node
        proxy_call = ast.Name(new_name, ast.Load(), None, None)

        new_node = ast.Assign([ast.Name(former_name, ast.Store(), None, None)],
                              ast.Call(
                                  ast.Attribute(
                                      ast.Name(mangle('functools'), ast.Load(),
                                               None, None), "partial",
                                      ast.Load()),
                                  [proxy_call] + binded_args,
                                  [],
                              ))

        self.generic_visit(node)
        return new_node
Пример #6
0
    def visit_Module(self, node):
        """Turn globals assignement to functionDef and visit function defs. """
        module_body = list()
        # Gather top level assigned variables.
        for stmt in node.body:
            if not isinstance(stmt, ast.Assign):
                continue
            for target in stmt.targets:
                assert isinstance(target, ast.Name)
                if target.id in self.to_expand:
                    raise PythranSyntaxError(
                        "Multiple top-level definition of %s." % target.id,
                        target)
                self.to_expand.add(target.id)

        for stmt in node.body:
            if isinstance(stmt, ast.Assign):
                self.local_decl = set()
                cst_value = self.visit(stmt.value)
                for target in stmt.targets:
                    assert isinstance(target, ast.Name)
                    module_body.append(
                        ast.FunctionDef(target.id,
                                        ast.arguments([], None, None, []),
                                        [ast.Return(value=cst_value)], []))
                    metadata.add(module_body[-1].body[0],
                                 metadata.StaticReturn())
            else:
                self.local_decl = self.passmanager.gather(
                    LocalNameDeclarations, stmt,
                    self.ctx)
                module_body.append(self.visit(stmt))

        node.body = module_body
        return node
Пример #7
0
    def visit_Lambda(self, node):
        if MODULES['functools'] not in self.global_declarations.values():
            import_ = ast.Import([ast.alias('functools', mangle('functools'))])
            self.imports.append(import_)
            functools_module = MODULES['functools']
            self.global_declarations[mangle('functools')] = functools_module

        self.generic_visit(node)
        forged_name = "{0}_lambda{1}".format(self.prefix,
                                             len(self.lambda_functions))

        ii = self.gather(ImportedIds, node)
        ii.difference_update(self.lambda_functions)  # remove current lambdas

        binded_args = [
            ast.Name(iin, ast.Load(), None, None) for iin in sorted(ii)
        ]
        node.args.args = (
            [ast.Name(iin, ast.Param(), None, None)
             for iin in sorted(ii)] + node.args.args)
        forged_fdef = ast.FunctionDef(forged_name, copy(node.args),
                                      [ast.Return(node.body)], [], None, None)
        metadata.add(forged_fdef, metadata.Local())
        self.lambda_functions.append(forged_fdef)
        self.global_declarations[forged_name] = forged_fdef
        proxy_call = ast.Name(forged_name, ast.Load(), None, None)
        if binded_args:
            return ast.Call(
                ast.Attribute(
                    ast.Name(mangle('functools'), ast.Load(), None, None),
                    "partial", ast.Load()), [proxy_call] + binded_args, [])
        else:
            return proxy_call
Пример #8
0
    def visit_Lambda(self, node):
        op = issimpleoperator(node)
        if op is not None:
            if mangle('operator') not in self.global_declarations:
                import_ = ast.Import(
                    [ast.alias('operator', mangle('operator'))])
                self.imports.append(import_)
                operator_module = MODULES['operator']
                self.global_declarations[mangle('operator')] = operator_module
            return ast.Attribute(
                ast.Name(mangle('operator'), ast.Load(), None, None), op,
                ast.Load())

        self.generic_visit(node)
        forged_name = "{0}_lambda{1}".format(self.prefix,
                                             len(self.lambda_functions))

        ii = self.gather(ImportedIds, node)
        ii.difference_update(self.lambda_functions)  # remove current lambdas

        binded_args = [
            ast.Name(iin, ast.Load(), None, None) for iin in sorted(ii)
        ]
        node.args.args = (
            [ast.Name(iin, ast.Param(), None, None)
             for iin in sorted(ii)] + node.args.args)
        for patternname, pattern in self.patterns.items():
            if issamelambda(pattern, node):
                proxy_call = ast.Name(patternname, ast.Load(), None, None)
                break
        else:
            duc = ExtendedDefUseChains()
            nodepattern = deepcopy(node)
            duc.visit(ast.Module([ast.Expr(nodepattern)], []))
            self.patterns[forged_name] = nodepattern, duc

            forged_fdef = ast.FunctionDef(forged_name, copy(node.args),
                                          [ast.Return(node.body)], [], None,
                                          None)
            metadata.add(forged_fdef, metadata.Local())
            self.lambda_functions.append(forged_fdef)
            self.global_declarations[forged_name] = forged_fdef
            proxy_call = ast.Name(forged_name, ast.Load(), None, None)

        if binded_args:
            if MODULES['functools'] not in self.global_declarations.values():
                import_ = ast.Import(
                    [ast.alias('functools', mangle('functools'))])
                self.imports.append(import_)
                functools_module = MODULES['functools']
                self.global_declarations[mangle(
                    'functools')] = functools_module

            return ast.Call(
                ast.Attribute(
                    ast.Name(mangle('functools'), ast.Load(), None, None),
                    "partial", ast.Load()), [proxy_call] + binded_args, [])
        else:
            return proxy_call
Пример #9
0
 def visit(self, node):
     """ Add OMPDirective from the old node to the new one. """
     old_omp = metadata.get(node, OMPDirective)
     node = super(DeadCodeElimination, self).visit(node)
     if not metadata.get(node, OMPDirective):
         for omp_directive in old_omp:
             metadata.add(node, omp_directive)
     return node
Пример #10
0
 def visit(self, node):
     """ Add OMPDirective from the old node to the new one. """
     old_omp = metadata.get(node, OMPDirective)
     node = super(DeadCodeElimination, self).visit(node)
     if not metadata.get(node, OMPDirective):
         for omp_directive in old_omp:
             metadata.add(node, omp_directive)
     return node
Пример #11
0
    def visit_AnyComp(self, node, comp_type, *path):
        self.update = True
        node.elt = self.visit(node.elt)
        name = "{0}_comprehension{1}".format(comp_type, self.count)
        self.count += 1
        args = self.passmanager.gather(ImportedIds, node, self.ctx)
        self.count_iter = 0

        starget = "__target"
        body = reduce(self.nest_reducer,
                      reversed(node.generators),
                      ast.Expr(
                          ast.Call(
                              reduce(lambda x, y: ast.Attribute(x, y,
                                                                ast.Load()),
                                     path[1:],
                                     ast.Name(path[0], ast.Load())),
                              [ast.Name(starget, ast.Load()), node.elt],
                              [],
                              None,
                              None
                              )
                          )
                      )
        # add extra metadata to this node
        metadata.add(body, metadata.Comprehension(starget))
        init = ast.Assign(
            [ast.Name(starget, ast.Store())],
            ast.Call(
                ast.Attribute(
                    ast.Name('__builtin__', ast.Load()),
                    comp_type,
                    ast.Load()
                    ),
                [], [], None, None)
            )
        result = ast.Return(ast.Name(starget, ast.Load()))
        sargs = sorted(ast.Name(arg, ast.Param()) for arg in args)
        fd = ast.FunctionDef(name,
                             ast.arguments(sargs, None, None, []),
                             [init, body, result],
                             [])
        self.ctx.module.body.append(fd)
        return ast.Call(
            ast.Name(name, ast.Load()),
            [ast.Name(arg.id, ast.Load()) for arg in sargs],
            [],
            None,
            None
            )  # no sharing !
Пример #12
0
    def visit_GeneratorExp(self, node):
        self.update = True
        node.elt = self.visit(node.elt)
        name = "generator_expression{0}".format(self.count)
        self.count += 1
        args = self.gather(ImportedIds, node)
        self.count_iter = 0

        body = reduce(self.nest_reducer, reversed(node.generators),
                      ast.Expr(ast.Yield(node.elt)))

        sargs = [ast.Name(arg, ast.Param(), None, None) for arg in args]
        fd = ast.FunctionDef(name,
                             ast.arguments(sargs, [], None, [], [], None, []),
                             [body], [], None, None)
        metadata.add(fd, metadata.Local())
        self.ctx.module.body.append(fd)
        return ast.Call(
            ast.Name(name, ast.Load(), None, None),
            [ast.Name(arg.id, ast.Load(), None, None) for arg in sargs],
            [],
        )  # no sharing !
Пример #13
0
    def visit_Module(self, node):
        """Turn globals assignment to functionDef and visit function defs. """
        module_body = list()
        symbols = set()
        # Gather top level assigned variables.
        for stmt in node.body:
            if isinstance(stmt, (ast.Import, ast.ImportFrom)):
                for alias in stmt.names:
                    name = alias.asname or alias.name
                    symbols.add(name)  # no warning here
            elif isinstance(stmt, ast.FunctionDef):
                if stmt.name in symbols:
                    raise PythranSyntaxError(
                        "Multiple top-level definition of %s." % stmt.name,
                        stmt)
                else:
                    symbols.add(stmt.name)

            if not isinstance(stmt, ast.Assign):
                continue

            for target in stmt.targets:
                if not isinstance(target, ast.Name):
                    raise PythranSyntaxError(
                        "Top-level assignment to an expression.",
                        target)
                if target.id in self.to_expand:
                    raise PythranSyntaxError(
                        "Multiple top-level definition of %s." % target.id,
                        target)
                if isinstance(stmt.value, ast.Name):
                    if stmt.value.id in symbols:
                        continue  # create aliasing between top level symbols
                self.to_expand.add(target.id)

        for stmt in node.body:
            if isinstance(stmt, ast.Assign):
                # that's not a global var, but a module/function aliasing
                if all(isinstance(t, ast.Name) and t.id not in self.to_expand
                       for t in stmt.targets):
                    module_body.append(stmt)
                    continue

                self.local_decl = set()
                cst_value = self.visit(stmt.value)
                for target in stmt.targets:
                    assert isinstance(target, ast.Name)
                    module_body.append(
                        ast.FunctionDef(target.id,
                                        ast.arguments([], None,
                                                      [], [], None, []),
                                        [ast.Return(value=cst_value)],
                                        [], None))
                    metadata.add(module_body[-1].body[0],
                                 metadata.StaticReturn())
            else:
                self.local_decl = self.passmanager.gather(
                    LocalNameDeclarations, stmt,
                    self.ctx)
                module_body.append(self.visit(stmt))

        node.body = module_body
        return node
Пример #14
0
    def visit_Compare(self, node):
        node = self.generic_visit(node)
        if len(node.ops) > 1:
            # in case we have more than one compare operator
            # we generate an auxiliary function
            # that lazily evaluates the needed parameters
            imported_ids = self.gather(ImportedIds, node)
            imported_ids = sorted(imported_ids)
            binded_args = [ast.Name(i, ast.Load(), None, None)
                           for i in imported_ids]

            # name of the new function
            forged_name = "{0}_compare{1}".format(self.prefix,
                                                  len(self.compare_functions))

            # call site
            call = ast.Call(
                ast.Name(forged_name, ast.Load(), None, None),
                binded_args,
                [])

            # new function
            arg_names = [ast.Name(i, ast.Param(), None, None)
                         for i in imported_ids]
            args = ast.arguments(arg_names, [], None, [], [], None, [])

            body = []  # iteratively fill the body (yeah, feel your body!)

            if is_trivially_copied(node.left):
                prev_holder = node.left
            else:
                body.append(
                    ast.Assign(
                        [ast.Name('$0', ast.Store(), None, None)],
                        node.left, None))
                prev_holder = ast.Name('$0', ast.Load(), None, None)

            for i, exp in enumerate(node.comparators):
                if is_trivially_copied(exp):
                    holder = exp
                else:
                    body.append(ast.Assign([ast.Name('${}'.format(i+1),
                                                     ast.Store(), None, None)],
                                           exp, None))
                    holder = ast.Name('${}'.format(i+1), ast.Load(),
                                      None, None)
                cond = ast.Compare(prev_holder,
                                   [node.ops[i]],
                                   [holder])
                body.append(
                    ast.If(cond,
                           [ast.Pass()],
                           [ast.Return(path_to_attr(('builtins', 'False')))]))
                prev_holder = holder

            body.append(ast.Return(path_to_attr(('builtins', 'True'))))

            forged_fdef = ast.FunctionDef(forged_name, args, body, [], None,
                                          None)
            metadata.add(forged_fdef, metadata.Local())
            self.compare_functions.append(forged_fdef)

            return call
        else:
            return node
Пример #15
0
    def visit_Module(self, node):
        """Turn globals assignment to functionDef and visit function defs. """
        module_body = list()
        symbols = set()
        # Gather top level assigned variables.
        for stmt in node.body:
            if isinstance(stmt, (ast.Import, ast.ImportFrom)):
                for alias in stmt.names:
                    name = alias.asname or alias.name
                    symbols.add(name)  # no warning here
            elif isinstance(stmt, ast.FunctionDef):
                if stmt.name in symbols:
                    raise PythranSyntaxError(
                        "Multiple top-level definition of %s." % stmt.name,
                        stmt)
                else:
                    symbols.add(stmt.name)

            if not isinstance(stmt, ast.Assign):
                continue

            for target in stmt.targets:
                if not isinstance(target, ast.Name):
                    raise PythranSyntaxError(
                        "Top-level assignment to an expression.", target)
                if target.id in self.to_expand:
                    raise PythranSyntaxError(
                        "Multiple top-level definition of %s." % target.id,
                        target)
                if isinstance(stmt.value, ast.Name):
                    if stmt.value.id in symbols:
                        continue  # create aliasing between top level symbols
                self.to_expand.add(target.id)

        for stmt in node.body:
            if isinstance(stmt, ast.Assign):
                # that's not a global var, but a module/function aliasing
                if all(
                        isinstance(t, ast.Name) and t.id not in self.to_expand
                        for t in stmt.targets):
                    module_body.append(stmt)
                    continue

                self.local_decl = set()
                cst_value = GlobalTransformer().visit(self.visit(stmt.value))
                for target in stmt.targets:
                    assert isinstance(target, ast.Name)
                    module_body.append(
                        ast.FunctionDef(
                            target.id,
                            ast.arguments([], [], None, [], [], None, []),
                            [ast.Return(value=cst_value)], [], None, None))
                    metadata.add(module_body[-1].body[0],
                                 metadata.StaticReturn())
            else:
                self.local_decl = self.gather(LocalNameDeclarations, stmt)
                module_body.append(self.visit(stmt))

        self.update |= bool(self.to_expand)

        node.body = module_body
        return node
Пример #16
0
 def nest_reducer(self, x, g):
     def wrap_in_ifs(node, ifs):
         return reduce(lambda n, if_: ast.If(if_, [n], []), ifs, node)
     metadata.add(g.target, metadata.LocalVariable())
     return ast.For(g.target, g.iter, [wrap_in_ifs(x, g.ifs)], [])