Skip to content

Commit c0b8496

Browse files
FrancoGiachettagabrielbosioJulianGCalderon
authored
[Sierra-Emu] implement missing libfuncs from int_range and array (#1200)
* Add sierra-emu as a debug utility * Change working dir in sierra-emu job * Remove repeated lines in sierra-emu gitignore * Exclude debug_utils from coverage job * remove some todos from value and implement Coupon libfunc * start adding corelib test * run tests from corelib * remove unwanted file * remove not related things * get return_value from trace * replace ids for debug info * add common folder for integration tests * fix tests * remove todo * ignore test for now * filter ignored tests * Update debug_utils/sierra-emu/tests/common/mod.rs Co-authored-by: Julian Gonzalez Calderon <gonzalezcalderonjulian@gmail.com> * run ignored test from the ci * better ignoring * remove debug_name in enums * refactor * remove unused dependency * More expressive naming for the workflow Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> * reviews * reviews * fmt * fmt ci * revert last commit * fmt * accidentally removed rayon usage * avoid map's short-circuiting * catch panics the avoid loosing the test name * log ignored tests * clippy * Add "(WIP)" to corelib's test job Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> * print progress as the test runs * fmt * format makefile Co-authored-by: Julian Gonzalez Calderon <gonzalezcalderonjulian@gmail.com> * fix name test in ci * add dependencies removed in merge * dependencies * clippy * remove unused import * better indent in makefile * uppercase tests summary comment for better sight * implement int_range libfuncs * implement missing array libfuncs * fmt * add is() for IntRange * remove unnecesary pubs * reviews * reviews * fix branching in int_range_try_new * clippy * reviews * fmt --------- Co-authored-by: gabrielbosio <gabrielbosio95@gmail.com> Co-authored-by: Julian Gonzalez Calderon <gonzalezcalderonjulian@gmail.com> Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com>
1 parent 61371fd commit c0b8496

File tree

5 files changed

+196
-13
lines changed

5 files changed

+196
-13
lines changed

debug_utils/sierra-emu/src/value.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ pub enum Value {
6969
U32(u32),
7070
U64(u64),
7171
U8(u8),
72+
IntRange {
73+
x: Box<Value>,
74+
y: Box<Value>,
75+
},
7276
Uninitialized {
7377
ty: ConcreteTypeId,
7478
},
@@ -220,7 +224,7 @@ impl Value {
220224
StarknetTypeConcrete::Secp256Point(_) => matches!(self, Self::Struct(_)),
221225
StarknetTypeConcrete::Sha256StateHandle(_) => matches!(self, Self::Struct { .. }),
222226
},
223-
CoreTypeConcrete::IntRange(_) => todo!(),
227+
CoreTypeConcrete::IntRange(_) => matches!(self, Self::IntRange { .. }),
224228
CoreTypeConcrete::Blake(_) => todo!(),
225229
CoreTypeConcrete::QM31(_) => todo!(),
226230
};

debug_utils/sierra-emu/src/vm.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ mod felt252_dict_entry;
4949
mod function_call;
5050
mod gas;
5151
mod int128;
52+
mod int_range;
5253
mod jump;
5354
mod mem;
5455
mod nullable;
@@ -519,7 +520,7 @@ fn eval<'a>(
519520

520521
EvalAction::NormalBranch(0, smallvec![value])
521522
}
522-
CoreConcreteLibfunc::IntRange(_) => todo!(),
523+
CoreConcreteLibfunc::IntRange(selector) => self::int_range::eval(registry, selector, args),
523524
CoreConcreteLibfunc::Blake(_) => todo!(),
524525
CoreConcreteLibfunc::QM31(_) => todo!(),
525526
CoreConcreteLibfunc::Felt252SquashedDict(_) => todo!(),

