Exemplo n.º 1
0
        def _make_function(self, instr):
            """
            Functions should have strict names.
            """
            yield instructions.LOAD_CONST(strict).steal(instr)
            # TOS = strict
            # TOS1 = func_name

            yield instructions.ROT_TWO()
            # TOS = func_name
            # TOS1 = strict

            yield instructions.CALL_FUNCTION(1)
            # TOS = strict(func_name)

            yield instr
            # TOS = new_function

            yield instructions.LOAD_CONST(thunk_type.fromexpr)
            # TOS  thunk_type.fromexpr
            # TOS1 new_function

            yield instructions.ROT_TWO()
            # TOS  new_function
            # TOS1 thunk_type.fromexpr

            yield instructions.CALL_FUNCTION(1)
Exemplo n.º 2
0
 def _dis():
     yield instructions.LOAD_CONST(dis)
     yield instructions.LOAD_CONST(sys._getframe)
     yield instructions.CALL_FUNCTION(0)
     yield instructions.LOAD_ATTR('f_code')
     yield instructions.CALL_FUNCTION(1)
     yield instructions.POP_TOP()
     yield next_instruction()
Exemplo n.º 3
0
 def words():
     yield instructions.LOAD_CONST(
         compose(
             pprint,
             partial(sorted, key=op.attrgetter('name')),
             dict.values,
         ))
     yield instructions.LOAD_CONST(globals)
     yield instructions.CALL_FUNCTION(0)
     yield instructions.CALL_FUNCTION(1)
     yield instructions.POP_TOP()
     yield next_instruction()
Exemplo n.º 4
0
 def lparen():
     loop = instructions.LOAD_CONST(')')
     yield loop
     yield from _word()
     yield instructions.COMPARE_OP.EQ
     yield instructions.POP_JUMP_IF_FALSE(loop)
     yield next_instruction()
Exemplo n.º 5
0
 def semicolon():
     yield from write_short(vocab['exit'].addr - 1)
     yield instructions.LOAD_CONST(push_return_addr)
     yield instructions.CALL_FUNCTION()
     yield instructions.POP_TOP()
     yield instructions.JUMP_ABSOLUTE(word_instrs[']'][0])
     yield next_instruction()
Exemplo n.º 6
0
    def _start_comprehension(self, instr, *instrs):
        yield instructions.LOAD_CONST(self.astype).steal(instr)
        # TOS  = self.astype

        yield instructions.CALL_FUNCTION(0)
        # TOS  = m = self.astype()

        yield instructions.STORE_FAST('__map__')

        body, map_add = instrs[:-1], instrs[-1]
        for item in self.patterndispatcher(body):
            yield item
        # TOS  = k
        # TOS1 = v

        yield instructions.LOAD_FAST('__map__').steal(map_add)
        # TOS  = __map__
        # TOS1 = k
        # TOS2 = v

        yield instructions.ROT_TWO()
        # TOS  = k
        # TOS1 = __map__
        # TOS2 = v

        yield instructions.STORE_SUBSCR()
        self.begin(IN_COMPREHENSION)
Exemplo n.º 7
0
    def pushcfa():
        yield instructions.DUP_TOP()
        yield instructions.LOAD_CONST(Word)
        yield instructions.LOAD_CONST(isinstance)
        yield instructions.ROT_THREE()
        yield instructions.CALL_FUNCTION(2)

        not_word_instr = instructions.LOAD_CONST(NotAWord)
        yield instructions.POP_JUMP_IF_FALSE(not_word_instr)

        yield instructions.LOAD_ATTR('addr')
        yield next_instruction()

        yield not_word_instr
        yield instructions.ROT_TWO()
        yield instructions.CALL_FUNCTION(1)
        yield instructions.RAISE_VARARGS(1)
Exemplo n.º 8
0
 def _build_list(self, instr):
     if instr.arg == 0:
         yield instrs.LOAD_CONST(jl.jlist).steal(instr)
         yield instrs.CALL_FUNCTION(0)
     elif instr.arg == 1:
         yield instrs.LOAD_CONST(jl.jlist._from_starargs).steal(instr)
         yield instrs.ROT_TWO()
         yield instrs.CALL_FUNCTION(1)
     elif instr.arg == 2:
         yield instrs.LOAD_CONST(jl.jlist._from_starargs).steal(instr)
         yield instrs.ROT_THREE()
         yield instrs.CALL_FUNCTION(2)
     else:
         yield instr
         yield instrs.LOAD_CONST(jl.jlist)
         yield instrs.ROT_TWO()
         yield instrs.CALL_FUNCTION(1)
