Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stdlib] Fix iterator ergonomics #3700

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
f726e54
fix iterator ergonomics
martinvuyk Oct 22, 2024
a68b635
fix detail
martinvuyk Oct 22, 2024
71540b0
fix details
martinvuyk Oct 22, 2024
4d0be8d
fix details
martinvuyk Oct 22, 2024
e8ffe4e
fix details
martinvuyk Oct 22, 2024
cf47de2
fix details
martinvuyk Oct 22, 2024
46b8ae3
fix details
martinvuyk Oct 22, 2024
42b23eb
fix details
martinvuyk Oct 22, 2024
b02899e
fix detail
martinvuyk Oct 22, 2024
542d409
revert name change and add next methods
martinvuyk Oct 22, 2024
44549b9
Merge branch 'nightly' into fix-iter-ergonomics
martinvuyk Oct 22, 2024
9cd0a28
fix detail
martinvuyk Oct 22, 2024
868f3f6
Merge branch 'fix-iter-ergonomics' of github.com:martinvuyk/mojo into…
martinvuyk Oct 22, 2024
393a9ec
Merge branch 'nightly' into fix-iter-ergonomics
martinvuyk Nov 6, 2024
f8c0591
fix __hasmore__ -> __has_next__
martinvuyk Nov 6, 2024
9adce79
remove bool dunders
martinvuyk Nov 15, 2024
6be47a6
Merge remote-tracking branch 'upstream/nightly' into fix-iter-ergonomics
martinvuyk Nov 15, 2024
733a600
mojo format
martinvuyk Nov 15, 2024
aba3216
fix remove use of bool
martinvuyk Nov 15, 2024
45b719d
fix the todo items to make them realistic
martinvuyk Nov 15, 2024
fb5f04e
fix detail
martinvuyk Nov 15, 2024
ea1370a
Merge remote-tracking branch 'upstream/nightly' into fix-iter-ergonomics
martinvuyk Nov 21, 2024
7b02d0a
add iter and reserved explicitly to string, stringliteral, and string…
martinvuyk Nov 21, 2024
0ee6e6b
fix detail in string_slice test
martinvuyk Nov 21, 2024
150dbb5
Merge remote-tracking branch 'upstream/nightly' into fix-iter-ergonomics
martinvuyk Dec 10, 2024
be2dfd6
fix details after merge
martinvuyk Dec 10, 2024
9ec7b45
fix details
martinvuyk Dec 10, 2024
3d14329
fix details
martinvuyk Dec 10, 2024
f60c04e
fix details
martinvuyk Dec 10, 2024
5496472
Merge remote-tracking branch 'upstream/main' into fix-iter-ergonomics
martinvuyk Feb 3, 2025
462ce86
fix after merge
martinvuyk Feb 3, 2025
3014876
fix after merge
martinvuyk Feb 3, 2025
dc14095
fix after merge
martinvuyk Feb 3, 2025
df753dc
fix after merge
martinvuyk Feb 3, 2025
0870a2b
fix after merge
martinvuyk Feb 3, 2025
6ea3ff4
fix after merge
martinvuyk Feb 3, 2025
1989e09
fix details
martinvuyk Feb 3, 2025
d0e0601
fix detail
martinvuyk Feb 3, 2025
96c1ba5
Merge remote-tracking branch 'upstream/main' into fix-iter-ergonomics
martinvuyk Feb 28, 2025
f11594a
change _StringSliceIter to CodepointSliceIter
martinvuyk Feb 28, 2025
d17b139
fix detail with origins
martinvuyk Feb 28, 2025
5368b18
fix details
martinvuyk Feb 28, 2025
a5baa36
fix details
martinvuyk Feb 28, 2025
20d9fe2
fix detail
martinvuyk Feb 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
334 changes: 334 additions & 0 deletions stdlib/src/builtin/range.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ from python import (
) # TODO: remove this and fixup downstream imports
from math import ceildiv
from utils._select import _select_register_value as select
from utils.string_slice import StringSlice, _StringSliceIter, Stringlike
from collections.list import _ListIter
from collections.dict import (
Dict,
_DictKeyIter,
_DictValueIter,
_DictEntryIter,
DictEntry,
)

