def visit_BUILD_MAP(self, instr): yield self.LOAD_CONST(self._astype).steal(instr) # TOS = self._astype yield instructions.CALL_FUNCTION(0) # TOS = m = self._astype() yield from (instructions.DUP_TOP(),) * instr.arg
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()
def _debug_print(): """DUP_TOP() and PRINT_EXPR() Used for debugging the bytecode by providing a "print statment" like feature in the bytecode. """ yield instructions.DUP_TOP() yield instructions.PRINT_EXPR()
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
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)
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)
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()
def _build_map(self, instr): yield instructions.LOAD_CONST(thunk_type(dict)).steal(instr) # TOS = m = thunk_type(dict) yield from (instructions.DUP_TOP(), ) * instr.arg
def over(): yield instructions.ROT_TWO() yield instructions.DUP_TOP() yield instructions.ROT_THREE() yield next_instruction()
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()