예제 #1
0
 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
예제 #2
0
 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))
예제 #3
0
 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)
예제 #4
0
 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)
예제 #5
0
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)
예제 #6
0
 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)
예제 #7
0
    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)