Permalink
Browse files

Merge branch 'hotfix/issue4'

  • Loading branch information...
2 parents 6136057 + 42ef165 commit f14fb8acf5f667f65685e34774a6be8824ff7f49 srossross committed Jul 17, 2012
View
5 meta/bytecodetools/instruction.py
@@ -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:
View
4 meta/bytecodetools/pyc_file.py
@@ -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))
View
28 meta/decompiler/control_flow_instructions.py
@@ -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()
@@ -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
@@ -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
View
11 meta/decompiler/tests/test_decompiler.py
@@ -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']

0 comments on commit f14fb8a

Please sign in to comment.