Skip to content

Commit

Permalink
fix: Fix handling of --skip-first argument Update release_crates.sh (#…
Browse files Browse the repository at this point in the history
…7087)

chore: orthographic correction in file if_else (#7088)

prevents closure parameters from being declared as refrences (#7078)

Refactored bounded_int_trim. (#7062)

Added const for starknet types. (#6961)

feat(corelib): Iterator::fold (#7084)

feat(corelib): Iterator::advance_by (#7059)

fix(corelib): Add the #[test] annotation to enumerate test (#7098)

feat(corelib): storage vectors iterators (#6941)

Extract ModuleHelper from const folding. (#7099)

Added support for basic `Into`s in consts. (#7100)

Removed taking value for `validate_literal`. (#7101)

added closure params to semantic defs in lowering (#7085)

Added support for `downcast` in constant context. (#7102)

fix(corelib): Add the #[test] annotation to enumerate test (#7098)
  • Loading branch information
mdqst authored and dean-starkware committed Jan 16, 2025
1 parent 0ec6865 commit 9b849dc
Show file tree
Hide file tree
Showing 36 changed files with 1,044 additions and 300 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions corelib/src/bytes_31.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -88,31 +88,31 @@ pub(crate) impl Felt252TryIntoBytes31 of TryInto<felt252, bytes31> {
impl Bytes31Serde = crate::serde::into_felt252_based::SerdeImpl<bytes31>;

pub(crate) impl U8IntoBytes31 of Into<u8, bytes31> {
fn into(self: u8) -> bytes31 {
const fn into(self: u8) -> bytes31 {
crate::integer::upcast(self)
}
}

impl U16IntoBytes31 of Into<u16, bytes31> {
fn into(self: u16) -> bytes31 {
const fn into(self: u16) -> bytes31 {
crate::integer::upcast(self)
}
}

impl U32IntoBytes31 of Into<u32, bytes31> {
fn into(self: u32) -> bytes31 {
const fn into(self: u32) -> bytes31 {
crate::integer::upcast(self)
}
}

impl U64IntoBytes31 of Into<u64, bytes31> {
fn into(self: u64) -> bytes31 {
const fn into(self: u64) -> bytes31 {
crate::integer::upcast(self)
}
}

pub(crate) impl U128IntoBytes31 of Into<u128, bytes31> {
fn into(self: u128) -> bytes31 {
const fn into(self: u128) -> bytes31 {
crate::integer::upcast(self)
}
}
Expand Down
16 changes: 8 additions & 8 deletions corelib/src/integer.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -1426,11 +1426,11 @@ pub(crate) impl I128IntoFelt252 of Into<i128, felt252> {

// TODO(lior): Restrict the function (using traits) in the high-level compiler so that wrong types
// will not lead to Sierra errors.
pub(crate) extern fn upcast<FromType, ToType>(x: FromType) -> ToType nopanic;
pub(crate) extern const fn upcast<FromType, ToType>(x: FromType) -> ToType nopanic;

// TODO(lior): Restrict the function (using traits) in the high-level compiler so that wrong types
// will not lead to Sierra errors.
pub(crate) extern fn downcast<FromType, ToType>(
pub(crate) extern const fn downcast<FromType, ToType>(
x: FromType,
) -> Option<ToType> implicits(RangeCheck) nopanic;

Expand Down Expand Up @@ -1599,21 +1599,21 @@ impl U128Felt252DictValue of Felt252DictValue<u128> {
}

impl UpcastableInto<From, To, +Upcastable<From, To>> of Into<From, To> {
fn into(self: From) -> To {
const fn into(self: From) -> To {
upcast(self)
}
}

impl DowncastableIntTryInto<
From, To, +DowncastableInt<From>, +DowncastableInt<To>, -Into<From, To>,
> of TryInto<From, To> {
fn try_into(self: From) -> Option<To> {
const fn try_into(self: From) -> Option<To> {
downcast(self)
}
}

impl U8IntoU256 of Into<u8, u256> {
fn into(self: u8) -> u256 {
const fn into(self: u8) -> u256 {
u256 { low: upcast(self), high: 0_u128 }
}
}
Expand All @@ -1631,7 +1631,7 @@ impl U256TryIntoU8 of TryInto<u256, u8> {
}

impl U16IntoU256 of Into<u16, u256> {
fn into(self: u16) -> u256 {
const fn into(self: u16) -> u256 {
u256 { low: upcast(self), high: 0_u128 }
}
}
Expand All @@ -1649,7 +1649,7 @@ impl U256TryIntoU16 of TryInto<u256, u16> {
}

impl U32IntoU256 of Into<u32, u256> {
fn into(self: u32) -> u256 {
const fn into(self: u32) -> u256 {
u256 { low: upcast(self), high: 0_u128 }
}
}
Expand All @@ -1667,7 +1667,7 @@ impl U256TryIntoU32 of TryInto<u256, u32> {
}

impl U64IntoU256 of Into<u64, u256> {
fn into(self: u64) -> u256 {
const fn into(self: u64) -> u256 {
u256 { low: upcast(self), high: 0_u128 }
}
}
Expand Down
81 changes: 37 additions & 44 deletions corelib/src/internal/bounded_int.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ impl NumericLiteralBoundedInt<
impl BoundedIntIntoFelt252<
const MIN: felt252, const MAX: felt252,
> of Into<BoundedInt<MIN, MAX>, felt252> {
fn into(self: BoundedInt<MIN, MAX>) -> felt252 {
const fn into(self: BoundedInt<MIN, MAX>) -> felt252 {
upcast(self)
}
}

impl Felt252TryIntoBoundedInt<
const MIN: felt252, const MAX: felt252,
> of TryInto<felt252, BoundedInt<MIN, MAX>> {
fn try_into(self: felt252) -> Option<BoundedInt<MIN, MAX>> {
const fn try_into(self: felt252) -> Option<BoundedInt<MIN, MAX>> {
// Using `downcast` is allowed, since `BoundedInt` itself is not `pub`, and only has a few
// specific `pub` instances, such as `u96`, `ConstZero` and `ConstOne`.
downcast(self)
Expand Down Expand Up @@ -113,56 +113,49 @@ extern fn bounded_int_constrain<T, const BOUNDARY: felt252, impl H: ConstrainHel
value: T,
) -> Result<H::LowT, H::HighT> implicits(RangeCheck) nopanic;

/// A helper trait for trimming a `BoundedInt` instance.
pub trait TrimHelper<T, const TRIMMED_VALUE: felt252> {
/// A helper trait for trimming a `BoundedInt` instance min value.
pub trait TrimMinHelper<T> {
type Target;
}
/// A helper trait for trimming a `BoundedInt` instance max value.
pub trait TrimMaxHelper<T> {
type Target;
}
mod trim_impl {
pub impl Impl<
T, const TRIMMED_VALUE: felt252, const MIN: felt252, const MAX: felt252,
> of super::TrimHelper<T, TRIMMED_VALUE> {
pub impl Min<T, const MIN: felt252, const MAX: felt252> of super::TrimMinHelper<T> {
type Target = super::BoundedInt<MIN, MAX>;
}
pub impl Max<T, const MIN: felt252, const MAX: felt252> of super::TrimMaxHelper<T> {
type Target = super::BoundedInt<MIN, MAX>;
}
}
impl U8TrimBelow = trim_impl::Impl<u8, 0, 1, 0xff>;
impl U8TrimAbove = trim_impl::Impl<u8, 0xff, 0, 0xfe>;
impl I8TrimBelow = trim_impl::Impl<i8, -0x80, -0x7f, 0x7f>;
impl I8TrimAbove = trim_impl::Impl<i8, 0x7f, -0x80, 0x7e>;
impl U16TrimBelow = trim_impl::Impl<u16, 0, 1, 0xffff>;
impl U16TrimAbove = trim_impl::Impl<u16, 0xffff, 0, 0xfffe>;
impl I16TrimBelow = trim_impl::Impl<i16, -0x8000, -0x7fff, 0x7fff>;
impl I16TrimAbove = trim_impl::Impl<i16, 0x7fff, -0x8000, 0x7ffe>;
impl U32TrimBelow = trim_impl::Impl<u32, 0, 1, 0xffffffff>;
impl U32TrimAbove = trim_impl::Impl<u32, 0xffffffff, 0, 0xfffffffe>;
impl I32TrimBelow = trim_impl::Impl<i32, -0x80000000, -0x7fffffff, 0x7fffffff>;
impl I32TrimAbove = trim_impl::Impl<i32, 0x7fffffff, -0x80000000, 0x7ffffffe>;
impl U64TrimBelow = trim_impl::Impl<u64, 0, 1, 0xffffffffffffffff>;
impl U64TrimAbove = trim_impl::Impl<u64, 0xffffffffffffffff, 0, 0xfffffffffffffffe>;
impl I64TrimBelow =
trim_impl::Impl<i64, -0x8000000000000000, -0x7fffffffffffffff, 0x7fffffffffffffff>;
impl I64TrimAbove =
trim_impl::Impl<i64, 0x7fffffffffffffff, -0x8000000000000000, 0x7ffffffffffffffe>;
impl U128TrimBelow = trim_impl::Impl<u128, 0, 1, 0xffffffffffffffffffffffffffffffff>;
impl U128TrimAbove =
trim_impl::Impl<
u128, 0xffffffffffffffffffffffffffffffff, 0, 0xfffffffffffffffffffffffffffffffe,
>;
impl U8TrimBelow = trim_impl::Min<u8, 1, 0xff>;
impl U8TrimAbove = trim_impl::Max<u8, 0, 0xfe>;
impl I8TrimBelow = trim_impl::Min<i8, -0x7f, 0x7f>;
impl I8TrimAbove = trim_impl::Max<i8, -0x80, 0x7e>;
impl U16TrimBelow = trim_impl::Min<u16, 1, 0xffff>;
impl U16TrimAbove = trim_impl::Max<u16, 0, 0xfffe>;
impl I16TrimBelow = trim_impl::Min<i16, -0x7fff, 0x7fff>;
impl I16TrimAbove = trim_impl::Max<i16, -0x8000, 0x7ffe>;
impl U32TrimBelow = trim_impl::Min<u32, 1, 0xffffffff>;
impl U32TrimAbove = trim_impl::Max<u32, 0, 0xfffffffe>;
impl I32TrimBelow = trim_impl::Min<i32, -0x7fffffff, 0x7fffffff>;
impl I32TrimAbove = trim_impl::Max<i32, -0x80000000, 0x7ffffffe>;
impl U64TrimBelow = trim_impl::Min<u64, 1, 0xffffffffffffffff>;
impl U64TrimAbove = trim_impl::Max<u64, 0, 0xfffffffffffffffe>;
impl I64TrimBelow = trim_impl::Min<i64, -0x7fffffffffffffff, 0x7fffffffffffffff>;
impl I64TrimAbove = trim_impl::Max<i64, -0x8000000000000000, 0x7ffffffffffffffe>;
impl U128TrimBelow = trim_impl::Min<u128, 1, 0xffffffffffffffffffffffffffffffff>;
impl U128TrimAbove = trim_impl::Max<u128, 0, 0xfffffffffffffffffffffffffffffffe>;
impl I128TrimBelow =
trim_impl::Impl<
i128,
-0x80000000000000000000000000000000,
-0x7fffffffffffffffffffffffffffffff,
0x7fffffffffffffffffffffffffffffff,
>;
trim_impl::Min<i128, -0x7fffffffffffffffffffffffffffffff, 0x7fffffffffffffffffffffffffffffff>;
impl I128TrimAbove =
trim_impl::Impl<
i128,
0x7fffffffffffffffffffffffffffffff,
-0x80000000000000000000000000000000,
0x7ffffffffffffffffffffffffffffffe,
>;
trim_impl::Max<i128, -0x80000000000000000000000000000000, 0x7ffffffffffffffffffffffffffffffe>;

extern fn bounded_int_trim<T, const TRIMMED_VALUE: felt252, impl H: TrimHelper<T, TRIMMED_VALUE>>(
extern fn bounded_int_trim_min<T, impl H: TrimMinHelper<T>>(
value: T,
) -> core::internal::OptionRev<H::Target> nopanic;
extern fn bounded_int_trim_max<T, impl H: TrimMaxHelper<T>>(
value: T,
) -> core::internal::OptionRev<H::Target> nopanic;

Expand Down Expand Up @@ -272,5 +265,5 @@ impl MulMinusOneNegateHelper<T, impl H: MulHelper<T, MinusOne>> of NegateHelper<
pub use {
bounded_int_add as add, bounded_int_constrain as constrain, bounded_int_div_rem as div_rem,
bounded_int_is_zero as is_zero, bounded_int_mul as mul, bounded_int_sub as sub,
bounded_int_trim as trim,
bounded_int_trim_max as trim_max, bounded_int_trim_min as trim_min,
};
135 changes: 135 additions & 0 deletions corelib/src/iter/traits/iterator.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,47 @@ pub trait Iterator<T> {
/// ```
fn next(ref self: T) -> Option<Self::Item>;

/// Advances the iterator by `n` elements.
///
/// This method will eagerly skip `n` elements by calling [`next`] up to `n`
/// times until [`None`] is encountered.
///
/// `advance_by(n)` will return `Ok(())` if the iterator successfully advances by
/// `n` elements, or a `Err(NonZero<usize>)` with value `k` if [`None`] is encountered,
/// where `k` is remaining number of steps that could not be advanced because the iterator ran
/// out.
/// If `self` is empty and `n` is non-zero, then this returns `Err(n)`.
/// Otherwise, `k` is always less than `n`.
///
/// [`None`]: Option::None
/// [`next`]: Iterator::next
///
/// # Examples
///
/// ```
/// let mut iter = array![1_u8, 2, 3, 4].into_iter();
///
/// assert_eq!(iter.advance_by(2), Result::Ok(()));
/// assert_eq!(iter.next(), Option::Some(3));
/// assert_eq!(iter.advance_by(0), Result::Ok(()));
/// assert_eq!(iter.advance_by(100), Result::Err(99));
/// ```
fn advance_by<+Destruct<T>, +Destruct<Self::Item>>(
ref self: T, n: usize,
) -> Result<
(), NonZero<usize>,
> {
if let Option::Some(nz_n) = n.try_into() {
if let Option::Some(_) = Self::next(ref self) {
return Self::advance_by(ref self, n - 1);
} else {
Result::Err(nz_n)
}
} else {
Result::Ok(())
}
}

/// Takes a closure and creates an iterator which calls that closure on each
/// element.
///
Expand Down Expand Up @@ -128,4 +169,98 @@ pub trait Iterator<T> {
fn enumerate(self: T) -> Enumerate<T> {
enumerated_iterator(self)
}

/// Folds every element into an accumulator by applying an operation,
/// returning the final result.
///
/// `fold()` takes two arguments: an initial value, and a closure with two
/// arguments: an 'accumulator', and an element. The closure returns the value that
/// the accumulator should have for the next iteration.
///
/// The initial value is the value the accumulator will have on the first
/// call.
///
/// After applying this closure to every element of the iterator, `fold()`
/// returns the accumulator.
///
/// Folding is useful whenever you have a collection of something, and want
/// to produce a single value from it.
///
/// Note: `fold()`, and similar methods that traverse the entire iterator,
/// might not terminate for infinite iterators, even on traits for which a
/// result is determinable in finite time.
///
/// Note: `fold()` combines elements in a *left-associative* fashion. For associative
/// operators like `+`, the order the elements are combined in is not important, but for
/// non-associative operators like `-` the order will affect the final result.
///
/// # Note to Implementors
///
/// Several of the other (forward) methods have default implementations in
/// terms of this one, so try to implement this explicitly if it can
/// do something better than the default `for` loop implementation.
///
/// In particular, try to have this call `fold()` on the internal parts
/// from which this iterator is composed.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let mut iter = array![1, 2, 3].into_iter();
///
/// // the sum of all of the elements of the array
/// let sum = iter.fold(0, |acc, x| acc + x);
///
/// assert_eq!(sum, 6);
/// ```
///
/// Let's walk through each step of the iteration here:
///
/// | element | acc | x | result |
/// |---------|-----|---|--------|
/// | | 0 | | |
/// | 1 | 0 | 1 | 1 |
/// | 2 | 1 | 2 | 3 |
/// | 3 | 3 | 3 | 6 |
///
/// And so, our final result, `6`.
///
/// It's common for people who haven't used iterators a lot to
/// use a `for` loop with a list of things to build up a result. Those
/// can be turned into `fold()`s:
///
/// ```
/// let mut numbers = array![1, 2, 3, 4, 5].span();
///
/// let mut result = 0;
///
/// // for loop:
/// for i in numbers{
/// result = result + (*i);
/// };
///
/// // fold:
/// let mut numbers_iter = numbers.into_iter();
/// let result2 = numbers_iter.fold(0, |acc, x| acc + (*x));
///
/// // they're the same
/// assert_eq!(result, result2);
/// ```
fn fold<
B,
F,
+core::ops::Fn<F, (B, Self::Item)>[Output: B],
+Destruct<T>,
+Destruct<F>,
+Destruct<B>,
>(
ref self: T, init: B, f: F,
) -> B {
match Self::next(ref self) {
Option::None => init,
Option::Some(x) => Self::fold(ref self, f(init, x), f),
}
}
}
Loading

0 comments on commit 9b849dc

Please sign in to comment.