Exemplo n.º 9
0
def make_noop_func(n):
    """Create a function with N noops"""
    co = Code(
        [inst.NOP() for _ in range(n)] +
        [inst.LOAD_CONST(None), inst.RETURN_VALUE()])
    f = lambda: None
    f.__code__ = co.to_pycode()

    return f
Exemplo n.º 10
0
        def _build_map(self, instr):
            yield instructions.LOAD_CONST(self.astype).steal(instr)
            # TOS  = self.astype

            yield instructions.CALL_FUNCTION(0)
            # TOS  = m = self.astype()

            for item in (instructions.DUP_TOP(), ) * instr.arg:
                yield item
Exemplo n.º 11
0
 def sync_frame():
     """Sync the frame object with some local variables in
     PyEval_EvalFrameEx. This needs to happend before using any primitive
     function that cares about the instruction pointer or the stacksize.
     """
     # our custom runner understands that `yield None` means 'do not jump
     # anywhere, just sync the frame and continue
     yield instructions.LOAD_CONST(None)
     yield instructions.YIELD_VALUE()
Exemplo n.º 12
0
        def _load_name(self, instr):
            yield instructions.LOAD_CONST(thunk_type.fromexpr).steal(instr)
            # TOS  thunk_type.fromexpr

            yield instr
            # TOS  v
            # TOS1 thunk_type.fromexpr

            yield instructions.CALL_FUNCTION(1)
Exemplo n.º 13
0
 def _tail():
     for _ in range(memory - len(list(_sparse_args(instrs))) - 15):
         yield instructions.NOP()
     yield handle_exception_instr
     yield from _nip()
     yield instructions.LOAD_CONST(handle_exception)
     yield instructions.ROT_TWO()
     yield instructions.CALL_FUNCTION(1)
     yield instructions.POP_TOP()
     yield instructions.POP_EXCEPT()
     yield instructions.JUMP_ABSOLUTE(setup_except_instr)
Exemplo n.º 14
0
 def colon():
     yield instructions.LOAD_CONST(push_return_addr)
     yield instructions.CALL_FUNCTION()
     yield instructions.POP_TOP()
     yield instructions.JUMP_ABSOLUTE(word_instrs['word'][0])
     yield instructions.LOAD_CONST(push_return_addr)
     yield instructions.CALL_FUNCTION()
     yield instructions.POP_TOP()
     yield instructions.JUMP_ABSOLUTE(word_instrs['create'][0])
     yield from write_byte(instructions.LOAD_CONST.opcode)
     yield from write_short(0)  # push_return_addr
     yield from write_byte(instructions.CALL_FUNCTION.opcode)
     yield from write_short(0)
     yield from write_byte(instructions.POP_TOP.opcode)
     yield from write_byte(instructions.JUMP_ABSOLUTE.opcode)
     yield from write_short(vocab['__docol'].addr)
     yield instructions.LOAD_CONST(push_return_addr)
     yield instructions.CALL_FUNCTION()
     yield instructions.POP_TOP()
     yield instructions.JUMP_ABSOLUTE(word_instrs['['][0])
     yield next_instruction()
Exemplo n.º 15
0
    def _binary_subscr(self, instr):
        yield instructions.LOAD_CONST(self._islicer).steal(instr)
        # TOS  = self._islicer
        # TOS1 = k
        # TOS2 = m

        yield instructions.ROT_THREE()
        # TOS  = k
        # TOS1 = m
        # TOS2 = self._islicer

        yield instructions.CALL_FUNCTION(2)
Exemplo n.º 16
0
        def _import_name(self, instr):
            # TOS  fromlist
            # TOS1 level

            yield instructions.LOAD_CONST(self._import_wrapper).steal(instr)
            # TOS  self._import_wrapper
            # TOS1 fromlist
            # TOS2 level

            yield instructions.ROT_THREE()
            # TOS  fromlist
            # TOS1 level
            # TOS2 self._import_wrapper

            yield instructions.LOAD_CONST(instr.arg)
            # TOS  name
            # TOS1 fromlist
            # TOS2 level
            # TOS3 self._import_wrapper

            yield instructions.CALL_FUNCTION(3)