debug_utils/sierra-emu/src/vm/array.rs

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ pub fn eval(
1919
match selector {
2020
ArrayConcreteLibfunc::New(info) => eval_new(registry, info, args),
2121
ArrayConcreteLibfunc::SpanFromTuple(info) => eval_span_from_tuple(registry, info, args),
22-
ArrayConcreteLibfunc::TupleFromSpan(_) => todo!(),
22+
ArrayConcreteLibfunc::TupleFromSpan(info) => eval_tuple_from_span(registry, info, args),
2323
ArrayConcreteLibfunc::Append(info) => eval_append(registry, info, args),
2424
ArrayConcreteLibfunc::PopFront(info) => eval_pop_front(registry, info, args),
25-
ArrayConcreteLibfunc::PopFrontConsume(_) => todo!(),
25+
ArrayConcreteLibfunc::PopFrontConsume(info) => eval_pop_front_consume(registry, info, args),
2626
ArrayConcreteLibfunc::Get(info) => eval_get(registry, info, args),
2727
ArrayConcreteLibfunc::Slice(info) => eval_slice(registry, info, args),
2828
ArrayConcreteLibfunc::Len(info) => eval_len(registry, info, args),
@@ -33,7 +33,9 @@ pub fn eval(
3333
ArrayConcreteLibfunc::SnapshotMultiPopFront(info) => {
3434
eval_snapshot_multi_pop_front(registry, info, args)
3535
}
36-
ArrayConcreteLibfunc::SnapshotMultiPopBack(_) => todo!(),
36+
ArrayConcreteLibfunc::SnapshotMultiPopBack(info) => {
37+
eval_snapshot_multi_pop_back(registry, info, args)
38+
}
3739
}
3840
}
3941

@@ -61,7 +63,31 @@ fn eval_span_from_tuple(
6163
EvalAction::NormalBranch(0, smallvec![value])
6264
}
6365

64-
pub fn eval_new(
66+
fn eval_tuple_from_span(
67+
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
68+
info: &SignatureAndTypeConcreteLibfunc,
69+
args: Vec<Value>,
70+
) -> EvalAction {
71+
let [Value::Array { data, .. }]: [Value; 1] = args.try_into().unwrap() else {
72+
panic!()
73+
};
74+
75+
let tuple_len = {
76+
let CoreTypeConcrete::Struct(param) = registry.get_type(&info.ty).unwrap() else {
77+
panic!()
78+
};
79+
80+
param.members.len()
81+
};
82+
83+
if data.len() == tuple_len {
84+
EvalAction::NormalBranch(0, smallvec![Value::Struct(data)])
85+
} else {
86+
EvalAction::NormalBranch(1, smallvec![])
87+
}
88+
}
89+
90+
fn eval_new(
6591
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
6692
info: &SignatureOnlyConcreteLibfunc,
6793
args: Vec<Value>,
@@ -85,7 +111,7 @@ pub fn eval_new(
85111
)
86112
}
87113

88-
pub fn eval_append(
114+
fn eval_append(
89115
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
90116
info: &SignatureAndTypeConcreteLibfunc,
91117
args: Vec<Value>,
@@ -101,7 +127,7 @@ pub fn eval_append(
101127
EvalAction::NormalBranch(0, smallvec![Value::Array { ty, data }])
102128
}
103129

104-
pub fn eval_get(
130+
fn eval_get(
105131
_registry: &ProgramRegistry<CoreType, CoreLibfunc>,
106132
_info: &SignatureAndTypeConcreteLibfunc,
107133
args: Vec<Value>,
@@ -118,7 +144,7 @@ pub fn eval_get(
118144
}
119145
}
120146

121-
pub fn eval_slice(
147+
fn eval_slice(
122148
_registry: &ProgramRegistry<CoreType, CoreLibfunc>,
123149
_info: &SignatureAndTypeConcreteLibfunc,
124150
args: Vec<Value>,
@@ -144,7 +170,7 @@ pub fn eval_slice(
144170
}
145171
}
146172

147-
pub fn eval_len(
173+
fn eval_len(
148174
_registry: &ProgramRegistry<CoreType, CoreLibfunc>,
149175
_info: &SignatureAndTypeConcreteLibfunc,
150176
args: Vec<Value>,
@@ -157,7 +183,7 @@ pub fn eval_len(
157183
EvalAction::NormalBranch(0, smallvec![Value::U32(array_len)])
158184
}
159185

160-
pub fn eval_pop_front(
186+
fn eval_pop_front(
161187
_registry: &ProgramRegistry<CoreType, CoreLibfunc>,
162188
_info: &SignatureAndTypeConcreteLibfunc,
163189
args: Vec<Value>,
@@ -175,7 +201,25 @@ pub fn eval_pop_front(
175201
}
176202
}
177203

178-
pub fn eval_snapshot_pop_front(
204+
fn eval_pop_front_consume(
205+
_registry: &ProgramRegistry<CoreType, CoreLibfunc>,
206+
_info: &SignatureAndTypeConcreteLibfunc,
207+
args: Vec<Value>,
208+
) -> EvalAction {
209+
let [Value::Array { mut data, ty }]: [Value; 1] = args.try_into().unwrap() else {
210+
panic!()
211+
};
212+
213+
if !data.is_empty() {
214+
let new_data = data.split_off(1);
215+
let value = data[0].clone();
216+
EvalAction::NormalBranch(0, smallvec![Value::Array { data: new_data, ty }, value])
217+
} else {
218+
EvalAction::NormalBranch(1, smallvec![])
219+
}
220+
}
221+
222+
fn eval_snapshot_pop_front(
179223
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
180224
info: &SignatureAndTypeConcreteLibfunc,
181225
args: Vec<Value>,
@@ -194,7 +238,7 @@ pub fn eval_snapshot_pop_front(
194238
}
195239
}
196240

197-
pub fn eval_snapshot_pop_back(
241+
fn eval_snapshot_pop_back(
198242
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
199243
info: &SignatureAndTypeConcreteLibfunc,
200244
args: Vec<Value>,
@@ -238,3 +282,29 @@ fn eval_snapshot_multi_pop_front(
238282
EvalAction::NormalBranch(1, smallvec![rangecheck, Value::Array { data, ty }])
239283
}
240284
}
285+
286+
fn eval_snapshot_multi_pop_back(
287+
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
288+
info: &cairo_lang_sierra::extensions::array::ConcreteMultiPopLibfunc,
289+
args: Vec<Value>,
290+
) -> EvalAction {
291+
let [rangecheck, Value::Array { mut data, ty }]: [Value; 2] = args.try_into().unwrap() else {
292+
panic!()
293+
};
294+
295+
let CoreTypeConcrete::Struct(popped_cty) = registry.get_type(&info.popped_ty).unwrap() else {
296+
panic!()
297+
};
298+
299+
if data.len() >= popped_cty.members.len() {
300+
let new_data = data.split_off(data.len() - popped_cty.members.len());
301+
let value = Value::Struct(data);
302+
assert!(value.is(registry, &info.popped_ty));
303+
EvalAction::NormalBranch(
304+
0,
305+
smallvec![rangecheck, Value::Array { data: new_data, ty }, value],
306+
)
307+
} else {
308+
EvalAction::NormalBranch(1, smallvec![rangecheck, Value::Array { data, ty }])
309+
}
310+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use cairo_lang_sierra::{
2+
extensions::{
3+
core::{CoreLibfunc, CoreType},
4+
lib_func::SignatureOnlyConcreteLibfunc,
5+
range::IntRangeConcreteLibfunc,
6+
ConcreteLibfunc,
7+
},
8+
program_registry::ProgramRegistry,
9+
};
10+
use num_bigint::BigInt;
11+
use smallvec::smallvec;
12+
13+
use crate::{
14+
utils::{get_numeric_args_as_bigints, get_value_from_integer},
15+
Value,
16+
};
17+
18+
use super::EvalAction;
19+
20+
pub fn eval(
21+
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
22+
selector: &IntRangeConcreteLibfunc,
23+
args: Vec<Value>,
24+
) -> EvalAction {
25+
match selector {
26+
IntRangeConcreteLibfunc::TryNew(info) => eval_try_new(registry, info, args),
27+
IntRangeConcreteLibfunc::PopFront(info) => eval_pop_front(registry, info, args),
28+
}
29+
}
30+
31+
fn eval_try_new(
32+
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
33+
info: &SignatureOnlyConcreteLibfunc,
34+
args: Vec<Value>,
35+
) -> EvalAction {
36+
let range_check @ Value::Unit: Value = args[0].clone() else {
37+
panic!()
38+
};
39+
let [x, y]: [BigInt; 2] = get_numeric_args_as_bigints(&args[1..]).try_into().unwrap();
40+
41+
let int_ty = registry.get_type(&info.param_signatures()[1].ty).unwrap();
42+
43+
// if x >= y then the range is not valid and we return [y, y) (empty range)
44+
if x < y {
45+
let x = get_value_from_integer(registry, int_ty, x);
46+
let y = get_value_from_integer(registry, int_ty, y);
47+
EvalAction::NormalBranch(
48+
0,
49+
smallvec![
50+
range_check,
51+
Value::IntRange {
52+
x: Box::new(x),
53+
y: Box::new(y),
54+
}
55+
],
56+
)
57+
} else {
58+
let y = get_value_from_integer(registry, int_ty, y);
59+
EvalAction::NormalBranch(
60+
1,
61+
smallvec![
62+
range_check,
63+
Value::IntRange {
64+
x: Box::new(y.clone()),
65+
y: Box::new(y),
66+
}
67+
],
68+
)
69+
}
70+
}
71+
72+
fn eval_pop_front(
73+
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
74+
info: &SignatureOnlyConcreteLibfunc,
75+
args: Vec<Value>,
76+
) -> EvalAction {
77+
let [Value::IntRange { x, y }]: [Value; 1] = args.try_into().unwrap() else {
78+
panic!()
79+
};
80+
let [x, y]: [BigInt; 2] = get_numeric_args_as_bigints(&[*x, *y]).try_into().unwrap();
81+
let int_ty = registry.get_type(&info.param_signatures()[1].ty).unwrap();
82+
83+
if x < y {
84+
let x_plus_1 = get_value_from_integer(registry, int_ty, &x + 1);
85+
let x = get_value_from_integer(registry, int_ty, x);
86+
let y = get_value_from_integer(registry, int_ty, y);
87+
88+
EvalAction::NormalBranch(
89+
0,
90+
smallvec![
91+
Value::IntRange {
92+
x: Box::new(x_plus_1),
93+
y: Box::new(y)
94+
},
95+
x
96+
],
97+
)
98+
} else {
99+
EvalAction::NormalBranch(1, smallvec![])
100+
}
101+
}

debug_utils/sierra-emu/tests/common/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ pub fn value_to_felt(value: &Value) -> Vec<Felt> {
8383
Value::U64(x) => vec![(*x).into()],
8484
Value::U128(x) => vec![(*x).into()],
8585
Value::U256(x, y) => vec![(*x).into(), (*y).into()],
86+
Value::IntRange { x, y } => {
87+
let felt = value_to_felt(x);
88+
felts.extend(felt);
89+
let felt = value_to_felt(y);
90+
felts.extend(felt);
91+
felts
92+
}
8693
Value::Unit | Value::Null | Value::Uninitialized { .. } => vec![0.into()],
8794
}
8895
}

0 commit comments

Comments
 (0)