diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index e642d936..68e63fe6 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -30,6 +30,7 @@ import re from uncompyle6.scanners.tok import Token from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func from uncompyle6.parsers.reducecheck import ( + and_check, except_handler_else, ifstmt, # iflaststmt, @@ -1528,13 +1529,18 @@ class Python3Parser(PythonParser): pass pass + if self.version >= 3.1: + self.check_reduce["and"] = "AST" self.check_reduce["aug_assign1"] = "AST" self.check_reduce["aug_assign2"] = "AST" self.check_reduce["while1stmt"] = "noAST" self.check_reduce["while1elsestmt"] = "noAST" self.check_reduce["ifelsestmt"] = "AST" self.check_reduce["ifstmt"] = "AST" - # self.check_reduce["iflaststmtl"] = "AST" + if self.version >= 3.1: + if self.version != 3.5: + self.check_reduce["iflaststmt"] = "AST" + self.check_reduce["iflaststmtl"] = "AST" self.check_reduce["annotate_tuple"] = "noAST" self.check_reduce["except_handler_else"] = "tokens" self.check_reduce["testtrue"] = "tokens" @@ -1554,7 +1560,9 @@ class Python3Parser(PythonParser): lhs = rule[0] n = len(tokens) last = min(last, n-1) - if lhs in ("aug_assign1", "aug_assign2") and ast[0][0] == "and": + if lhs == "and": + return and_check(self, lhs, n, rule, ast, tokens, first, last) + elif lhs in ("aug_assign1", "aug_assign2") and ast[0][0] == "and": return True elif lhs == "annotate_tuple": return not isinstance(tokens[first].attr, tuple) @@ -1563,8 +1571,8 @@ class Python3Parser(PythonParser): elif lhs == "kwarg": arg = tokens[first].attr return not (isinstance(arg, str) or isinstance(arg, unicode)) - # elif lhs == "iflaststmtl": - # return iflaststmt(self, lhs, n, rule, ast, tokens, first, last) + elif lhs in ("iflaststmt", "iflaststmtl") and self.version >= 3.1: + return ifstmt(self, lhs, n, rule, ast, tokens, first, last) elif rule == ("ifstmt", ("testexpr", "_ifstmts_jump")): # FIXME: go over what's up with 3.0. Evetually I'd like to remove RETURN_END_IF if self.version <= 3.0 or tokens[last] == "RETURN_END_IF": diff --git a/uncompyle6/parsers/reducecheck/and_check.py b/uncompyle6/parsers/reducecheck/and_check.py index 333bb1ec..5e590821 100644 --- a/uncompyle6/parsers/reducecheck/and_check.py +++ b/uncompyle6/parsers/reducecheck/and_check.py @@ -14,6 +14,9 @@ def and_check(self, lhs, n, rule, ast, tokens, first, last): if rule == ("and", ("expr", "jmp_false", "expr", "jmp_false")): jmp2_target = ast[3][0].attr return jmp_target != jmp2_target + elif rule == ("and", ("expr", "jmp_false", "expr", "POP_JUMP_IF_TRUE")): + jmp2_target = ast[3].attr + return jmp_target == jmp2_target elif rule == ("and", ("expr", "jmp_false", "expr")): if tokens[last] == "POP_JUMP_IF_FALSE": # Ok if jump_target doesn't jump to last instruction diff --git a/uncompyle6/parsers/reducecheck/and_not_check.py b/uncompyle6/parsers/reducecheck/and_not_check.py new file mode 100644 index 00000000..a246e630 --- /dev/null +++ b/uncompyle6/parsers/reducecheck/and_not_check.py @@ -0,0 +1,19 @@ +# Copyright (c) 2020 Rocky Bernstein + + +def and_not_check( + self, lhs, n, rule, ast, tokens, first, last +) -> bool: + jmp = ast[1] + if jmp.kind.startswith("jmp_"): + if last == n: + return True + jmp_target = jmp[0].attr + + if tokens[first].off2int() <= jmp_target < tokens[last].off2int(): + return True + if rule == ("and_not", ("expr", "jmp_false", "expr", "POP_JUMP_IF_TRUE")): + jmp2_target = ast[3].attr + return jmp_target != jmp2_target + return jmp_target != tokens[last].off2int() + return False