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): 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): # Copy instruction and remove extended args if any (in-place) c_instructions = self[:] self._remove_extended_args(c_instructions) # find jump targets jump_targets = set() offset = 0 for instr in c_instructions: 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(c_instructions, self.first_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, offset=instr.offset) 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, offset=instr.offset) 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