Exemplo n.º 17
0
    def quote():
        yield instructions.LOAD_CONST(push_return_addr)
        yield instructions.CALL_FUNCTION()
        yield instructions.POP_TOP()
        yield instructions.JUMP_ABSOLUTE(word_instrs['word'][0])
        # We need to duplicate the word on the stack for proper error handling
        # later.
        # We dup it once giving us 2 copies on the stack for:
        #   find
        #   unknown word error
        yield instructions.DUP_TOP()
        yield instructions.LOAD_CONST(push_return_addr)
        yield instructions.CALL_FUNCTION(0)
        yield instructions.POP_TOP()
        yield instructions.JUMP_ABSOLUTE(word_instrs['find'][0])
        yield instructions.DUP_TOP()
        yield instructions.LOAD_CONST(None)
        yield instructions.COMPARE_OP.IS

        unknown_word_instr = instructions.POP_TOP()
        yield instructions.POP_JUMP_IF_TRUE(unknown_word_instr)

        # clear the word strings from the stack
        yield from _nip()
        yield instructions.LOAD_CONST(push_return_addr)
        yield instructions.CALL_FUNCTION(0)
        yield instructions.POP_TOP()
        yield instructions.JUMP_ABSOLUTE(word_instrs['>cfa'][0])
        yield next_instruction()

        yield instructions.POP_JUMP_IF_TRUE(unknown_word_instr)
        # clear the word string left for the unknown word case
        yield from _nip()
        yield next_instruction()

        yield unknown_word_instr
        yield instructions.LOAD_CONST(UnknownWord)
        yield instructions.ROT_TWO()
        yield instructions.CALL_FUNCTION(1)
        yield instructions.RAISE_VARARGS(1)
Exemplo n.º 18
0
def _build(self, instr):
    yield instr
    # TOS  = new_list

    yield instructions.LOAD_CONST(self.xform)
    # TOS  = astype
    # TOS1 = new_list

    yield instructions.ROT_TWO()
    # TOS  = new_list
    # TOS1 = astype

    yield instructions.CALL_FUNCTION(1)
Exemplo n.º 19
0
        def _start_dict_comprehension(self, instr, *instrs):
            # put thunk call on the stack for right befor the return.
            yield instructions.LOAD_CONST(partial(thunk_type, dict))
            # TOS  partial(thunk_type, dict)

            yield instr
            # TOS  dict_
            # TOS1 partial(thunk_type, dict)

            *body, ret = instrs
            yield from self.patterndispatcher(body)
            # TOS  dict_
            # TOS1 partial(thunk_type, dict)

            yield ret
Exemplo n.º 20
0
        def _unary_not(self, instr):
            """
            Replace the `not` operator to act on the values that the thunks.
            represent.
            This makes `not` lazy.
            """
            yield instructions.LOAD_CONST(_lazy_not).steal(instr)
            # TOS  = _lazy_not
            # TOS1 = arg

            yield instructions.ROT_TWO()
            # TOS  = arg
            # TOS1 = _lazy_not

            yield instructions.CALL_FUNCTION(1)
Exemplo n.º 21
0
def _return_value(self, instr):
    # TOS  = collection

    yield instructions.LOAD_CONST(self.xform).steal(instr)
    # TOS  = self.xform
    # TOS1 = collection

    yield instructions.ROT_TWO()
    # TOS  = collection
    # TOS1 = self.xform

    yield instructions.CALL_FUNCTION(1)
    # TOS  = self.xform(collection)

    yield instr
Exemplo n.º 22
0
            def build_seq(self, instr):
                # TOS  v_0
                # ...
                # TOSn v_n

                yield instructions.BUILD_TUPLE(instr.arg).steal(instr)
                # TOS  (v_0, ..., v_n)

                yield instructions.LOAD_CONST(partial(thunk_type, type_))
                # TOS  partial(thunk_type, type_)
                # TOS1 (v_0, ..., v_n)

                yield instructions.ROT_TWO()
                # TOS  (v_0, ..., v_n)
                # TOS1 partial(thunk_type, type_)

                yield instructions.CALL_FUNCTION(1)
