You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
Add "if_not_and" rule similar to "if_not_or" rule.
This commit is contained in:
BIN
test/bytecode_3.6_run/02_if_not_or.pyc
Normal file
BIN
test/bytecode_3.6_run/02_if_not_or.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.7_run/02_if_not_or.pyc
Normal file
BIN
test/bytecode_3.7_run/02_if_not_or.pyc
Normal file
Binary file not shown.
43
test/simple_source/bug37/02_if_not_or.py
Normal file
43
test/simple_source/bug37/02_if_not_or.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# from 3.7 inspect.py
|
||||||
|
# Bug was "if not predicate or" inside "for".
|
||||||
|
# Jump optimization turns a POP_JUMP_IF_TRUE into
|
||||||
|
# a POP_JUMP_IF_FALSE and this has to be
|
||||||
|
# dealt with at the "if" (or actually "testfalse") level.
|
||||||
|
|
||||||
|
# RUNNABLE!
|
||||||
|
def getmembers(names, object, predicate):
|
||||||
|
for key in names:
|
||||||
|
if not predicate or object:
|
||||||
|
object = 2
|
||||||
|
object += 1
|
||||||
|
return object
|
||||||
|
|
||||||
|
assert getmembers([1], 0, False) == 3
|
||||||
|
assert getmembers([1], 1, True) == 3
|
||||||
|
assert getmembers([1], 0, True) == 1
|
||||||
|
assert getmembers([1], 1, False) == 3
|
||||||
|
assert getmembers([], 1, False) == 1
|
||||||
|
assert getmembers([], 2, True) == 2
|
||||||
|
|
||||||
|
def _shadowed_dict(klass, a, b, c):
|
||||||
|
for entry in klass:
|
||||||
|
if not (a and b):
|
||||||
|
c = 1
|
||||||
|
return c
|
||||||
|
|
||||||
|
assert _shadowed_dict([1], True, True, 3) == 3
|
||||||
|
assert _shadowed_dict([1], True, False, 3) == 1
|
||||||
|
assert _shadowed_dict([1], False, True, 3) == 1
|
||||||
|
assert _shadowed_dict([1], False, False, 3) == 1
|
||||||
|
assert _shadowed_dict([], False, False, 3) == 3
|
||||||
|
|
||||||
|
# Bug: the double "and" comes out as if .. if not and
|
||||||
|
def _shadowed_dict2(klass, a, b, c, d):
|
||||||
|
for entry in klass:
|
||||||
|
if not (a and b and c):
|
||||||
|
d = 1
|
||||||
|
return d
|
||||||
|
|
||||||
|
# Not yet --
|
||||||
|
# assert _shadowed_dict2([1], False, False, False, 3) == 1
|
||||||
|
# assert _shadowed_dict2([1], True, True, True, 3) == 3
|
@@ -954,13 +954,21 @@ class Python37Parser(Python37BaseParser):
|
|||||||
ret_cond ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF COME_FROM ret_expr_or_cond
|
ret_cond ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF COME_FROM ret_expr_or_cond
|
||||||
|
|
||||||
jitop_come_from ::= JUMP_IF_TRUE_OR_POP COME_FROM
|
jitop_come_from ::= JUMP_IF_TRUE_OR_POP COME_FROM
|
||||||
or ::= and jitop_come_from expr COME_FROM
|
or ::= and jitop_come_from expr COME_FROM
|
||||||
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
|
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
|
||||||
or ::= expr JUMP_IF_TRUE expr COME_FROM
|
or ::= expr JUMP_IF_TRUE expr COME_FROM
|
||||||
|
|
||||||
|
testfalse_not_or ::= expr jmp_false expr jmp_false COME_FROM
|
||||||
|
testfalse_not_and ::= and jmp_true come_froms
|
||||||
|
|
||||||
|
testfalse_not_and ::= expr jmp_false expr jmp_true COME_FROM
|
||||||
|
testfalse ::= testfalse_not_or
|
||||||
|
testfalse ::= testfalse_not_and
|
||||||
testfalse ::= or jmp_false COME_FROM
|
testfalse ::= or jmp_false COME_FROM
|
||||||
or ::= expr jmp_true expr
|
or ::= expr jmp_true expr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
||||||
and ::= expr JUMP_IF_FALSE expr COME_FROM
|
and ::= expr JUMP_IF_FALSE expr COME_FROM
|
||||||
and ::= expr jmp_false expr
|
and ::= expr jmp_false expr
|
||||||
|
@@ -1046,7 +1046,7 @@ class Python37BaseParser(PythonParser):
|
|||||||
if tokens[last] == "POP_JUMP_IF_FALSE":
|
if tokens[last] == "POP_JUMP_IF_FALSE":
|
||||||
# Ok if jump_target doesn't jump to last instruction
|
# Ok if jump_target doesn't jump to last instruction
|
||||||
return jmp_target != tokens[last].attr
|
return jmp_target != tokens[last].attr
|
||||||
elif tokens[last] == "JUMP_IF_TRUE_OR_POP":
|
elif tokens[last] in ("POP_JUMP_IF_TRUE", "JUMP_IF_TRUE_OR_POP"):
|
||||||
# Ok if jump_target jumps to a COME_FROM after
|
# Ok if jump_target jumps to a COME_FROM after
|
||||||
# the last instruction or jumps right after last instruction
|
# the last instruction or jumps right after last instruction
|
||||||
if last + 1 < n and tokens[last + 1] == "COME_FROM":
|
if last + 1 < n and tokens[last + 1] == "COME_FROM":
|
||||||
|
@@ -888,32 +888,6 @@ class Scanner37Base(Scanner):
|
|||||||
elif op in self.setup_opts_no_loop:
|
elif op in self.setup_opts_no_loop:
|
||||||
count_SETUP_ += 1
|
count_SETUP_ += 1
|
||||||
|
|
||||||
def rem_or(self, start, end, instr, target=None, include_beyond_target=False):
|
|
||||||
"""
|
|
||||||
Find offsets of all requested <instr> between <start> and <end>,
|
|
||||||
optionally <target>ing specified offset, and return list found
|
|
||||||
<instr> offsets which are not within any POP_JUMP_IF_TRUE jumps.
|
|
||||||
"""
|
|
||||||
assert start >= 0 and end <= len(self.code) and start <= end
|
|
||||||
|
|
||||||
# Find all offsets of requested instructions
|
|
||||||
instr_offsets = self.inst_matches(
|
|
||||||
start, end, instr, target, include_beyond_target
|
|
||||||
)
|
|
||||||
# Get all POP_JUMP_IF_TRUE (or) offsets
|
|
||||||
jump_true_op = self.opc.POP_JUMP_IF_TRUE
|
|
||||||
pjit_offsets = self.inst_matches(start, end, jump_true_op)
|
|
||||||
filtered = []
|
|
||||||
for pjit_offset in pjit_offsets:
|
|
||||||
pjit_tgt = self.get_target(pjit_offset) - 3
|
|
||||||
for instr_offset in instr_offsets:
|
|
||||||
if instr_offset <= pjit_offset or instr_offset >= pjit_tgt:
|
|
||||||
filtered.append(instr_offset)
|
|
||||||
instr_offsets = filtered
|
|
||||||
filtered = []
|
|
||||||
return instr_offsets
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from uncompyle6 import PYTHON_VERSION
|
from uncompyle6 import PYTHON_VERSION
|
||||||
|
|
||||||
|
@@ -67,5 +67,7 @@ def customize_for_version37(self, version):
|
|||||||
'%[3]{pattr.replace("-", " ")} %p %p', (0, 19), (6, 19) ),
|
'%[3]{pattr.replace("-", " ")} %p %p', (0, 19), (6, 19) ),
|
||||||
'if_exp_37a': ( '%p if %p else %p', (1, 'expr', 27), (0, 27), (4, 'expr', 27) ),
|
'if_exp_37a': ( '%p if %p else %p', (1, 'expr', 27), (0, 27), (4, 'expr', 27) ),
|
||||||
'if_exp_37b': ( '%p if %p else %p', (2, 'expr', 27), (0, 'expr', 27), (5, 'expr', 27) ),
|
'if_exp_37b': ( '%p if %p else %p', (2, 'expr', 27), (0, 'expr', 27), (5, 'expr', 27) ),
|
||||||
|
'testfalse_not_or': ( "not %c or %c",
|
||||||
|
(0, "expr"),
|
||||||
|
(2, "expr") ),
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user