From 21023fea74c5e310470501fc9119aeb9892d3823 Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 8 Jan 2017 08:54:03 -0500 Subject: [PATCH] Add 3.5+ async with/for .. scanner3.py: 3.6 bytecode vs wordcode fix --- test/bytecode_3.5/03_async_await.pyc | Bin 227 -> 967 bytes test/bytecode_3.6/03_async_await.pyc | Bin 223 -> 939 bytes test/simple_source/bug35/03_async_await.py | 25 ++++++- uncompyle6/parsers/parse35.py | 76 ++++++++++++++++++--- uncompyle6/scanners/scanner3.py | 8 ++- uncompyle6/semantics/pysource.py | 14 +++- 6 files changed, 109 insertions(+), 14 deletions(-) diff --git a/test/bytecode_3.5/03_async_await.pyc b/test/bytecode_3.5/03_async_await.pyc index bc621ee7051e3191aea2411c3ff0f11f364caae5..cc528841a5b93569c1e3b6158d0042130e5065a3 100644 GIT binary patch literal 967 zcmbu7&u-H|5XNV0Crymq6sQm{fRHZ~k(LvxS|I^B5D9Wf=p}MvQ!LUr-E~BQ$f-O9 zZ@_c(EqvvaSK!1qpq8pC``v}8|BzT#=6P>_t zC~?(hN<2y$YGboW$(GtKB`r$YYU6-UgXqo#x73f^Ezax?q#(K^>cPbuh72O^M||R* z#^xs(P*w8#k_SLQX*aCV#_vRQEh zLYqZ1i7v>BPfD>X4kQNRkWB}3%^>G%h6oEZ!8OBOLfwIc8eiT<;Z$itUbgWcCe2IT ztyMk4iXyfO@(>5FK{{-t^ZQXl8&eCc=}|uYc57Iz7w37hn5Kskq!pKe7c_%b;QayB Clb_K5 delta 106 zcmX@k{+Q81jF*?|z~aIPdjDWE1S>>8uYWTS>a!eXH}wJ-{;Ot7AFEo0c(vQ zXREvv;gFr_u0<*1JlIx{*=k4a96rEkBV@!c32h?-B7Eet%e@|4!5lBw#8>FByAale z#9m0Y6su<^z8oJ2-?7gr^F=vIO@&2;)4Re*{-~PSr;?Pq!CM!yfZ0Jx*w)+^Y82%%35wb-lq z3=H*_nc-XnU`k!qCk30&9++PdtZqMICuO14cAXPM`V&v~}=!|F=`SJ_@SwYq% zhqe*hNKbiJW61XpFf86-%o*zH-xy}uD(+32qp;E5)Kj{=%+?Ykb4v330f|g}H;r^4 h^>(#I3P|$quXV+{7p0vH^F683Ny<2k8*vB*JMYAhfz000~gc>n+a 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]