Пример #1
0
        def _store_map(self, instr):
            # TOS  = k
            # TOS1 = v
            # TOS2 = m
            # TOS3 = m

            yield instructions.ROT_THREE().steal(instr)
            # TOS  = v
            # TOS1 = m
            # TOS2 = k
            # TOS3 = m

            yield instructions.ROT_THREE()
            # TOS  = m
            # TOS1 = k
            # TOS2 = v
            # TOS3 = m

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

            yield instructions.STORE_SUBSCR()
Пример #2
0
    def visit_STORE_MAP(self, instr):
        # TOS  = k
        # TOS1 = v
        # TOS2 = m
        # TOS3 = m

        yield instructions.ROT_THREE().steal(instr)
        # TOS  = v
        # TOS1 = m
        # TOS2 = k
        # TOS3 = m

        yield instructions.ROT_THREE()
        # TOS  = m
        # TOS1 = k
        # TOS2 = v
        # TOS3 = m

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

        yield instructions.STORE_SUBSCR()
Пример #3
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)
Пример #4
0
    def visit_BINARY_SUBSCR(self, instr):
        yield self.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)
Пример #5
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)
Пример #6
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)
Пример #7
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)
Пример #8
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)
Пример #9
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)
Пример #10
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()
Пример #11
0
 def _nrot():
     yield instructions.ROT_THREE()
     yield instructions.ROT_THREE()
Пример #12
0
 def py_getattr():
     yield instructions.LOAD_CONST(getattr)
     yield instructions.ROT_THREE()
     yield instructions.CALL_FUNCTION(2)
     yield next_instruction()
Пример #13
0
 def _divmod():
     yield instructions.LOAD_CONST(divmod)
     yield instructions.ROT_THREE()
     yield instructions.CALL_FUNCTION()
     yield next_instruction()
Пример #14
0
 def over():
     yield instructions.ROT_TWO()
     yield instructions.DUP_TOP()
     yield instructions.ROT_THREE()
     yield next_instruction()
Пример #15
0
 def bwrite():
     yield instructions.LOAD_CONST(bwrite_impl)
     yield instructions.ROT_THREE()
     yield instructions.CALL_FUNCTION(2)
     yield instructions.POP_TOP()
     yield next_instruction()
Пример #16
0
    def __start(*, counting_run=False):
        yield setup_except_instr
        first = instructions.LOAD_CONST(push_return_addr)
        yield first
        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 twice giving us 3 copies on the stack for:
        #   find
        #   literal lookup
        #   unknown word error
        yield instructions.DUP_TOP()
        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

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

        # clear the word strings from the stack
        yield instructions.ROT_THREE()
        yield instructions.POP_TOP()
        yield instructions.POP_TOP()
        yield instructions.DUP_TOP()
        yield instructions.LOAD_ATTR('addr')
        yield instructions.LOAD_CONST(1)
        yield instructions.BINARY_SUBTRACT()
        yield instructions.LOAD_FAST('immediate')

        immediate_with_nip_instr = instructions.ROT_TWO()
        yield instructions.POP_JUMP_IF_TRUE(immediate_with_nip_instr)

        yield instructions.ROT_TWO()
        yield instructions.LOAD_ATTR('immediate')

        immediate_instr = instructions.LOAD_CONST(push_return_addr)
        yield instructions.POP_JUMP_IF_TRUE(immediate_instr)

        yield instructions.LOAD_CONST(push_return_addr)
        yield instructions.CALL_FUNCTION(0)
        yield instructions.POP_TOP()
        yield instructions.JUMP_ABSOLUTE(word_instrs[','][0])
        yield instructions.JUMP_ABSOLUTE(first)

        yield immediate_with_nip_instr
        yield instructions.POP_TOP()
        yield immediate_instr
        yield instructions.CALL_FUNCTION()
        yield instructions.POP_TOP()
        yield instructions.YIELD_VALUE()
        # We need to add some padding so that the return adress gets
        # computed correctly. Maybe we should have two functions like:
        # push_return_jmp_addr/push_return_yield_addr to handle this.
        yield instructions.NOP()
        yield instructions.NOP()
        yield instructions.JUMP_ABSOLUTE(first)

        yield process_lit_instr
        yield instructions.LOAD_CONST(process_lit)
        yield instructions.ROT_TWO()
        yield instructions.CALL_FUNCTION(1)
        yield instructions.DUP_TOP()
        yield instructions.LOAD_CONST(NotImplemented)
        yield instructions.COMPARE_OP.IS

        unknown_word_instr = instructions.POP_TOP()
        yield instructions.POP_JUMP_IF_TRUE(unknown_word_instr)
        # clear the word string left for the unknown word case
        yield from _nip()
        yield instructions.LOAD_FAST('immediate')
        yield instructions.POP_JUMP_IF_TRUE(first)

        yield instructions.LOAD_CONST(append_lit)
        yield instructions.ROT_TWO()
        yield instructions.CALL_FUNCTION(1)
        yield from inline_write_short(
            None if counting_run else
            len(list(_sparse_args(__start(counting_run=True)))) - 1, )
        yield from inline_write_short_from_stack()
        yield instructions.JUMP_ABSOLUTE(first)

        yield unknown_word_instr
        yield instructions.LOAD_CONST(UnknownWord)
        yield instructions.ROT_TWO()
        yield instructions.CALL_FUNCTION(1)
        yield instructions.RAISE_VARARGS(1)

        # this is the bytecode side of the literal implementation which
        # appears to be dead code but does get jumped to
        if counting_run:
            return

        yield instructions.LOAD_CONST(lit_impl)
        yield instructions.LOAD_CONST(pop_return_addr)
        yield instructions.CALL_FUNCTION(0)
        yield instructions.CALL_FUNCTION(1)
        yield instructions.UNPACK_SEQUENCE(2)
        yield instructions.YIELD_VALUE()