LOAD_CONST -> LOAD_CODE where appropriate

This commit is contained in:
rocky
2019-06-19 14:43:07 -04:00
parent e2d7f01298
commit 24afe072b7
7 changed files with 72 additions and 42 deletions

View File

@@ -498,6 +498,7 @@ class PythonParser(GenericASTBuilder):
def p_expr(self, args):
'''
expr ::= _mklambda
expr ::= LOAD_CODE
expr ::= LOAD_FAST
expr ::= LOAD_NAME
expr ::= LOAD_CONST

View File

@@ -459,7 +459,7 @@ class Python2Parser(PythonParser):
if i > 0 and tokens[i-1] == 'LOAD_LAMBDA':
self.addRule('mklambda ::= %s LOAD_LAMBDA %s' %
('pos_arg ' * token.attr, opname), nop_func)
rule = 'mkfunc ::= %s LOAD_CONST %s' % ('expr ' * token.attr, opname)
rule = 'mkfunc ::= %s LOAD_CODE %s' % ('expr ' * token.attr, opname)
elif opname_base == 'MAKE_CLOSURE':
# FIXME: use add_unique_rules to tidy this up.
if i > 0 and tokens[i-1] == 'LOAD_LAMBDA':
@@ -474,7 +474,7 @@ class Python2Parser(PythonParser):
('expr ' * token.attr, opname))], customize)
pass
self.add_unique_rules([
('mkfunc ::= %s load_closure LOAD_CONST %s' %
('mkfunc ::= %s load_closure LOAD_CODE %s' %
('expr ' * token.attr, opname))], customize)
if self.version >= 2.7:

View File

@@ -1015,19 +1015,19 @@ class Python3Parser(PythonParser):
# Note order of kwargs and pos args changed between 3.3-3.4
if self.version <= 3.2:
rule = "mkfunc ::= %s%sload_closure LOAD_CONST %s" % (
rule = "mkfunc ::= %s%sload_closure LOAD_CODE %s" % (
kwargs_str,
"expr " * args_pos,
opname,
)
elif self.version == 3.3:
rule = "mkfunc ::= %s%sload_closure LOAD_CONST LOAD_STR %s" % (
rule = "mkfunc ::= %s%sload_closure LOAD_CODE LOAD_STR %s" % (
kwargs_str,
"expr " * args_pos,
opname,
)
elif self.version >= 3.4:
rule = "mkfunc ::= %s%s load_closure LOAD_CONST LOAD_STR %s" % (
rule = "mkfunc ::= %s%s load_closure LOAD_CODE LOAD_STR %s" % (
"expr " * args_pos,
kwargs_str,
opname,
@@ -1043,7 +1043,7 @@ class Python3Parser(PythonParser):
self.add_unique_rule(rule, opname, token.attr, customize)
if self.version < 3.4:
rule = "mkfunc ::= %sload_closure LOAD_CONST %s" % (
rule = "mkfunc ::= %sload_closure LOAD_CODE %s" % (
"expr " * args_pos,
opname,
)
@@ -1083,7 +1083,7 @@ class Python3Parser(PythonParser):
rule = "mkfunc ::= %s%s%s%s" % (
"expr " * stack_count,
"load_closure " * closure,
"LOAD_CONST LOAD_STR ",
"LOAD_CODE LOAD_STR ",
opname,
)
self.add_unique_rule(rule, opname, token.attr, customize)
@@ -1186,13 +1186,13 @@ class Python3Parser(PythonParser):
rule = "mkfunc ::= %s %s%s%s" % (
kwargs,
"pos_arg " * args_pos,
"LOAD_CONST ",
"LOAD_CODE ",
opname,
)
self.add_unique_rule(rule, opname, token.attr, customize)
rule = "mkfunc ::= %s%s%s" % (
"pos_arg " * args_pos,
"LOAD_CONST ",
"LOAD_CODE ",
opname,
)
elif self.version == 3.3:
@@ -1200,7 +1200,7 @@ class Python3Parser(PythonParser):
rule = "mkfunc ::= %s %s%s%s" % (
kwargs,
"pos_arg " * args_pos,
"LOAD_CONST LOAD_STR ",
"LOAD_CODE LOAD_STR ",
opname,
)
elif self.version > 3.5:
@@ -1208,7 +1208,7 @@ class Python3Parser(PythonParser):
rule = "mkfunc ::= %s%s %s%s" % (
"pos_arg " * args_pos,
kwargs,
"LOAD_CONST LOAD_STR ",
"LOAD_CODE LOAD_STR ",
opname,
)
elif self.version > 3.3:
@@ -1216,7 +1216,7 @@ class Python3Parser(PythonParser):
rule = "mkfunc ::= %s%s %s%s" % (
"pos_arg " * args_pos,
kwargs,
"LOAD_CONST LOAD_STR ",
"LOAD_CODE LOAD_STR ",
opname,
)
else:

View File

@@ -287,6 +287,8 @@ class Scanner2(Scanner):
op_name = 'LOAD_DICTCOMP'
elif const.co_name == '<setcomp>':
op_name = 'LOAD_SETCOMP'
else:
op_name = "LOAD_CODE"
# verify() uses 'pattr' for comparison, since 'attr'
# now holds Code(const) and thus can not be used
# for comparison (todo: think about changing this)

View File

@@ -173,6 +173,8 @@ class Scanner26(scan.Scanner2):
op_name = 'LOAD_DICTCOMP'
elif const.co_name == '<setcomp>':
op_name = 'LOAD_SETCOMP'
else:
op_name = "LOAD_CODE"
# verify uses 'pattr' for comparison, since 'attr'
# now holds Code(const) and thus can not be used
# for comparison (todo: think about changing this)

View File

@@ -361,6 +361,8 @@ class Scanner3(Scanner):
opname = "LOAD_SETCOMP"
elif const.co_name == "<listcomp>":
opname = "LOAD_LISTCOMP"
else:
opname = "LOAD_CODE"
# verify() uses 'pattr' for comparison, since 'attr'
# now holds Code(const) and thus can not be used
# for comparison (todo: think about changing this)

View File

@@ -21,19 +21,30 @@ from uncompyle6 import PYTHON3
if PYTHON3:
intern = sys.intern
class Token():
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):
def __init__(
self,
opname,
attr=None,
pattr=None,
offset=-1,
linestart=None,
op=None,
has_arg=None,
opc=None,
):
self.kind = intern(opname)
self.has_arg = has_arg
self.attr = attr
@@ -46,6 +57,7 @@ class Token():
if opc is None:
from xdis.std import _std_api
self.opc = _std_api.opc
else:
self.opc = opc
@@ -58,10 +70,9 @@ class Token():
""" '==' 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) or self.attr == o.attr)
)
return (self.kind == o.kind) and (
(self.pattr == o.pattr) or self.attr == o.attr
)
else:
# ?? do we need this?
return self.kind == o
@@ -80,56 +91,67 @@ class Token():
# ('%9s %-18s %r' % (self.offset, self.kind, pattr)))
def __str__(self):
return self.format(line_prefix='')
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)
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)
argstr = "%6d " % self.attr if isinstance(self.attr, int) else (" " * 7)
name = self.kind
if self.has_arg:
pattr = self.pattr
if self.opc:
if self.op in self.opc.JREL_OPS:
if not self.pattr.startswith('to '):
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 '):
if not self.pattr.startswith("to "):
pattr = "to " + str(self.pattr)
pass
elif self.op in self.opc.CONST_OPS:
if name == 'LOAD_STR':
if name == "LOAD_STR":
pattr = self.attr
elif name == 'LOAD_CODE':
return "%s%s%s %s" % (prefix, offset_opname, argstr, pattr)
elif name == "LOAD_CODE":
return "%s%s%s %s" % (prefix, offset_opname, argstr, pattr)
else:
return "%s%s %r" % (prefix, offset_opname, pattr)
return "%s%s %r" % (prefix, offset_opname, pattr)
elif self.op in self.opc.hascompare:
if isinstance(self.attr, int):
pattr = self.opc.cmp_op[self.attr]
return "%s%s%s %s" % (prefix, offset_opname, argstr, pattr)
return "%s%s%s %s" % (prefix, offset_opname, argstr, pattr)
elif self.op in self.opc.hasvargs:
return "%s%s%s" % (prefix, offset_opname, argstr)
return "%s%s%s" % (prefix, offset_opname, argstr)
elif name == 'LOAD_ASSERT':
return "%s%s %s" % (prefix, offset_opname, pattr)
elif self.op in self.opc.NAME_OPS:
if self.opc.version >= 3.0:
return "%s%s%s %s" % (prefix, offset_opname, argstr, self.attr)
elif name == 'EXTENDED_ARG':
return "%s%s%s 0x%x << %s = %s" % (prefix, offset_opname, argstr, self.attr,
self.opc.EXTENDED_ARG_SHIFT, pattr)
return "%s%s%s %s" % (prefix, offset_opname, argstr, self.attr)
elif name == "EXTENDED_ARG":
return "%s%s%s 0x%x << %s = %s" % (
prefix,
offset_opname,
argstr,
self.attr,
self.opc.EXTENDED_ARG_SHIFT,
pattr,
)
# And so on. See xdis/bytecode.py get_instructions_bytes
pass
elif re.search(r'_\d+$', self.kind):
return "%s%s%s" % (prefix, offset_opname, argstr)
elif re.search(r"_\d+$", self.kind):
return "%s%s%s" % (prefix, offset_opname, argstr)
else:
pattr = ''
return "%s%s%s %r" % (prefix, offset_opname, argstr, pattr)
pattr = ""
return "%s%s%s %r" % (prefix, offset_opname, argstr, pattr)
def __hash__(self):
return hash(self.kind)
@@ -137,4 +159,5 @@ class Token():
def __getitem__(self, i):
raise IndexError
NoneToken = Token('LOAD_CONST', offset=-1, attr=None, pattr=None)
NoneToken = Token("LOAD_CONST", offset=-1, attr=None, pattr=None)