Beispiel #1
0
def identify_consumers(func, env):
    """
    Identify consumers of generators, that is find the loops that iterate
    over a generator.
    """
    generator_objects = find_generators(func, env)
    #print("generators", generator_objects)
    if not generator_objects:
        # We can stop now
        return

    loop_forest = loop_detection.find_natural_loops(func)
    loops = loop_detection.flatloops(loop_forest)
    heads = dict((loop.head, loop) for loop in loops)

    expect_call = partial(expect_single_call, func, env)
    #print("loops", loops, "heads", heads)

    for generator_obj in generator_objects:
        # Check for a nesting of next(iter(my_generator()))
        iter = expect_call(generator_obj, builtins.iter)
        next = expect_call(iter, builtins.next)
        if iter and next and next.block in heads:
            loop = heads[next.block]
            yield Consumer(generator_obj, iter, next, loop)
Beispiel #2
0
def identify_consumers(func, env):
    """
    Identify consumers of generators, that is find the loops that iterate
    over a generator.
    """
    generator_objects = find_generators(func, env)
    #print("generators", generator_objects)
    if not generator_objects:
        # We can stop now
        return

    loop_forest = loop_detection.find_natural_loops(func)
    loops = loop_detection.flatloops(loop_forest)
    heads = dict((loop.head, loop) for loop in loops)

    expect_call = partial(expect_single_call, func, env)
    #print("loops", loops, "heads", heads)

    for generator_obj in generator_objects:
        # Check for a nesting of next(iter(my_generator()))
        iter = expect_call(generator_obj, builtins.iter)
        next = expect_call(iter, builtins.next)
        if iter and next and next.block in heads:
            loop = heads[next.block]
            yield Consumer(generator_obj, iter, next, loop)
Beispiel #3
0
 def test_unnested(self):
     loops = loop_detection.find_natural_loops(self.f)
     assert len(loops) == 2
     assert len(loops[0].children) == 0
     assert len(loops[1].children) == 0
     assert len(loops[0].blocks) >= 4
     assert len(loops[1].blocks) >= 2
Beispiel #4
0
def assert_inlinable(func, call, callee, uses):
    """
    Verify that a function call can be inlined.

    We can inline generators if they are consumed in a single loop:

        - iter(g) must be in a loop header
        - next(g) must be in the loop body

    :return: None if inlineable, or an exception with a message
    """
    if not isinstance(callee, Function):
        return CompileError("Cannot inline external function: %s" % (callee,))

    yields = findallops(callee, 'yield')
    if yields:
        for use in uses[call]:
            if use.opcode not in ('iter', 'next'):
                return CompileError(
                    "Cannot inline generator with use %s" % (use,))

        if len(uses[call]) != 2:
            return CompileError("Can only")
        loops = loop_detection.find_natural_loops(func)
Beispiel #5
0
 def test_nested(self):
     loops = loop_detection.find_natural_loops(self.f)
     for i in range(3):
         loop, = loops
         loops = loop.children