Exemplo n.º 23
0
        def _load_fast(self, instr):
            name = instr.arg
            if name in self.code.argnames:
                # perf note: we only need to wrap lookups to arguments as
                # thunks To assign to a name, it must have been a value already
                # so it is a thunk_type unless it was passed into the function.
                yield instructions.LOAD_CONST(thunk_type.fromexpr).steal(instr)
                # TOS  thunk_type.fromexpr

                yield instr
                # TOS  v
                # TOS  thunk_type.fromexpr

                yield instructions.CALL_FUNCTION(1)
                # TOS  thunk_type.fromexpr(v)
            else:
                yield instr
Exemplo n.º 24
0
            def comprehension(self, *instrs):
                first, *body, ret = instrs

                yield instructions.LOAD_CONST(partial(thunk_type, type_))
                # TOS  partial(thunk_type, type_)

                yield first
                # TOS  strict_seq
                # TOS1 partial(thunk_type, type_)

                yield from self.patterndispatcher(body)
                # TOS  strict_seq
                # TOS1 partial(thunk_type, type_)

                yield instructions.CALL_FUNCTION(1)
                # TOS  partial(thunk_type, type_)(*strict_seq)

                yield ret
Exemplo n.º 25
0
            def _build_map(self, instr):
                # TOS  k_0
                # TOS1 v_0
                # ...
                # TOSn k_n
                # TOSm v_n

                yield instr
                # TOS  dict_

                yield instructions.LOAD_CONST(partial(thunk_type, dict), )
                # TOS  partial(thunk_type, dict)
                # TOS1 dict_

                yield instructions.ROT_TWO()
                # TOS  dict_
                # TOS1 partial(thunk_type, dict)

                yield instructions.CALL_FUNCTION_KW(0)
Exemplo n.º 26
0
        def _build_const_map(self, keys, instr):
            yield instructions.BUILD_TUPLE(len(keys.arg)).steal(keys)
            # TOS  = (v0, v1, ..., vn)

            yield keys
            # TOS  = (k0, k1, ..., kn)
            # TOS1 = (v0, v1, ..., vn)

            yield instructions.LOAD_CONST(self._construct_const_map)
            # TOS  = self._construct_const_map
            # TOS1 = (k0, k1, ..., kn)
            # TOS2 = (v0, v1, ..., vn)

            yield instructions.ROT_THREE()
            # TOS  = (k0, k1, ..., kn)
            # TOS1 = (v0, v1, ..., vn)
            # TOS2 = self._construct_const_map

            yield instructions.CALL_FUNCTION(2)
Exemplo n.º 27
0
        def _build_map(self, instr):
            # TOS      = vn
            # TOS1     = kn
            # ...
            # TOSN     = v0
            # TOSN + 1 = k0
            # Construct a tuple of (k0, v0, k1, v1, ..., kn, vn) for
            # each of the key: value pairs in the dictionary.
            yield instructions.BUILD_TUPLE(instr.arg * 2).steal(instr)
            # TOS  = (k0, v0, k1, v1, ..., kn, vn)

            yield instructions.LOAD_CONST(self._construct_map)
            # TOS  = self._construct_map
            # TOS1 = (k0, v0, k1, v1, ..., kn, vn)

            yield instructions.ROT_TWO()
            # TOS  = (k0, v0, k1, v1, ..., kn, vn)
            # TOS1 = self._construct_map

            yield instructions.CALL_FUNCTION(1)
Exemplo n.º 28
0
    def py_call():
        start = instructions.BUILD_LIST(0)

        # validate that nargs is >= 0 to avoid infinite loop
        yield instructions.DUP_TOP()
        yield instructions.LOAD_CONST(0)
        yield instructions.COMPARE_OP.LT
        yield instructions.POP_JUMP_IF_FALSE(start)
        yield instructions.LOAD_CONST('nargs must be >= 0; got %s')
        yield instructions.ROT_TWO()
        yield instructions.BINARY_MODULO()
        yield instructions.LOAD_CONST(ValueError)
        yield instructions.ROT_TWO()
        yield instructions.CALL_FUNCTION(1)
        yield instructions.RAISE_VARARGS(1)

        # create a list to hold the function and arguments; append the function
        # first
        yield start
        yield from _nrot()
        yield instructions.LIST_APPEND(1)
        yield instructions.STORE_FAST('tmp')

        # use the nargs as a counter; append elements until nargs == 0
        loop = instructions.DUP_TOP()
        yield loop
        yield instructions.LOAD_CONST(0)
        yield instructions.COMPARE_OP.EQ

        call_impl = instructions.POP_TOP()
        yield instructions.POP_JUMP_IF_TRUE(call_impl)

        yield instructions.LOAD_CONST(1)
        yield instructions.BINARY_SUBTRACT()
        yield instructions.LOAD_FAST('tmp')
        yield from _nrot()
        yield instructions.LIST_APPEND(1)
        yield instructions.POP_TOP()
        yield instructions.JUMP_ABSOLUTE(loop)

        # *unpack the argument list into `py_call_impl`
        yield call_impl
        yield instructions.LOAD_CONST(py_call_impl)
        yield instructions.LOAD_FAST('tmp')
        yield instructions.CALL_FUNCTION_VAR(0)
        yield next_instruction()
