You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
2.6 ifelse/while modifications
This commit is contained in:
BIN
test/bytecode_2.6/07_for_if_continue.pyc
Normal file
BIN
test/bytecode_2.6/07_for_if_continue.pyc
Normal file
Binary file not shown.
16
test/simple_source/stmts/07_for_if_continue.py
Normal file
16
test/simple_source/stmts/07_for_if_continue.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Python 2.6.9 Cookie.py
|
||||||
|
# Problem in 2.6 is making sure
|
||||||
|
# the two JUMP_ABSOLUTES get turned into:
|
||||||
|
# 26 CONTINUE 7 '7'
|
||||||
|
# 29 JUMP_BACK 7 '7'
|
||||||
|
# The fact that the "continue" is on the same
|
||||||
|
# line as the "if" is important.
|
||||||
|
|
||||||
|
for K in items:
|
||||||
|
if V: continue
|
||||||
|
|
||||||
|
# 32 CONTINUE 7 '7'
|
||||||
|
# 35 JUMP_FORWARD 1 (to 39)
|
||||||
|
for K,V in items:
|
||||||
|
if V == "": continue
|
||||||
|
if K not in attrs: continue
|
@@ -57,29 +57,47 @@ class Python26Parser(Python2Parser):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def p_misc26(self, args):
|
# In contrast to Python 2.7, Python 2.6 has a lot of
|
||||||
|
# POP_TOP's which come right after various jumps.
|
||||||
|
# The COME_FROM instructions our scanner adds, here it is to assist
|
||||||
|
# distinguishing the extraneous POP_TOPs from those that start
|
||||||
|
# after one of these jumps
|
||||||
|
def p_jumps26(self, args):
|
||||||
"""
|
"""
|
||||||
|
jmp_false ::= JUMP_IF_FALSE
|
||||||
|
jmp_true ::= JUMP_IF_TRUE
|
||||||
jmp_true ::= JUMP_IF_TRUE POP_TOP
|
jmp_true ::= JUMP_IF_TRUE POP_TOP
|
||||||
jmp_false ::= JUMP_IF_FALSE POP_TOP
|
jmp_false ::= JUMP_IF_FALSE POP_TOP
|
||||||
jf_pop ::= JUMP_FORWARD come_from_pop
|
jf_pop ::= JUMP_FORWARD come_from_pop
|
||||||
jb_pop ::= JUMP_BACK come_from_pop
|
jb_pop ::= JUMP_BACK come_from_pop
|
||||||
|
|
||||||
|
jb_cf_pop ::= JUMP_BACK come_froms POP_TOP
|
||||||
|
ja_cf_pop ::= JUMP_ABSOLUTE come_from_pop
|
||||||
|
|
||||||
|
_ifstmts_jump ::= c_stmts_opt jf_pop COME_FROM
|
||||||
|
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD COME_FROM come_from_pop
|
||||||
|
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD come_froms POP_TOP COME_FROM
|
||||||
|
|
||||||
# This is what happens after a jump where
|
# This is what happens after a jump where
|
||||||
# we start a new block. For reasons I don't fully
|
# we start a new block. For reasons I don't fully
|
||||||
# understand, there is also a value on the top of the stack
|
# understand, there is also a value on the top of the stack
|
||||||
come_from_pop ::= COME_FROM POP_TOP
|
come_from_pop ::= COME_FROM POP_TOP
|
||||||
|
|
||||||
_ifstmts_jump ::= c_stmts_opt jf_pop COME_FROM
|
|
||||||
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD COME_FROM come_from_pop
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def p_stmt26(self, args):
|
def p_stmt26(self, args):
|
||||||
"""
|
"""
|
||||||
assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1 come_from_pop
|
assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1 come_from_pop
|
||||||
ifelsestmt ::= testexpr c_stmts_opt jf_pop else_suite COME_FROM
|
|
||||||
|
|
||||||
# This rule is contorted a little to make sutie_stmts_opt be the
|
ifelsestmt ::= testexpr c_stmts_opt jf_pop else_suite COME_FROM
|
||||||
# forth argument for the semantic routines.
|
ifelsestmt ::= testexpr c_stmts_opt else_suitel come_froms POP_TOP
|
||||||
|
|
||||||
|
# Semantic actions want else_suitel to be at index 2 or 3
|
||||||
|
ifelsestmtl ::= testexpr c_stmts_opt jb_cf_pop else_suitel
|
||||||
|
ifelsestmtc ::= testexpr c_stmts_opt ja_cf_pop else_suitec
|
||||||
|
|
||||||
|
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE come_froms POP_TOP
|
||||||
|
|
||||||
|
# Semantic actions want suite_stmts_opt to be at index 3
|
||||||
withstmt ::= expr setupwith SETUP_FINALLY suite_stmts_opt
|
withstmt ::= expr setupwith SETUP_FINALLY suite_stmts_opt
|
||||||
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
||||||
|
|
||||||
@@ -87,12 +105,14 @@ class Python26Parser(Python2Parser):
|
|||||||
# opcode SETUP_WITH
|
# opcode SETUP_WITH
|
||||||
setupwith ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 POP_TOP
|
setupwith ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 POP_TOP
|
||||||
|
|
||||||
whilestmt ::= SETUP_LOOP
|
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_pop POP_BLOCK _come_from
|
||||||
testexpr
|
|
||||||
l_stmts_opt jb_pop
|
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_cf_pop POP_BLOCK COME_FROM
|
||||||
POP_BLOCK _come_from
|
|
||||||
|
|
||||||
return_if_stmt ::= ret_expr RETURN_END_IF come_from_pop
|
return_if_stmt ::= ret_expr RETURN_END_IF come_from_pop
|
||||||
|
|
||||||
|
iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK come_from_pop
|
||||||
|
iflaststmt ::= testexpr c_stmts_opt JUMP_ABSOLUTE come_from_pop
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def p_comp26(self, args):
|
def p_comp26(self, args):
|
||||||
@@ -130,11 +150,6 @@ class Python26Parser(Python2Parser):
|
|||||||
except_suite ::= c_stmts_opt jmp_abs new_block
|
except_suite ::= c_stmts_opt jmp_abs new_block
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def p_jump26(self, args):
|
|
||||||
"""
|
|
||||||
jmp_false ::= JUMP_IF_FALSE
|
|
||||||
jmp_true ::= JUMP_IF_TRUE
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class Python26ParserSingle(Python2Parser, PythonParserSingle):
|
class Python26ParserSingle(Python2Parser, PythonParserSingle):
|
||||||
|
@@ -10,6 +10,11 @@ other versions of Python. Also, we save token information for later
|
|||||||
use in deparsing.
|
use in deparsing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from uncompyle6 import PYTHON3
|
||||||
|
if PYTHON3:
|
||||||
|
intern = sys.intern
|
||||||
|
|
||||||
from xdis.bytecode import findlinestarts
|
from xdis.bytecode import findlinestarts
|
||||||
import uncompyle6.scanners.scanner2 as scan
|
import uncompyle6.scanners.scanner2 as scan
|
||||||
|
|
||||||
@@ -217,6 +222,11 @@ class Scanner26(scan.Scanner2):
|
|||||||
if target > offset and self.code[target] == self.opc.RETURN_VALUE:
|
if target > offset and self.code[target] == self.opc.RETURN_VALUE:
|
||||||
# Python 2.5 sometimes has this
|
# Python 2.5 sometimes has this
|
||||||
op_name = 'JUMP_RETURN'
|
op_name = 'JUMP_RETURN'
|
||||||
|
# FIXME: this is a hack to catch stuff like:
|
||||||
|
# if x: continue
|
||||||
|
# the "continue" is not on a new line.
|
||||||
|
if tokens[-1].type == 'JUMP_BACK':
|
||||||
|
tokens[-1].type = intern('CONTINUE')
|
||||||
|
|
||||||
elif op in self.opc.hasjabs:
|
elif op in self.opc.hasjabs:
|
||||||
pattr = repr(oparg)
|
pattr = repr(oparg)
|
||||||
@@ -252,6 +262,11 @@ class Scanner26(scan.Scanner2):
|
|||||||
op_name = 'CONTINUE'
|
op_name = 'CONTINUE'
|
||||||
else:
|
else:
|
||||||
op_name = 'JUMP_BACK'
|
op_name = 'JUMP_BACK'
|
||||||
|
# FIXME: this is a hack to catch stuff like:
|
||||||
|
# if x: continue
|
||||||
|
# the "continue" is not on a new line.
|
||||||
|
if tokens[-1].type == 'JUMP_BACK':
|
||||||
|
tokens[-1].type = intern('CONTINUE')
|
||||||
|
|
||||||
elif op == self.opc.LOAD_GLOBAL:
|
elif op == self.opc.LOAD_GLOBAL:
|
||||||
if offset in self.load_asserts:
|
if offset in self.load_asserts:
|
||||||
|
@@ -849,8 +849,14 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
self.println()
|
self.println()
|
||||||
self.prune() # stop recursing
|
self.prune() # stop recursing
|
||||||
|
|
||||||
def n_ifelsestmt(self, node, preprocess=0):
|
def n_ifelsestmt(self, node, preprocess=False):
|
||||||
n = node[3][0]
|
if node[2].type.startswith('else_suite'):
|
||||||
|
else_suite = node[2]
|
||||||
|
elif node[3].type.startswith('else_suite'):
|
||||||
|
else_suite = node[3]
|
||||||
|
|
||||||
|
n = else_suite[0]
|
||||||
|
|
||||||
if len(n) == 1 == len(n[0]) and n[0] == '_stmts':
|
if len(n) == 1 == len(n[0]) and n[0] == '_stmts':
|
||||||
n = n[0][0][0]
|
n = n[0][0][0]
|
||||||
elif n[0].type in ('lastc_stmt', 'lastl_stmt'):
|
elif n[0].type in ('lastc_stmt', 'lastl_stmt'):
|
||||||
@@ -868,7 +874,7 @@ class SourceWalker(GenericASTTraversal, object):
|
|||||||
n.type = 'elifelsestmtr'
|
n.type = 'elifelsestmtr'
|
||||||
elif n.type in ('ifelsestmt', 'ifelsestmtc', 'ifelsestmtl'):
|
elif n.type in ('ifelsestmt', 'ifelsestmtc', 'ifelsestmtl'):
|
||||||
node.type = 'ifelifstmt'
|
node.type = 'ifelifstmt'
|
||||||
self.n_ifelsestmt(n, preprocess=1)
|
self.n_ifelsestmt(n, preprocess=True)
|
||||||
if n == 'ifelifstmt':
|
if n == 'ifelifstmt':
|
||||||
n.type = 'elifelifstmt'
|
n.type = 'elifelifstmt'
|
||||||
elif n.type in ('ifelsestmt', 'ifelsestmtc', 'ifelsestmtl'):
|
elif n.type in ('ifelsestmt', 'ifelsestmtc', 'ifelsestmtl'):
|
||||||
|
Reference in New Issue
Block a user