Example #1
0
def COMPARE_OP(ctx: _VSContext, instruction: dis.Instruction):
    """
    Implements comparison operators.
    """
    # TODO: Rewrite COMPARE_OP into Vanstein-ran function calls.
    # TODO: Add all of the comparison functions.
    if instruction.arg == 10:
        # Pop the too match off.
        to_match = ctx.pop()
        # This is what we check.
        raised = ctx.pop()

        from collections import Iterable

        if not isinstance(to_match, Iterable):
            to_match = (to_match, )

        for e in to_match:
            # PyType_IsSubType
            if issubclass(type(raised), e):
                ctx.push(True)
                break
        else:
            ctx.push(False)

    return ctx
Example #2
0
def DUP_TOP(ctx: _VSContext, instruction: dis.Instruction):
    """
    Duplicates the top-most item on the stack.
    """
    item = ctx.pop()
    ctx.push(item)
    ctx.push(item)
    return ctx
Example #3
0
def LOAD_FAST(ctx: _VSContext, instruction: dis.Instruction):
    """
    Loads from VARNAMES.
    """
    item = ctx.varnames[instruction.arg]
    if item == NO_RESULT:
        safe_raise(
            ctx,
            NameError("name '{}' is not defined".format(
                ctx.co_varnames[instruction.arg])))
        return ctx
    ctx.push(item)
    return ctx
Example #4
0
def LOAD_GLOBAL(ctx: _VSContext, instruction: dis.Instruction):
    """
    Loads a global from `ctx.__globals__`.
    """
    name = ctx.co_names[instruction.arg]
    try:
        item = ctx.get_global(name)
    except KeyError:
        # todo: safe_raise
        return safe_raise(ctx,
                          NameError("name '{}' is not defined".format(name)))

    ctx.push(item)
    return ctx
Example #5
0
    def run_context(self, context: _VSContext) -> _VSContext:
        """
        Runs the current bytecode for a context.

        This will instructions off of the instruction stack, until it reaches a context switch.
        """
        # Welcome to the main bulk of Vanstein.
        # Enjoy your stay!

        # Switch to running state for this context.
        context.state = VSCtxState.RUNNING
        self.current_context = context
        while True:
            if context.state is VSCtxState.FINISHED:
                # Done after a successful RETURN_VALUE.
                # Break the loop, and return the context.
                context.finish()
                return context

            if context.state is VSCtxState.ERRORED:
                return context

            next_instruction = context.next_instruction()
            self.current_instruction = next_instruction

            # First, we check if we need to context switch.
            # Check if it's CALL_FUNCTION.
            if next_instruction.opname == "CALL_FUNCTION":
                # This is the instruction for CALL_FUNCTION. No specialized one exists in the instructions.py file.

                # We need to context switch, so suspend this current one.
                context.state = VSCtxState.SUSPENDED
                # Get STACK[-arg]
                # CALL_FUNCTION(arg) => arg is number of positional arguments to use, so pop that off of the stack.
                bottom_of_stack = context.stack[-(next_instruction.arg + 1)]

                # method wrappers die
                if type(bottom_of_stack) is type:
                    bottom_of_stack = bottom_of_stack.__new__

                # Here's some context switching.
                # First, check if it's a builtin or is a native invoke.
                # Also, check if we should even do context switching.
                if inspect.isbuiltin(bottom_of_stack) or hasattr(bottom_of_stack, "_native_invoke")\
                        or self.do_context_switching is False:
                    # Run it!
                    result = self.__run_natively(context, next_instruction)
                    # Set the result on the context.
                    context.state = VSCtxState.RUNNING
                    # Push the result onto the stack.
                    context.push(result)
                    # Continue the loop to the next instruction.
                    continue

                if isinstance(bottom_of_stack, VSWrappedFunction):
                    # Call the VSWrappedFunction to get a new context.
                    # We'll manually fill these args.
                    new_ctx = bottom_of_stack()

                else:
                    # Wrap the function in a context.
                    new_ctx = _VSContext(bottom_of_stack)

                # Set the previous context, for stack frame chaining.
                new_ctx.prev_ctx = context
                # Doubly linked list!
                context.next_ctx = new_ctx
                # Set the new state to PENDING so it knows to run it on the next run.
                new_ctx.state = VSCtxState.PENDING

                # Add a callback to the new context.
                # This is so the loop can schedule execution of the new context soon.
                new_ctx.add_done_callback(context._on_result_cb)
                new_ctx.add_exception_callback(context._on_exception_cb)

                # Fill the number of arguments the function call requests.
                args = []
                for _ in range(0, next_instruction.arg):
                    args.append(context.pop())

                args = reversed(args)

                new_ctx.fill_args(*args)

                # Pop the function object off, too.
                context.pop()

                return new_ctx

            # Else, we run the respective instruction.
            try:
                i = getattr(instructions, next_instruction.opname)
            except AttributeError:
                raise NotImplementedError(next_instruction.opname)

            # Call the instruction handler.
            i(context, next_instruction)
Example #6
0
def LOAD_CONST(ctx: _VSContext, instruction: dis.Instruction):
    """
    Loads a const from `ctx.co_consts`.
    """
    ctx.push(ctx.co_consts[instruction.arg])
    return ctx