From 9b1dd0f26c65f42313315d1017395e559be11d8e Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 27 Dec 2016 10:29:29 -0500 Subject: [PATCH 1/4] Make 2.6 and 2.7 ingest more alike --- uncompyle6/scanners/scanner2.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/uncompyle6/scanners/scanner2.py b/uncompyle6/scanners/scanner2.py index 052ab011..ac6d3a9e 100644 --- a/uncompyle6/scanners/scanner2.py +++ b/uncompyle6/scanners/scanner2.py @@ -101,10 +101,10 @@ class Scanner2(scan.Scanner): Token = self.Token # shortcut - n = self.setup_code(co) + codelen = self.setup_code(co) - self.build_lines_data(co, n) - self.build_prev_op(n) + self.build_lines_data(co, codelen) + self.build_prev_op(codelen) free, names, varnames = self.unmangle_code_names(co, classname) self.names = names @@ -113,7 +113,7 @@ class Scanner2(scan.Scanner): # turn 'LOAD_GLOBAL' to 'LOAD_ASSERT'. # 'LOAD_ASSERT' is used in assert statements. self.load_asserts = set() - for i in self.op_range(0, n): + for i in self.op_range(0, codelen): # We need to detect the difference between: # raise AssertionError # and @@ -138,7 +138,7 @@ class Scanner2(scan.Scanner): last_stmt = self.next_stmt[0] i = self.next_stmt[last_stmt] replace = {} - while i < n-1: + while i < codelen - 1: if self.lines[last_stmt].next > i: # Distinguish "print ..." from "print ...," if self.code[last_stmt] == self.opc.PRINT_ITEM: @@ -150,7 +150,7 @@ class Scanner2(scan.Scanner): i = self.next_stmt[i] extended_arg = 0 - for offset in self.op_range(0, n): + for offset in self.op_range(0, codelen): if offset in jump_targets: jump_idx = 0 # We want to process COME_FROMs to the same offset to be in *descending* @@ -176,6 +176,7 @@ class Scanner2(scan.Scanner): offset="%s_%d" % (offset, jump_idx), has_arg = True)) jump_idx += 1 + pass op = self.code[offset] op_name = self.opc.opname[op] From 4d4e59c40bc6cabac73d918d72e1700eda76cec5 Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 28 Dec 2016 18:57:09 -0500 Subject: [PATCH 2/4] Towards fixing a 3.2 while true: ... break bug --- uncompyle6/parsers/parse3.py | 7 +++++++ uncompyle6/parsers/parse32.py | 5 +++++ uncompyle6/parsers/parse33.py | 5 ----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index ea1a0729..610b3b4b 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -696,12 +696,19 @@ class Python3Parser(PythonParser): self.check_reduce['augassign1'] = 'AST' self.check_reduce['augassign2'] = 'AST' self.check_reduce['while1stmt'] = 'noAST' + # FIXME: remove parser errors caused by the below + # self.check_reduce['while1elsestmt'] = 'noAST' return def reduce_is_invalid(self, rule, ast, tokens, first, last): lhs = rule[0] if lhs in ('augassign1', 'augassign2') and ast[0][0] == 'and': return True + elif lhs == 'while1elsestmt': + last += 1 + while isinstance(tokens[last], str): + last += 1 + return tokens[first].attr != tokens[last].offset elif lhs == 'while1stmt': if tokens[last] in ('COME_FROM_LOOP', 'JUMP_BACK'): # jump_back should be right afer SETUP_LOOP. Test? diff --git a/uncompyle6/parsers/parse32.py b/uncompyle6/parsers/parse32.py index 24d4e573..cac33810 100644 --- a/uncompyle6/parsers/parse32.py +++ b/uncompyle6/parsers/parse32.py @@ -19,6 +19,11 @@ class Python32Parser(Python3Parser): COME_FROM_LOOP whileTruestmt ::= SETUP_LOOP return_stmts COME_FROM_LOOP + + # Python 3.2+ has more loop optimization that removes + # JUMP_FORWARD in some cases, and hence we also don't + # see COME_FROM + _ifstmts_jump ::= c_stmts_opt """ pass diff --git a/uncompyle6/parsers/parse33.py b/uncompyle6/parsers/parse33.py index b310af61..990a914e 100644 --- a/uncompyle6/parsers/parse33.py +++ b/uncompyle6/parsers/parse33.py @@ -21,11 +21,6 @@ class Python33Parser(Python32Parser): iflaststmt ::= testexpr c_stmts_opt33 c_stmts_opt33 ::= JUMP_BACK JUMP_ABSOLUTE c_stmts_opt _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_from - - # Python 3.3+ has more loop optimization that removes - # JUMP_FORWARD in some cases, and hence we also don't - # see COME_FROM - _ifstmts_jump ::= c_stmts_opt """ class Python33ParserSingle(Python33Parser, PythonParserSingle): From 723fa5dfed5bb198c66741c594e2c277ded88970 Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 28 Dec 2016 18:57:09 -0500 Subject: [PATCH 3/4] Towards fixing a 3.2 while true: ... break bug --- uncompyle6/parsers/parse3.py | 7 +++++++ uncompyle6/parsers/parse32.py | 5 +++++ uncompyle6/parsers/parse33.py | 5 ----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index ea1a0729..610b3b4b 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -696,12 +696,19 @@ class Python3Parser(PythonParser): self.check_reduce['augassign1'] = 'AST' self.check_reduce['augassign2'] = 'AST' self.check_reduce['while1stmt'] = 'noAST' + # FIXME: remove parser errors caused by the below + # self.check_reduce['while1elsestmt'] = 'noAST' return def reduce_is_invalid(self, rule, ast, tokens, first, last): lhs = rule[0] if lhs in ('augassign1', 'augassign2') and ast[0][0] == 'and': return True + elif lhs == 'while1elsestmt': + last += 1 + while isinstance(tokens[last], str): + last += 1 + return tokens[first].attr != tokens[last].offset elif lhs == 'while1stmt': if tokens[last] in ('COME_FROM_LOOP', 'JUMP_BACK'): # jump_back should be right afer SETUP_LOOP. Test? diff --git a/uncompyle6/parsers/parse32.py b/uncompyle6/parsers/parse32.py index 24d4e573..cac33810 100644 --- a/uncompyle6/parsers/parse32.py +++ b/uncompyle6/parsers/parse32.py @@ -19,6 +19,11 @@ class Python32Parser(Python3Parser): COME_FROM_LOOP whileTruestmt ::= SETUP_LOOP return_stmts COME_FROM_LOOP + + # Python 3.2+ has more loop optimization that removes + # JUMP_FORWARD in some cases, and hence we also don't + # see COME_FROM + _ifstmts_jump ::= c_stmts_opt """ pass diff --git a/uncompyle6/parsers/parse33.py b/uncompyle6/parsers/parse33.py index b310af61..990a914e 100644 --- a/uncompyle6/parsers/parse33.py +++ b/uncompyle6/parsers/parse33.py @@ -21,11 +21,6 @@ class Python33Parser(Python32Parser): iflaststmt ::= testexpr c_stmts_opt33 c_stmts_opt33 ::= JUMP_BACK JUMP_ABSOLUTE c_stmts_opt _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_from - - # Python 3.3+ has more loop optimization that removes - # JUMP_FORWARD in some cases, and hence we also don't - # see COME_FROM - _ifstmts_jump ::= c_stmts_opt """ class Python33ParserSingle(Python33Parser, PythonParserSingle): From 39814fab8b7421dfe79688b75c924fa05f397150 Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 28 Dec 2016 20:16:13 -0500 Subject: [PATCH 4/4] Misc bugs --- uncompyle6/parsers/parse3.py | 6 ++++-- uncompyle6/scanners/tok.py | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index 610b3b4b..32402864 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -705,10 +705,12 @@ class Python3Parser(PythonParser): if lhs in ('augassign1', 'augassign2') and ast[0][0] == 'and': return True elif lhs == 'while1elsestmt': + # if SETUP_LOOP target spans the else part, then this is + # not while1else. Also do for whileTrue? last += 1 - while isinstance(tokens[last], str): + while isinstance(tokens[last].offset, str): last += 1 - return tokens[first].attr != tokens[last].offset + return tokens[first].attr == tokens[last].offset elif lhs == 'while1stmt': if tokens[last] in ('COME_FROM_LOOP', 'JUMP_BACK'): # jump_back should be right afer SETUP_LOOP. Test? diff --git a/uncompyle6/scanners/tok.py b/uncompyle6/scanners/tok.py index fb1690fc..88b3a3b3 100644 --- a/uncompyle6/scanners/tok.py +++ b/uncompyle6/scanners/tok.py @@ -66,7 +66,8 @@ class Token: pattr = self.pattr if self.opc: if self.op in self.opc.hasjrel: - pattr = "to " + self.pattr + if not self.pattr.startswith('to '): + pattr = "to " + self.pattr elif self.op in self.opc.hasjabs: self.pattr= str(self.pattr) if not self.pattr.startswith('to '):