Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if jump_target is None:
instr = Instr(instr.name, arg, lineno=lineno)
else:
instr_index = len(instructions)
instructions.append(instr)
offset += size
if jump_target is not None:
jumps.append((instr_index, jump_target))
# replace jump targets with labels
for index, jump_target in jumps:
instr = instructions[index]
# FIXME: better error reporting on missing label
label = labels[jump_target]
instructions[index] = Instr(instr.name, label, lineno=instr.lineno)
bytecode = _bytecode.Bytecode()
bytecode._copy_attr_from(self)
nargs = bytecode.argcount + bytecode.kwonlyargcount
if sys.version_info > (3, 8):
nargs += bytecode.posonlyargcount
if bytecode.flags & inspect.CO_VARARGS:
nargs += 1
if bytecode.flags & inspect.CO_VARKEYWORDS:
nargs += 1
bytecode.argnames = self.varnames[:nargs]
_set_docstring(bytecode, self.consts)
bytecode.extend(instructions)
return bytecode
def __call__(self, *args, **kwargs) -> Instr:
ret = Instr(self.name, *args, **kwargs)
self.instrs.append(ret)
return ret
const_key,
_check_arg_int,
)
_WORDCODE = sys.version_info >= (3, 6)
def _set_docstring(code, consts):
if not consts:
return
first_const = consts[0]
if isinstance(first_const, str) or first_const is None:
code.docstring = first_const
class ConcreteInstr(Instr):
"""Concrete instruction.
arg must be an integer in the range 0..2147483647.
It has a read-only size attribute.
"""
__slots__ = ("_size", "_extended_args")
def __init__(self, name, arg=UNSET, *, lineno=None, extended_args=None):
# Allow to remember a potentially meaningless EXTENDED_ARG emitted by
# Python to properly compute the size and avoid messing up the jump
# targets
self._extended_args = extended_args
self._set(name, arg, lineno)
ncells = len(self.bytecode.cellvars)
lineno = self.bytecode.first_lineno
for instr in self.bytecode:
if isinstance(instr, Label):
self.labels[instr] = len(self.instructions)
continue
if isinstance(instr, SetLineno):
lineno = instr.lineno
continue
if isinstance(instr, ConcreteInstr):
instr = instr.copy()
else:
assert isinstance(instr, Instr)
if instr.lineno is not None:
lineno = instr.lineno
arg = instr.arg
is_jump = isinstance(arg, Label)
if is_jump:
label = arg
# fake value, real value is set in compute_jumps()
arg = 0
elif instr.opcode in _opcode.hasconst:
arg = self.add_const(arg)
elif instr.opcode in _opcode.haslocal:
arg = self.add(self.varnames, arg)
elif instr.opcode in _opcode.hasname:
arg = self.add(self.names, arg)
elif instr.opcode in _opcode.haslocal:
arg = self.varnames[arg]
elif instr.opcode in _opcode.hasname:
arg = self.names[arg]
elif instr.opcode in _opcode.hasfree:
if arg < ncells:
name = self.cellvars[arg]
arg = CellVar(name)
else:
name = self.freevars[arg - ncells]
arg = FreeVar(name)
elif instr.opcode in _opcode.hascompare:
arg = Compare(arg)
if jump_target is None:
instr = Instr(instr.name, arg, lineno=lineno)
else:
instr_index = len(instructions)
instructions.append(instr)
offset += size
if jump_target is not None:
jumps.append((instr_index, jump_target))
# replace jump targets with labels
for index, jump_target in jumps:
instr = instructions[index]
# FIXME: better error reporting on missing label
label = labels[jump_target]
instructions[index] = Instr(instr.name, label, lineno=instr.lineno)
bytecode = _bytecode.Bytecode()
def from_bytecode(bytecode):
# label => instruction index
label_to_block_index = {}
jumps = []
block_starts = {}
for index, instr in enumerate(bytecode):
if isinstance(instr, Label):
label_to_block_index[instr] = index
else:
if isinstance(instr, Instr) and isinstance(instr.arg, Label):
jumps.append((index, instr.arg))
for target_index, target_label in jumps:
target_index = label_to_block_index[target_label]
block_starts[target_index] = target_label
bytecode_blocks = _bytecode.ControlFlowGraph()
bytecode_blocks._copy_attr_from(bytecode)
bytecode_blocks.argnames = list(bytecode.argnames)
# copy instructions, convert labels to block labels
block = bytecode_blocks[0]
labels = {}
jumps = []
for index, instr in enumerate(bytecode):
if index in block_starts:
def _flat(self):
instructions = []
labels = {}
jumps = []
offset = 0
for index, instr in enumerate(self):
if isinstance(instr, Label):
instructions.append("label_instr%s" % index)
labels[instr] = offset
else:
if isinstance(instr, Instr) and isinstance(instr.arg, Label):
target_label = instr.arg
instr = _bytecode.ConcreteInstr(instr.name, 0, lineno=instr.lineno)
jumps.append((target_label, instr))
instructions.append(instr)
offset += 1
for target_label, instr in jumps:
instr.arg = labels[target_label]
return instructions