diff --git a/uncompyle6/scanners/scanner26.py b/uncompyle6/scanners/scanner26.py index 35ff5ff6..208e94b1 100755 --- a/uncompyle6/scanners/scanner26.py +++ b/uncompyle6/scanners/scanner26.py @@ -23,27 +23,31 @@ use in deparsing. """ import sys -import uncompyle6.scanners.scanner2 as scan # bytecode verification, verify(), uses JUMP_OPs from here from xdis import iscode -from xdis.opcodes import opcode_26 from xdis.bytecode import _get_const_info +from xdis.opcodes import opcode_26 +import uncompyle6.scanners.scanner2 as scan from uncompyle6.scanner import Token intern = sys.intern JUMP_OPS = opcode_26.JUMP_OPS + class Scanner26(scan.Scanner2): def __init__(self, show_asm=False): super(Scanner26, self).__init__((2, 6), show_asm) # "setup" opcodes - self.setup_ops = frozenset([ - self.opc.SETUP_EXCEPT, self.opc.SETUP_FINALLY, - ]) + self.setup_ops = frozenset( + [ + self.opc.SETUP_EXCEPT, + self.opc.SETUP_FINALLY, + ] + ) return @@ -76,8 +80,9 @@ class Scanner26(scan.Scanner2): # show_asm = 'after' if show_asm in ("both", "before"): + print("\n# ---- before tokenization:") for instr in bytecode.get_instructions(co): - print(instr.disassemble()) + print(instr.disassemble(self.opc)) # Container for tokens tokens = [] @@ -96,17 +101,18 @@ class Scanner26(scan.Scanner2): # 'LOAD_ASSERT' is used in assert statements. self.load_asserts = set() for i in self.op_range(0, codelen): - # We need to detect the difference between: # raise AssertionError # and # assert ... - if (self.code[i] == self.opc.JUMP_IF_TRUE and - i + 4 < codelen and - self.code[i+3] == self.opc.POP_TOP and - self.code[i+4] == self.opc.LOAD_GLOBAL): - if names[self.get_argument(i+4)] == 'AssertionError': - self.load_asserts.add(i+4) + if ( + self.code[i] == self.opc.JUMP_IF_TRUE + and i + 4 < codelen + and self.code[i + 3] == self.opc.POP_TOP + and self.code[i + 4] == self.opc.LOAD_GLOBAL + ): + if names[self.get_argument(i + 4)] == "AssertionError": + self.load_asserts.add(i + 4) jump_targets = self.find_jump_targets(show_asm) # contains (code, [addrRefToCode]) @@ -131,7 +137,8 @@ class Scanner26(scan.Scanner2): i += 1 op = self.code[offset] op_name = self.opname[op] - oparg = None; pattr = None + oparg = None + pattr = None if offset in jump_targets: jump_idx = 0 @@ -142,28 +149,37 @@ class Scanner26(scan.Scanner2): # properly. For example, a "loop" with an "if" nested in it should have the # "loop" tag last so the grammar rule matches that properly. last_jump_offset = -1 - for jump_offset in sorted(jump_targets[offset], reverse=True): + for jump_offset in sorted(jump_targets[offset], reverse=True): if jump_offset != last_jump_offset: - tokens.append(Token( - 'COME_FROM', jump_offset, repr(jump_offset), - offset="%s_%d" % (offset, jump_idx), - has_arg = True)) + tokens.append( + Token( + "COME_FROM", + jump_offset, + repr(jump_offset), + offset="%s_%d" % (offset, jump_idx), + has_arg=True, + ) + ) jump_idx += 1 last_jump_offset = jump_offset elif offset in self.thens: - tokens.append(Token( - 'THEN', None, self.thens[offset], - offset="%s_0" % offset, - has_arg = True)) + tokens.append( + Token( + "THEN", + None, + self.thens[offset], + offset="%s_0" % offset, + has_arg=True, + ) + ) - has_arg = (op >= self.opc.HAVE_ARGUMENT) + has_arg = op >= self.opc.HAVE_ARGUMENT if has_arg: oparg = self.get_argument(offset) + extended_arg extended_arg = 0 if op == self.opc.EXTENDED_ARG: - extended_arg += self.extended_arg_val(oparg) - continue - + extended_arg += self.extended_arg_val(oparg) + continue # Note: name used to match on rather than op since # BUILD_SET isn't in earlier Pythons. @@ -172,7 +188,14 @@ class Scanner26(scan.Scanner2): "BUILD_SET", ): t = Token( - op_name, oparg, pattr, offset, self.linestarts.get(offset, None), op, has_arg, self.opc + op_name, + oparg, + pattr, + offset, + self.linestarts.get(offset, None), + op, + has_arg, + self.opc, ) collection_type = op_name.split("_")[1] @@ -221,8 +244,8 @@ class Scanner26(scan.Scanner2): # FIXME: this is a hack to catch stuff like: # if x: continue # the "continue" is not on a new line. - if len(tokens) and tokens[-1].kind == 'JUMP_BACK': - tokens[-1].kind = intern('CONTINUE') + if len(tokens) and tokens[-1].kind == "JUMP_BACK": + tokens[-1].kind = intern("CONTINUE") elif op in self.opc.JABS_OPS: pattr = repr(oparg) @@ -240,17 +263,23 @@ class Scanner26(scan.Scanner2): # CE - Hack for >= 2.5 # Now all values loaded via LOAD_CLOSURE are packed into # a tuple before calling MAKE_CLOSURE. - if (self.version >= (2, 5) and op == self.opc.BUILD_TUPLE and - self.code[self.prev[offset]] == self.opc.LOAD_CLOSURE): + if ( + self.version >= (2, 5) + and op == self.opc.BUILD_TUPLE + and self.code[self.prev[offset]] == self.opc.LOAD_CLOSURE + ): continue else: - op_name = '%s_%d' % (op_name, oparg) + op_name = "%s_%d" % (op_name, oparg) customize[op_name] = oparg elif self.version > (2, 0) and op == self.opc.CONTINUE_LOOP: customize[op_name] = 0 - elif op_name in """ + elif ( + op_name + in """ CONTINUE_LOOP EXEC_STMT LOAD_LISTCOMP LOAD_SETCOMP - """.split(): + """.split() + ): customize[op_name] = 0 elif op == self.opc.JUMP_ABSOLUTE: # Further classify JUMP_ABSOLUTE into backward jumps @@ -266,23 +295,24 @@ class Scanner26(scan.Scanner2): # rule for that. target = self.get_target(offset) if target <= offset: - op_name = 'JUMP_BACK' - if (offset in self.stmts - and self.code[offset+3] not in (self.opc.END_FINALLY, - self.opc.POP_BLOCK)): - if ((offset in self.linestarts and - tokens[-1].kind == 'JUMP_BACK') - or offset not in self.not_continue): - op_name = 'CONTINUE' + op_name = "JUMP_BACK" + if offset in self.stmts and self.code[offset + 3] not in ( + self.opc.END_FINALLY, + self.opc.POP_BLOCK, + ): + if ( + offset in self.linestarts and tokens[-1].kind == "JUMP_BACK" + ) or offset not in self.not_continue: + op_name = "CONTINUE" else: # FIXME: this is a hack to catch stuff like: # if x: continue # the "continue" is not on a new line. - if tokens[-1].kind == 'JUMP_BACK': + if tokens[-1].kind == "JUMP_BACK": # We need 'intern' since we have # already have processed the previous # token. - tokens[-1].kind = intern('CONTINUE') + tokens[-1].kind = intern("CONTINUE") elif op == self.opc.LOAD_GLOBAL: if offset in self.load_asserts: @@ -316,6 +346,7 @@ class Scanner26(scan.Scanner2): pass if show_asm in ("both", "after"): + print("\n# ---- after tokenization:") for t in tokens: print(t.format(line_prefix="")) print()