From 32f3d947bbfb4d77e12cdc1f9b235b5e64f9300d Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 3 Dec 2017 05:10:59 -0500 Subject: [PATCH] Grammar "COME_FROM"_from cleanups ... tryelse constructs in 2.x fixed up _come_from -> _come_froms (COME_FROM*) consolidate come_froms rule into sincle parser.py --- uncompyle6/parser.py | 22 ++++++++++++---------- uncompyle6/parsers/parse25.py | 2 +- uncompyle6/parsers/parse26.py | 19 +++++++------------ uncompyle6/parsers/parse27.py | 5 +---- uncompyle6/parsers/parse3.py | 9 ++++----- uncompyle6/parsers/parse30.py | 2 +- uncompyle6/parsers/parse32.py | 2 +- uncompyle6/scanners/scanner2.py | 17 ++++++++++------- 8 files changed, 37 insertions(+), 41 deletions(-) diff --git a/uncompyle6/parser.py b/uncompyle6/parser.py index 0e46802a..3a537647 100644 --- a/uncompyle6/parser.py +++ b/uncompyle6/parser.py @@ -33,7 +33,7 @@ class PythonParser(GenericASTBuilder): # FIXME: customize per python parser version nt_list = [ 'stmts', 'except_stmts', '_stmts', 'load_attrs', - 'exprlist', 'kvlist', 'kwargs', 'come_froms', '_come_from', + 'exprlist', 'kvlist', 'kwargs', 'come_froms', '_come_froms', 'importlist', # Python < 3 'print_items', @@ -306,9 +306,11 @@ class PythonParser(GenericASTBuilder): _jump ::= JUMP_FORWARD _jump ::= JUMP_BACK - # Zero or more COME_FROMs - # loops can have this - _come_from ::= COME_FROM* + # Zero or more COME_FROMs - loops can have this + _come_froms ::= COME_FROM* + + # One or more COME_FROMs - joins of tryelse's have this + come_froms ::= COME_FROM+ # Zero or one COME_FROM # And/or expressions have this @@ -360,19 +362,19 @@ class PythonParser(GenericASTBuilder): """ _for ::= GET_ITER FOR_ITER - for_block ::= l_stmts_opt _come_from JUMP_BACK + for_block ::= l_stmts_opt _come_froms JUMP_BACK forstmt ::= SETUP_LOOP expr _for store - for_block POP_BLOCK _come_from + for_block POP_BLOCK _come_froms forelsestmt ::= SETUP_LOOP expr _for store - for_block POP_BLOCK else_suite _come_from + for_block POP_BLOCK else_suite _come_froms forelselaststmt ::= SETUP_LOOP expr _for store - for_block POP_BLOCK else_suitec _come_from + for_block POP_BLOCK else_suitec _come_froms forelselaststmtl ::= SETUP_LOOP expr _for store - for_block POP_BLOCK else_suitel _come_from + for_block POP_BLOCK else_suitel _come_froms """ def p_import20(self, args): @@ -495,7 +497,7 @@ class PythonParser(GenericASTBuilder): compare_single ::= expr expr COMPARE_OP # A compare_chained is two comparisions like x <= y <= z - compare_chained ::= expr compare_chained1 ROT_TWO POP_TOP _come_from + compare_chained ::= expr compare_chained1 ROT_TWO POP_TOP _come_froms compare_chained2 ::= expr COMPARE_OP JUMP_FORWARD # Non-null kvlist items are broken out in the indiviual grammars diff --git a/uncompyle6/parsers/parse25.py b/uncompyle6/parsers/parse25.py index 27525306..4c0de8d0 100644 --- a/uncompyle6/parsers/parse25.py +++ b/uncompyle6/parsers/parse25.py @@ -33,7 +33,7 @@ class Python25Parser(Python26Parser): store ::= STORE_NAME tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK - try_middle else_suite COME_FROM + try_middle else_suite come_froms # Python 2.6 omits the LOAD_FAST DELETE_FAST below # withas is allowed as a "from future" in 2.5 diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py index f9e93dfd..107fde53 100644 --- a/uncompyle6/parsers/parse26.py +++ b/uncompyle6/parsers/parse26.py @@ -47,16 +47,11 @@ class Python26Parser(Python2Parser): except_suite ::= c_stmts_opt JUMP_FORWARD POP_TOP except_suite ::= c_stmts_opt jmp_abs come_from_pop - # Python 3 also has this. - come_froms ::= come_froms COME_FROM - come_froms ::= COME_FROM - # This is what happens after a jump where # we start a new block. For reasons I don't fully # understand, there is also a value on the top of the stack come_from_pop ::= COME_FROM POP_TOP come_froms_pop ::= come_froms POP_TOP - """ # In contrast to Python 2.7, Python 2.6 has a lot of @@ -86,7 +81,7 @@ class Python26Parser(Python2Parser): # COME_FROM_LOOP, but in <= 2.6 we don't distinguish # this - cf_jb_cf_pop ::= _come_from JUMP_BACK come_froms POP_TOP + cf_jb_cf_pop ::= _come_froms JUMP_BACK come_froms POP_TOP bp_come_from ::= POP_BLOCK COME_FROM jb_bp_come_from ::= JUMP_BACK bp_come_from @@ -137,7 +132,7 @@ class Python26Parser(Python2Parser): while1stmt ::= SETUP_LOOP l_stmts JUMP_BACK COME_FROM - whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_pop POP_BLOCK _come_from + whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_pop POP_BLOCK _come_froms whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_cf_pop bp_come_from whilestmt ::= SETUP_LOOP testexpr return_stmts POP_BLOCK COME_FROM @@ -179,7 +174,7 @@ class Python26Parser(Python2Parser): jmp_true_then ::= JUMP_IF_TRUE THEN POP_TOP while1stmt ::= SETUP_LOOP return_stmts COME_FROM - for_block ::= return_stmts _come_from + for_block ::= return_stmts _come_froms """ def p_comp26(self, args): @@ -206,7 +201,7 @@ class Python26Parser(Python2Parser): comp_body ::= gen_comp_body - for_block ::= l_stmts_opt _come_from POP_TOP JUMP_BACK + for_block ::= l_stmts_opt _come_froms POP_TOP JUMP_BACK # Make sure we keep indices the same as 2.7 setup_loop_lf ::= SETUP_LOOP LOAD_FAST @@ -242,11 +237,11 @@ class Python26Parser(Python2Parser): and ::= expr JUMP_IF_FALSE POP_TOP expr JUMP_IF_FALSE POP_TOP # compare_chained is like x <= y <= z - compare_chained ::= expr compare_chained1 ROT_TWO COME_FROM POP_TOP _come_from + compare_chained ::= expr compare_chained1 ROT_TWO COME_FROM POP_TOP _come_froms compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP - jmp_false compare_chained1 _come_from + jmp_false compare_chained1 _come_froms compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP - jmp_false compare_chained2 _come_from + jmp_false compare_chained2 _come_froms return_if_lambda ::= RETURN_END_IF_LAMBDA POP_TOP stmt ::= conditional_lambda conditional_lambda ::= expr jmp_false_then expr return_if_lambda diff --git a/uncompyle6/parsers/parse27.py b/uncompyle6/parsers/parse27.py index 29d25065..e11764a2 100644 --- a/uncompyle6/parsers/parse27.py +++ b/uncompyle6/parsers/parse27.py @@ -61,9 +61,6 @@ class Python27Parser(Python2Parser): def p_jump27(self, args): """ - come_froms ::= come_froms COME_FROM - come_froms ::= COME_FROM - iflaststmtl ::= testexpr c_stmts_opt _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD come_froms @@ -112,7 +109,7 @@ class Python27Parser(Python2Parser): while1stmt ::= SETUP_LOOP return_stmts bp_come_from while1stmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK COME_FROM - whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK _come_from + whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK _come_froms while1elsestmt ::= SETUP_LOOP l_stmts JUMP_BACK POP_BLOCK else_suite COME_FROM whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index e57f12f4..e10e14fd 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -156,10 +156,10 @@ class Python3Parser(PythonParser): ifelsestmt ::= testexpr c_stmts_opt JUMP_FORWARD else_suite opt_come_from_except ifelsestmt ::= testexpr c_stmts_opt jump_forward_else - else_suite _come_from + else_suite _come_froms # ifelsestmt ::= testexpr c_stmts_opt jump_forward_else - # passstmt _come_from + # passstmt _come_froms ifelsestmtc ::= testexpr c_stmts_opt JUMP_ABSOLUTE else_suitec ifelsestmtc ::= testexpr c_stmts_opt jump_absolute_else else_suitec @@ -300,10 +300,9 @@ class Python3Parser(PythonParser): def p_come_from3(self, args): """ opt_come_from_except ::= COME_FROM_EXCEPT - opt_come_from_except ::= come_froms + opt_come_from_except ::= _come_froms opt_come_from_except ::= come_from_except_clauses - come_froms ::= COME_FROM* come_from_except_clauses ::= COME_FROM_EXCEPT_CLAUSE+ come_from_loops ::= COME_FROM_LOOP* """ @@ -334,7 +333,7 @@ class Python3Parser(PythonParser): return_closure ::= LOAD_CLOSURE RETURN_VALUE RETURN_LAST stmt ::= whileTruestmt - ifelsestmt ::= testexpr c_stmts_opt JUMP_FORWARD else_suite _come_from + ifelsestmt ::= testexpr c_stmts_opt JUMP_FORWARD else_suite _come_froms """ def p_loop_stmt3(self, args): diff --git a/uncompyle6/parsers/parse30.py b/uncompyle6/parsers/parse30.py index 3ce151fd..242bf963 100644 --- a/uncompyle6/parsers/parse30.py +++ b/uncompyle6/parsers/parse30.py @@ -24,7 +24,7 @@ class Python30Parser(Python31Parser): # In many ways Python 3.0 code generation is more like Python 2.6 than # it is 2.7 or 3.1. So we have a number of 2.6ish (and before) rules below - _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD come_froms POP_TOP COME_FROM + _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_froms POP_TOP COME_FROM jmp_true ::= JUMP_IF_TRUE POP_TOP jmp_false ::= JUMP_IF_FALSE POP_TOP diff --git a/uncompyle6/parsers/parse32.py b/uncompyle6/parsers/parse32.py index 2d561805..a335cb8c 100644 --- a/uncompyle6/parsers/parse32.py +++ b/uncompyle6/parsers/parse32.py @@ -45,7 +45,7 @@ class Python32Parser(Python3Parser): # JUMP_FORWARD in some cases, and hence we also don't # see COME_FROM _ifstmts_jump ::= c_stmts_opt - _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_from + _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_froms stmt ::= del_deref_stmt del_deref_stmt ::= DELETE_DEREF diff --git a/uncompyle6/scanners/scanner2.py b/uncompyle6/scanners/scanner2.py index 4f28d672..f38beb58 100644 --- a/uncompyle6/scanners/scanner2.py +++ b/uncompyle6/scanners/scanner2.py @@ -1037,14 +1037,17 @@ class Scanner2(Scanner): elif not (code[label] == self.opc.POP_TOP and code[self.prev[label]] == self.opc.RETURN_VALUE): # In Python < 2.7, don't add a COME_FROM, for: - # RETURN_VALUE POP_TOP .. END_FINALLY + # ~RETURN_VALUE POP_TOP .. END_FINALLY # or: - # RETURN_VALUE POP_TOP .. POP_TOP END_FINALLY - skip_come_from = False - if self.version <= 2.6: - skip_come_from = (code[offset+3] == self.opc.END_FINALLY or - (code[offset+3] == self.opc.POP_TOP - and code[offset+4] == self.opc.END_FINALLY)) + # ~RETURN_VALUE POP_TOP .. POP_TOP END_FINALLY + skip_come_from = (code[offset+3] == self.opc.END_FINALLY or + (code[offset+3] == self.opc.POP_TOP + and code[offset+4] == self.opc.END_FINALLY)) + + # The below is for special try/else handling + if skip_come_from and op == self.opc.JUMP_FORWARD: + skip_come_from = False + if not skip_come_from: # FIXME: rocky: I think we need something like this... if offset not in set(self.ignore_if):