Skip to content

Commit

Permalink
Merge branch 'hotfix/issue4'
Browse files Browse the repository at this point in the history
  • Loading branch information
srossross committed Jul 17, 2012
2 parents 6136057 + 42ef165 commit f14fb8a
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
5 changes: 5 additions & 0 deletions meta/bytecodetools/instruction.py
Expand Up @@ -28,6 +28,11 @@ def __init__(self, i= -1, op=None, lineno=None):
@property
def opname(self):
return opcode.opname[self.op]

@property
def is_jump(self):
return self.op in opcode.hasjrel or self.op in opcode.hasjabs

@property
def to(self):
if self.op in opcode.hasjrel:
Expand Down
4 changes: 4 additions & 0 deletions meta/bytecodetools/pyc_file.py
Expand Up @@ -10,7 +10,11 @@
import marshal

def extract(binary):
'''
Extract a code object from a binary pyc file.
:param binary: a sequence of bytes from a pyc file.
'''
if len(binary) <= 8:
raise Exception("Binary pyc must be greater than 8 bytes (got %i)" % len(binary))

Expand Down
28 changes: 16 additions & 12 deletions meta/decompiler/control_flow_instructions.py
Expand Up @@ -706,33 +706,36 @@ def JUMP_IF_TRUE_OR_POP(self, instr):
def make_if(self, instr, left, and_block):
block = [instr] + and_block[:-1]

# maxmax = max(block, key=lambda ins: (0, 0) if (ins.op not in JUMP_OPS) else (ins.oparg, ins.i))
maxmax = max(block, key=lambda ins: (0, 0) if (ins.op not in JUMP_OPS) else (self.jump_map.get(ins.oparg, ins.oparg), ins.i))

idx = block.index(maxmax)

assert idx is not None

hi = self.process_logic(block[:idx + 1])

if hi.right is None and hi.parent is None:
if instr.opname == 'POP_JUMP_IF_TRUE':
cond = _ast.UnaryOp(op=_ast.Not(), operand=left, lineno=0, col_offset=0)
# cond = ast.Not(left, lineno=instr.lineno)
else:
cond = left

else:
cond = self.logic_ast(instr, left, hi)

# if block[-1].opname == 'JUMP_ABSOLUTE':
# pass

body = self.decompile_block(block[idx + 1:]).stmnt()

# tests = [(cond, body)]


jump = and_block[-1]
else_block = self.make_block(jump.to, inclusive=False, raise_=False)

if jump.opname == 'RETURN_VALUE':
body_block = block[idx + 1:] + [jump]
else:
body_block = block[idx + 1:]

body = self.decompile_block(body_block).stmnt()

if jump.is_jump:
else_block = self.make_block(jump.to, inclusive=False, raise_=False)
else: # it is a return
else_block = []

if len(else_block):
else_ = self.decompile_block(else_block).stmnt()
Expand All @@ -757,7 +760,7 @@ def POP_JUMP_IF_TRUE(self, instr):

and_block = self.gather_jumps(instr)

if and_block[-1].opname in ['JUMP_FORWARD', 'JUMP_ABSOLUTE']:
if and_block[-1].opname in ['JUMP_FORWARD', 'JUMP_ABSOLUTE', 'RETURN_VALUE']:

self.make_if(instr, left, and_block)
return
Expand All @@ -774,6 +777,7 @@ def POP_JUMP_IF_FALSE(self, instr):

and_block = self.gather_jumps(instr)
#This is an IF statement

if and_block[-1].opname in ['JUMP_FORWARD', 'JUMP_ABSOLUTE', 'RETURN_VALUE']:

#this happens if the function was going to return anyway
Expand Down
11 changes: 11 additions & 0 deletions meta/decompiler/tests/test_decompiler.py
Expand Up @@ -515,6 +515,17 @@ def test_aug_assign_slice(self):
stmnt = 'c[idx:a:3] += b[idx:a]'
self.statement(stmnt)

def test_issue_4(self):
example = """
def example(idx):
if(idx == 2 or idx == 3):
idx = 1
return None
i += 1
return None
"""
self.statement(example)


if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.test_assign']
Expand Down

0 comments on commit f14fb8a

Please sign in to comment.