Ejemplo n.º 1
0
 def visit_List(self, node):
     if not node.elts:  # empty list
         return "pythonic::__builtin__::proxy::list{}()"
     else:
         elts = [self.visit(n) for n in node.elts]
         # constructor disambiguation, clang++ workaround
         if len(elts) == 1:
             elts.append('pythonic::types::single_value()')
             return "{0}({{ {1} }})".format(Assignable(self.types[node]),
                                            ", ".join(elts))
         else:
             return "{0}({{ {1} }})".format(Assignable(self.types[node]),
                                            ", ".join(elts))
Ejemplo n.º 2
0
 def visit_Set(self, node):
     if not node.elts:  # empty set
         return "pythonic::__builtin__::functor::set{}()"
     else:
         elts = [self.visit(n) for n in node.elts]
         return "{0}{{{{{1}}}}}".format(Assignable(self.types[node]),
                                        ", ".join(elts))
Ejemplo n.º 3
0
 def visit_Dict(self, node):
     if not node.keys:  # empty dict
         return "pythonic::__builtin__::functor::dict{}()"
     else:
         keys = [self.visit(n) for n in node.keys]
         values = [self.visit(n) for n in node.values]
         return "{0}{{{{{1}}}}}".format(
             Assignable(self.types[node]),
             ", ".join("{{ {0}, {1} }}".format(k, v)
                       for k, v in zip(keys, values)))
Ejemplo n.º 4
0
    def visit_List(self, node):
        if not node.elts:  # empty list
            return "pythonic::__builtin__::functor::list{}()"
        else:
            elts = [self.visit(n) for n in node.elts]
            elts_type = [DeclType(elt) for elt in elts]
            elts_type = CombinedTypes(*elts_type)

            # constructor disambiguation, clang++ workaround
            if len(elts) == 1:
                elts.append('pythonic::types::single_value()')

            node_type = ListType(elts_type)
            return "{0}({{{1}}})".format(Assignable(node_type),
                                         ", ".join(elts))
Ejemplo n.º 5
0
    def visit_Assign(self, node):
        """
        Create Assign node for final Cxx representation.

        It tries to handle multi assignment like:

        >> a = b = c = 2

        If only one local variable is assigned, typing is added:

        >> int a = 2;

        TODO: Handle case of multi-assignement for some local variables.

        Finally, process OpenMP clause like #pragma omp atomic
        """
        if not all(isinstance(n, (ast.Name, ast.Subscript))
                   for n in node.targets):
            raise PythranSyntaxError(
                "Must assign to an identifier or a subscript",
                node)
        value = self.visit(node.value)
        targets = [self.visit(t) for t in node.targets]
        alltargets = "= ".join(targets)
        islocal = (len(targets) == 1 and
                   isinstance(node.targets[0], ast.Name) and
                   node.targets[0].id in self.scope[node])
        if islocal and not self.yields:
            # remove this decl from local decls
            tdecls = {t.id for t in node.targets}
            self.ldecls = {d for d in self.ldecls if d.id not in tdecls}
            # add a local declaration
            if self.types[node.targets[0]].iscombined():
                alltargets = '{} {}'.format(self.typeof(node.targets[0]),
                                            alltargets)
            elif isinstance(self.types[node.targets[0]], Assignable):
                alltargets = '{} {}'.format(
                    Assignable(NamedType('decltype({})'.format(value))),
                    alltargets)
            else:
                assert isinstance(self.types[node.targets[0]], Lazy)
                alltargets = '{} {}'.format(
                    Lazy(NamedType('decltype({})'.format(value))),
                    alltargets)
        stmt = Assign(alltargets, value)
        return self.process_omp_attachements(node, stmt)
Ejemplo n.º 6
0
    def visit_For(self, node):
        """
        Create For representation for Cxx generation.

        Examples
        --------
        >> for i in xrange(10):
        >>     ... work ...

        Becomes

        >> typename returnable<decltype(__builtin__.xrange(10))>::type __iterX
           = __builtin__.xrange(10);
        >> ... possible container size reservation ...
        >> for (auto&& i: __iterX)
        >>     ... the work ...

        This function also handle assignment for local variables.

        We can notice that three kind of loop are possible:
        - Normal for loop on iterator
        - Autofor loop.
        - Normal for loop using integer variable iteration
        Kind of loop used depend on OpenMP, yield use and variable scope.
        """
        if not isinstance(node.target, ast.Name):
            raise PythranSyntaxError(
                "Using something other than an identifier as loop target",
                node.target)
        target = self.visit(node.target)

        # Handle the body of the for loop
        loop_body = Block([self.visit(stmt) for stmt in node.body])

        # Declare local variables at the top of the loop body
        loop_body = self.process_locals(node, loop_body, node.target.id)
        iterable = self.visit(node.iter)

        if self.can_use_c_for(node):
            header, loop = self.gen_c_for(node, target, loop_body)
        else:

            if self.can_use_autofor(node):
                header = []
                self.ldecls = {
                    d
                    for d in self.ldecls if d.id != node.target.id
                }
                autofor = AutoFor(target, iterable, loop_body)
                loop = [self.process_omp_attachements(node, autofor)]
            else:
                # Iterator declaration
                local_iter = "__iter{0}".format(len(self.break_handlers))
                local_iter_decl = Assignable(DeclType(iterable))

                self.handle_omp_for(node, local_iter)

                # For yield function, iterable is globals.
                if self.yields:
                    self.extra_declarations.append((
                        local_iter,
                        local_iter_decl,
                    ))
                    local_iter_decl = ""

                # Assign iterable
                # For C loop, it avoids issues
                # if the upper bound is assigned in the loop
                header = [
                    Statement("{0} {1} = {2}".format(local_iter_decl,
                                                     local_iter, iterable))
                ]
                loop = self.gen_for(node, target, local_iter, loop_body)

        # For xxxComprehension, it is replaced by a for loop. In this case,
        # pre-allocate size of container.
        for comp in metadata.get(node, metadata.Comprehension):
            header.append(
                Statement("pythonic::utils::reserve({0},{1})".format(
                    comp.target, iterable)))

        return Block(header + loop)