X Tutup
Skip to content

Commit 982a601

Browse files
committed
WIP 2.6 redo bytecode handling
Don't try to convert 2.6 bytecode to 2.7 psuedo bytecode. Instead adjust grammar and semantic actions. Down the line we should to segregate version changes in semantic code better.
1 parent 9a251b2 commit 982a601

File tree

7 files changed

+148
-106
lines changed

7 files changed

+148
-106
lines changed

__pkginfo__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
]}
3838
ftp_url = None
3939
install_requires = ['spark-parser >= 1.4.0',
40-
'xdis >= 1.1.1']
40+
'xdis >= 1.1.2']
4141
license = 'MIT'
4242
mailing_list = 'python-debugger@googlegroups.com'
4343
modname = 'uncompyle6'

uncompyle6/parsers/astnode.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55

66
if PYTHON3:
77
intern = sys.intern
8-
from collections import UserList
9-
else:
10-
from UserList import UserList
118

129

1310
class AST(spark_AST):

uncompyle6/parsers/parse2.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ def p_grammar(self, args):
186186
187187
try_middle ::= jmp_abs COME_FROM except_stmts
188188
END_FINALLY
189+
190+
## FIXME: this might be a 2.7+ thing only
189191
try_middle ::= JUMP_FORWARD COME_FROM except_stmts
190192
END_FINALLY COME_FROM
191193
@@ -200,9 +202,11 @@ def p_grammar(self, args):
200202
except_suite ::= c_stmts_opt jmp_abs
201203
except_suite ::= return_stmts
202204
205+
## FIXME: this might be a 2.7+ thing only
203206
except_cond1 ::= DUP_TOP expr COMPARE_OP
204207
jmp_false POP_TOP POP_TOP POP_TOP
205208
209+
## FIXME: this might be a 2.7+ thing only
206210
except_cond2 ::= DUP_TOP expr COMPARE_OP
207211
jmp_false POP_TOP designator POP_TOP
208212

uncompyle6/parsers/parse26.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,27 @@ def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
1414
self.customized = {}
1515

1616

17-
def p_lis_iter(self, args):
17+
def p_try_except26(self, args):
18+
"""
19+
# FIXME: move parse2's corresponding rules to 2.7
20+
21+
except_cond1 ::= DUP_TOP expr COMPARE_OP
22+
JUMP_IF_FALSE POP_TOP POP_TOP POP_TOP POP_TOP
23+
except_cond2 ::= DUP_TOP expr COMPARE_OP
24+
JUMP_IF_FALSE POP_TOP POP_TOP designator POP_TOP
25+
try_middle ::= JUMP_FORWARD COME_FROM except_stmts
26+
POP_TOP END_FINALLY COME_FROM
27+
"""
28+
29+
30+
def p_comp26(self, args):
1831
'''
19-
list_iter ::= list_if JUMP_BACK
32+
list_iter ::= list_if JUMP_BACK
33+
list_compr ::= BUILD_LIST_0 DUP_TOP
34+
designator list_iter del_stmt
35+
lc_body ::= LOAD_NAME expr LIST_APPEND
36+
37+
2038
'''
2139

2240
class Python26ParserSingle(Python2Parser, PythonParserSingle):

uncompyle6/scanners/scanner2.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,11 @@ def unmangle(name):
184184
elif op == self.opc.JA:
185185
target = self.get_target(offset)
186186
if target < offset:
187-
if offset in self.stmts and self.code[offset+3] not in (self.opc.END_FINALLY, self.opc.POP_BLOCK) \
188-
and offset not in self.not_continue:
187+
if (offset in self.stmts
188+
and self.code[offset+3] not in (self.opc.END_FINALLY,
189+
self.opc.POP_BLOCK)
190+
and offset not in self.not_continue):
191+
print("WOOT", target, offset, self.stmts)
189192
opname = 'CONTINUE'
190193
else:
191194
opname = 'JUMP_BACK'
@@ -366,7 +369,8 @@ def next_except_jump(self, start):
366369
op = self.code[i]
367370
if op == self.opc.END_FINALLY:
368371
if count_END_FINALLY == count_SETUP_:
369-
assert self.code[self.prev[i]] in (self.opc.JA, self.opc.JF, self.opc.RETURN_VALUE)
372+
if self.version == 2.7:
373+
assert self.code[self.prev[i]] in (self.opc.JA, self.opc.JF, self.opc.RETURN_VALUE)
370374
self.not_continue.add(self.prev[i])
371375
return self.prev[i]
372376
count_END_FINALLY += 1

