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