diff --git a/test/bytecode_3.5/03_async_await.pyc b/test/bytecode_3.5/03_async_await.pyc index bc621ee7..cc528841 100644 Binary files a/test/bytecode_3.5/03_async_await.pyc and b/test/bytecode_3.5/03_async_await.pyc differ diff --git a/test/bytecode_3.6/03_async_await.pyc b/test/bytecode_3.6/03_async_await.pyc index f32408c3..0d50fe37 100644 Binary files a/test/bytecode_3.6/03_async_await.pyc and b/test/bytecode_3.6/03_async_await.pyc differ diff --git a/test/simple_source/bug35/03_async_await.py b/test/simple_source/bug35/03_async_await.py index d438b66e..7dec4df4 100644 --- a/test/simple_source/bug35/03_async_await.py +++ b/test/simple_source/bug35/03_async_await.py @@ -1,3 +1,26 @@ # Python 3.5+ async and await -async def foo(): +async def await_test(): await bar() + + +async def afor_test(): + + async for i in [1,2,3]: + x = i + + +async def afor_else_test(): + + async for i in [1,2,3]: + x = i + else: + z = 4 + + +async def awith_test(): + async with i: + print(i) + +async def awith_as_test(): + async with 1 as i: + print(i) diff --git a/uncompyle6/parsers/parse35.py b/uncompyle6/parsers/parse35.py index 828f80cd..de32c96b 100644 --- a/uncompyle6/parsers/parse35.py +++ b/uncompyle6/parsers/parse35.py @@ -16,23 +16,79 @@ class Python35Parser(Python34Parser): def p_35on(self, args): """ + # The number of canned instructions in new statements is mind boggling. + # I'm sure by the time Python 4 comes around these will be turned + # into special opcodes + # Python 3.5+ Await statement - sstmt ::= await_stmt + stmt ::= await_stmt await_stmt ::= call_function GET_AWAITABLE LOAD_CONST YIELD_FROM POP_TOP # Python 3.5+ has WITH_CLEANUP_START/FINISH - withstmt ::= expr SETUP_WITH exprlist suite_stmts_opt - POP_BLOCK LOAD_CONST COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + withstmt ::= expr + SETUP_WITH exprlist suite_stmts_opt + POP_BLOCK LOAD_CONST COME_FROM_WITH + WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY - withstmt ::= expr SETUP_WITH POP_TOP suite_stmts_opt - POP_BLOCK LOAD_CONST COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + withstmt ::= expr + SETUP_WITH POP_TOP suite_stmts_opt + POP_BLOCK LOAD_CONST COME_FROM_WITH + WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + + withasstmt ::= expr + SETUP_WITH designator suite_stmts_opt + POP_BLOCK LOAD_CONST COME_FROM_WITH + WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + + + # Python 3.5+ async additions + + stmt ::= async_with_stmt + async_with_stmt ::= expr + BEFORE_ASYNC_WITH GET_AWAITABLE LOAD_CONST YIELD_FROM + SETUP_ASYNC_WITH POP_TOP suite_stmts_opt + POP_BLOCK LOAD_CONST + WITH_CLEANUP_START + GET_AWAITABLE LOAD_CONST YIELD_FROM + WITH_CLEANUP_FINISH END_FINALLY + + stmt ::= async_with_as_stmt + async_with_as_stmt ::= expr + BEFORE_ASYNC_WITH GET_AWAITABLE LOAD_CONST YIELD_FROM + SETUP_ASYNC_WITH designator suite_stmts_opt + POP_BLOCK LOAD_CONST + WITH_CLEANUP_START + GET_AWAITABLE LOAD_CONST YIELD_FROM + WITH_CLEANUP_FINISH END_FINALLY + + + stmt ::= async_for_stmt + async_for_stmt ::= SETUP_LOOP expr + GET_AITER + LOAD_CONST YIELD_FROM SETUP_EXCEPT GET_ANEXT LOAD_CONST + YIELD_FROM + designator + POP_BLOCK JUMP_FORWARD COME_FROM_EXCEPT DUP_TOP + LOAD_GLOBAL COMPARE_OP POP_JUMP_IF_FALSE + POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_BLOCK + JUMP_ABSOLUTE END_FINALLY COME_FROM + for_block POP_BLOCK JUMP_ABSOLUTE + opt_come_from_loop + + stmt ::= async_forelse_stmt + async_forelse_stmt ::= SETUP_LOOP expr + GET_AITER + LOAD_CONST YIELD_FROM SETUP_EXCEPT GET_ANEXT LOAD_CONST + YIELD_FROM + designator + POP_BLOCK JUMP_FORWARD COME_FROM_EXCEPT DUP_TOP + LOAD_GLOBAL COMPARE_OP POP_JUMP_IF_FALSE + POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_BLOCK + JUMP_ABSOLUTE END_FINALLY COME_FROM + for_block POP_BLOCK JUMP_ABSOLUTE + else_suite COME_FROM_LOOP - withasstmt ::= expr SETUP_WITH designator suite_stmts_opt - POP_BLOCK LOAD_CONST COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY inplace_op ::= INPLACE_MATRIX_MULTIPLY binary_op ::= BINARY_MATRIX_MULTIPLY diff --git a/uncompyle6/scanners/scanner3.py b/uncompyle6/scanners/scanner3.py index e6dfac25..6095b1c9 100644 --- a/uncompyle6/scanners/scanner3.py +++ b/uncompyle6/scanners/scanner3.py @@ -461,11 +461,15 @@ class Scanner3(Scanner): has_arg = (op >= op3.HAVE_ARGUMENT) if has_arg: label = self.fixed_jumps.get(offset) - oparg = code[offset+1] + code[offset+2] * 256 + if self.version >= 3.6: + oparg = code[offset+1] + else: + oparg = code[offset+1] + code[offset+2] * 256 + next_offset = offset + self.op_size(op) if label is None: if op in op3.hasjrel and op != self.opc.FOR_ITER: - label = offset + 3 + oparg + label = next_offset + oparg elif op in op3.hasjabs: if op in self.jump_if_pop: if oparg > offset: diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index be96a081..649f7ed0 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -649,9 +649,21 @@ class SourceWalker(GenericASTTraversal, object): TABLE_DIRECT.update({ 'LOAD_CLASSDEREF': ( '%{pattr}', ), }) + ######################## + # Python 3.5+ Additions + ####################### if version >= 3.5: TABLE_DIRECT.update({ - 'await_stmt': ( '%|await %c', 0), + 'await_stmt': ( '%|await %c', 0), + 'async_for_stmt': ( + '%|async for %c in %c:\n%+%c%-\n\n', 9, 1, 25 ), + 'async_forelse_stmt': ( + '%|async for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n', 9, 1, 25, 28 ), + 'async_with_stmt': ( + '%|async with %c:\n%+%c%-', 0, 7), + 'async_with_as_stmt': ( + '%|async with %c as %c:\n%+%c%-', 0, 6, 7), + }) def n_funcdef(node): code_node = node[0][1]