Example #1
0
    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
Example #2
0
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
Example #3
0
    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()
Example #4
0
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
    })
Example #5
0
    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,
        )
Example #6
0
 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()
Example #7
0
    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
Example #8
0
    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