Beispiel #1
0
 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))
Beispiel #2
0
 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))
Beispiel #3
0
    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
Beispiel #4
0
    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
Beispiel #5
0
    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