# myrange.py
#
# ICS 33 Spring 2025
# Code Example
#
# This module implements a stripped-down version of Python's range type, which we've
# named MyRange, along with an iterator for it.



class MyRangeIterator:
    def __init__(self, myrange):
        'Initializes a MyRangeIterator, given a MyRange to iterate.'
        self._myrange = myrange
        self._next = myrange.start()


    def __iter__(self):
        return self


    def __next__(self):
        if self._next >= self._myrange.stop():
            raise StopIteration
        else:
            result = self._next
            self._next += self._myrange.step()
            return result



class MyRange:
    def __init__(self, start, stop = None, step = None, /):
        '''
        Initializes a MyRange, given either a stop value or start, stop, and
        (optionally) step values.
        '''
        if stop is None:
            stop = start
            start = 0

        if step is None:
            step = 1

        self._require_int(start, 'start')
        self._require_int(stop, 'stop')
        self._require_int(step, 'step')

        self._start = start
        self._stop = stop
        self._step = step


    @staticmethod
    def _require_int(value, name):
        if type(value) is not int:
            raise TypeError(f'{name} must be an integer, but was {value}')


    def start(self):
        'Returns the start value associated with a MyRange.'
        return self._start


    def stop(self):
        'Returns the stop value associated with a MyRange.'
        return self._stop


    def step(self):
        'Returns the step value associated with a MyRange.'
        return self._step


    def __iter__(self):
        return MyRangeIterator(self)


    def __repr__(self):
        step_repr = f'' if self._step == 1 else f', {self._step}'
        return f'MyRange({self._start}, {self._stop}{step_repr})'
