Exemplo n.º 1
0
def pop_with_body_instrs(setup_with_instr, queue):
    """
    Pop instructions from `queue` that form the body of a with block.
    """
    body_instrs = popwhile(op.is_not(setup_with_instr.arg), queue, side='left')

    # Last two instructions should always be POP_BLOCK, LOAD_CONST(None).
    # These don't correspond to anything in the AST, so remove them here.
    load_none = body_instrs.pop()
    expect(load_none, instrs.LOAD_CONST, "at end of with-block")
    pop_block = body_instrs.pop()
    expect(pop_block, instrs.POP_BLOCK, "at end of with-block")
    if load_none.arg is not None:
        raise DecompilationError(
            "Expected LOAD_CONST(None), but got "
            "%r instead" % (load_none)
        )

    # Target of the setup_with should be a WITH_CLEANUP instruction followed by
    # an END_FINALLY.  Neither of these correspond to anything in the AST.
    with_cleanup = queue.popleft()
    expect(with_cleanup, instrs.WITH_CLEANUP, "at end of with-block")
    end_finally = queue.popleft()
    expect(end_finally, instrs.END_FINALLY, "at end of with-block")

    return body_instrs
Exemplo n.º 2
0
def pop_loop_instrs(setup_loop_instr, queue):
    """
    Determine whether setup_loop_instr is setting up a for-loop or a
    while-loop.  Then pop the loop instructions from queue.

    The easiest way to tell the difference is to look at the target of the
    JUMP_ABSOLUTE instruction at the end of the loop.  If it jumps to a
    FOR_ITER, then this is a for-loop.  Otherwise it's a while-loop.

    The jump we want to inspect is the first JUMP_ABSOLUTE instruction prior to
    the jump target of `setup_loop_instr`.

    Parameters
    ----------
    setup_loop_instr : instructions.SETUP_LOOP
        First instruction of the loop being parsed.
    queue : collections.deque
        Queue of unprocessed instructions.

    Returns
    -------
    loop_type : str, {'for', 'while'}
        The kind of loop being constructed.
    loop_instrs : deque
        The instructions forming body of the loop.
    else_instrs : deque
        The instructions forming the else-block of the loop.

    Side Effects
    ------------
    Pops all returned instructions from `queue`.
    """
    # Grab everything from left side of the queue until the jump target of
    # SETUP_LOOP.
    body = popwhile(op.is_not(setup_loop_instr.arg), queue, side='left')

    # Anything after the last POP_BLOCK instruction is the else-block.
    else_body = popwhile(not_a(instrs.POP_BLOCK), body, side='right')

    jump_to_top, pop_block = body[-2], body[-1]
    if not isinstance(jump_to_top, instrs.JUMP_ABSOLUTE):
        raise DecompilationError(
            "Penultimate instruction of loop body is "
            "%s, not JUMP_ABSOLUTE." % jump_to_top,
        )

    if not isinstance(pop_block, instrs.POP_BLOCK):
        raise DecompilationError(
            "Last instruction of loop body is "
            "%s, not pop_block." % pop_block,
        )

    loop_expr = jump_to_top.arg
    if isinstance(loop_expr, instrs.FOR_ITER):
        return 'for', body, else_body
    return 'while', body, else_body