def init(self, expr_reg: Value, target_type: RType) -> None: # Define targets to contain the expression, along with the iterator that will be used # for the for-loop. If we are inside of a generator function, spill these into the # environment class. builder = self.builder iter_reg = builder.primitive_op(iter_op, [expr_reg], self.line) builder.maybe_spill(expr_reg) self.iter_target = builder.maybe_spill(iter_reg) self.target_type = target_type
def gen_condition(self) -> None: # We call __next__ on the iterator and check to see if the return value # is NULL, which signals either the end of the Iterable being traversed # or an exception being raised. Note that Branch.IS_ERROR checks only # for NULL (an exception does not necessarily have to be raised). builder = self.builder line = self.line self.next_reg = builder.primitive_op(next_op, [builder.read(self.iter_target, line)], line) builder.add(Branch(self.next_reg, self.loop_exit, self.body_block, Branch.IS_ERROR))
def gen_step(self) -> None: # Step to the next item. builder = self.builder line = self.line step = 1 if not self.reverse else -1 builder.assign(self.index_target, builder.primitive_op( unsafe_short_add, [builder.read(self.index_target, line), builder.add(LoadInt(step))], line), line)
def gen_step(self) -> None: builder = self.builder line = self.line # We can safely assume that the integer is short, since we are not going to wrap # around a 63-bit integer. # NOTE: This would be questionable if short ints could be 32 bits. new_val = builder.primitive_op( unsafe_short_add, [builder.read(self.index_reg, line), builder.add(LoadInt(1))], line) builder.assign(self.index_reg, new_val, line) builder.assign(self.index_target, new_val, line)
def unsafe_index(builder: 'mypyc.irbuild.builder.IRBuilder', target: Value, index: Value, line: int) -> Value: """Emit a potentially unsafe index into a target.""" # This doesn't really fit nicely into any of our data-driven frameworks # since we want to use __getitem__ if we don't have an unsafe version, # so we just check manually. if is_list_rprimitive(target.type): return builder.primitive_op(list_get_item_unsafe_op, [target, index], line) else: return builder.gen_method_call(target, '__getitem__', [index], None, line)
def begin_body(self) -> None: builder = self.builder line = self.line # Read the next list item. value_box = builder.primitive_op( list_get_item_unsafe_op, [builder.read(self.expr_target, line), builder.read(self.index_target, line)], line) assert value_box # We coerce to the type of list elements here so that # iterating with tuple unpacking generates a tuple based # unpack instead of an iterator based one. builder.assign(builder.get_assignment_target(self.index), builder.coerce(value_box, self.target_type, line), line)
def gen_step(self) -> None: builder = self.builder line = self.line # Increment index register. If the range is known to fit in short ints, use # short ints. if (is_short_int_rprimitive(self.start_reg.type) and is_short_int_rprimitive(self.end_reg.type)): new_val = builder.primitive_op( unsafe_short_add, [builder.read(self.index_reg, line), builder.add(LoadInt(self.step))], line) else: new_val = builder.binary_op( builder.read(self.index_reg, line), builder.add(LoadInt(self.step)), '+', line) builder.assign(self.index_reg, new_val, line) builder.assign(self.index_target, new_val, line)