You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
97 lines
3.3 KiB
Python
97 lines
3.3 KiB
Python
# Copyright (c) 2016-2018 by Rocky Bernstein
|
|
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
|
# Copyright (c) 1999 John Aycock
|
|
|
|
import re, sys
|
|
from uncompyle6 import PYTHON3
|
|
|
|
if PYTHON3:
|
|
intern = sys.intern
|
|
|
|
class Token():
|
|
"""
|
|
Class representing a byte-code instruction.
|
|
|
|
A byte-code token is equivalent to Python 3's dis.instruction or
|
|
the contents of one line as output by dis.dis().
|
|
"""
|
|
# FIXME: match Python 3.4's terms:
|
|
# linestart = starts_line
|
|
# attr = argval
|
|
# pattr = argrepr
|
|
def __init__(self, opname, attr=None, pattr=None, offset=-1,
|
|
linestart=None, op=None, has_arg=None, opc=None):
|
|
self.kind = intern(opname)
|
|
self.op = op
|
|
self.has_arg = has_arg
|
|
self.attr = attr
|
|
self.pattr = pattr
|
|
self.offset = offset
|
|
self.linestart = linestart
|
|
if has_arg is False:
|
|
self.attr = None
|
|
self.pattr = None
|
|
self.opc = opc
|
|
|
|
def __eq__(self, o):
|
|
""" '==' on kind and "pattr" attributes.
|
|
It is okay if offsets and linestarts are different"""
|
|
if isinstance(o, Token):
|
|
return (self.kind == o.kind) and (self.pattr == o.pattr)
|
|
else:
|
|
# ?? do we need this?
|
|
return self.kind == o
|
|
|
|
def __ne__(self, o):
|
|
""" '!=', but it's okay if offsets and linestarts are different"""
|
|
return not self.__eq__(o)
|
|
|
|
def __repr__(self):
|
|
return str(self.kind)
|
|
|
|
# def __str__(self):
|
|
# pattr = self.pattr if self.pattr is not None else ''
|
|
# prefix = '\n%3d ' % self.linestart if self.linestart else (' ' * 6)
|
|
# return (prefix +
|
|
# ('%9s %-18s %r' % (self.offset, self.kind, pattr)))
|
|
|
|
def __str__(self):
|
|
return self.format(line_prefix='')
|
|
|
|
def format(self, line_prefix=''):
|
|
prefix = ('\n%s%4d ' % (line_prefix, self.linestart)
|
|
if self.linestart else (' ' * (6 + len(line_prefix))))
|
|
offset_opname = '%6s %-17s' % (self.offset, self.kind)
|
|
if not self.has_arg:
|
|
return "%s%s" % (prefix, offset_opname)
|
|
argstr = "%6d " % self.attr if isinstance(self.attr, int) else (' '*7)
|
|
if self.pattr:
|
|
pattr = self.pattr
|
|
if self.opc:
|
|
if self.op in self.opc.JREL_OPS:
|
|
if not self.pattr.startswith('to '):
|
|
pattr = "to " + self.pattr
|
|
elif self.op in self.opc.JABS_OPS:
|
|
self.pattr= str(self.pattr)
|
|
if not self.pattr.startswith('to '):
|
|
pattr = "to " + str(self.pattr)
|
|
pass
|
|
elif self.op in self.opc.hascompare:
|
|
if isinstance(self.attr, int):
|
|
pattr = self.opc.cmp_op[self.attr]
|
|
# And so on. See xdis/bytecode.py get_instructions_bytes
|
|
pass
|
|
elif re.search('_\d+$', self.kind):
|
|
return "%s%s%s" % (prefix, offset_opname, argstr)
|
|
else:
|
|
pattr = ''
|
|
return "%s%s%s %r" % (prefix, offset_opname, argstr, pattr)
|
|
|
|
def __hash__(self):
|
|
return hash(self.kind)
|
|
|
|
def __getitem__(self, i):
|
|
raise IndexError
|
|
|
|
NoneToken = Token('LOAD_CONST', offset=-1, attr=None, pattr=None)
|