uncompyle6/scanners/scanner26.py

Lines changed: 96 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,12 @@ def disassemble(self, co, classname=None, code_objects={}, show_asm=None):
7676
'''
7777

7878
show_asm = self.show_asm if not show_asm else show_asm
79-
if self.show_asm in ('both', 'before'):
79+
if show_asm in ('both', 'before'):
8080
from xdis.bytecode import Bytecode
8181
bytecode = Bytecode(co, self.opc)
8282
for instr in bytecode.get_instructions(co):
8383
print(instr._disassemble())
84+
show_asm = 'both'
8485

8586
# from xdis.bytecode import Bytecode
8687
# bytecode = Bytecode(co, self.opc)
@@ -120,7 +121,9 @@ def unmangle(name):
120121

121122
# list of instruction to remove/add or change to match with bytecode 2.7
122123
self.toChange = []
123-
self.restructBytecode()
124+
# Rocky: the restructure code isn't adjusting linestarts
125+
# and this causes problems
126+
# self.restructBytecode()
124127
codelen = len(self.code)
125128

126129
self.build_prev_op(codelen)
@@ -170,6 +173,7 @@ def unmangle(name):
170173
tokens.append(Token('COME_FROM', None, repr(j),
171174
offset="%s_%d" % (offset, k) ))
172175
k += 1
176+
173177
if self.op_hasArgument(op):
174178
oparg = self.get_argument(offset) + extended_arg
175179
extended_arg = 0
@@ -234,7 +238,7 @@ def unmangle(name):
234238
target = self.get_target(offset)
235239
if target < offset:
236240
if (offset in self.stmts
237-
and self.code[offset + 3] not in (self.opc.END_FINALLY,
241+
and self.code[offset+3] not in (self.opc.END_FINALLY,
238242
self.opc.POP_BLOCK)
239243
and offset not in self.not_continue):
240244
op_name = 'CONTINUE'
@@ -260,7 +264,7 @@ def unmangle(name):
260264
pass
261265
pass
262266

263-
if self.show_asm:
267+
if show_asm:
264268
for t in tokens:
265269
print(t)
266270
print()
@@ -470,94 +474,94 @@ def restructCode(self, listDel, listExp):
470474
jmp += 3
471475
else: jmp += 1
472476

473-
def restructBytecode(self):
474-
'''
475-
add/change/delete bytecode for suiting bytecode 2.7
476-
'''
477-
# we can't use op_range for the moment
478-
# convert jump opcode to 2.7
479-
self.restructRelativeJump()
480-
481-
listExp = self.getOpcodeToExp()
482-
# change code structure
483-
if listExp:
484-
listExp = sorted(list(set(listExp)))
485-
self.restructCode([], listExp)
486-
# we add arg to expended opcode
487-
offset=0
488-
for toExp in listExp:
489-
self.code.insert(toExp+offset+1, 0)
490-
self.code.insert(toExp+offset+1, 0)
491-
offset+=2
492-
# op_range is now ok :)
493-
# add instruction to change in "toChange" list + MAJ toDel
494-
listDel = []
495-
for i in self.op_range(0, len(self.code)):
496-
ret = self.getOpcodeToDel(i)
497-
if ret is not None:
498-
listDel += ret
499-
500-
# change code structure after deleting byte
501-
if listDel:
502-
listDel = sorted(list(set(listDel)))
503-
self.restructCode(listDel, [])
504-
# finaly we delete useless opcode
505-
delta = 0
506-
for x in listDel:
507-
if self.op_hasArgument(self.code[x-delta]):
508-
self.code.pop(x-delta)
509-
self.code.pop(x-delta)
510-
self.code.pop(x-delta)
511-
delta += 3
512-
else:
513-
self.code.pop(x-delta)
514-
delta += 1
515-
516-
def restructRelativeJump(self):
517-
'''
518-
change relative JUMP_IF_FALSE/TRUE to absolut jump
519-
and remap the target of PJIF/PJIT
520-
'''
521-
i=0
522-
while i < len(self.code): # we can't use op_range for the moment
523-
op = self.code[i]
524-
if op in self.pop_jump_if:
525-
target = self.get_argument(i)
526-
target += i + 3
527-
self.restructJump(i, target)
528-
i += self.op_size(op)
529-
530-
i=0
531-
while i < len(self.code): # we can't use op_range for the moment
532-
op = self.code[i]
533-
if op in self.pop_jump_if:
534-
target = self.get_target(i)
535-
if self.code[target] == self.opc.JA:
536-
target = self.get_target(target)
537-
self.restructJump(i, target)
538-
i += self.op_size(op)
539-
i=0
540-
# while i < len(self.code): # we can't use op_range for the moment
541-
# op = self.code[i]
542-
# name = self.opc.opname[op]
543-
# if self.op_hasArgument(op):
544-
# oparg = self.get_argument(i)
545-
# print("%d %s %d" % (i, name, oparg))
546-
# else:
547-
# print("%d %s" % (i, name))
548-
# i += self.op_size(op)
549-
550-
def restructJump(self, pos, newTarget):
551-
if self.code[pos] not in self.opc.hasjabs + self.opc.hasjrel:
552-
raise 'Can t change this argument. Opcode is not a jump'
553-
if newTarget > 0xFFFF:
554-
raise NotImplementedError
555-
offset = newTarget-self.get_target(pos)
556-
target = self.get_argument(pos)+offset
557-
if target < 0 or target > 0xFFFF:
558-
raise NotImplementedError
559-
self.code[pos+2] = (target >> 8) & 0xFF
560-
self.code[pos+1] = target & 0xFF
477+
# def restructBytecode(self):
478+
# '''
479+
# add/change/delete bytecode for suiting bytecode 2.7
480+
# '''
481+
# # we can't use op_range for the moment
482+
# # convert jump opcode to 2.7
483+
# self.restructRelativeJump()
484+
485+
# listExp = self.getOpcodeToExp()
486+
# # change code structure
487+
# if listExp:
488+
# listExp = sorted(list(set(listExp)))
489+
# self.restructCode([], listExp)
490+
# # we add arg to expended opcode
491+
# offset=0
492+
# for toExp in listExp:
493+
# self.code.insert(toExp+offset+1, 0)
494+
# self.code.insert(toExp+offset+1, 0)
495+
# offset+=2
496+
# # op_range is now ok :)
497+
# # add instruction to change in "toChange" list + MAJ toDel
498+
# listDel = []
499+
# for i in self.op_range(0, len(self.code)):
500+
# ret = self.getOpcodeToDel(i)
501+
# if ret is not None:
502+
# listDel += ret
503+
504+
# # change code structure after deleting byte
505+
# if listDel:
506+
# listDel = sorted(list(set(listDel)))
507+
# self.restructCode(listDel, [])
508+
# # finaly we delete useless opcode
509+
# delta = 0
510+
# for x in listDel:
511+
# if self.op_hasArgument(self.code[x-delta]):
512+
# self.code.pop(x-delta)
513+
# self.code.pop(x-delta)
514+
# self.code.pop(x-delta)
515+
# delta += 3
516+
# else:
517+
# self.code.pop(x-delta)
518+
# delta += 1
519+
520+
# def restructRelativeJump(self):
521+
# '''
522+
# change relative JUMP_IF_FALSE/TRUE to absolut jump
523+
# and remap the target of PJIF/PJIT
524+
# '''
525+
# i=0
526+
# while i < len(self.code): # we can't use op_range for the moment
527+
# op = self.code[i]
528+
# if op in self.pop_jump_if:
529+
# target = self.get_argument(i)
530+
# target += i + 3
531+
# self.restructJump(i, target)
532+
# i += self.op_size(op)
533+
534+
# i=0
535+
# while i < len(self.code): # we can't use op_range for the moment
536+
# op = self.code[i]
537+
# if op in self.pop_jump_if:
538+
# target = self.get_target(i)
539+
# if self.code[target] == self.opc.JA:
540+
# target = self.get_target(target)
541+
# self.restructJump(i, target)
542+
# i += self.op_size(op)
543+
# i=0
544+
# # while i < len(self.code): # we can't use op_range for the moment
545+
# # op = self.code[i]
546+
# # name = self.opc.opname[op]
547+
# # if self.op_hasArgument(op):
548+
# # oparg = self.get_argument(i)
549+
# # print("%d %s %d" % (i, name, oparg))
550+
# # else:
551+
# # print("%d %s" % (i, name))
552+
# # i += self.op_size(op)
553+
554+
# def restructJump(self, pos, newTarget):
555+
# if self.code[pos] not in self.opc.hasjabs + self.opc.hasjrel:
556+
# raise 'Can t change this argument. Opcode is not a jump'
557+
# if newTarget > 0xFFFF:
558+
# raise NotImplementedError
559+
# offset = newTarget-self.get_target(pos)
560+
# target = self.get_argument(pos)+offset
561+
# if target < 0 or target > 0xFFFF:
562+
# raise NotImplementedError
563+
# self.code[pos+2] = (target >> 8) & 0xFF
564+
# self.code[pos+1] = target & 0xFF
561565

