def __exit__(self, *args): self.test_frames = inspect.getouterframes(inspect.currentframe()) # from IPython.core.debugger import set_trace; set_trace() retcode = super(CacheLocals, self).__exit__(*args) funcode = copy.copy(self.bytecode) funcode.append(bytecode.Instr('LOAD_CONST', None)) funcode.append(bytecode.Instr('RETURN_VALUE')) frame = self._get_context_frame() change_lookups(funcode, locals_=frame.f_locals) # self.source = inspect.getsource(funcode.to_code()) assigned_locals = {} for i, instr in enumerate(funcode): if getattr(instr, 'name', None) in ('STORE_FAST', 'STORE_NAME'): # TODO: Could we use the code leading up to a variable as a # hash? assigned_locals[instr.arg] = bytecode.Bytecode(funcode[:i + 1]) self._get_cached(funcode.to_code(), assigned_locals) self.assigned_locals = assigned_locals return retcode
def make_code_obj( name: str, filename: str, lineno: int, doc: str, args: List[str], frees: List[str], cells: List[str], instructions: List[BC.Instr], ): """Create code object from given metadata and instructions """ if not instructions: instructions.append(I.LOAD_CONST(None)) instructions.append(I.RETURN_VALUE()) instructions = list(merge_labels(instructions)) bc_code = BC.Bytecode(instructions) bc_code.name = name bc_code.filename = filename bc_code.first_lineno = lineno bc_code.docstring = doc bc_code.argnames.extend(args) bc_code.argcount = len(bc_code.argnames) bc_code.freevars.extend(frees) bc_code.cellvars.extend(cells) stack_size = bc_code.compute_stacksize() c_code = bc_code.to_concrete_bytecode() c_code.flags = BC.flags.infer_flags(c_code) py_code = c_code.to_code(stacksize=stack_size) return py_code
def to_code(self): """ Create a Python code object from the current code ops. """ bc_code = bc.Bytecode(self.code_ops) bc_code.argnames = self.args # The number of positional or keyword args correspond to all args minus: # - the positionals only # - the keywords only # - the variadic positional # - the variadic keyword bc_code.argcount = (len(self.args) - self.kwonlyargs - self.posonlyargs - self.varargs - self.varkwargs) if POS_ONLY_ARGS: bc_code.posonlyargcount = self.posonlyargs bc_code.kwonlyargcount = self.kwonlyargs for name in ("name", "filename", "firstlineno", "docstring"): setattr(bc_code, name, getattr(self, name)) # Set flags appropriately and update flags based on the instructions for setting, flag in zip( (self.varargs, self.varkwargs, self.newlocals), (bc.CompilerFlags.VARARGS, bc.CompilerFlags.VARKEYWORDS, bc.CompilerFlags.NEWLOCALS)): # Set the flag if setting: bc_code.flags |= flag # Unset the flag if it was set else: bc_code.flags ^= (bc_code.flags & flag) bc_code.update_flags() return bc_code.to_code()
def serialize_code(code): c = bytecode.Bytecode().from_code(code).to_concrete_bytecode() return ({ "co_consts": consts_to_rust_enum(c.consts), "co_names": c.names, "co_name": c.name, "co_code": parse_co_code_to_str(c), "co_varnames": c.varnames })
def build(self, arguments=[], name="<input>"): if isinstance(arguments, ast_objects.Null): arguments = [] elif isinstance(arguments, ast_objects.Array): arguments = [s.getname() for s in arguments.getstatements()] return bytecode.Bytecode( instructions=self.instructions, name=name, arguments=arguments, constants=self.constants, variables=self.variables, )
def inject_instructions_to_bytecode(byte_co): byte_code = bytecode.Bytecode.from_code(byte_co) line_number = 1 bc_instr = bytecode._InstrList() for i in range(len(byte_code)): instruction = byte_code[i] if instruction.__class__ is bytecode.Label: bc_instr.append(instruction) continue new_line_number = instruction.lineno if instruction.name == 'LOAD_CONST' and inspect.iscode( instruction.arg): bc_instr.append( bytecode.Instr('LOAD_GLOBAL', 'Debugger.get_instruction')) bc_instr.append(instruction) bc_instr.append(bytecode.Instr('CALL_FUNCTION', 1)) line_number = new_line_number elif new_line_number != line_number: bc_instr.append(instruction) bc_instr.append( bytecode.Instr('LOAD_GLOBAL', 'self.debug_function', lineno=new_line_number)) bc_instr.append( bytecode.Instr('CALL_FUNCTION', 0, lineno=new_line_number)) bc_instr.append( bytecode.Instr('POP_TOP', lineno=new_line_number)) line_number = new_line_number else: bc_instr.append(instruction) print() for i in bc_instr: print(i) code = bytecode.Bytecode(bc_instr) code.name = byte_co.co_name code.argcount = byte_co.co_argcount code.argnames = byte_code.argnames code.filename = byte_code.filename code.flags = byte_code.flags code.first_lineno = byte_code.first_lineno code.cellvars = byte_code.cellvars code.freevars = byte_code.freevars return code.to_code()
def to_bytecode(self): """Convert to Bytecode.""" used_blocks = set() for block in self: target_block = block.get_jump() if target_block is not None: used_blocks.add(id(target_block)) labels = {} jumps = [] instructions = [] for block in self: if id(block) in used_blocks: new_label = Label() labels[id(block)] = new_label instructions.append(new_label) for instr in block: # don't copy SetLineno objects if isinstance(instr, (Instr, ConcreteInstr)): instr = instr.copy() if isinstance(instr.arg, BasicBlock): jumps.append(instr) instructions.append(instr) # Map to new labels for instr in jumps: instr.arg = labels[id(instr.arg)] bytecode = _bytecode.Bytecode() bytecode._copy_attr_from(self) bytecode.argnames = list(self.argnames) bytecode[:] = instructions return bytecode
def to_bytecode(self): # find jump targets jump_targets = set() offset = 0 for instr in self: if isinstance(instr, SetLineno): continue target = instr.get_jump_target(offset) if target is not None: jump_targets.add(target) offset += instr.size # create labels jumps = [] instructions = [] labels = {} offset = 0 ncells = len(self.cellvars) for lineno, instr in self._normalize_lineno(): if offset in jump_targets: label = Label() labels[offset] = label instructions.append(label) jump_target = instr.get_jump_target(offset) size = instr.size arg = instr.arg # FIXME: better error reporting if instr.opcode in _opcode.hasconst: arg = self.consts[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() 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