You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
Merge branch 'master' into python-2.4
This commit is contained in:
13
NEWS
13
NEWS
@@ -1,4 +1,11 @@
|
|||||||
uncompyle6 2.15.0 2017-01-27
|
uncompyle6 2.15.0 2018-02-05 pycon2018.co
|
||||||
|
|
||||||
|
- Bug fixes
|
||||||
|
- Code fragment improvements
|
||||||
|
- Code cleanups
|
||||||
|
- Expand testing
|
||||||
|
|
||||||
|
uncompyle6 2.15.1 2018-01-27
|
||||||
|
|
||||||
- Add --linemap option to give line correspondences
|
- Add --linemap option to give line correspondences
|
||||||
between original source lines and reconstructed line sources.
|
between original source lines and reconstructed line sources.
|
||||||
@@ -10,7 +17,7 @@ uncompyle6 2.15.0 2017-01-27
|
|||||||
- Correct 3.6+ calls with kwargs
|
- Correct 3.6+ calls with kwargs
|
||||||
- Describe the difficulty of 3.6 in README
|
- Describe the difficulty of 3.6 in README
|
||||||
|
|
||||||
uncompyle6 2.14.3 2017-01-19
|
uncompyle6 2.14.3 2018-01-19
|
||||||
|
|
||||||
- Fix bug in 3.5+ await stmt
|
- Fix bug in 3.5+ await stmt
|
||||||
- Better version to magic handling; handle 3.5.2 .. 3.5.4 versions
|
- Better version to magic handling; handle 3.5.2 .. 3.5.4 versions
|
||||||
@@ -22,7 +29,7 @@ uncompyle6 2.14.3 2017-01-19
|
|||||||
- better tests in setup.py for running the right version of Python
|
- better tests in setup.py for running the right version of Python
|
||||||
- Fix 2.6- parsing of "for .. try/else" ... with "continue" inside
|
- Fix 2.6- parsing of "for .. try/else" ... with "continue" inside
|
||||||
|
|
||||||
uncompyle6 2.14.2 2017-01-09 Samish
|
uncompyle6 2.14.2 2018-01-09 Samish
|
||||||
|
|
||||||
Decompilation bug fixes, mostly 3.6 and pre 2.7
|
Decompilation bug fixes, mostly 3.6 and pre 2.7
|
||||||
|
|
||||||
|
@@ -74,8 +74,8 @@ def check_expect(expect, parsed, fn_name):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason='needs reworking')
|
|
||||||
def test_stuff():
|
def test_stuff():
|
||||||
|
return
|
||||||
parsed = get_parsed_for_fn(map_stmts)
|
parsed = get_parsed_for_fn(map_stmts)
|
||||||
expect = """
|
expect = """
|
||||||
-1
|
-1
|
||||||
|
@@ -29,6 +29,9 @@ def test_if_in_for():
|
|||||||
bytecode = Bytecode(code, scan.opc)
|
bytecode = Bytecode(code, scan.opc)
|
||||||
scan.build_lines_data(code, n)
|
scan.build_lines_data(code, n)
|
||||||
scan.insts = list(bytecode)
|
scan.insts = list(bytecode)
|
||||||
|
scan.offset2inst_index = {}
|
||||||
|
for i, inst in enumerate(scan.insts):
|
||||||
|
scan.offset2inst_index[inst.offset] = i
|
||||||
scan.build_prev_op(n)
|
scan.build_prev_op(n)
|
||||||
fjt = scan.find_jump_targets(False)
|
fjt = scan.find_jump_targets(False)
|
||||||
|
|
||||||
@@ -45,8 +48,13 @@ def test_if_in_for():
|
|||||||
|
|
||||||
code = bug_loop.__code__
|
code = bug_loop.__code__
|
||||||
n = scan.setup_code(code)
|
n = scan.setup_code(code)
|
||||||
|
bytecode = Bytecode(code, scan.opc)
|
||||||
scan.build_lines_data(code, n)
|
scan.build_lines_data(code, n)
|
||||||
|
scan.insts = list(bytecode)
|
||||||
scan.build_prev_op(n)
|
scan.build_prev_op(n)
|
||||||
|
scan.offset2inst_index = {}
|
||||||
|
for i, inst in enumerate(scan.insts):
|
||||||
|
scan.offset2inst_index[inst.offset] = i
|
||||||
fjt = scan.find_jump_targets(False)
|
fjt = scan.find_jump_targets(False)
|
||||||
assert{64: [42], 67: [42, 42], 42: [16, 41], 19: [6]} == fjt
|
assert{64: [42], 67: [42, 42], 42: [16, 41], 19: [6]} == fjt
|
||||||
assert scan.structs == [
|
assert scan.structs == [
|
||||||
|
BIN
test/bytecode_2.7/05_while_if_return.pyc-notyet
Normal file
BIN
test/bytecode_2.7/05_while_if_return.pyc-notyet
Normal file
Binary file not shown.
10
test/simple_source/bug27+/05_while_if_return.py
Normal file
10
test/simple_source/bug27+/05_while_if_return.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Issue #149. Bug in Python 2.7 was handling a return stmt at the end
|
||||||
|
# of a while with so no jump back, confusing which block the
|
||||||
|
# return should be part of
|
||||||
|
def test(a):
|
||||||
|
while True:
|
||||||
|
if a:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
return
|
@@ -170,8 +170,9 @@ def main_bin():
|
|||||||
try:
|
try:
|
||||||
result = main(src_base, out_base, files, codes, outfile,
|
result = main(src_base, out_base, files, codes, outfile,
|
||||||
**options)
|
**options)
|
||||||
|
result = list(result) + [options.get('do_verify', None)]
|
||||||
if len(files) > 1:
|
if len(files) > 1:
|
||||||
mess = status_msg(do_verify, result, do_verify)
|
mess = status_msg(do_verify, *result)
|
||||||
print('# ' + mess)
|
print('# ' + mess)
|
||||||
pass
|
pass
|
||||||
except (KeyboardInterrupt):
|
except (KeyboardInterrupt):
|
||||||
|
@@ -207,7 +207,7 @@ def main(in_base, out_base, files, codes, outfile=None,
|
|||||||
for d in deparsed:
|
for d in deparsed:
|
||||||
last_mod = None
|
last_mod = None
|
||||||
offsets = d.offsets
|
offsets = d.offsets
|
||||||
for e in sorted(offsets.keys()):
|
for e in sorted([k for k in offsets.keys() if isinstance(k[1], int)]):
|
||||||
if e[0] != last_mod:
|
if e[0] != last_mod:
|
||||||
line = '=' * len(e[0])
|
line = '=' * len(e[0])
|
||||||
outstream.write("%s\n%s\n%s\n" % (line, e[0], line))
|
outstream.write("%s\n%s\n%s\n" % (line, e[0], line))
|
||||||
|
@@ -119,7 +119,8 @@ class Python27Parser(Python2Parser):
|
|||||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||||
WITH_CLEANUP END_FINALLY
|
WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
whilestmt ::= SETUP_LOOP testexpr returns POP_BLOCK COME_FROM
|
whilestmt ::= SETUP_LOOP testexpr returns
|
||||||
|
_come_froms POP_BLOCK COME_FROM
|
||||||
|
|
||||||
while1stmt ::= SETUP_LOOP returns bp_come_from
|
while1stmt ::= SETUP_LOOP returns bp_come_from
|
||||||
while1stmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK COME_FROM
|
while1stmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK COME_FROM
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2015-2017 by Rocky Bernstein
|
# Copyright (c) 2015-2018 by Rocky Bernstein
|
||||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
"""
|
"""
|
||||||
@@ -113,7 +113,11 @@ class Scanner2(Scanner):
|
|||||||
|
|
||||||
self.build_lines_data(co, codelen)
|
self.build_lines_data(co, codelen)
|
||||||
self.build_prev_op(codelen)
|
self.build_prev_op(codelen)
|
||||||
|
|
||||||
self.insts = list(bytecode)
|
self.insts = list(bytecode)
|
||||||
|
self.offset2inst_index = {}
|
||||||
|
for i, inst in enumerate(self.insts):
|
||||||
|
self.offset2inst_index[inst.offset] = i
|
||||||
|
|
||||||
free, names, varnames = self.unmangle_code_names(co, classname)
|
free, names, varnames = self.unmangle_code_names(co, classname)
|
||||||
self.names = names
|
self.names = names
|
||||||
@@ -510,50 +514,55 @@ class Scanner2(Scanner):
|
|||||||
# Try to find the jump_back instruction of the loop.
|
# Try to find the jump_back instruction of the loop.
|
||||||
# It could be a return instruction.
|
# It could be a return instruction.
|
||||||
|
|
||||||
|
inst = self.insts[self.offset2inst_index[offset]]
|
||||||
start += instruction_size(op, self.opc)
|
start += instruction_size(op, self.opc)
|
||||||
target = self.get_target(offset) + extended_arg
|
setup_target = inst.argval
|
||||||
end = self.restrict_to_parent(target, parent)
|
loop_end_offset = self.restrict_to_parent(setup_target, parent)
|
||||||
self.setup_loop_targets[offset] = target
|
self.setup_loop_targets[offset] = setup_target
|
||||||
self.setup_loops[target] = offset
|
self.setup_loops[setup_target] = offset
|
||||||
|
|
||||||
if target != end:
|
if setup_target != loop_end_offset:
|
||||||
self.fixed_jumps[offset] = end
|
self.fixed_jumps[offset] = loop_end_offset
|
||||||
|
|
||||||
(line_no, next_line_byte) = self.lines[offset]
|
(line_no, next_line_byte) = self.lines[offset]
|
||||||
jump_back = self.last_instr(start, end, self.opc.JUMP_ABSOLUTE,
|
|
||||||
|
# jump_back_offset is the instruction after the SETUP_LOOP
|
||||||
|
# where we iterate back to.
|
||||||
|
jump_back_offset = self.last_instr(start, loop_end_offset, self.opc.JUMP_ABSOLUTE,
|
||||||
next_line_byte, False)
|
next_line_byte, False)
|
||||||
|
|
||||||
if jump_back:
|
if jump_back_offset:
|
||||||
# Account for the fact that < 2.7 has an explicit
|
# Account for the fact that < 2.7 has an explicit
|
||||||
# POP_TOP instruction in the equivalate POP_JUMP_IF
|
# POP_TOP instruction in the equivalate POP_JUMP_IF
|
||||||
# construct
|
# construct
|
||||||
if self.version < 2.7:
|
if self.version < 2.7:
|
||||||
jump_forward_offset = jump_back+4
|
jump_forward_offset = jump_back_offset+4
|
||||||
return_val_offset1 = self.prev[self.prev[self.prev[end]]]
|
return_val_offset1 = self.prev[self.prev[self.prev[loop_end_offset]]]
|
||||||
# Is jump back really "back"?
|
# Is jump back really "back"?
|
||||||
jump_target = self.get_target(jump_back, code[jump_back])
|
jump_target = self.get_target(jump_back_offset, code[jump_back_offset])
|
||||||
if (jump_target > jump_back or
|
if (jump_target > jump_back_offset or
|
||||||
code[jump_back+3] in [self.opc.JUMP_FORWARD, self.opc.JUMP_ABSOLUTE]):
|
code[jump_back_offset+3] in [self.opc.JUMP_FORWARD, self.opc.JUMP_ABSOLUTE]):
|
||||||
jump_back = None
|
jump_back_offset = None
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
jump_forward_offset = jump_back+3
|
jump_forward_offset = jump_back_offset+3
|
||||||
return_val_offset1 = self.prev[self.prev[end]]
|
return_val_offset1 = self.prev[self.prev[loop_end_offset]]
|
||||||
|
|
||||||
if (jump_back and jump_back != self.prev[end]
|
if (jump_back_offset and jump_back_offset != self.prev[loop_end_offset]
|
||||||
and code[jump_forward_offset] in self.jump_forward):
|
and code[jump_forward_offset] in self.jump_forward):
|
||||||
if (code[self.prev[end]] == self.opc.RETURN_VALUE or
|
if (code[self.prev[loop_end_offset]] == self.opc.RETURN_VALUE or
|
||||||
(code[self.prev[end]] == self.opc.POP_BLOCK
|
(code[self.prev[loop_end_offset]] == self.opc.POP_BLOCK
|
||||||
and code[return_val_offset1] == self.opc.RETURN_VALUE)):
|
and code[return_val_offset1] == self.opc.RETURN_VALUE)):
|
||||||
jump_back = None
|
jump_back_offset = None
|
||||||
if not jump_back:
|
|
||||||
|
if not jump_back_offset:
|
||||||
# loop suite ends in return
|
# loop suite ends in return
|
||||||
# scanner26 of wbiti had:
|
# scanner26 of wbiti had:
|
||||||
# jump_back = self.last_instr(start, end, self.opc.JUMP_ABSOLUTE, start, False)
|
# jump_back_offset = self.last_instr(start, loop_end_offset, self.opc.JUMP_ABSOLUTE, start, False)
|
||||||
jump_back = self.last_instr(start, end, self.opc.RETURN_VALUE)
|
jump_back_offset = self.last_instr(start, loop_end_offset, self.opc.RETURN_VALUE)
|
||||||
if not jump_back:
|
if not jump_back_offset:
|
||||||
return
|
return
|
||||||
jump_back += 1
|
jump_back_offset += 1
|
||||||
|
|
||||||
if_offset = None
|
if_offset = None
|
||||||
if self.version < 2.7:
|
if self.version < 2.7:
|
||||||
@@ -569,71 +578,76 @@ class Scanner2(Scanner):
|
|||||||
loop_type = 'while'
|
loop_type = 'while'
|
||||||
self.ignore_if.add(if_offset)
|
self.ignore_if.add(if_offset)
|
||||||
if self.version < 2.7 and (
|
if self.version < 2.7 and (
|
||||||
code[self.prev[jump_back]] == self.opc.RETURN_VALUE):
|
code[self.prev[jump_back_offset]] == self.opc.RETURN_VALUE):
|
||||||
self.ignore_if.add(self.prev[jump_back])
|
self.ignore_if.add(self.prev[jump_back_offset])
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
loop_type = 'for'
|
loop_type = 'for'
|
||||||
target = next_line_byte
|
setup_target = next_line_byte
|
||||||
end = jump_back + 3
|
loop_end_offset = jump_back_offset + 3
|
||||||
else:
|
else:
|
||||||
if self.get_target(jump_back) >= next_line_byte:
|
# We have a loop with a jump-back instruction
|
||||||
jump_back = self.last_instr(start, end, self.opc.JUMP_ABSOLUTE, start, False)
|
if self.get_target(jump_back_offset) >= next_line_byte:
|
||||||
if end > jump_back+4 and code[end] in self.jump_forward:
|
jump_back_offset = self.last_instr(start, loop_end_offset, self.opc.JUMP_ABSOLUTE, start, False)
|
||||||
if code[jump_back+4] in self.jump_forward:
|
if loop_end_offset > jump_back_offset+4 and code[loop_end_offset] in self.jump_forward:
|
||||||
if self.get_target(jump_back+4) == self.get_target(end):
|
if code[jump_back_offset+4] in self.jump_forward:
|
||||||
self.fixed_jumps[offset] = jump_back+4
|
if self.get_target(jump_back_offset+4) == self.get_target(loop_end_offset):
|
||||||
end = jump_back+4
|
self.fixed_jumps[offset] = jump_back_offset+4
|
||||||
elif target < offset:
|
loop_end_offset = jump_back_offset+4
|
||||||
self.fixed_jumps[offset] = jump_back+4
|
elif setup_target < offset:
|
||||||
end = jump_back+4
|
self.fixed_jumps[offset] = jump_back_offset+4
|
||||||
|
loop_end_offset = jump_back_offset+4
|
||||||
|
|
||||||
target = self.get_target(jump_back, self.opc.JUMP_ABSOLUTE)
|
setup_target = self.get_target(jump_back_offset, self.opc.JUMP_ABSOLUTE)
|
||||||
|
|
||||||
if (self.version > 2.1 and
|
if (self.version > 2.1 and
|
||||||
code[target] in (self.opc.FOR_ITER, self.opc.GET_ITER)):
|
code[setup_target] in (self.opc.FOR_ITER, self.opc.GET_ITER)):
|
||||||
loop_type = 'for'
|
loop_type = 'for'
|
||||||
else:
|
else:
|
||||||
loop_type = 'while'
|
loop_type = 'while'
|
||||||
|
# Look for a test condition immediately after the
|
||||||
|
# SETUP_LOOP while
|
||||||
if (self.version < 2.7
|
if (self.version < 2.7
|
||||||
and self.code[self.prev[next_line_byte]] == self.opc.POP_TOP):
|
and self.code[self.prev[next_line_byte]] == self.opc.POP_TOP):
|
||||||
test = self.prev[self.prev[next_line_byte]]
|
test_op_offset = self.prev[self.prev[next_line_byte]]
|
||||||
else:
|
else:
|
||||||
test = self.prev[next_line_byte]
|
test_op_offset = self.prev[next_line_byte]
|
||||||
|
|
||||||
if test == offset:
|
if test_op_offset == offset:
|
||||||
loop_type = 'while 1'
|
loop_type = 'while 1'
|
||||||
elif self.code[test] in self.opc.JUMP_OPs:
|
elif self.code[test_op_offset] in self.opc.JUMP_OPs:
|
||||||
self.ignore_if.add(test)
|
test_target = self.get_target(test_op_offset)
|
||||||
test_target = self.get_target(test)
|
|
||||||
if test_target > (jump_back+3):
|
self.ignore_if.add(test_op_offset)
|
||||||
jump_back = test_target
|
|
||||||
self.not_continue.add(jump_back)
|
if test_target > (jump_back_offset+3):
|
||||||
self.loops.append(target)
|
jump_back_offset = test_target
|
||||||
|
self.not_continue.add(jump_back_offset)
|
||||||
|
self.loops.append(setup_target)
|
||||||
self.structs.append({'type': loop_type + '-loop',
|
self.structs.append({'type': loop_type + '-loop',
|
||||||
'start': target,
|
'start': setup_target,
|
||||||
'end': jump_back})
|
'end': jump_back_offset})
|
||||||
if jump_back+3 != end:
|
if jump_back_offset+3 != loop_end_offset:
|
||||||
self.structs.append({'type': loop_type + '-else',
|
self.structs.append({'type': loop_type + '-else',
|
||||||
'start': jump_back+3,
|
'start': jump_back_offset+3,
|
||||||
'end': end})
|
'end': loop_end_offset})
|
||||||
elif op == self.opc.SETUP_EXCEPT:
|
elif op == self.opc.SETUP_EXCEPT:
|
||||||
start = offset + op_size(op, self.opc)
|
start = offset + op_size(op, self.opc)
|
||||||
target = self.get_target(offset, op)
|
target = self.get_target(offset, op)
|
||||||
end = self.restrict_to_parent(target, parent)
|
end_offset = self.restrict_to_parent(target, parent)
|
||||||
if target != end:
|
if target != end_offset:
|
||||||
self.fixed_jumps[offset] = end
|
self.fixed_jumps[offset] = end_offset
|
||||||
# print target, end, parent
|
# print target, end, parent
|
||||||
# Add the try block
|
# Add the try block
|
||||||
self.structs.append({'type': 'try',
|
self.structs.append({'type': 'try',
|
||||||
'start': start-3,
|
'start': start-3,
|
||||||
'end': end-4})
|
'end': end_offset-4})
|
||||||
# Now isolate the except and else blocks
|
# Now isolate the except and else blocks
|
||||||
end_else = start_else = self.get_target(self.prev[end])
|
end_else = start_else = self.get_target(self.prev[end_offset])
|
||||||
|
|
||||||
|
|
||||||
end_finally_offset = end
|
end_finally_offset = end_offset
|
||||||
setup_except_nest = 0
|
setup_except_nest = 0
|
||||||
while end_finally_offset < len(self.code):
|
while end_finally_offset < len(self.code):
|
||||||
if self.code[end_finally_offset] == self.opc.END_FINALLY:
|
if self.code[end_finally_offset] == self.opc.END_FINALLY:
|
||||||
@@ -647,7 +661,7 @@ class Scanner2(Scanner):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# Add the except blocks
|
# Add the except blocks
|
||||||
i = end
|
i = end_offset
|
||||||
while i < len(self.code) and i < end_finally_offset:
|
while i < len(self.code) and i < end_finally_offset:
|
||||||
jmp = self.next_except_jump(i)
|
jmp = self.next_except_jump(i)
|
||||||
if jmp is None: # check
|
if jmp is None: # check
|
||||||
@@ -705,7 +719,7 @@ class Scanner2(Scanner):
|
|||||||
|
|
||||||
test_target = target
|
test_target = target
|
||||||
if self.version < 2.7:
|
if self.version < 2.7:
|
||||||
# Before 2.6 we have to deal with the fact that there is an extra
|
# Before 2.7 we have to deal with the fact that there is an extra
|
||||||
# POP_TOP that is logically associated with the JUMP_IF's (even though
|
# POP_TOP that is logically associated with the JUMP_IF's (even though
|
||||||
# the instance set is called "self.pop_jump_if")
|
# the instance set is called "self.pop_jump_if")
|
||||||
if code[pre[test_target]] == self.opc.POP_TOP:
|
if code[pre[test_target]] == self.opc.POP_TOP:
|
||||||
@@ -715,22 +729,29 @@ class Scanner2(Scanner):
|
|||||||
test_set = self.pop_jump_if_or_pop | self.pop_jump_if
|
test_set = self.pop_jump_if_or_pop | self.pop_jump_if
|
||||||
|
|
||||||
if ( code[pre[test_target]] in test_set and target > offset ):
|
if ( code[pre[test_target]] in test_set and target > offset ):
|
||||||
|
# We have POP_JUMP_IF... target
|
||||||
|
# ...
|
||||||
|
# pre: POP_JUMP_IF ...
|
||||||
|
# target: ...
|
||||||
|
#
|
||||||
|
# We will take that as either as "and" or "or".
|
||||||
self.fixed_jumps[offset] = pre[target]
|
self.fixed_jumps[offset] = pre[target]
|
||||||
self.structs.append({'type': 'and/or',
|
self.structs.append({'type': 'and/or',
|
||||||
'start': start,
|
'start': start,
|
||||||
'end': pre[target]})
|
'end': pre[target]})
|
||||||
return
|
return
|
||||||
|
|
||||||
# The op offset just before the target jump offset is important
|
# The instruction offset just before the target jump offset is important
|
||||||
# in making a determination of what we have. Save that.
|
# in making a determination of what we have. Save that.
|
||||||
pre_rtarget = pre[rtarget]
|
pre_rtarget = pre[rtarget]
|
||||||
|
|
||||||
# Is it an "and" inside an "if" or "while" block
|
# Is it an "and" inside an "if" or "while" block
|
||||||
if op == self.opc.PJIF:
|
if op == self.opc.PJIF:
|
||||||
|
|
||||||
# Search for other POP_JUMP_IF_FALSE targetting the same op,
|
# Search for other POP_JUMP_IF_...'s targetting the
|
||||||
# in current statement, starting from current offset, and filter
|
# same target, of the current POP_JUMP_... instruction,
|
||||||
# everything inside inner 'or' jumps and midline ifs
|
# starting from current offset, and filter everything inside inner 'or'
|
||||||
|
# jumps and mid-line ifs
|
||||||
match = self.rem_or(start, self.next_stmt[offset], self.opc.PJIF, target)
|
match = self.rem_or(start, self.next_stmt[offset], self.opc.PJIF, target)
|
||||||
|
|
||||||
# If we still have any offsets in set, start working on it
|
# If we still have any offsets in set, start working on it
|
||||||
@@ -829,7 +850,7 @@ class Scanner2(Scanner):
|
|||||||
# JUMP_FORWARD
|
# JUMP_FORWARD
|
||||||
# HERE:
|
# HERE:
|
||||||
#
|
#
|
||||||
# If so, this can be block inside an "if" statement
|
# If so, this can be a block inside an "if" statement
|
||||||
# or a conditional assignment like:
|
# or a conditional assignment like:
|
||||||
# x = 1 if x else 2
|
# x = 1 if x else 2
|
||||||
#
|
#
|
||||||
@@ -860,7 +881,7 @@ class Scanner2(Scanner):
|
|||||||
self.fixed_jumps[jump_if_offset] = jump_target
|
self.fixed_jumps[jump_if_offset] = jump_target
|
||||||
return
|
return
|
||||||
|
|
||||||
end = self.restrict_to_parent(if_end, parent)
|
end_offset = self.restrict_to_parent(if_end, parent)
|
||||||
|
|
||||||
if_then_maybe = None
|
if_then_maybe = None
|
||||||
|
|
||||||
@@ -899,7 +920,7 @@ class Scanner2(Scanner):
|
|||||||
self.structs.append({'type': 'if-then',
|
self.structs.append({'type': 'if-then',
|
||||||
'start': start-3,
|
'start': start-3,
|
||||||
'end': pre_rtarget})
|
'end': pre_rtarget})
|
||||||
self.thens[start] = end
|
self.thens[start] = end_offset
|
||||||
elif jump_op == 'JUMP_ABSOLUTE':
|
elif jump_op == 'JUMP_ABSOLUTE':
|
||||||
if_then_maybe = {'type': 'if-then',
|
if_then_maybe = {'type': 'if-then',
|
||||||
'start': start-3,
|
'start': start-3,
|
||||||
@@ -914,7 +935,7 @@ class Scanner2(Scanner):
|
|||||||
if pre_rtarget not in self.linestartoffsets or self.version < 2.7:
|
if pre_rtarget not in self.linestartoffsets or self.version < 2.7:
|
||||||
self.not_continue.add(pre_rtarget)
|
self.not_continue.add(pre_rtarget)
|
||||||
|
|
||||||
if rtarget < end:
|
if rtarget < end_offset:
|
||||||
# We have an "else" block of some kind.
|
# We have an "else" block of some kind.
|
||||||
# Is it associated with "if_then_maybe" seen above?
|
# Is it associated with "if_then_maybe" seen above?
|
||||||
# These will be linked in this funny way:
|
# These will be linked in this funny way:
|
||||||
@@ -930,15 +951,15 @@ class Scanner2(Scanner):
|
|||||||
# 256
|
# 256
|
||||||
if if_then_maybe and jump_op == 'JUMP_ABSOLUTE':
|
if if_then_maybe and jump_op == 'JUMP_ABSOLUTE':
|
||||||
jump_target = self.get_target(jump_inst, code[jump_inst])
|
jump_target = self.get_target(jump_inst, code[jump_inst])
|
||||||
if self.opname_for_offset(end) == 'JUMP_FORWARD':
|
if self.opname_for_offset(end_offset) == 'JUMP_FORWARD':
|
||||||
end_target = self.get_target(end, code[end])
|
end_target = self.get_target(end_offset, code[end_offset])
|
||||||
if jump_target == end_target:
|
if jump_target == end_target:
|
||||||
self.structs.append(if_then_maybe)
|
self.structs.append(if_then_maybe)
|
||||||
self.thens[start] = end
|
self.thens[start] = end_offset
|
||||||
|
|
||||||
self.structs.append({'type': 'else',
|
self.structs.append({'type': 'else',
|
||||||
'start': rtarget,
|
'start': rtarget,
|
||||||
'end': end})
|
'end': end_offset})
|
||||||
elif code_pre_rtarget == self.opc.RETURN_VALUE:
|
elif code_pre_rtarget == self.opc.RETURN_VALUE:
|
||||||
if self.version == 2.7 or pre_rtarget not in self.ignore_if:
|
if self.version == 2.7 or pre_rtarget not in self.ignore_if:
|
||||||
# 10 is exception-match. If there is an exception match in the
|
# 10 is exception-match. If there is an exception match in the
|
||||||
|
@@ -110,7 +110,11 @@ class Scanner26(scan.Scanner2):
|
|||||||
|
|
||||||
self.build_lines_data(co, codelen)
|
self.build_lines_data(co, codelen)
|
||||||
self.build_prev_op(codelen)
|
self.build_prev_op(codelen)
|
||||||
|
|
||||||
self.insts = list(bytecode)
|
self.insts = list(bytecode)
|
||||||
|
self.offset2inst_index = {}
|
||||||
|
for i, inst in enumerate(self.insts):
|
||||||
|
self.offset2inst_index[inst.offset] = i
|
||||||
|
|
||||||
free, names, varnames = self.unmangle_code_names(co, classname)
|
free, names, varnames = self.unmangle_code_names(co, classname)
|
||||||
self.names = names
|
self.names = names
|
||||||
|
@@ -258,13 +258,13 @@ TABLE_DIRECT = {
|
|||||||
'while1elsestmt': ( '%|while 1:\n%+%c%-%|else:\n%+%c%-\n\n', 1, -2 ),
|
'while1elsestmt': ( '%|while 1:\n%+%c%-%|else:\n%+%c%-\n\n', 1, -2 ),
|
||||||
'whileelsestmt': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-\n\n', 1, 2, -2 ),
|
'whileelsestmt': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-\n\n', 1, 2, -2 ),
|
||||||
'whileelselaststmt': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-', 1, 2, -2 ),
|
'whileelselaststmt': ( '%|while %c:\n%+%c%-%|else:\n%+%c%-', 1, 2, -2 ),
|
||||||
'for': ( '%|for %c in %c:\n%+%c%-\n\n', 3, 1, 4 ),
|
'for': ( '%|for %c in %c:\n%+%c%-\n\n', (3, 'store'), 1, 4 ),
|
||||||
'forelsestmt': (
|
'forelsestmt': (
|
||||||
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n', 3, 1, 4, -2 ),
|
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n', (3, 'store'), 1, 4, -2 ),
|
||||||
'forelselaststmt': (
|
'forelselaststmt': (
|
||||||
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-', 3, 1, 4, -2 ),
|
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-', (3, 'store'), 1, 4, -2 ),
|
||||||
'forelselaststmtl': (
|
'forelselaststmtl': (
|
||||||
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n', 3, 1, 4, -2 ),
|
'%|for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n', (3, 'store'), 1, 4, -2 ),
|
||||||
'try_except': ( '%|try:\n%+%c%-%c\n\n', 1, 3 ),
|
'try_except': ( '%|try:\n%+%c%-%c\n\n', 1, 3 ),
|
||||||
'tryelsestmt': ( '%|try:\n%+%c%-%c%|else:\n%+%c%-\n\n', 1, 3, 4 ),
|
'tryelsestmt': ( '%|try:\n%+%c%-%c%|else:\n%+%c%-\n\n', 1, 3, 4 ),
|
||||||
'tryelsestmtc': ( '%|try:\n%+%c%-%c%|else:\n%+%c%-', 1, 3, 4 ),
|
'tryelsestmtc': ( '%|try:\n%+%c%-%c%|else:\n%+%c%-', 1, 3, 4 ),
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
# Copyright (c) 2015-2018 by Rocky Bernstein
|
# Copyright (c) 2015-2018 by Rocky Bernstein
|
||||||
# Copyright (c) 1999 John Aycock
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Creates Python source code from an uncompyle6 abstract syntax tree,
|
Creates Python source code from an uncompyle6 abstract syntax tree,
|
||||||
@@ -15,12 +14,13 @@ We add some format specifiers here not used in pysource
|
|||||||
-----
|
-----
|
||||||
|
|
||||||
%x takes an argument (src, (dest...)) and copies all of the range attributes
|
%x takes an argument (src, (dest...)) and copies all of the range attributes
|
||||||
from src to dest.
|
from src to all nodes under dest.
|
||||||
|
|
||||||
For example in:
|
For example in:
|
||||||
'import': ( '%|import %c%x\n', 2, (2,(0,1)), ),
|
'import': ( '%|import %c%x\n', 2, (2,(0,1)), ),
|
||||||
|
|
||||||
node 2 range information, it in %c, is copied to nodes 0 and 1.
|
node 2 range information, it in %c, is copied to nodes 0 and 1. If
|
||||||
|
1. is a nonterminal, all the nodes under it get node2 range information.
|
||||||
|
|
||||||
2. %r
|
2. %r
|
||||||
-----
|
-----
|
||||||
@@ -43,7 +43,7 @@ do it recursively which is where offsets are probably located.
|
|||||||
|
|
||||||
For example in:
|
For example in:
|
||||||
'importmultiple': ( '%|import%b %c%c\n', 0, 2, 3 ),
|
'importmultiple': ( '%|import%b %c%c\n', 0, 2, 3 ),
|
||||||
n
|
|
||||||
The node position 0 will be associated with "import".
|
The node position 0 will be associated with "import".
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -99,17 +99,22 @@ TABLE_DIRECT_FRAGMENT = {
|
|||||||
'importmultiple': ( '%|import%b %c%c\n', 0, 2, 3 ),
|
'importmultiple': ( '%|import%b %c%c\n', 0, 2, 3 ),
|
||||||
|
|
||||||
'list_for': (' for %c%x in %c%c', 2, (2, (1, )), 0, 3 ),
|
'list_for': (' for %c%x in %c%c', 2, (2, (1, )), 0, 3 ),
|
||||||
'forelsestmt': (
|
'for':
|
||||||
'%|for %c%x in %c:\n%+%c%-%|else:\n%+%c%-\n\n', 3, (3, (2,)), 1, 4, -2),
|
('%|for%b %c%x in %c:\n%+%c%-\n\n',
|
||||||
'forelselaststmt': (
|
0, (3, 'store'), (3, (2,)), 1, 4 ),
|
||||||
'%|for %c%x in %c:\n%+%c%-%|else:\n%+%c%-', 3, (3, (2,)), 1, 4, -2),
|
'forelsestmt':
|
||||||
'forelselaststmtl': (
|
('%|for%b %c%x in %c:\n%+%c%-%|else:\n%+%c%-\n\n',
|
||||||
'%|for %c%x in %c:\n%+%c%-%|else:\n%+%c%-\n\n', 3, (3, (2, )), 1, 4, -2),
|
0, (3, 'store'), (3, (2,)), 1, 4, -2),
|
||||||
|
'forelselaststmt':
|
||||||
|
('%|for%b %c%x in %c:\n%+%c%-%|else:\n%+%c%-',
|
||||||
|
0, (3, 'store'), (3, (2,)), 1, 4, -2),
|
||||||
|
'forelselaststmtl':
|
||||||
|
('%|for%b %c%x in %c:\n%+%c%-%|else:\n%+%c%-\n\n',
|
||||||
|
0, (3, 'store'), (3, (2,)), 1, 4, -2),
|
||||||
|
|
||||||
'whilestmt': ( '%|while%b %c:\n%+%c%-\n\n', 0, 1, 2 ),
|
'whilestmt': ( '%|while%b %c:\n%+%c%-\n\n', 0, 1, 2 ),
|
||||||
'whileelsestmt': ( '%|while%b %c:\n%+%c%-%|else:\n%+%c%-\n\n', 0, 1, 2, -2 ),
|
'whileelsestmt': ( '%|while%b %c:\n%+%c%-%|else:\n%+%c%-\n\n', 0, 1, 2, -2 ),
|
||||||
'whileelselaststmt': ( '%|while%b %c:\n%+%c%-%|else:\n%+%c%-', 0, 1, 2, -2 ),
|
'whileelselaststmt': ( '%|while%b %c:\n%+%c%-%|else:\n%+%c%-', 0, 1, 2, -2 ),
|
||||||
'for': ( '%|for%b %c in %c:\n%+%c%-\n\n', 0, 3, 1, 4 ),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -207,12 +212,55 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
self.default(node)
|
self.default(node)
|
||||||
|
|
||||||
def n_try_except(self, node):
|
def n_try_except(self, node):
|
||||||
|
# Note: we could also do this via modifying the
|
||||||
|
# 5 or so template rules. That is change:
|
||||||
|
# 'try_except': ( '%|try%:\n%+%c%-%c\n\n', 1, 3 ),
|
||||||
|
# to:
|
||||||
|
# 'try_except': ( '%|try%b:\n%+%c%-%c\n\n', 0, 1, 3 ),
|
||||||
|
|
||||||
start = len(self.f.getvalue()) + len(self.indent)
|
start = len(self.f.getvalue()) + len(self.indent)
|
||||||
self.set_pos_info(node[0], start, start+len("try:"))
|
self.set_pos_info(node[0], start, start+len("try:"))
|
||||||
self.default(node)
|
self.default(node)
|
||||||
|
|
||||||
n_tryelsestmt = n_tryelsestmtc = n_tryelsestmtl = n_tryfinallystmt = n_try_except
|
n_tryelsestmt = n_tryelsestmtc = n_tryelsestmtl = n_tryfinallystmt = n_try_except
|
||||||
|
|
||||||
|
def n_raise_stmt0(self, node):
|
||||||
|
assert node[0] == 'RAISE_VARARGS_0'
|
||||||
|
start = len(self.f.getvalue()) + len(self.indent)
|
||||||
|
try:
|
||||||
|
self.default(node)
|
||||||
|
except GenericASTTraversalPruningException:
|
||||||
|
self.set_pos_info(node[0], start, len(self.f.getvalue()))
|
||||||
|
self.prune()
|
||||||
|
|
||||||
|
def n_raise_stmt1(self, node):
|
||||||
|
assert node[1] == 'RAISE_VARARGS_1'
|
||||||
|
start = len(self.f.getvalue()) + len(self.indent)
|
||||||
|
try:
|
||||||
|
self.default(node)
|
||||||
|
except GenericASTTraversalPruningException:
|
||||||
|
self.set_pos_info(node[1], start, len(self.f.getvalue()))
|
||||||
|
self.prune()
|
||||||
|
|
||||||
|
def n_raise_stmt2(self, node):
|
||||||
|
assert node[2] == 'RAISE_VARARGS_2'
|
||||||
|
start = len(self.f.getvalue()) + len(self.indent)
|
||||||
|
try:
|
||||||
|
self.default(node)
|
||||||
|
except GenericASTTraversalPruningException:
|
||||||
|
self.set_pos_info(node[2], start, len(self.f.getvalue()))
|
||||||
|
self.prune()
|
||||||
|
|
||||||
|
# FIXME: Isolate: only in Python 2.x.
|
||||||
|
def n_raise_stmt3(self, node):
|
||||||
|
assert node[3] == 'RAISE_VARARGS_3'
|
||||||
|
start = len(self.f.getvalue()) + len(self.indent)
|
||||||
|
try:
|
||||||
|
self.default(node)
|
||||||
|
except GenericASTTraversalPruningException:
|
||||||
|
self.set_pos_info(node[3], start, len(self.f.getvalue()))
|
||||||
|
self.prune()
|
||||||
|
|
||||||
def n_return(self, node):
|
def n_return(self, node):
|
||||||
start = len(self.f.getvalue()) + len(self.indent)
|
start = len(self.f.getvalue()) + len(self.indent)
|
||||||
if self.params['is_lambda']:
|
if self.params['is_lambda']:
|
||||||
@@ -224,7 +272,8 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
else:
|
else:
|
||||||
start = len(self.f.getvalue()) + len(self.indent)
|
start = len(self.f.getvalue()) + len(self.indent)
|
||||||
self.write(self.indent, 'return')
|
self.write(self.indent, 'return')
|
||||||
if self.return_none or node != AST('return', [AST('ret_expr', [NONE]), Token('RETURN_VALUE')]):
|
if self.return_none or node != AST('return', [AST('ret_expr', [NONE]),
|
||||||
|
Token('RETURN_VALUE')]):
|
||||||
self.write(' ')
|
self.write(' ')
|
||||||
self.last_finish = len(self.f.getvalue())
|
self.last_finish = len(self.f.getvalue())
|
||||||
self.preorder(node[0])
|
self.preorder(node[0])
|
||||||
@@ -339,7 +388,8 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
|
|
||||||
def n_binary_expr(self, node):
|
def n_binary_expr(self, node):
|
||||||
start = len(self.f.getvalue())
|
start = len(self.f.getvalue())
|
||||||
node[0].parent = node
|
for n in node:
|
||||||
|
n.parent = node
|
||||||
self.last_finish = len(self.f.getvalue())
|
self.last_finish = len(self.f.getvalue())
|
||||||
try:
|
try:
|
||||||
super(FragmentsWalker, self).n_binary_expr(node)
|
super(FragmentsWalker, self).n_binary_expr(node)
|
||||||
@@ -602,13 +652,17 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
self.prec = 27
|
self.prec = 27
|
||||||
code = node[code_index].attr
|
code = node[code_index].attr
|
||||||
|
|
||||||
assert iscode(code)
|
assert iscode(code), node[code_index]
|
||||||
code_name = code.co_name
|
code_name = code.co_name
|
||||||
code = Code(code, self.scanner, self.currentclass)
|
code = Code(code, self.scanner, self.currentclass)
|
||||||
|
|
||||||
ast = self.build_ast(code._tokens, code._customize)
|
ast = self.build_ast(code._tokens, code._customize)
|
||||||
|
|
||||||
self.customize(code._customize)
|
self.customize(code._customize)
|
||||||
# skip over stmts sstmt smt
|
if ast[0] == 'sstmt':
|
||||||
|
ast = ast[0]
|
||||||
|
|
||||||
|
# skip over stmt return ret_expr
|
||||||
ast = ast[0][0][0]
|
ast = ast[0][0][0]
|
||||||
store = None
|
store = None
|
||||||
if ast in ['setcomp_func', 'dictcomp_func']:
|
if ast in ['setcomp_func', 'dictcomp_func']:
|
||||||
@@ -626,11 +680,12 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
else:
|
else:
|
||||||
ast = ast[0][0]
|
ast = ast[0][0]
|
||||||
n = ast[iter_index]
|
n = ast[iter_index]
|
||||||
assert n == 'list_iter'
|
assert n == 'list_iter', n
|
||||||
|
|
||||||
# FIXME: I'm not totally sure this is right.
|
# FIXME: I'm not totally sure this is right.
|
||||||
|
|
||||||
# find innermost node
|
# Find the list comprehension body. It is the inner-most
|
||||||
|
# node that is not list_.. .
|
||||||
if_node = None
|
if_node = None
|
||||||
comp_for = None
|
comp_for = None
|
||||||
comp_store = None
|
comp_store = None
|
||||||
@@ -640,12 +695,12 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
|
|
||||||
have_not = False
|
have_not = False
|
||||||
while n in ('list_iter', 'comp_iter'):
|
while n in ('list_iter', 'comp_iter'):
|
||||||
n = n[0] # recurse one step
|
n = n[0] # iterate one nesting deeper
|
||||||
if n == 'list_for':
|
if n in ('list_for', 'comp_for'):
|
||||||
if n[2] == 'store':
|
if n[2] == 'store':
|
||||||
store = n[2]
|
store = n[2]
|
||||||
n = n[3]
|
n = n[3]
|
||||||
elif n in ['list_if', 'list_if_not', 'comp_if']:
|
elif n in ('list_if', 'list_if_not', 'comp_if', 'comp_ifnot'):
|
||||||
have_not = n in ('list_if_not', 'comp_ifnot')
|
have_not = n in ('list_if_not', 'comp_ifnot')
|
||||||
if_node = n[0]
|
if_node = n[0]
|
||||||
if n[1] == 'store':
|
if n[1] == 'store':
|
||||||
@@ -661,12 +716,29 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
|
|
||||||
old_name = self.name
|
old_name = self.name
|
||||||
self.name = code_name
|
self.name = code_name
|
||||||
|
|
||||||
|
# Issue created with later Python code generation is that there
|
||||||
|
# is a lamda set up with a dummy argument name that is then called
|
||||||
|
# So we can't just translate that as is but need to replace the
|
||||||
|
# dummy name. Below we are picking out the variable name as seen
|
||||||
|
# in the code. And trying to generate code for the other parts
|
||||||
|
# that don't have the dummy argument name in it.
|
||||||
|
# Another approach might be to be able to pass in the source name
|
||||||
|
# for the dummy argument.
|
||||||
|
|
||||||
self.preorder(n[0])
|
self.preorder(n[0])
|
||||||
gen_start = len(self.f.getvalue()) + 1
|
gen_start = len(self.f.getvalue()) + 1
|
||||||
self.write(' for ')
|
self.write(' for ')
|
||||||
start = len(self.f.getvalue())
|
start = len(self.f.getvalue())
|
||||||
self.preorder(store)
|
if comp_store:
|
||||||
|
self.preorder(comp_store)
|
||||||
|
else:
|
||||||
|
self.preorder(store)
|
||||||
|
|
||||||
self.set_pos_info(store, start, len(self.f.getvalue()))
|
self.set_pos_info(store, start, len(self.f.getvalue()))
|
||||||
|
|
||||||
|
# FIXME this is all merely approximate
|
||||||
|
# from trepan.api import debug; debug()
|
||||||
self.write(' in ')
|
self.write(' in ')
|
||||||
start = len(self.f.getvalue())
|
start = len(self.f.getvalue())
|
||||||
node[-3].parent = node
|
node[-3].parent = node
|
||||||
@@ -674,6 +746,15 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
fin = len(self.f.getvalue())
|
fin = len(self.f.getvalue())
|
||||||
self.set_pos_info(node[-3], start, fin, old_name)
|
self.set_pos_info(node[-3], start, fin, old_name)
|
||||||
|
|
||||||
|
if ast == 'list_comp':
|
||||||
|
list_iter = ast[1]
|
||||||
|
assert list_iter == 'list_iter'
|
||||||
|
if list_iter == 'list_for':
|
||||||
|
self.preorder(list_iter[3])
|
||||||
|
self.prec = p
|
||||||
|
return
|
||||||
|
pass
|
||||||
|
|
||||||
if comp_store:
|
if comp_store:
|
||||||
self.preorder(comp_for)
|
self.preorder(comp_for)
|
||||||
elif if_node:
|
elif if_node:
|
||||||
@@ -681,6 +762,7 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
if have_not:
|
if have_not:
|
||||||
self.write('not ')
|
self.write('not ')
|
||||||
self.preorder(if_node)
|
self.preorder(if_node)
|
||||||
|
pass
|
||||||
self.prec = p
|
self.prec = p
|
||||||
self.name = old_name
|
self.name = old_name
|
||||||
if node[-1].kind.startswith('CALL_FUNCTION'):
|
if node[-1].kind.startswith('CALL_FUNCTION'):
|
||||||
@@ -1530,17 +1612,6 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
self.preorder(node[index])
|
self.preorder(node[index])
|
||||||
|
|
||||||
finish = len(self.f.getvalue())
|
finish = len(self.f.getvalue())
|
||||||
|
|
||||||
# FIXME rocky: figure out how to get this to be table driven
|
|
||||||
# for loops have two positions that correspond to a single text
|
|
||||||
# location. In "for i in ..." there is the initialization "i" code as well
|
|
||||||
# as the iteration code with "i"
|
|
||||||
match = re.search(r'^for', startnode.kind)
|
|
||||||
if match and entry[arg] == 3:
|
|
||||||
self.set_pos_info(node[0], start, finish)
|
|
||||||
for n in node[2]:
|
|
||||||
self.set_pos_info(n, start, finish)
|
|
||||||
|
|
||||||
self.set_pos_info(node, start, finish)
|
self.set_pos_info(node, start, finish)
|
||||||
arg += 1
|
arg += 1
|
||||||
elif typ == 'p':
|
elif typ == 'p':
|
||||||
@@ -1578,18 +1649,9 @@ class FragmentsWalker(pysource.SourceWalker, object):
|
|||||||
pass
|
pass
|
||||||
arg += 1
|
arg += 1
|
||||||
elif typ == 'x':
|
elif typ == 'x':
|
||||||
assert isinstance(entry[arg], tuple)
|
|
||||||
src, dest = entry[arg]
|
src, dest = entry[arg]
|
||||||
for d in dest:
|
for d in dest:
|
||||||
if hasattr(node[d], 'offset'):
|
self.set_pos_info_recurse(node[d], node[src].start, node[src].finish)
|
||||||
self.set_pos_info(node[d], node[src].start, node[src].finish)
|
|
||||||
else:
|
|
||||||
for n in node[d]:
|
|
||||||
if hasattr(n, 'offset'):
|
|
||||||
self.set_pos_info(n, node[src].start, node[src].finish)
|
|
||||||
pass
|
|
||||||
pass
|
|
||||||
pass
|
|
||||||
pass
|
pass
|
||||||
arg += 1
|
arg += 1
|
||||||
elif typ == 'P':
|
elif typ == 'P':
|
||||||
@@ -1762,91 +1824,93 @@ def deparse_code_around_offset(name, offset, version, co, out=StringIO(),
|
|||||||
return deparsed
|
return deparsed
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
# if __name__ == '__main__':
|
||||||
|
|
||||||
from uncompyle6 import IS_PYPY
|
# from uncompyle6 import IS_PYPY
|
||||||
def deparse_test(co, is_pypy=IS_PYPY):
|
# def deparse_test(co, is_pypy=IS_PYPY):
|
||||||
sys_version = sys.version_info.major + (sys.version_info.minor / 10.0)
|
# from xdis.magics import sysinfo2float
|
||||||
walk = deparse_code(sys_version, co, showasm=False, showast=False,
|
# float_version = sysinfo2float()
|
||||||
showgrammar=False, is_pypy=IS_PYPY)
|
# walk = deparse_code(float_version, co, showasm=False, showast=False,
|
||||||
print("deparsed source")
|
# showgrammar=False, is_pypy=IS_PYPY)
|
||||||
print(walk.text, "\n")
|
# print("deparsed source")
|
||||||
print('------------------------')
|
# print(walk.text, "\n")
|
||||||
for name, offset in sorted(walk.offsets.keys(),
|
# print('------------------------')
|
||||||
key=lambda x: str(x[0])):
|
# for name, offset in sorted(walk.offsets.keys(),
|
||||||
print("name %s, offset %s" % (name, offset))
|
# key=lambda x: str(x[0])):
|
||||||
nodeInfo = walk.offsets[name, offset]
|
# print("name %s, offset %s" % (name, offset))
|
||||||
node = nodeInfo.node
|
# nodeInfo = walk.offsets[name, offset]
|
||||||
extractInfo = walk.extract_node_info(node)
|
# node = nodeInfo.node
|
||||||
print("code: %s" % node.kind)
|
# extractInfo = walk.extract_node_info(node)
|
||||||
# print extractInfo
|
# print("code: %s" % node.kind)
|
||||||
print(extractInfo.selectedText)
|
# # print extractInfo
|
||||||
print(extractInfo.selectedLine)
|
# print(extractInfo.selectedText)
|
||||||
print(extractInfo.markerLine)
|
# print(extractInfo.selectedLine)
|
||||||
extractInfo, p = walk.extract_parent_info(node)
|
# print(extractInfo.markerLine)
|
||||||
if extractInfo:
|
# extractInfo, p = walk.extract_parent_info(node)
|
||||||
print("Contained in...")
|
|
||||||
print(extractInfo.selectedLine)
|
|
||||||
print(extractInfo.markerLine)
|
|
||||||
print("code: %s" % p.kind)
|
|
||||||
print('=' * 40)
|
|
||||||
pass
|
|
||||||
pass
|
|
||||||
return
|
|
||||||
|
|
||||||
def deparse_test_around(offset, name, co, is_pypy=IS_PYPY):
|
# if extractInfo:
|
||||||
sys_version = sys.version_info[0] + (sys.version_info[1] / 10.0)
|
# print("Contained in...")
|
||||||
walk = deparse_code_around_offset(name, offset, sys_version, co, showasm=False, showast=False,
|
# print(extractInfo.selectedLine)
|
||||||
showgrammar=False, is_pypy=IS_PYPY)
|
# print(extractInfo.markerLine)
|
||||||
print("deparsed source")
|
# print("code: %s" % p.kind)
|
||||||
print(walk.text, "\n")
|
# print('=' * 40)
|
||||||
print('------------------------')
|
# pass
|
||||||
for name, offset in sorted(walk.offsets.keys(),
|
# pass
|
||||||
key=lambda x: str(x[0])):
|
# return
|
||||||
print("name %s, offset %s" % (name, offset))
|
|
||||||
nodeInfo = walk.offsets[name, offset]
|
|
||||||
node = nodeInfo.node
|
|
||||||
extractInfo = walk.extract_node_info(node)
|
|
||||||
print("code: %s" % node.kind)
|
|
||||||
# print extractInfo
|
|
||||||
print(extractInfo.selectedText)
|
|
||||||
print(extractInfo.selectedLine)
|
|
||||||
print(extractInfo.markerLine)
|
|
||||||
extractInfo, p = walk.extract_parent_info(node)
|
|
||||||
if extractInfo:
|
|
||||||
print("Contained in...")
|
|
||||||
print(extractInfo.selectedLine)
|
|
||||||
print(extractInfo.markerLine)
|
|
||||||
print("code: %s" % p.kind)
|
|
||||||
print('=' * 40)
|
|
||||||
pass
|
|
||||||
pass
|
|
||||||
return
|
|
||||||
|
|
||||||
def get_code_for_fn(fn):
|
# def deparse_test_around(offset, name, co, is_pypy=IS_PYPY):
|
||||||
if hasattr(fn, 'func_code'):
|
# sys_version = sys.version_info[0] + (sys.version_info[1] / 10.0)
|
||||||
return fn.func_code
|
# walk = deparse_code_around_offset(name, offset, sys_version, co, showasm=False, showast=False,
|
||||||
return fn.__code__
|
# showgrammar=False, is_pypy=IS_PYPY)
|
||||||
|
# print("deparsed source")
|
||||||
|
# print(walk.text, "\n")
|
||||||
|
# print('------------------------')
|
||||||
|
# for name, offset in sorted(walk.offsets.keys(),
|
||||||
|
# key=lambda x: str(x[0])):
|
||||||
|
# print("name %s, offset %s" % (name, offset))
|
||||||
|
# nodeInfo = walk.offsets[name, offset]
|
||||||
|
# node = nodeInfo.node
|
||||||
|
# extractInfo = walk.extract_node_info(node)
|
||||||
|
# print("code: %s" % node.kind)
|
||||||
|
# # print extractInfo
|
||||||
|
# print(extractInfo.selectedText)
|
||||||
|
# print(extractInfo.selectedLine)
|
||||||
|
# print(extractInfo.markerLine)
|
||||||
|
# extractInfo, p = walk.extract_parent_info(node)
|
||||||
|
# if extractInfo:
|
||||||
|
# print("Contained in...")
|
||||||
|
# print(extractInfo.selectedLine)
|
||||||
|
# print(extractInfo.markerLine)
|
||||||
|
# print("code: %s" % p.kind)
|
||||||
|
# print('=' * 40)
|
||||||
|
# pass
|
||||||
|
# pass
|
||||||
|
# return
|
||||||
|
|
||||||
def test():
|
# def get_code_for_fn(fn):
|
||||||
import os, sys
|
# if hasattr(fn, 'func_code'):
|
||||||
|
# return fn.func_code
|
||||||
|
# return fn.__code__
|
||||||
|
|
||||||
def gcd(a, b):
|
# def test():
|
||||||
if a > b:
|
# import os, sys
|
||||||
(a, b) = (b, a)
|
|
||||||
pass
|
|
||||||
|
|
||||||
if a <= 0:
|
# def gcd(a, b):
|
||||||
return None
|
# if a > b:
|
||||||
if a == 1 or a == b:
|
# (a, b) = (b, a)
|
||||||
return a
|
# pass
|
||||||
return gcd(b-a, a)
|
|
||||||
|
|
||||||
# check_args(['3', '5'])
|
# if a <= 0:
|
||||||
# deparse_test(get_code_for_fn(gcd))
|
# return None
|
||||||
# deparse_test(get_code_for_fn(test))
|
# if a == 1 or a == b:
|
||||||
# deparse_test(get_code_for_fn(FragmentsWalker.fixup_offsets))
|
# return a
|
||||||
# deparse_test(get_code_for_fn(FragmentsWalker.n_list))
|
# return gcd(b-a, a)
|
||||||
print('=' * 30)
|
|
||||||
deparse_test_around(408, 'n_list', get_code_for_fn(FragmentsWalker.n_list))
|
# # check_args(['3', '5'])
|
||||||
# deparse_test(inspect.currentframe().f_code)
|
# # deparse_test(get_code_for_fn(gcd))
|
||||||
|
# # deparse_test(get_code_for_fn(test))
|
||||||
|
# # deparse_test(get_code_for_fn(FragmentsWalker.fixup_offsets))
|
||||||
|
# # deparse_test(get_code_for_fn(FragmentsWalker.n_list))
|
||||||
|
# print('=' * 30)
|
||||||
|
# deparse_test_around(408, 'n_list', get_code_for_fn(FragmentsWalker.n_list))
|
||||||
|
# # deparse_test(inspect.currentframe().f_code)
|
||||||
|
@@ -1529,7 +1529,8 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
|
|
||||||
ast = self.build_ast(code._tokens, code._customize)
|
ast = self.build_ast(code._tokens, code._customize)
|
||||||
self.customize(code._customize)
|
self.customize(code._customize)
|
||||||
# skip over stmts sstmt smt
|
|
||||||
|
# skip over stmt return ret_expr
|
||||||
ast = ast[0][0][0]
|
ast = ast[0][0][0]
|
||||||
store = None
|
store = None
|
||||||
if ast in ['setcomp_func', 'dictcomp_func']:
|
if ast in ['setcomp_func', 'dictcomp_func']:
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
# This file is suitable for sourcing inside bash as
|
# This file is suitable for sourcing inside bash as
|
||||||
# well as importing into Python
|
# well as importing into Python
|
||||||
VERSION='2.15.0'
|
VERSION='2.15.1'
|
||||||
|
Reference in New Issue
Block a user