def visit_If(self, node): test = self.visit(node.test) body = [self.visit(n) for n in node.body] orelse = [self.visit(n) for n in node.orelse] if isinstance(node.test, ast.Num) and node.test.n == 1: stmt = Block(body) else: stmt = If(test, Block(body), Block(orelse) if orelse else None) return self.process_locals(node, self.process_omp_attachements(node, stmt))
def visit_If(self, node): test = self.visit(node.test) body = [self.visit(n) for n in node.body] orelse = [self.visit(n) for n in node.orelse] # compound statement required for some OpenMP Directives if isnum(node.test) and node.test.value == 1: stmt = Block(body) else: stmt = If(test, Block(body), Block(orelse) if orelse else None) return self.process_locals(node, self.process_omp_attachements(node, stmt))
def handle_real_loop_comparison(self, args, stmts, target, upper_bound, step): """ Handle comparison for real loops. Add the correct comparison operator if possible or set a runtime __cmp comparison. """ # order is 1 for increasing loop, -1 for decreasing loop and 0 if it is # not known at compile time if len(args) <= 2: order = 1 elif isinstance(args[2], ast.Num): order = -1 + 2 * (int(args[2].n) > 0) elif isinstance(args[1], ast.Num) and isinstance(args[0], ast.Num): order = -1 + 2 * (int(args[1].n) > int(args[0].n)) else: order = 0 if order: comparison = "{} < {}" if order == 1 else "{} > {}" comparison = comparison.format(target, upper_bound) for_pos = 0 else: cmp_type = "std::function<bool(long, long)> " cmp_op = "__cmp{}".format(len(self.break_handlers)) # For yield function, all variables are globals. if self.yields: self.extra_declarations.append((cmp_op, cmp_type)) cmp_type = "" stmts.insert( 0, Statement("{} {} = std::less<long>()".format(cmp_type, cmp_op))) stmts.insert( 1, If("{} < 0L".format(step), Statement("{} = std::greater<long>()".format(cmp_op)))) for_pos = 2 comparison = "{0}({1}, {2})".format(cmp_op, target, upper_bound) return comparison, for_pos
def gen_c_for(self, node, local_iter, loop_body): """ Create C For representation for Cxx generation. Examples -------- >> for i in xrange(10): >> ... do things ... Becomes >> for(long i = 0, __targetX = 10; i < __targetX; i += 1) >> ... do things ... Or >> for i in xrange(10, 0, -1): >> ... do things ... Becomes >> for(long i = 10, __targetX = 0; i > __targetX; i += -1) >> ... do things ... It the case of not local variable, typing for `i` disappear """ args = node.iter.args step = "1L" if len(args) <= 2 else self.visit(args[2]) if len(args) == 1: lower_bound = "0L" upper_value = self.visit(args[0]) else: lower_bound = self.visit(args[0]) upper_value = self.visit(args[1]) upper_bound = "__target{0}".format(id(node)) upper_type = iter_type = "long " # If variable is local to the for body keep it local... if node.target.id in self.scope[node] and not hasattr(self, 'yields'): self.ldecls.remove(node.target.id) loop = list() else: # For yield function, upper_bound is globals. iter_type = "" # Back one step to keep Python behavior (except for break) loop = [ If("{} == {}".format(local_iter, upper_bound), Statement("{} -= {}".format(local_iter, step))) ] comparison = self.handle_real_loop_comparison(args, loop, local_iter, upper_bound, step) forloop = For("{0} {1}={2}".format(iter_type, local_iter, lower_bound), comparison, "{0} += {1}".format(local_iter, step), loop_body) loop.insert(0, self.process_omp_attachements(node, forloop)) # Store upper bound value assgnt = self.make_assign(upper_type, upper_bound, upper_value) header = [Statement(assgnt)] return header, loop
def gen_c_for(self, node, local_iter, loop_body): """ Create C For representation for Cxx generation. Examples -------- >> for i in xrange(10): >> ... do things ... Becomes >> for(long i = 0, __targetX = 10; i < __targetX; i += 1) >> ... do things ... Or >> for i in xrange(10, 0, -1): >> ... do things ... Becomes >> for(long i = 10, __targetX = 0; i > __targetX; i += -1) >> ... do things ... Or >> for i in xrange(a, b, c): >> ... do things ... Becomes >> std::function<bool(int, int)> __cmpX = std::less<long>(); >> if(c < 0) >> __cmpX = std::greater<long>(); >> for(long i = a, __targetX = b; __cmpX(i, __targetX); i += c) >> ... do things ... It the case of not local variable, typing for `i` disappear """ args = node.iter.args step = "1L" if len(args) <= 2 else self.visit(args[2]) if len(args) == 1: lower_bound = "0L" upper_value = self.visit(args[0]) else: lower_bound = self.visit(args[0]) upper_value = self.visit(args[1]) upper_bound = "__target{0}".format(len(self.break_handlers)) upper_type = iter_type = "long " # If variable is local to the for body keep it local... if node.target.id in self.scope[node] and not self.yields: self.ldecls = {d for d in self.ldecls if d.id != node.target.id} loop = list() else: # For yield function, upper_bound is globals. if self.yields: self.extra_declarations.append((upper_bound, upper_type)) upper_type = "" iter_type = "" # Back one step to keep Python behavior (except for break) loop = [ If("{} == {}".format(local_iter, upper_bound), Statement("{} -= {}".format(local_iter, step))) ] comparison, for_pos = self.handle_real_loop_comparison( args, loop, local_iter, upper_bound, step) forloop = For( "{0} {1} = {2}".format(iter_type, local_iter, lower_bound), comparison, "{0} += {1}".format(local_iter, step), loop_body) loop.insert(for_pos, self.process_omp_attachements(node, forloop)) # Store upper bound value header = [ Statement("{0} {1} = {2}".format(upper_type, upper_bound, upper_value)) ] return header, loop