562566
def detect_structure(self, pos, op=None):
563567
'''

uncompyle6/semantics/pysource.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,8 +1000,13 @@ def n_list_compr(self, node):
10001000
"""
10011001
p = self.prec
10021002
self.prec = 27
1003-
n = node[-1]
1003+
if self.version >= 2.7:
1004+
n = node[-1]
1005+
elif node[-1] == 'del_stmt':
1006+
n = node[-2]
1007+
10041008
assert n == 'list_iter'
1009+
10051010
# find innermost node
10061011
while n == 'list_iter':
10071012
n = n[0] # recurse one step
@@ -1010,8 +1015,18 @@ def n_list_compr(self, node):
10101015
elif n == 'list_if_not': n= n[2]
10111016
assert n == 'lc_body'
10121017
self.write( '[ ')
1013-
self.preorder(n[0]) # lc_body
1014-
self.preorder(node[-1]) # for/if parts
1018+
1019+
if self.version >= 2.7:
1020+
expr = n[0]
1021+
list_iter = node[-1]
1022+
else:
1023+
expr = n[1]
1024+
list_iter = node[-2]
1025+
1026+
assert expr == 'expr'
1027+
assert list_iter == 'list_iter'
1028+
self.preorder(expr)
1029+
self.preorder(list_iter)
10151030
self.write( ' ]')
10161031
self.prec = p
10171032
self.prune() # stop recursing
@@ -1572,8 +1587,8 @@ def n_assign3(self, node):
15721587
self.default(node)
15731588

15741589
def n_except_cond2(self, node):
1575-
if node[5][0] == 'unpack':
1576-
node[5][0].type = 'unpack_w_parens'
1590+
if node[-2][0] == 'unpack':
1591+
node[-2][0].type = 'unpack_w_parens'
15771592
self.default(node)
15781593

15791594
def engine(self, entry, startnode):

0 commit comments

Comments
 (0)
X Tutup