2.6 ifelse/while modifications

This commit is contained in:
rocky
2016-06-29 06:54:29 -04:00
parent 0af3dd28bc
commit 32ca0c4482
5 changed files with 71 additions and 19 deletions

Binary file not shown.

View 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

View File

@@ -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):

View File

@@ -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:

View File

@@ -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'):