def init(self) -> None: builder = self.builder # Create a register to store the state of the loop index and # initialize this register along with the loop index to 0. zero = builder.add(LoadInt(0)) self.index_reg = builder.maybe_spill_assignable(zero) self.index_target = builder.get_assignment_target( self.index) # type: Union[Register, AssignmentTarget] builder.assign(self.index_target, zero, self.line)
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 begin_body(self) -> None: # Assign the value obtained from __next__ to the # lvalue so that it can be referenced by code in the body of the loop. builder = self.builder line = self.line # We unbox here so that iterating with tuple unpacking generates a tuple based # unpack instead of an iterator based one. next_reg = builder.coerce(self.next_reg, self.target_type, line) builder.assign(builder.get_assignment_target(self.index), next_reg, 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 init(self, start_reg: Value, end_reg: Value, step: int) -> None: builder = self.builder self.start_reg = start_reg self.end_reg = end_reg self.step = step self.end_target = builder.maybe_spill(end_reg) self.index_reg = builder.maybe_spill_assignable(start_reg) # Initialize loop index to 0. Assert that the index target is assignable. self.index_target = builder.get_assignment_target( self.index) # type: Union[Register, AssignmentTarget] builder.assign(self.index_target, builder.read(self.index_reg, self.line), self.line)
def begin_body(self) -> None: builder = self.builder line = self.line # Read the next list item. value_box = unsafe_index(builder, 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)