Skip to content

Commit

Permalink
Update for Cairo 2.5.0 (#57)
Browse files Browse the repository at this point in the history
* Update for Cairo 2.4.3

* Improve taint (#58)

* update taint to use fxhash

* remove debug + timing

* clippy and fmt

* remove file

* Update for Cairo 2.5.0

---------

Co-authored-by: technovision99 <[email protected]>
  • Loading branch information
smonicas and technovision99 authored Jan 24, 2024
1 parent 39d328e commit b0be7d8
Show file tree
Hide file tree
Showing 115 changed files with 5,140 additions and 2,313 deletions.
652 changes: 519 additions & 133 deletions Cargo.lock

Large diffs are not rendered by default.

29 changes: 16 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,24 @@ once_cell = "1.17"
smol_str = "0.2"
num-integer = "0.1"
termcolor = "1.2"
graphviz-rust = "0.6.2"
cairo-felt = "0.8.7"
graphviz-rust = "0.7.0"
cairo-felt = "0.9.1"
thiserror = "1.0.47"
rayon = "1.8"
fxhash = "0.2.1"

cairo-lang-compiler = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }
cairo-lang-defs = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }
cairo-lang-plugins = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }
cairo-lang-starknet = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }
cairo-lang-filesystem = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }
cairo-lang-parser = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }
cairo-lang-syntax = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }
cairo-lang-semantic = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }
cairo-lang-utils = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }
cairo-lang-sierra-generator = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }
cairo-lang-sierra = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.5.0" }

cairo-lang-compiler = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }
cairo-lang-defs = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }
cairo-lang-plugins = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }
cairo-lang-starknet = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }
cairo-lang-filesystem = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }
cairo-lang-parser = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }
cairo-lang-syntax = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }
cairo-lang-semantic = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }
cairo-lang-utils = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }
cairo-lang-sierra-generator = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }
cairo-lang-sierra = { git = "https://github.com/starkware-libs/cairo.git", tag = "v2.2.0" }

[dev-dependencies]
insta = { version = "1.30", features = ["glob"] }
Expand Down
3 changes: 2 additions & 1 deletion corelib/Scarb.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "core"
version = "2.2.0"
version = "2.5.0"
edition = "2023_11"

# NOTE: This is non-public, unstable Scarb's field, which instructs resolver that this package does not
# depend on `core`, which is only true for this particular package. Nobody else should use it.
Expand Down
6 changes: 6 additions & 0 deletions corelib/cairo_project.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
[crate_roots]
core = "src"

[config.global]
edition = "2023_11"

[config.global.experimental_features]
negative_impls = true
93 changes: 61 additions & 32 deletions corelib/src/array.cairo
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use traits::IndexView;
use core::traits::IndexView;

use box::BoxTrait;
use gas::withdraw_gas;
use option::OptionTrait;
use serde::Serde;
use core::box::BoxTrait;
use core::gas::withdraw_gas;
use core::option::OptionTrait;
use core::serde::Serde;
use core::metaprogramming::TypeEqual;

#[derive(Drop)]
extern type Array<T>;
pub extern type Array<T>;