Exemplo n.º 29
0
        def _compare_op(self, instr):
            """
            Replace the `is` operator to act on the values the thunk represent.
            This makes `is` lazy.
            """
            if instr.arg != 8:  # is
                yield instr
                return

            yield instructions.LOAD_CONST(_lazy_is).steal(instr)
            # TOS  = _lazy_is
            # TOS1 = a
            # TOS2 = b

            # This safe to do because `is` is commutative 100% of the time.
            # We are doing a pointer compare so we can move the operands
            # around. This saves us from doing an extra ROT_TWO to preserve the
            # order.
            yield instructions.ROT_THREE()
            # TOS  = a
            # TOS1 = b
            # TOS2 = _lazy_is

            yield instructions.CALL_FUNCTION(2)
Exemplo n.º 30
0
        def _build_list_in_comprehension(self, build_instr, load_instr):
            yield instrs.LOAD_CONST(jl.jlist).steal(build_instr)
            yield instrs.CALL_FUNCTION(0)
            yield instrs.DUP_TOP()
            yield instrs.DUP_TOP()
            # TOS  = <jlist>
            # TOS1 = <jlist>
            # TOS2 = <jlist>

            yield instrs.LOAD_ATTR('append')
            yield instrs.STORE_FAST('.append')
            # TOS  = <jlist>
            # TOS1 = <jlist>

            yield load_instr
            # TOS  = .0
            # TOS1 = <jlist>
            # TOS2 = <jlist>

            yield instrs.DUP_TOP()
            # TOS  = .0
            # TOS1 = .0
            # TOS2 = <jlist>
            # TOS3 = <jlist>

            yield instrs.ROT_THREE()
            # TOS  =  .0
            # TOS1 = <jlist>
            # TOS2 = .0
            # TOS3 = <jlist>

            yield instrs.LOAD_CONST(operator.length_hint)
            yield instrs.ROT_TWO()
            yield instrs.CALL_FUNCTION(1)
            # TOS  = <length_hint>
            # TOS1 = <jlist>
            # TOS2 = .0
            # TOS3 = <jlist>

            yield instrs.ROT_TWO()
            # TOS  = <jlist>
            # TOS1 = <length_hint>
            # TOS2 = .0
            # TOS3 = <jlist>

            if sys.version_info >= (3, 7):
                yield instrs.LOAD_METHOD('_reserve')
                # TOS  = <jlist._reserve>
                # TOS1 = <length_hint>
                # TOS2 = .0
                # TOS3 = <jlist>
                yield instrs.ROT_TWO()
                # TOS  = <length_hint>
                # TOS1 = <jlist._reserve>
                # TOS2 = .0
                # TOS3 = <jlist>
                yield instrs.CALL_METHOD(1)
                # TOS  = None
                # TOS1 = .0
                # TOS3 = <jlist>
            else:
                yield instrs.LOAD_ATTR('_reserve')
                # TOS  = <jlist._reserve>
                # TOS1 = <length_hint>
                # TOS2 = .0
                # TOS3 = <jlist>
                yield instrs.ROT_TWO()
                # TOS  = <length_hint>
                # TOS1 = <jlist._reserve>
                # TOS2 = .0
                # TOS3 = <jlist>
                yield instrs.CALL_FUNCTION(1)
                # TOS  = None
                # TOS1 = .0
                # TOS3 = <jlist>

            yield instrs.POP_TOP()