From 5e1340a2fc83658ae69115c5a2c79548072ddea1 Mon Sep 17 00:00:00 2001 From: rocky Date: Thu, 11 Apr 2019 12:09:24 -0400 Subject: [PATCH] 3.8 exception handling --- test/bytecode_3.8/04_try_finally.pyc | Bin 0 -> 868 bytes uncompyle6/parsers/parse38.py | 40 +++++++++++++++++++++++---- uncompyle6/scanners/scanner3.py | 2 +- uncompyle6/semantics/customize3.py | 6 +++- uncompyle6/semantics/pysource.py | 3 +- 5 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 test/bytecode_3.8/04_try_finally.pyc diff --git a/test/bytecode_3.8/04_try_finally.pyc b/test/bytecode_3.8/04_try_finally.pyc new file mode 100644 index 0000000000000000000000000000000000000000..501fd868ec579e71fedfb66f5a9eaf10fd39558f GIT binary patch literal 868 zcmaiy&u`N(6vv;Pv~|li3I_xnIKd$t7>J1znvnP*O`swzhn5N{N@H(}mL`?sjJZ^BGPm(G02Li&a~Lh4cA zb><#U<~H}7&ROM`D%;aG=FG1LWjY*XDk_VyPSoaLy#Mss=Hso%=t;Df=5dxy9*riI z*jMH#&c;gM%hJ9|j5EP?1G|4$)W*qWMLk!Mtp^g&+;T6fuZ0zBzT9-R7iHhx|DDGWazM^?=k4a=mW$J2{DG)8%8Ib(R6Lb>(s^B z8N`x^o$?;M9Cii~1Kyd}aA&})8-1mVSLsn&rbYf*>q1wJ_o3Sap0-JqFJlw;y-x>| zt2EaR;#@*vtzvlxspSTY<6#@D&f4rQ*OoJ}QrKbdTTu<*Oj|Sl85H2!U2<)K!FLS) zUkv`K?-(8~SwH?K53E+1fOUYm9-3mbW0Z~!IIFeYacbspHf{Q2>Y)b_>Y2EjH7)5bp%O>mv7Ooe(bk$6c;lU1Nyn!$OWT NwY_RX(GV@s{tbJEqK*In literal 0 HcmV?d00001 diff --git a/uncompyle6/parsers/parse38.py b/uncompyle6/parsers/parse38.py index 5e93e106..665784d5 100644 --- a/uncompyle6/parsers/parse38.py +++ b/uncompyle6/parsers/parse38.py @@ -29,6 +29,10 @@ class Python38Parser(Python37Parser): stmt ::= forelsestmt38 stmt ::= forelselaststmt38 stmt ::= forelselaststmtl38 + stmt ::= tryfinally38 + + # FIXME this should be restricted to being inside a try block + stmt ::= except_ret38 for38 ::= expr get_iter store for_block JUMP_BACK for38 ::= expr for_iter store for_block JUMP_BACK @@ -39,21 +43,38 @@ class Python38Parser(Python37Parser): forelselaststmtl38 ::= expr for_iter store for_block POP_BLOCK else_suitel whilestmt ::= testexpr l_stmts_opt COME_FROM JUMP_BACK POP_BLOCK whilestmt ::= testexpr l_stmts_opt JUMP_BACK POP_BLOCK - whilestmt ::= testexpr returns POP_BLOCK + whilestmt ::= testexpr returns POP_BLOCK while1elsestmt ::= l_stmts JUMP_BACK - whileelsestmt ::= testexpr l_stmts_opt JUMP_BACK POP_BLOCK - whileTruestmt ::= l_stmts_opt JUMP_BACK POP_BLOCK + whileelsestmt ::= testexpr l_stmts JUMP_BACK POP_BLOCK + whileTruestmt ::= l_stmts JUMP_BACK POP_BLOCK while1stmt ::= l_stmts COME_FROM_LOOP while1stmt ::= l_stmts COME_FROM JUMP_BACK COME_FROM_LOOP while1elsestmt ::= l_stmts JUMP_BACK - whileTruestmt ::= l_stmts_opt JUMP_BACK NOP - whileTruestmt ::= l_stmts_opt JUMP_BACK POP_BLOCK NOP + whileTruestmt ::= l_stmts JUMP_BACK NOP + whileTruestmt ::= l_stmts JUMP_BACK POP_BLOCK NOP for_block ::= l_stmts_opt _come_from_loops JUMP_BACK + except_cond1 ::= DUP_TOP expr COMPARE_OP jmp_false + POP_TOP POP_TOP POP_TOP + POP_EXCEPT try_except ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK except_handler38 + except_ret38 ::= SETUP_FINALLY expr ROT_FOUR POP_BLOCK POP_EXCEPT + CALL_FINALLY RETURN_VALUE COME_FROM_FINALLY + suite_stmts_opt END_FINALLY except_handler38 ::= JUMP_FORWARD COME_FROM_FINALLY except_stmts END_FINALLY opt_come_from_except + tryfinallystmt ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK + BEGIN_FINALLY COME_FROM_FINALLY suite_stmts_opt + END_FINALLY + tryfinally38 ::= SETUP_FINALLY POP_BLOCK CALL_FINALLY + returns + COME_FROM_FINALLY END_FINALLY suite_stmts + tryfinally38 ::= SETUP_FINALLY POP_BLOCK CALL_FINALLY + returns + COME_FROM_FINALLY POP_FINALLY returns + END_FINALLY + """ def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG): @@ -64,14 +85,23 @@ class Python38Parser(Python37Parser): self.remove_rules(""" stmt ::= for stmt ::= forelsestmt + stmt ::= try_except36 + for ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK for ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK NOP + for_block ::= l_stmts_opt COME_FROM_LOOP JUMP_BACK forelsestmt ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK else_suite forelselaststmt ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK else_suitec forelselaststmtl ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK else_suitel try_except ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK except_handler opt_come_from_except + tryfinallystmt ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK + LOAD_CONST COME_FROM_FINALLY suite_stmts_opt + END_FINALLY + tryfinally36 ::= SETUP_FINALLY returns + COME_FROM_FINALLY suite_stmts_opt END_FINALLY + """) super(Python37Parser, self).customize_grammar_rules(tokens, customize) diff --git a/uncompyle6/scanners/scanner3.py b/uncompyle6/scanners/scanner3.py index 7b0b328f..9ad9c799 100644 --- a/uncompyle6/scanners/scanner3.py +++ b/uncompyle6/scanners/scanner3.py @@ -872,7 +872,7 @@ class Scanner3(Scanner): if_end = self.get_target(pre_rtarget) # If the jump target is back, we are looping - if (if_end < pre_rtarget and + if (if_end < pre_rtarget and self.version < 3.8 and (code[prev_op[if_end]] == self.opc.SETUP_LOOP)): if (if_end > start): return diff --git a/uncompyle6/semantics/customize3.py b/uncompyle6/semantics/customize3.py index 08e58af1..8fedcc61 100644 --- a/uncompyle6/semantics/customize3.py +++ b/uncompyle6/semantics/customize3.py @@ -938,7 +938,8 @@ def customize_for_version3(self, version): ####################### # FIXME: pytest doesn't add proper keys in testing. Reinstate after we have fixed pytest. - # for lhs in 'for forelsestmt forelselaststmt forelselaststmtl'.split(): + # for lhs in 'for forelsestmt forelselaststmt ' + # 'forelselaststmtl tryfinally38'.split(): # del TABLE_DIRECT[lhs] TABLE_DIRECT.update({ @@ -962,6 +963,9 @@ def customize_for_version3(self, version): (2, 'store'), (0, 'expr'), (3, 'for_block'), -2 ), + 'tryfinally38': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n', + (3, 'returns'), 6 ), + 'except_ret38': ( '%|return %c\n', (1, 'expr') ), }) pass pass diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index b9b259a4..b79b902d 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -1815,7 +1815,6 @@ class SourceWalker(GenericASTTraversal, object): # except_cond3 is only in Python <= 2.6 n_except_cond3 = n_except_cond2 - def template_engine(self, entry, startnode): """The format template interpetation engine. See the comment at the beginning of this module for the how we interpret format @@ -1862,7 +1861,7 @@ class SourceWalker(GenericASTTraversal, object): if isinstance(index, tuple): assert node[index[0]] == index[1], ( "at %s[%d], expected %s node; got %s" % ( - node.kind, arg, node[index[0]].kind, index[1]) + node.kind, arg, index[1], node[index[0]].kind) ) index = index[0] assert isinstance(index, int), (