Ejemplo n.º 1
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()
Ejemplo n.º 2
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)
Ejemplo n.º 3
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()
Ejemplo n.º 4
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)
Ejemplo n.º 5
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()
Ejemplo n.º 6
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()
Ejemplo n.º 7
0
 def write_short(s):
     yield instructions.LOAD_CONST(s)
     yield instructions.LOAD_CONST(push_return_addr)
     yield instructions.CALL_FUNCTION()
     yield instructions.POP_TOP()
     yield instructions.JUMP_ABSOLUTE(word_instrs[','][0])
Ejemplo n.º 8
0
 def next_instruction():
     """Create a new instruction that will exit using the control stack.
     """
     return instructions.JUMP_ABSOLUTE(word_instrs['__next'][0])