# ===----------------------------------------------------------------------=== #
# Utilities
Expand Down Expand Up @@ -625,3 +634,328 @@ fn range[
The constructed range.
"""
return _StridedScalarRange(start, end, step)


# ===----------------------------------------------------------------------=== #
# Utils
# ===----------------------------------------------------------------------=== #


trait _Iterator:
fn __iter__(self) -> Self:
...

fn __has_next__(self) -> Bool:
...


# TODO: this is the goal
# fn __next__(inout self) -> ref [origin]T:
# ...


# fn __bool__(self) -> Bool:
# return self.__has_next__()


# trait _Iterable[T: AnyType]:
# fn __iter__[
# is_mutable: Bool, origin: Origin[is_mutable].type
# ](ref [_]self) -> _Iterator[T, origin]:
# ...


# fn iter[
# is_mutable: Bool,
# origin: Origin[is_mutable].type,
# T: AnyType,
# I: _Iterable[T],
# ](ref [_]value: I) -> _Iterator[T, origin]:
# return value.__iter__[is_mutable, origin]()


# fn next[
# is_mutable: Bool,
# origin: Origin[is_mutable].type,
# T: AnyType,
# I: _Iterator[T, origin],
# ](value: I) -> ref [origin]T:
# debug_assert(bool(value), "iterator has no next value to yield")
# return value.__next__()


fn iter[T: _Iterator](value: T) -> T:
"""Get an iterator from the iterator.

Parameters:
T: The type conforming to _Iterator.

Args:
value: The value to get the iterator of.

Returns:
The iterator of the value.
"""
return value.__iter__()


fn iter[
T: DType
](value: _StridedScalarRange[T]) -> _StridedScalarRangeIterator[T]:
"""Return an iterator.

Parameters:
T: The type that the iterator yields.

Args:
value: The iterable value.

Returns:
The type's Iterator.
"""
return value.__iter__()


@always_inline
fn iter[
T: CollectionElement
](ref [_]value: List[T, *_]) -> _ListIter[
T, __type_of(value).hint_trivial_type, __origin_of(value)
]:
"""Return an iterator.

Parameters:
T: The type that the iterator yields.

Args:
value: The iterable value.

Returns:
The type's Iterator.
"""
return value.__iter__()


fn iter[
K: KeyElement, V: CollectionElement
](ref [_]value: Dict[K, V]) -> _DictKeyIter[K, V, __origin_of(value)]:
"""Get an iterator of the input dict.

Parameters:
K: The type of the keys in the dict.
V: The type of the values in the dict.

Args:
value: The dict to get the iterator of.

Returns:
The iterator of the dict keys.
"""
return value.__iter__()


fn iter[
K: KeyElement, V: CollectionElement
](ref [_]value: _DictValueIter[K, V, *_]) -> _DictValueIter[
K, V, __type_of(value).dict_origin
] as output:
"""Get an iterator of the input dict values.

Parameters:
K: The type of the keys in the dict.
V: The type of the values in the dict.

Args:
value: The dict values to get the iterator of.

Returns:
The iterator of the dict values.
"""
output = rebind[__type_of(output)](value.__iter__())


fn iter[
K: KeyElement,
V: CollectionElement,
](ref [_]value: _DictEntryIter[K, V, *_]) -> _DictEntryIter[
K, V, __type_of(value).dict_origin
] as output:
"""Get an iterator of the input dict items.

Parameters:
K: The type of the keys in the dict.
V: The type of the values in the dict.

Args:
value: The dict items to get the iterator of.

Returns:
The iterator of the dict items.
"""
var src = value.src
output = __type_of(output)(src[]._reserved() - 1, 0, src)


@always_inline
fn iter[T: Stringlike](ref [_]value: T) -> _StringSliceIter[__origin_of(value)]:
"""Return an iterator.

Parameters:
T: The type that the iterator yields.

Args:
value: The iterable value.

Returns:
The type's Iterator.
"""
return value.__iter__()


fn next[T: DType](inout value: _ZeroStartingScalarRange[T]) -> Scalar[T]:
"""Return an iterator.

Parameters:
T: The type that the iterator yields.

Args:
value: The iterable value.

Returns:
The type's Iterator.
"""
debug_assert(value.__has_next__(), "iterator has no next value to yield")
return value.__next__()


fn next[T: DType](inout value: _SequentialScalarRange[T]) -> Scalar[T]:
"""Return an iterator.

Parameters:
T: The type that the iterator yields.

Args:
value: The iterable value.

Returns:
The type's Iterator.
"""
debug_assert(value.__has_next__(), "iterator has no next value to yield")
return value.__next__()


fn next[T: DType](inout value: _StridedScalarRangeIterator[T]) -> Scalar[T]:
"""Return an iterator.

Parameters:
T: The type that the iterator yields.

Args:
value: The iterable value.

Returns:
The type's Iterator.
"""
debug_assert(value.__has_next__(), "iterator has no next value to yield")
return value.__next__()


fn next(inout value: _UIntZeroStartingRange) -> UInt:
"""Return an iterator.

Args:
value: The iterable value.

Returns:
The type's Iterator.
"""
debug_assert(value.__has_next__(), "iterator has no next value to yield")
return value.__next__()


fn next(inout value: _UIntStridedRangeIterator) -> UInt:
"""Return an iterator.

Args:
value: The iterable value.

Returns:
The type's Iterator.
"""
debug_assert(value.__has_next__(), "iterator has no next value to yield")
return value.__next__()


@always_inline
fn next[
T: CollectionElement
](inout value: _ListIter[T, *_]) -> Pointer[T, __type_of(value).list_origin]:
"""Return an iterator.

Parameters:
T: The type that the iterator yields.

Args:
value: The iterable value.

Returns:
The type's Iterator.
"""
debug_assert(value.__has_next__(), "iterator has no next value to yield")
return value.__next__()


fn next[
K: KeyElement, V: CollectionElement
](inout value: _DictValueIter[K, V, *_]) -> Pointer[
V, __type_of(value).dict_origin
]:
"""Get an iterator of the input dict values.

Parameters:
K: The type of the keys in the dict.
V: The type of the values in the dict.

Args:
value: The dict values to get the iterator of.

Returns:
The iterator of the dict values.
"""
debug_assert(value.__has_next__(), "iterator has no next value to yield")
return value.__next__()


fn next[
K: KeyElement, V: CollectionElement
](inout value: _DictEntryIter[K, V, *_]) -> Pointer[
DictEntry[K, V], __type_of(value).dict_origin
] as output:
"""Get an iterator of the input dict items.

Parameters:
K: The type of the keys in the dict.
V: The type of the values in the dict.

Args:
value: The dict items to get the iterator of.

Returns:
The iterator of the dict items.
"""
debug_assert(value.__has_next__(), "iterator has no next value to yield")
output = rebind[__type_of(output)](value.__next__())


@always_inline
fn next(inout value: _StringSliceIter) -> StringSlice[__type_of(value).origin]:
"""Return an iterator.

Args:
value: The iterable value.

Returns:
The type's Iterator.
"""
debug_assert(value.__has_next__(), "iterator has no next value to yield")
return value.__next__()
Loading