extern fn array_new<T>() -> Array<T> nopanic;
extern fn array_append<T>(ref arr: Array<T>, value: T) nopanic;
Expand All @@ -24,15 +25,24 @@ extern fn array_slice<T>(
extern fn array_len<T>(arr: @Array<T>) -> usize nopanic;

#[generate_trait]
impl ArrayImpl<T> of ArrayTrait<T> {
pub impl ArrayImpl<T> of ArrayTrait<T> {
#[inline(always)]
fn new() -> Array<T> {
array_new()
}
#[inline(always)]
fn append(ref self: Array<T>, value: T) {
fn append(ref self: Array<T>, value: T) nopanic {
array_append(ref self, value)
}
fn append_span<+Clone<T>, +Drop<T>>(ref self: Array<T>, mut span: Span<T>) {
match span.pop_front() {
Option::Some(current) => {
self.append(current.clone());
self.append_span(span);
},
Option::None => {}
};
}
#[inline(always)]
fn pop_front(ref self: Array<T>) -> Option<T> nopanic {
match array_pop_front(ref self) {
Expand All @@ -55,14 +65,21 @@ impl ArrayImpl<T> of ArrayTrait<T> {
array_at(self, index).unbox()
}
#[inline(always)]
#[must_use]
fn len(self: @Array<T>) -> usize {
array_len(self)
}
#[inline(always)]
#[must_use]
fn is_empty(self: @Array<T>) -> bool {
self.len() == 0_usize
let mut snapshot = self;
match array_snapshot_pop_front(ref snapshot) {
Option::Some(_) => false,
Option::None => true,
}
}
#[inline(always)]
#[must_use]
fn span(self: @Array<T>) -> Span<T> {
Span { snapshot: self }
}
Expand All @@ -81,7 +98,7 @@ impl ArrayIndex<T> of IndexView<Array<T>, usize, @T> {
}
}

impl ArraySerde<T, impl TSerde: Serde<T>, impl TDrop: Drop<T>> of Serde<Array<T>> {
impl ArraySerde<T, +Serde<T>, +Drop<T>> of Serde<Array<T>> {
fn serialize(self: @Array<T>, ref output: Array<felt252>) {
self.len().serialize(ref output);
serialize_array_helper(self.span(), ref output);
Expand All @@ -93,9 +110,7 @@ impl ArraySerde<T, impl TSerde: Serde<T>, impl TDrop: Drop<T>> of Serde<Array<T>
}
}

fn serialize_array_helper<T, impl TSerde: Serde<T>, impl TDrop: Drop<T>>(
mut input: Span<T>, ref output: Array<felt252>
) {
fn serialize_array_helper<T, +Serde<T>, +Drop<T>>(mut input: Span<T>, ref output: Array<felt252>) {
match input.pop_front() {
Option::Some(value) => {
value.serialize(ref output);
Expand All @@ -105,25 +120,39 @@ fn serialize_array_helper<T, impl TSerde: Serde<T>, impl TDrop: Drop<T>>(
}
}

fn deserialize_array_helper<T, impl TSerde: Serde<T>, impl TDrop: Drop<T>>(
fn deserialize_array_helper<T, +Serde<T>, +Drop<T>>(
ref serialized: Span<felt252>, mut curr_output: Array<T>, remaining: felt252
) -> Option<Array<T>> {
if remaining == 0 {
return Option::Some(curr_output);
}
curr_output.append(TSerde::deserialize(ref serialized)?);
curr_output.append(Serde::deserialize(ref serialized)?);
deserialize_array_helper(ref serialized, curr_output, remaining - 1)
}

// Span.
struct Span<T> {
pub struct Span<T> {
snapshot: @Array<T>
}

impl SpanCopy<T> of Copy<Span<T>>;
impl SpanDrop<T> of Drop<Span<T>>;

impl SpanSerde<T, impl TSerde: Serde<T>, impl TDrop: Drop<T>> of Serde<Span<T>> {
impl SpanFelt252Serde of Serde<Span<felt252>> {
fn serialize(self: @Span<felt252>, ref output: Array<felt252>) {
(*self).len().serialize(ref output);
serialize_array_helper(*self, ref output)
}

fn deserialize(ref serialized: Span<felt252>) -> Option<Span<felt252>> {
let length: u32 = (*serialized.pop_front()?).try_into()?;
let res = serialized.slice(0, length);
serialized = serialized.slice(length, serialized.len() - length);
Option::Some(res)
}
}

impl SpanSerde<T, +Serde<T>, +Drop<T>, -TypeEqual<felt252, T>> of Serde<Span<T>> {
fn serialize(self: @Span<T>, ref output: Array<felt252>) {
(*self).len().serialize(ref output);
serialize_array_helper(*self, ref output)
Expand All @@ -137,7 +166,7 @@ impl SpanSerde<T, impl TSerde: Serde<T>, impl TDrop: Drop<T>> of Serde<Span<T>>
}

#[generate_trait]
impl SpanImpl<T> of SpanTrait<T> {
pub impl SpanImpl<T> of SpanTrait<T> {
#[inline(always)]
fn pop_front(ref self: Span<T>) -> Option<@T> {
let mut snapshot = self.snapshot;
Expand Down Expand Up @@ -171,42 +200,44 @@ impl SpanImpl<T> of SpanTrait<T> {
Span { snapshot: array_slice(self.snapshot, start, length).expect('Index out of bounds') }
}
#[inline(always)]
#[must_use]
fn len(self: Span<T>) -> usize {
array_len(self.snapshot)
}
#[inline(always)]
#[must_use]
fn is_empty(self: Span<T>) -> bool {
self.len() == 0_usize
let mut snapshot = self.snapshot;
match array_snapshot_pop_front(ref snapshot) {
Option::Some(_) => false,
Option::None => true,
}
}
}

impl SpanIndex<T> of IndexView<Span<T>, usize, @T> {
pub impl SpanIndex<T> of IndexView<Span<T>, usize, @T> {
#[inline(always)]
fn index(self: @Span<T>, index: usize) -> @T {
array_at(*self.snapshot, index).unbox()
}
}

// TODO(spapini): Remove TDrop. It is necessary to get rid of response in case of panic.
impl ArrayTCloneImpl<T, impl TClone: Clone<T>, impl TDrop: Drop<T>> of Clone<Array<T>> {
impl ArrayTCloneImpl<T, +Clone<T>, +Drop<T>> of Clone<Array<T>> {
fn clone(self: @Array<T>) -> Array<T> {
let mut response = array_new();
let mut span = self.span();
loop {
match span.pop_front() {
Option::Some(v) => {
response.append(TClone::clone(v));
},
Option::None => {
break ();
},
Option::Some(v) => { response.append(v.clone()); },
Option::None => { break (); },
};
};
response
}
}

impl ArrayPartialEq<T, impl PartialEqImpl: PartialEq<T>> of PartialEq<Array<T>> {
impl ArrayPartialEq<T, +PartialEq<T>> of PartialEq<Array<T>> {
fn eq(lhs: @Array<T>, rhs: @Array<T>) -> bool {
lhs.span() == rhs.span()
}
Expand All @@ -215,7 +246,7 @@ impl ArrayPartialEq<T, impl PartialEqImpl: PartialEq<T>> of PartialEq<Array<T>>
}
}

impl SpanPartialEq<T, impl PartialEqImpl: PartialEq<T>> of PartialEq<Span<T>> {
impl SpanPartialEq<T, +PartialEq<T>> of PartialEq<Span<T>> {
fn eq(lhs: @Span<T>, rhs: @Span<T>) -> bool {
if (*lhs).len() != (*rhs).len() {
return false;
Expand All @@ -229,9 +260,7 @@ impl SpanPartialEq<T, impl PartialEqImpl: PartialEq<T>> of PartialEq<Span<T>> {
break false;
}
},
Option::None => {
break true;
},
Option::None => { break true; },
};
}
}
Expand Down
19 changes: 19 additions & 0 deletions corelib/src/boolean.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[generate_trait]
pub impl BoolImpl<T, +Drop<T>> of BoolTrait<T> {
/// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise.
///
/// # Examples
///
/// ```
/// assert(false.then_some(0) == Option::None);
/// assert(true.then_some(0) == Option::Some(0));
/// ```
#[inline(always)]
fn then_some(self: bool, t: T) -> Option<T> nopanic {
if self {
Option::Some(t)
} else {
Option::None
}
}
}
18 changes: 16 additions & 2 deletions corelib/src/box.cairo
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
#[derive(Copy, Drop)]
extern type Box<T>;
pub extern type Box<T>;

// These functions are only exposed in the corelib through the trait below since calling them
// directly with tuples panics due to auto unpacking of the tuple.
// TODO(Gil): Expose in the core lib when the described behaviour is fixed.
extern fn into_box<T>(value: T) -> Box<T> nopanic;
extern fn unbox<T>(box: Box<T>) -> T nopanic;
extern fn box_forward_snapshot<T>(value: @Box<T>) -> Box<@T> nopanic;

#[generate_trait]
impl BoxImpl<T> of BoxTrait<T> {
pub impl BoxImpl<T> of BoxTrait<T> {
#[inline(always)]
#[must_use]
fn new(value: T) -> Box<T> nopanic {
into_box(value)
}
#[inline(always)]
#[must_use]
fn unbox(self: Box<T>) -> T nopanic {
unbox(self)
}
#[must_use]
fn as_snapshot(self: @Box<T>) -> Box<@T> nopanic {
box_forward_snapshot(self)
}
}

impl BoxDebug<T, impl TDebug: core::fmt::Debug<T>> of core::fmt::Debug<Box<T>> {
fn fmt(self: @Box<T>, ref f: core::fmt::Formatter) -> Result<(), core::fmt::Error> {
write!(f, "&")?;
TDebug::fmt(self.as_snapshot().unbox(), ref f)
}
}
Loading

0 comments on commit b0be7d8

Please sign in to comment.