def _transform_constant_sequence(self, seq): """ Transform a frozenset or tuple. """ should_transform = is_a(self.types) if not any(filter(should_transform, flatten(seq))): # Tuple doesn't contain any transformable strings. Ignore. yield LOAD_CONST(seq) return for const in seq: if should_transform(const): for item in self.transform_stringlike(const): yield item elif isinstance(const, (tuple, frozenset)): for item in self._transform_constant_sequence(const): yield item else: yield LOAD_CONST(const) if isinstance(seq, tuple): yield BUILD_TUPLE(len(seq)) else: assert isinstance(seq, frozenset) yield BUILD_TUPLE(len(seq)) yield LOAD_CONST(frozenset) yield ROT_TWO() yield CALL_FUNCTION(1)
def abc_code(): a = LOAD_CONST('a') b = LOAD_CONST('b') c = LOAD_CONST('c') # not in instrs code = Code((a, b), argnames=()) return (a, b, c), code
def _match(self, instr, CALL_FUNCTION_VAR=CALL_FUNCTION_VAR): yield ROT_TWO().steal(instr) yield POP_TOP() yield LOAD_CONST(self._matcher) yield ROT_TWO() yield LOAD_CONST(sys.exc_info) yield CALL_FUNCTION(0) yield CALL_FUNCTION_VAR(1)
def _match(self, instr, CALL_FUNCTION_EX=CALL_FUNCTION_EX, BUILD_TUPLE_UNPACK_WITH_CALL=BUILD_TUPLE_UNPACK_WITH_CALL): yield ROT_TWO().steal(instr) yield POP_TOP() yield LOAD_CONST(self._matcher) yield ROT_TWO() yield BUILD_TUPLE(1) yield LOAD_CONST(sys.exc_info) yield CALL_FUNCTION(0) yield BUILD_TUPLE_UNPACK_WITH_CALL(2) yield CALL_FUNCTION_EX(0)
def str_instrs(self): """ Yield instructions to call TOS.format(**locals()). """ yield LOAD_ATTR('format') yield LOAD_CONST(locals) yield CALL_FUNCTION(0) yield CALL_FUNCTION_KW()
def bytes_instrs(self): """ Yield instructions to call TOS.decode('utf-8').format(**locals()). """ yield LOAD_ATTR('decode') yield LOAD_CONST('utf-8') yield CALL_FUNCTION(1) yield from self.str_instrs
def transform_stringlike(self, const): """ Yield instructions to process a str or bytes constant. """ yield LOAD_CONST(const) if isinstance(const, bytes): yield from self.bytes_instrs elif isinstance(const, str): yield from self.str_instrs
def _load_name(self, instr): name = instr.arg if name not in self._constnames: yield instr return ret = LOAD_CONST(self._constnames[name]).steal(instr) yield ret
def make_constant_slice(self, *instrs): *loads, build = instrs if build.arg != len(loads): # There are non-constant loads before the consts: # e.g. x[<non-const expr>:1:2] yield from instrs slice_ = slice(*(instr.arg for instr in loads)) yield LOAD_CONST(slice_).steal(loads[0])
def make_constant_slice(self, *instrs): loads, build = instrs[:-1], instrs[-1] if build.arg != len(loads): # There are non-constant loads before the consts: # e.g. x[<non-const expr>:1:2] for item in instrs: yield item slice_ = slice(*(instr.arg for instr in loads)) yield LOAD_CONST(slice_).steal(loads[0])
def test_precomputed_slices(): @precomputed_slices() def foo(a): return a[1:5] l = list(range(10)) assert foo(l) == l[1:5] assert slice(1, 5) in foo.__code__.co_consts instrs = Code.from_pyfunc(foo).instrs assert LOAD_CONST(slice(1, 5)).equiv(instrs[1]) assert BUILD_SLICE not in set(map(type, instrs))
def call_function(fn): """Return the instructions needed to call fn. Parameters ---------- fn : function The function to call. Returns ------- instrs : tuple The instructions to use. """ return LOAD_CONST(fn), ROT_TWO(), CALL_FUNCTION(1)