diff --git a/src/libfuncs/ec.rs b/src/libfuncs/ec.rs index 5563d1f6b..635477dcc 100644 --- a/src/libfuncs/ec.rs +++ b/src/libfuncs/ec.rs @@ -493,98 +493,80 @@ pub fn build_zero<'ctx, 'this>( #[cfg(test)] mod test { use crate::{ - utils::test::{jit_enum, jit_struct, load_cairo, run_program, run_program_assert_output}, + utils::{ + sierra_gen::SierraGenerator, + test::{jit_enum, jit_struct, run_sierra_program}, + }, values::Value, }; - use cairo_lang_sierra::program::Program; + use cairo_lang_sierra::{ + extensions::ec::{ + EcCreatePointLibfunc, EcIsZeroLibfunc, EcNegLibfunc, EcPointFromXLibfunc, + EcStateAddLibfunc, EcStateAddMulLibfunc, EcStateFinalizeLibfunc, EcStateInitLibfunc, + EcUnwrapPointLibfunc, EcZeroLibfunc, + }, + program::Program, + }; use lazy_static::lazy_static; use starknet_types_core::felt::Felt; use std::ops::Neg; lazy_static! { - static ref EC_POINT_IS_ZERO: (String, Program) = load_cairo! { - use core::{ec::{ec_point_is_zero, EcPoint}, zeroable::IsZeroResult}; + static ref EC_POINT_IS_ZERO: Program = { + let generator = SierraGenerator::::default(); - fn run_test(point: EcPoint) -> IsZeroResult { - ec_point_is_zero(point) - } + generator.build(&[]) }; - static ref EC_NEG: (String, Program) = load_cairo! { - use core::ec::{ec_neg, EcPoint}; + static ref EC_NEG: Program = { + let generator = SierraGenerator::::default(); - fn run_test(point: EcPoint) -> EcPoint { - ec_neg(point) - } + generator.build(&[]) }; - static ref EC_POINT_FROM_X_NZ: (String, Program) = load_cairo! { - use core::ec::{ec_point_from_x_nz, EcPoint}; - use core::zeroable::NonZero; + static ref EC_POINT_FROM_X_NZ: Program = { + let generator = SierraGenerator::::default(); - fn run_test(x: felt252) -> Option> { - ec_point_from_x_nz(x) - } + generator.build(&[]) }; - static ref EC_STATE_ADD: (String, Program) = load_cairo! { - use core::ec::{ec_state_add, EcPoint, EcState}; - use core::zeroable::NonZero; + static ref EC_STATE_ADD: Program = { + let generator = SierraGenerator::::default(); - fn run_test(mut state: EcState, point: NonZero) -> EcState { - ec_state_add(ref state, point); - state - } + generator.build(&[]) }; - static ref EC_STATE_ADD_MUL: (String, Program) = load_cairo! { - use core::ec::{ec_state_add_mul, EcPoint, EcState}; - use core::zeroable::NonZero; + static ref EC_STATE_ADD_MUL: Program = { + let generator = SierraGenerator::::default(); - fn run_test(mut state: EcState, scalar: felt252, point: NonZero) -> EcState { - ec_state_add_mul(ref state, scalar, point); - state - } + generator.build(&[]) }; - static ref EC_STATE_FINALIZE: (String, Program) = load_cairo! { - use core::ec::{ec_state_try_finalize_nz, EcPoint, EcState}; - use core::zeroable::NonZero; + static ref EC_STATE_FINALIZE: Program = { + let generator = SierraGenerator::::default(); - fn run_test(state: EcState) -> Option> { - ec_state_try_finalize_nz(state) - } + generator.build(&[]) }; - static ref EC_STATE_INIT: (String, Program) = load_cairo! { - use core::ec::{ec_state_init, EcState}; + static ref EC_STATE_INIT: Program = { + let generator = SierraGenerator::::default(); - fn run_test() -> EcState { - ec_state_init() - } + generator.build(&[]) }; - static ref EC_POINT_TRY_NEW_NZ: (String, Program) = load_cairo! { - use core::ec::{ec_point_try_new_nz, EcPoint}; - use core::zeroable::NonZero; + static ref EC_POINT_TRY_NEW_NZ: Program = { + let generator = SierraGenerator::::default(); - fn run_test(x: felt252, y: felt252) -> Option> { - ec_point_try_new_nz(x, y) - } + generator.build(&[]) }; - static ref EC_POINT_UNWRAP: (String, Program) = load_cairo! { - use core::{ec::{ec_point_unwrap, EcPoint}, zeroable::NonZero}; + static ref EC_POINT_UNWRAP: Program = { + let generator = SierraGenerator::::default(); - fn run_test(point: NonZero) -> (felt252, felt252) { - ec_point_unwrap(point) - } + generator.build(&[]) }; - static ref EC_POINT_ZERO: (String, Program) = load_cairo! { - use core::ec::{ec_point_zero, EcPoint}; + static ref EC_POINT_ZERO: Program = { + let generator = SierraGenerator::::default(); - fn run_test() -> EcPoint { - ec_point_zero() - } + generator.build(&[]) }; } #[test] fn ec_point_is_zero() { - let r = - |x, y| run_program(&EC_POINT_IS_ZERO, "run_test", &[Value::EcPoint(x, y)]).return_value; + let r = |x, y| run_sierra_program(&EC_POINT_IS_ZERO, &[Value::EcPoint(x, y)]).return_value; assert_eq!(r(0.into(), 0.into()), jit_enum!(0, jit_struct!())); assert_eq!( @@ -600,7 +582,7 @@ mod test { #[test] fn ec_neg() { - let r = |x, y| run_program(&EC_NEG, "run_test", &[Value::EcPoint(x, y)]).return_value; + let r = |x, y| run_sierra_program(&EC_NEG, &[Value::EcPoint(x, y)]).return_value; assert_eq!(r(0.into(), 0.into()), Value::EcPoint(0.into(), 0.into())); assert_eq!( @@ -616,7 +598,7 @@ mod test { #[test] fn ec_point_from_x() { - let r = |x| run_program(&EC_POINT_FROM_X_NZ, "run_test", &[Value::Felt252(x)]).return_value; + let r = |x| run_sierra_program(&EC_POINT_FROM_X_NZ, &[Value::Felt252(x)]).return_value; assert_eq!(r(0.into()), jit_enum!(1, jit_struct!())); assert_eq!(r(1234.into()), jit_enum!(0, Value::EcPoint( @@ -627,7 +609,7 @@ mod test { #[test] fn ec_state_add() { - run_program_assert_output(&EC_STATE_ADD, "run_test", &[ + let result = run_sierra_program(&EC_STATE_ADD, &[ Value::EcState( Felt::from_dec_str("3151312365169595090315724863753927489909436624354740709748557281394568342450").unwrap(), Felt::from_dec_str("2835232394579952276045648147338966184268723952674536708929458753792035266179").unwrap(), @@ -638,18 +620,34 @@ mod test { Felt::from_dec_str("1234").unwrap(), Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap() ) - ], - Value::EcState( - Felt::from_dec_str("763975897824944497806946001227010133599886598340174017198031710397718335159").unwrap(), - Felt::from_dec_str("2805180267536471620369715068237762638204710971142209985448115065526708105983").unwrap(), - Felt::from_dec_str("3151312365169595090315724863753927489909436624354740709748557281394568342450").unwrap(), - Felt::from_dec_str("2835232394579952276045648147338966184268723952674536708929458753792035266179").unwrap() - )); + ]).return_value; + + assert_eq!( + Value::EcState( + Felt::from_dec_str( + "763975897824944497806946001227010133599886598340174017198031710397718335159" + ) + .unwrap(), + Felt::from_dec_str( + "2805180267536471620369715068237762638204710971142209985448115065526708105983" + ) + .unwrap(), + Felt::from_dec_str( + "3151312365169595090315724863753927489909436624354740709748557281394568342450" + ) + .unwrap(), + Felt::from_dec_str( + "2835232394579952276045648147338966184268723952674536708929458753792035266179" + ) + .unwrap() + ), + result + ); } #[test] fn ec_state_add_mul() { - run_program_assert_output(&EC_STATE_ADD_MUL, "run_test", &[ + let result = run_sierra_program(&EC_STATE_ADD_MUL, &[ Value::EcState( Felt::from_dec_str("3151312365169595090315724863753927489909436624354740709748557281394568342450").unwrap(), Felt::from_dec_str("2835232394579952276045648147338966184268723952674536708929458753792035266179").unwrap(), @@ -661,16 +659,31 @@ mod test { Felt::from_dec_str("1234").unwrap(), Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap() ) - ], + ]).return_value; + + assert_eq!( Value::EcState( - Felt::from_dec_str("763975897824944497806946001227010133599886598340174017198031710397718335159").unwrap(), - Felt::from_dec_str("2805180267536471620369715068237762638204710971142209985448115065526708105983").unwrap(), - Felt::from_dec_str("3151312365169595090315724863753927489909436624354740709748557281394568342450").unwrap(), - Felt::from_dec_str("2835232394579952276045648147338966184268723952674536708929458753792035266179").unwrap() - ) + Felt::from_dec_str( + "763975897824944497806946001227010133599886598340174017198031710397718335159" + ) + .unwrap(), + Felt::from_dec_str( + "2805180267536471620369715068237762638204710971142209985448115065526708105983" + ) + .unwrap(), + Felt::from_dec_str( + "3151312365169595090315724863753927489909436624354740709748557281394568342450" + ) + .unwrap(), + Felt::from_dec_str( + "2835232394579952276045648147338966184268723952674536708929458753792035266179" + ) + .unwrap() + ), + result ); - run_program_assert_output(&EC_STATE_ADD_MUL, "run_test", &[ + let result = run_sierra_program(&EC_STATE_ADD_MUL, &[ Value::EcState( Felt::from_dec_str("3151312365169595090315724863753927489909436624354740709748557281394568342450").unwrap(), Felt::from_dec_str("2835232394579952276045648147338966184268723952674536708929458753792035266179").unwrap(), @@ -682,21 +695,36 @@ mod test { Felt::from_dec_str("1234").unwrap(), Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap() ) - ], + ] + ).return_value; + + assert_eq!( Value::EcState( - Felt::from_dec_str("3016674370847061744386893405108272070153695046160622325692702034987910716850").unwrap(), - Felt::from_dec_str("898133181809473419542838028331350248951548889944002871647069130998202992502").unwrap(), - Felt::from_dec_str("3151312365169595090315724863753927489909436624354740709748557281394568342450").unwrap(), - Felt::from_dec_str("2835232394579952276045648147338966184268723952674536708929458753792035266179").unwrap() - ) - ); + Felt::from_dec_str( + "3016674370847061744386893405108272070153695046160622325692702034987910716850" + ) + .unwrap(), + Felt::from_dec_str( + "898133181809473419542838028331350248951548889944002871647069130998202992502" + ) + .unwrap(), + Felt::from_dec_str( + "3151312365169595090315724863753927489909436624354740709748557281394568342450" + ) + .unwrap(), + Felt::from_dec_str( + "2835232394579952276045648147338966184268723952674536708929458753792035266179" + ) + .unwrap() + ), + result + ) } #[test] fn ec_state_finalize() { - run_program_assert_output( + let result = run_sierra_program( &EC_STATE_FINALIZE, - "run_test", &[Value::EcState( Felt::from_dec_str( "3151312365169595090315724863753927489909436624354740709748557281394568342450", @@ -715,67 +743,97 @@ mod test { ) .unwrap(), )], - jit_enum!(1, jit_struct!()), - ); - run_program_assert_output(&EC_STATE_FINALIZE, "run_test", &[ - Value::EcState( - Felt::from_dec_str("763975897824944497806946001227010133599886598340174017198031710397718335159").unwrap(), - Felt::from_dec_str("2805180267536471620369715068237762638204710971142209985448115065526708105983").unwrap(), - Felt::from_dec_str("3151312365169595090315724863753927489909436624354740709748557281394568342450").unwrap(), - Felt::from_dec_str("2835232394579952276045648147338966184268723952674536708929458753792035266179").unwrap() - ), - ], - jit_enum!(0, Value::EcPoint( - Felt::from(1234), - Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap() + ) + .return_value; + + assert_eq!(jit_enum!(1, jit_struct!()), result); + + let result = run_sierra_program( + &EC_STATE_FINALIZE, + &[Value::EcState( + Felt::from_dec_str( + "763975897824944497806946001227010133599886598340174017198031710397718335159", + ) + .unwrap(), + Felt::from_dec_str( + "2805180267536471620369715068237762638204710971142209985448115065526708105983", ) + .unwrap(), + Felt::from_dec_str( + "3151312365169595090315724863753927489909436624354740709748557281394568342450", + ) + .unwrap(), + Felt::from_dec_str( + "2835232394579952276045648147338966184268723952674536708929458753792035266179", + ) + .unwrap(), + )], + ) + .return_value; + + assert_eq!( jit_enum!(0, Value::EcPoint( + Felt::from(1234), + Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap() ) - ); + ), result); } #[test] fn ec_state_init() { - let result = run_program(&EC_STATE_INIT, "run_test", &[]); + let result = run_sierra_program(&EC_STATE_INIT, &[]); // cant match the values because the state init is a random point assert!(matches!(result.return_value, Value::EcState(_, _, _, _))); } #[test] fn ec_point_try_new_nz() { - run_program_assert_output( + let result = run_sierra_program( &EC_POINT_TRY_NEW_NZ, - "run_test", &[ Felt::from_dec_str("0").unwrap().into(), Felt::from_dec_str("0").unwrap().into(), ], - jit_enum!(1, jit_struct!()), - ); - run_program_assert_output( + ) + .return_value; + + assert_eq!(jit_enum!(1, jit_struct!()), result); + + let result = run_sierra_program( &EC_POINT_TRY_NEW_NZ, - "run_test", &[ Felt::from_dec_str("1234").unwrap().into(), - Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap().into() + Felt::from_dec_str( + "1301976514684871091717790968549291947487646995000837413367950573852273027507", + ) + .unwrap() + .into(), ], - jit_enum!(0, Value::EcPoint( - Felt::from_dec_str("1234").unwrap(), - Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap() - )) - , - ); - run_program_assert_output( + ) + .return_value; + + assert_eq!(jit_enum!(0, Value::EcPoint( + Felt::from_dec_str("1234").unwrap(), + Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap() + )), result); + + let result = run_sierra_program( &EC_POINT_TRY_NEW_NZ, - "run_test", - &[ Felt::from_dec_str("1234").unwrap().into(), - Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap().neg().into() - ], - jit_enum!(0, Value::EcPoint( - Felt::from_dec_str("1234").unwrap(), - Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap().neg() - )) - , - ); + &[ + Felt::from_dec_str("1234").unwrap().into(), + Felt::from_dec_str( + "1301976514684871091717790968549291947487646995000837413367950573852273027507", + ) + .unwrap() + .neg() + .into(), + ], + ) + .return_value; + + assert_eq!(jit_enum!(0, Value::EcPoint( + Felt::from_dec_str("1234").unwrap(), + Felt::from_dec_str("1301976514684871091717790968549291947487646995000837413367950573852273027507").unwrap().neg() + )), result); } #[test] @@ -790,12 +848,11 @@ mod test { #[track_caller] fn run(a: &str, b: &str, ea: &str, eb: &str) { - run_program_assert_output( - &EC_POINT_UNWRAP, - "run_test", - &[Value::EcPoint(parse(a), parse(b))], - jit_struct!(parse(ea).into(), parse(eb).into()), - ); + let result = + run_sierra_program(&EC_POINT_UNWRAP, &[Value::EcPoint(parse(a), parse(b))]) + .return_value; + + assert_eq!(jit_struct!(parse(ea).into(), parse(eb).into()), result) } run("0", "0", "0", "0"); @@ -811,14 +868,14 @@ mod test { #[test] fn ec_point_zero() { - run_program_assert_output( - &EC_POINT_ZERO, - "run_test", - &[], + let result = run_sierra_program(&EC_POINT_ZERO, &[]).return_value; + + assert_eq!( Value::EcPoint( Felt::from_dec_str("0").unwrap(), Felt::from_dec_str("0").unwrap().neg(), ), + result ); } } diff --git a/src/libfuncs/enum.rs b/src/libfuncs/enum.rs index 2a774b835..7c3bd5d81 100644 --- a/src/libfuncs/enum.rs +++ b/src/libfuncs/enum.rs @@ -546,103 +546,160 @@ pub fn build_snapshot_match<'ctx, 'this>( #[cfg(test)] mod test { + use std::sync::{Arc, Mutex}; + use crate::{ context::NativeContext, - utils::test::{jit_enum, jit_struct, load_cairo, run_program_assert_output}, + utils::{ + sierra_gen::SierraGenerator, + test::{jit_enum, run_sierra_program}, + }, + Value, + }; + use cairo_lang_sierra::{ + extensions::{ + enm::{EnumInitLibfunc, EnumMatchLibfunc, EnumType}, + felt252::Felt252Type, + int::unsigned::{Uint16Type, Uint32Type, Uint64Type, Uint8Type}, + }, + ids::UserTypeId, + program::{GenericArg, Program}, }; - use cairo_lang_sierra::program::Program; use lazy_static::lazy_static; + use num_bigint::BigInt; use starknet_types_core::felt::Felt; lazy_static! { - static ref ENUM_INIT: (String, Program) = load_cairo! { - enum MySmallEnum { - A: felt252, - } + static ref SMALL_ENUM_INIT: Program = { + let mut generator = SierraGenerator::::default(); - enum MyEnum { - A: felt252, - B: u8, - C: u16, - D: u32, - E: u64, - } - - fn run_test() -> (MySmallEnum, MyEnum, MyEnum, MyEnum, MyEnum, MyEnum) { - ( - MySmallEnum::A(-1), - MyEnum::A(5678), - MyEnum::B(90), - MyEnum::C(9012), - MyEnum::D(34567890), - MyEnum::E(1234567890123456), - ) - } - }; - static ref ENUM_MATCH: (String, Program) = load_cairo! { - enum MyEnum { - A: felt252, - B: u8, - C: u16, - D: u32, - E: u64, - } + let felt252_ty = generator.push_type_declaration::(&[]).clone(); - fn match_a() -> felt252 { - let x = MyEnum::A(5); - match x { - MyEnum::A(x) => x, - MyEnum::B(_) => 0, - MyEnum::C(_) => 1, - MyEnum::D(_) => 2, - MyEnum::E(_) => 3, - } - } + let enum_ty_1 = generator + .push_type_declaration::(&[ + GenericArg::UserType(UserTypeId::from_string("MySmallEnum")), + GenericArg::Type(felt252_ty.clone()), + ]) + .clone(); - fn match_b() -> u8 { - let x = MyEnum::B(5_u8); - match x { - MyEnum::A(_) => 0_u8, - MyEnum::B(x) => x, - MyEnum::C(_) => 1_u8, - MyEnum::D(_) => 2_u8, - MyEnum::E(_) => 3_u8, - } - } + generator.build(&[GenericArg::Type(enum_ty_1), GenericArg::Value(BigInt::ZERO)]) + }; + static ref ENUM_INIT: Arc Program + Send + 'static>> = + Arc::new(Mutex::new(|enum_index| { + let mut generator = SierraGenerator::::default(); + + let felt252_ty = generator.push_type_declaration::(&[]).clone(); + let u8_ty = generator.push_type_declaration::(&[]).clone(); + let u16_ty = generator.push_type_declaration::(&[]).clone(); + let u32_ty = generator.push_type_declaration::(&[]).clone(); + let u64_ty = generator.push_type_declaration::(&[]).clone(); + + let enum_ty_2 = generator + .push_type_declaration::(&[ + GenericArg::UserType(UserTypeId::from_string("MyEnum")), + GenericArg::Type(felt252_ty.clone()), + GenericArg::Type(u8_ty.clone()), + GenericArg::Type(u16_ty.clone()), + GenericArg::Type(u32_ty.clone()), + GenericArg::Type(u64_ty.clone()), + ]) + .clone(); + + generator.build(&[ + GenericArg::Type(enum_ty_2), + GenericArg::Value(BigInt::from(enum_index)), + ]) + })); + static ref ENUM_MATCH: Program = { + let mut generator = SierraGenerator::::default(); + + let felt252_ty = generator.push_type_declaration::(&[]).clone(); + let u8_ty = generator.push_type_declaration::(&[]).clone(); + let u16_ty = generator.push_type_declaration::(&[]).clone(); + let u32_ty = generator.push_type_declaration::(&[]).clone(); + let u64_ty = generator.push_type_declaration::(&[]).clone(); + + let enum_ty = generator + .push_type_declaration::(&[ + GenericArg::UserType(UserTypeId::from_string("MyEnum")), + GenericArg::Type(felt252_ty.clone()), + GenericArg::Type(u8_ty.clone()), + GenericArg::Type(u16_ty.clone()), + GenericArg::Type(u32_ty.clone()), + GenericArg::Type(u64_ty.clone()), + ]) + .clone(); + + generator.build(&[GenericArg::Type(enum_ty)]) }; } #[test] fn enum_init() { - run_program_assert_output( - &ENUM_INIT, - "run_test", - &[], - jit_struct!( - jit_enum!(0, Felt::from(-1).into()), - jit_enum!(0, Felt::from(5678).into()), - jit_enum!(1, 90u8.into()), - jit_enum!(2, 9012u16.into()), - jit_enum!(3, 34567890u32.into()), - jit_enum!(4, 1234567890123456u64.into()), - ), - ); + let result = run_sierra_program( + &ENUM_INIT.lock().unwrap()(0), + &[Value::Felt252((-1).into())], + ) + .return_value; + + assert_eq!(jit_enum!(0, Felt::from(-1).into()), result); + + let result = run_sierra_program( + &ENUM_INIT.lock().unwrap()(0), + &[Value::Felt252(5678.into())], + ) + .return_value; + + assert_eq!(jit_enum!(0, Felt::from(5678).into()), result); + + let result = run_sierra_program(&ENUM_INIT.lock().unwrap()(1), &[90u8.into()]).return_value; + + assert_eq!(jit_enum!(1, Value::Uint8(90u8)), result); + + let result = + run_sierra_program(&ENUM_INIT.lock().unwrap()(2), &[9012u16.into()]).return_value; + + assert_eq!(jit_enum!(2, Value::Uint16(9012u16)), result); + + let result = + run_sierra_program(&ENUM_INIT.lock().unwrap()(3), &[34567890u32.into()]).return_value; + + assert_eq!(jit_enum!(3, Value::Uint32(34567890u32)), result); + + let result = + run_sierra_program(&ENUM_INIT.lock().unwrap()(4), &[1234567890123456u64.into()]) + .return_value; + + assert_eq!(jit_enum!(4, Value::Uint64(1234567890123456u64)), result); } #[test] fn enum_match() { - run_program_assert_output(&ENUM_MATCH, "match_a", &[], Felt::from(5).into()); - run_program_assert_output(&ENUM_MATCH, "match_b", &[], 5u8.into()); + let result = run_sierra_program(&ENUM_INIT.lock().unwrap()(0), &[Value::Felt252(5.into())]) + .return_value; + let result = run_sierra_program(&ENUM_MATCH, &[result]).return_value; + + assert_eq!(jit_enum!(0, Value::Felt252(5.into())), result); + + let result = + run_sierra_program(&ENUM_INIT.lock().unwrap()(1), &[Value::Uint8(5)]).return_value; + let result = run_sierra_program(&ENUM_MATCH, &[result]).return_value; + + assert_eq!(jit_enum!(1, Value::Uint8(5u8)), result); } #[test] fn compile_enum_match_without_variants() { - let (_, program) = load_cairo! { - enum MyEnum {} + let program = { + let mut generator = SierraGenerator::::default(); - fn main(value: MyEnum) { - match value {} - } + let enum_ty = generator + .push_type_declaration::(&[GenericArg::UserType( + UserTypeId::from_string("MyEnum"), + )]) + .clone(); + + generator.build(&[GenericArg::Type(enum_ty)]) }; let native_context = NativeContext::new(); diff --git a/src/libfuncs/felt252_dict.rs b/src/libfuncs/felt252_dict.rs index 43d2165e3..13af7e95f 100644 --- a/src/libfuncs/felt252_dict.rs +++ b/src/libfuncs/felt252_dict.rs @@ -143,23 +143,45 @@ pub fn build_squash<'ctx, 'this>( #[cfg(test)] mod test { + use std::collections::HashMap; + + use cairo_lang_sierra::{ + extensions::{ + felt252_dict::{Felt252DictNewLibfunc, Felt252DictSquashLibfunc}, + int::unsigned::{Uint32Type, Uint64Type}, + }, + program::GenericArg, + }; + use crate::{ - utils::test::{jit_dict, jit_enum, jit_struct, load_cairo, run_program_assert_output}, + utils::{ + sierra_gen::SierraGenerator, + test::{ + jit_dict, jit_enum, jit_struct, load_cairo, run_program_assert_output, + run_sierra_program, + }, + }, values::Value, }; #[test] fn run_dict_new() { - let program = load_cairo!( - use traits::Default; - use dict::Felt252DictTrait; + let program = { + let mut generator = SierraGenerator::::default(); - fn run_test() { - let mut _dict: Felt252Dict = Default::default(); - } - ); + let u32_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(u32_ty)]) + }; + + let result = run_sierra_program(&program, &[]).return_value; + + let dict = Value::Felt252Dict { + value: HashMap::new(), + debug_name: None, + }; - run_program_assert_output(&program, "run_test", &[], jit_struct!()); + assert_eq!(result, dict); } #[test] @@ -208,6 +230,26 @@ mod test { ); } + #[test] + fn run_dict_squash() { + let program = { + let mut generator = SierraGenerator::::default(); + + let u64_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(u64_ty)]) + }; + + let dict = Value::Felt252Dict { + value: HashMap::new(), + debug_name: None, + }; + + let result = run_sierra_program(&program, &[dict.clone()]).return_value; + + assert_eq!(result, dict); + } + #[test] fn run_dict_deserialize() { let program = load_cairo!( diff --git a/src/libfuncs/nullable.rs b/src/libfuncs/nullable.rs index 8e11a1f0f..7e2991055 100644 --- a/src/libfuncs/nullable.rs +++ b/src/libfuncs/nullable.rs @@ -117,26 +117,40 @@ fn build_match_nullable<'ctx, 'this>( #[cfg(test)] mod test { + use cairo_lang_sierra::{ + extensions::{ + int::unsigned::Uint8Type, + nullable::{MatchNullableLibfunc, NullLibfunc, NullableFromBoxLibfunc, NullableType}, + }, + program::GenericArg, + }; + use crate::{ - utils::test::{jit_enum, jit_struct, load_cairo, run_program_assert_output}, + utils::{ + sierra_gen::SierraGenerator, + test::{ + jit_enum, jit_struct, load_cairo, run_program_assert_output, run_sierra_program, + }, + }, values::Value, }; #[test] fn run_null() { - let program = load_cairo!( - use nullable::null; - use nullable::match_nullable; - use nullable::FromNullableResult; - use nullable::nullable_from_box; - use box::BoxTrait; + let program = { + let mut generator = SierraGenerator::::default(); - fn run_test() { - let _a: Nullable = null(); - } - ); + let u8_ty = generator.push_type_declaration::(&[]).clone(); + let nullable_ty = generator + .push_type_declaration::(&[GenericArg::Type(u8_ty)]) + .clone(); - run_program_assert_output(&program, "run_test", &[], jit_struct!()); + generator.build(&[GenericArg::Type(nullable_ty)]) + }; + + let result = run_sierra_program(&program, &[]).return_value; + + assert_eq!(Value::Null, result); } #[test] @@ -159,30 +173,46 @@ mod test { #[test] fn run_not_null() { - let program = load_cairo!( - use nullable::null; - use nullable::match_nullable; - use nullable::FromNullableResult; - use nullable::nullable_from_box; - use box::BoxTrait; + let program_from_box = { + let mut generator = SierraGenerator::::default(); - fn run_test(x: u8) -> u8 { - let b: Box = BoxTrait::new(x); - let c = if x == 0 { - null() - } else { - nullable_from_box(b) - }; - let d = match match_nullable(c) { - FromNullableResult::Null(_) => 99_u8, - FromNullableResult::NotNull(value) => value.unbox() - }; - d - } - ); + let u8_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(u8_ty)]) + }; + let program_match = { + let mut generator = SierraGenerator::::default(); + + let u8_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(u8_ty)]) + }; + + let result = run_sierra_program(&program_from_box, &[4u8.into()]).return_value; + let result = run_sierra_program(&program_match, &[result]).return_value; + + assert_eq!(jit_enum!(1, 4u8.into()), result); + + let result = run_sierra_program(&program_match, &[Value::Null]).return_value; + + assert_eq!(jit_enum!(0, jit_struct!()), result); + } + + #[test] + fn match_nullable() { + let program_match = { + let mut generator = SierraGenerator::::default(); + + let u8_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(u8_ty)]) + }; + + let result = run_sierra_program(&program_match, &[Value::Null]).return_value; + assert_eq!(result, jit_enum!(0, jit_struct!())); - run_program_assert_output(&program, "run_test", &[4u8.into()], 4u8.into()); - run_program_assert_output(&program, "run_test", &[0u8.into()], 99u8.into()); + let result = run_sierra_program(&program_match, &[1u8.into()]).return_value; + assert_eq!(result, jit_enum!(1, 1u8.into())); } #[test] diff --git a/src/libfuncs/pedersen.rs b/src/libfuncs/pedersen.rs index 4c42fe98b..6de8bd107 100644 --- a/src/libfuncs/pedersen.rs +++ b/src/libfuncs/pedersen.rs @@ -97,29 +97,33 @@ pub fn build_pedersen<'ctx>( #[cfg(test)] mod test { - use crate::utils::test::{load_cairo, run_program_assert_output}; + use crate::{ + utils::{sierra_gen::SierraGenerator, test::run_sierra_program}, + Value, + }; + use cairo_lang_sierra::extensions::pedersen::PedersenHashLibfunc; use starknet_types_core::felt::Felt; #[test] fn run_pedersen() { - let program = load_cairo!( - use core::pedersen::pedersen; - - fn run_test(a: felt252, b: felt252) -> felt252 { - pedersen(a, b) - } - ); - - run_program_assert_output( - &program, - "run_test", - &[Felt::from(2).into(), Felt::from(4).into()], - Felt::from_dec_str( - "2178161520066714737684323463974044933282313051386084149915030950231093462467", - ) - .unwrap() - .into(), + let program = { + let generator = SierraGenerator::::default(); + + generator.build(&[]) + }; + + let result = run_sierra_program(&program, &[Felt::from(2).into(), Felt::from(4).into()]) + .return_value; + + assert_eq!( + Value::Felt252( + Felt::from_dec_str( + "2178161520066714737684323463974044933282313051386084149915030950231093462467", + ) + .unwrap() + ), + result ); } } diff --git a/src/libfuncs/poseidon.rs b/src/libfuncs/poseidon.rs index 67d6dce97..eb9009365 100644 --- a/src/libfuncs/poseidon.rs +++ b/src/libfuncs/poseidon.rs @@ -111,28 +111,33 @@ pub fn build_hades_permutation<'ctx>( #[cfg(test)] mod test { - use crate::utils::test::{jit_struct, load_cairo, run_program_assert_output}; + use crate::utils::{ + sierra_gen::SierraGenerator, + test::{jit_struct, run_sierra_program}, + }; + use cairo_lang_sierra::extensions::poseidon::HadesPermutationLibfunc; use starknet_types_core::felt::Felt; #[test] fn run_hades_permutation() { - let program = load_cairo!( - use core::poseidon::hades_permutation; + let program = { + let generator = SierraGenerator::::default(); - fn run_test(a: felt252, b: felt252, c: felt252) -> (felt252, felt252, felt252) { - hades_permutation(a, b, c) - } - ); + generator.build(&[]) + }; - run_program_assert_output( + let result = run_sierra_program( &program, - "run_test", &[ Felt::from(2).into(), Felt::from(4).into(), Felt::from(4).into(), ], + ) + .return_value; + + assert_eq!( jit_struct!( Felt::from_dec_str( "1627044480024625333712068603977073585655327747658231320998869768849911913066" @@ -150,6 +155,7 @@ mod test { .unwrap() .into(), ), + result ); } } diff --git a/src/libfuncs/starknet.rs b/src/libfuncs/starknet.rs index e5a26546b..6feca3310 100644 --- a/src/libfuncs/starknet.rs +++ b/src/libfuncs/starknet.rs @@ -2965,269 +2965,315 @@ pub fn build_get_class_hash_at<'ctx, 'this>( #[cfg(test)] mod test { - use crate::utils::test::{jit_enum, jit_struct, load_cairo, run_program_assert_output}; - use cairo_lang_sierra::program::Program; + use crate::{ + utils::{ + sierra_gen::SierraGenerator, + test::{jit_enum, jit_struct, run_sierra_program}, + }, + Value, + }; + use cairo_lang_sierra::{ + extensions::{ + starknet::{ + interoperability::ClassHashConstLibfunc, + storage::{ + StorageAddressFromBaseAndOffsetLibfunc, StorageAddressFromBaseLibfunc, + StorageAddressToFelt252Libfunc, StorageAddressTryFromFelt252Trait, + StorageBaseAddressFromFelt252Libfunc, + }, + }, + try_from_felt252::TryFromFelt252Libfunc, + }, + program::{GenericArg, Program}, + }; use lazy_static::lazy_static; use starknet_types_core::felt::Felt; lazy_static! { - static ref STORAGE_BASE_ADDRESS_FROM_FELT252: (String, Program) = load_cairo! { - use starknet::storage_access::{StorageBaseAddress, storage_base_address_from_felt252}; + static ref STORAGE_BASE_ADDRESS_FROM_FELT252: Program = { + let generator = SierraGenerator::::default(); - fn run_program(value: felt252) -> StorageBaseAddress { - storage_base_address_from_felt252(value) - } + generator.build(&[]) }; - static ref STORAGE_ADDRESS_FROM_BASE: (String, Program) = load_cairo! { - use starknet::storage_access::{StorageAddress, StorageBaseAddress, storage_address_from_base}; + static ref STORAGE_ADDRESS_FROM_BASE: Program = { + let generator = SierraGenerator::::default(); - fn run_program(value: StorageBaseAddress) -> StorageAddress { - storage_address_from_base(value) - } + generator.build(&[]) }; - static ref STORAGE_ADDRESS_FROM_BASE_AND_OFFSET: (String, Program) = load_cairo! { - use starknet::storage_access::{StorageAddress, StorageBaseAddress, storage_address_from_base_and_offset}; + static ref STORAGE_ADDRESS_FROM_BASE_AND_OFFSET: Program = { + let generator = SierraGenerator::::default(); - fn run_program(addr: StorageBaseAddress, offset: u8) -> StorageAddress { - storage_address_from_base_and_offset(addr, offset) - } + generator.build(&[]) }; - static ref STORAGE_ADDRESS_TO_FELT252: (String, Program) = load_cairo! { - use starknet::storage_access::{StorageAddress, storage_address_to_felt252}; + static ref STORAGE_ADDRESS_TO_FELT252: Program = { + let generator = SierraGenerator::::default(); - fn run_program(value: StorageAddress) -> felt252 { - storage_address_to_felt252(value) - } + generator.build(&[]) }; - static ref STORAGE_ADDRESS_TRY_FROM_FELT252: (String, Program) = load_cairo! { - use starknet::storage_access::{StorageAddress, storage_address_try_from_felt252}; + static ref STORAGE_ADDRESS_TRY_FROM_FELT252: Program = { + let generator = SierraGenerator::< + TryFromFelt252Libfunc, + >::default(); - fn run_program(value: felt252) -> Option { - storage_address_try_from_felt252(value) - } + generator.build(&[]) }; - static ref CLASS_HASH_CONST: (String, Program) = load_cairo! { - use starknet::class_hash::ClassHash; + static ref CLASS_HASH_CONST: Program = { + let generator = SierraGenerator::::default(); - fn run_program() -> ClassHash { - 0.try_into().unwrap() - } + generator.build(&[GenericArg::Value(0.into())]) }; } #[test] fn class_hash_const() { - let expected = jit_enum!(0, jit_struct!(Felt::ZERO.into())); - run_program_assert_output(&CLASS_HASH_CONST, "run_program", &[], expected) + let result = run_sierra_program(&CLASS_HASH_CONST, &[]).return_value; + + assert_eq!(Value::Felt252(0.into()), result); } #[test] fn storage_base_address_from_felt252() { - run_program_assert_output( - &STORAGE_BASE_ADDRESS_FROM_FELT252, - "run_program", - &[Felt::ZERO.into()], - Felt::ZERO.into(), - ); - run_program_assert_output( - &STORAGE_BASE_ADDRESS_FROM_FELT252, - "run_program", - &[Felt::ONE.into()], - Felt::ONE.into(), - ); - run_program_assert_output( - &STORAGE_BASE_ADDRESS_FROM_FELT252, - "run_program", - &[Felt::from(-1).into()], - Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") - .unwrap() - .into(), + let result = run_sierra_program(&STORAGE_BASE_ADDRESS_FROM_FELT252, &[Felt::ZERO.into()]) + .return_value; + + assert_eq!(Value::Felt252(0.into()), result); + + let result = run_sierra_program(&STORAGE_BASE_ADDRESS_FROM_FELT252, &[Felt::ONE.into()]) + .return_value; + + assert_eq!(Value::Felt252(1.into()), result); + + let result = + run_sierra_program(&STORAGE_BASE_ADDRESS_FROM_FELT252, &[Felt::from(-1).into()]) + .return_value; + + assert_eq!( + Value::Felt252( + Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") + .unwrap() + ), + result ); - run_program_assert_output( + + let result = run_sierra_program( &STORAGE_BASE_ADDRESS_FROM_FELT252, - "run_program", &[Felt::from_dec_str( "3618502788666131106986593281521497120414687020801267626233049500247285300992", ) .unwrap() .into()], - Felt::ZERO.into(), - ); + ) + .return_value; + + assert_eq!(Value::Felt252(0.into()), result); } #[test] fn storage_address_from_base() { - run_program_assert_output( - &STORAGE_ADDRESS_FROM_BASE, - "run_program", - &[Felt::ZERO.into()], - Felt::ZERO.into(), - ); - run_program_assert_output( - &STORAGE_ADDRESS_FROM_BASE, - "run_program", - &[Felt::ONE.into()], - Felt::ONE.into(), - ); - run_program_assert_output( + let result = + run_sierra_program(&STORAGE_ADDRESS_FROM_BASE, &[Felt::ZERO.into()]).return_value; + + assert_eq!(Value::Felt252(0.into()), result); + + let result = + run_sierra_program(&STORAGE_ADDRESS_FROM_BASE, &[Felt::ONE.into()]).return_value; + + assert_eq!(Value::Felt252(1.into()), result); + + let result = run_sierra_program( &STORAGE_ADDRESS_FROM_BASE, - "run_program", &[ Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") .unwrap() .into(), ], - Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") - .unwrap() - .into(), + ) + .return_value; + + assert_eq!( + Value::Felt252( + Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") + .unwrap() + ), + result ); } #[test] fn storage_address_from_base_and_offset() { - run_program_assert_output( + let result = run_sierra_program( &STORAGE_ADDRESS_FROM_BASE_AND_OFFSET, - "run_program", &[Felt::ZERO.into(), 0u8.into()], - Felt::ZERO.into(), - ); - run_program_assert_output( + ) + .return_value; + + assert_eq!(Value::Felt252(0.into()), result); + + let result = run_sierra_program( &STORAGE_ADDRESS_FROM_BASE_AND_OFFSET, - "run_program", &[Felt::ONE.into(), 0u8.into()], - Felt::ONE.into(), - ); - run_program_assert_output( + ) + .return_value; + + assert_eq!(Value::Felt252(1.into()), result); + + let result = run_sierra_program( &STORAGE_ADDRESS_FROM_BASE_AND_OFFSET, - "run_program", &[ Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") .unwrap() .into(), 0u8.into(), ], - Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") - .unwrap() - .into(), + ) + .return_value; + + assert_eq!( + Value::Felt252( + Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") + .unwrap() + ), + result ); - run_program_assert_output( + let result = run_sierra_program( &STORAGE_ADDRESS_FROM_BASE_AND_OFFSET, - "run_program", &[Felt::ZERO.into(), 1u8.into()], - Felt::ONE.into(), - ); - run_program_assert_output( + ) + .return_value; + + assert_eq!(Value::Felt252(1.into()), result); + + let result = run_sierra_program( &STORAGE_ADDRESS_FROM_BASE_AND_OFFSET, - "run_program", &[Felt::ONE.into(), 1u8.into()], - Felt::from(2).into(), - ); - run_program_assert_output( + ) + .return_value; + + assert_eq!(Value::Felt252(2.into()), result); + + let result = run_sierra_program( &STORAGE_ADDRESS_FROM_BASE_AND_OFFSET, - "run_program", &[ Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") .unwrap() .into(), 1u8.into(), ], - Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719489") - .unwrap() - .into(), + ) + .return_value; + + assert_eq!( + Value::Felt252( + Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719489") + .unwrap() + ), + result ); - run_program_assert_output( + let result = run_sierra_program( &STORAGE_ADDRESS_FROM_BASE_AND_OFFSET, - "run_program", &[Felt::ZERO.into(), 255u8.into()], - Felt::from(255).into(), - ); - run_program_assert_output( + ) + .return_value; + + assert_eq!(Value::Felt252(255.into()), result); + + let result = run_sierra_program( &STORAGE_ADDRESS_FROM_BASE_AND_OFFSET, - "run_program", &[Felt::ONE.into(), 255u8.into()], - Felt::from(256).into(), - ); + ) + .return_value; + + assert_eq!(Value::Felt252(256.into()), result); - run_program_assert_output( + let result = run_sierra_program( &STORAGE_ADDRESS_FROM_BASE_AND_OFFSET, - "run_program", &[ Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") .unwrap() .into(), 255u8.into(), ], - Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719743") - .unwrap() - .into(), + ) + .return_value; + + assert_eq!( + Value::Felt252( + Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719743") + .unwrap() + ), + result ); } #[test] fn storage_address_to_felt252() { - run_program_assert_output( - &STORAGE_ADDRESS_TO_FELT252, - "run_program", - &[Felt::ZERO.into()], - Felt::ZERO.into(), - ); - run_program_assert_output( - &STORAGE_ADDRESS_TO_FELT252, - "run_program", - &[Felt::ONE.into()], - Felt::ONE.into(), - ); - run_program_assert_output( + let result = + run_sierra_program(&STORAGE_ADDRESS_TO_FELT252, &[Felt::ZERO.into()]).return_value; + + assert_eq!(Value::Felt252(0.into()), result); + + let result = + run_sierra_program(&STORAGE_ADDRESS_TO_FELT252, &[Felt::ONE.into()]).return_value; + + assert_eq!(Value::Felt252(1.into()), result); + + let result = run_sierra_program( &STORAGE_ADDRESS_TO_FELT252, - "run_program", &[ Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") .unwrap() .into(), ], - Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") - .unwrap() - .into(), + ) + .return_value; + + assert_eq!( + Value::Felt252( + Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") + .unwrap() + ), + result ); } #[test] fn storage_address_try_from_felt252() { - run_program_assert_output( - &STORAGE_ADDRESS_TRY_FROM_FELT252, - "run_program", - &[Felt::ZERO.into()], - jit_enum!(0, Felt::ZERO.into()), - ); - run_program_assert_output( - &STORAGE_ADDRESS_TRY_FROM_FELT252, - "run_program", - &[Felt::ONE.into()], - jit_enum!(0, Felt::ONE.into()), - ); - run_program_assert_output( + let result = run_sierra_program(&STORAGE_ADDRESS_TRY_FROM_FELT252, &[Felt::ZERO.into()]) + .return_value; + + assert_eq!(jit_enum!(0, Felt::ZERO.into()), result); + + let result = + run_sierra_program(&STORAGE_ADDRESS_TRY_FROM_FELT252, &[Felt::ONE.into()]).return_value; + + assert_eq!(jit_enum!(0, Felt::ONE.into()), result); + + let result = run_sierra_program( &STORAGE_ADDRESS_TRY_FROM_FELT252, - "run_program", &[ Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") .unwrap() .into(), ], + ) + .return_value; + + assert_eq!( jit_enum!( 0, Felt::from_dec_str("106710729501573572985208420194530329073740042555888586719488") .unwrap() .into() ), + result ); - run_program_assert_output( - &STORAGE_ADDRESS_TRY_FROM_FELT252, - "run_program", - &[Felt::from(-1).into()], - jit_enum!(1, jit_struct!()), - ); + let result = + run_sierra_program(&STORAGE_ADDRESS_TRY_FROM_FELT252, &[Felt::from(-1).into()]) + .return_value; + + assert_eq!(jit_enum!(1, jit_struct!()), result); } } diff --git a/src/libfuncs/uint256.rs b/src/libfuncs/uint256.rs index fba56f598..4bb484ea1 100644 --- a/src/libfuncs/uint256.rs +++ b/src/libfuncs/uint256.rs @@ -950,50 +950,44 @@ pub fn build_u256_guarantee_inv_mod_n<'ctx, 'this>( #[cfg(test)] mod test { use crate::{ - utils::test::{jit_enum, jit_panic, jit_struct, load_cairo, run_program_assert_output}, + utils::{ + sierra_gen::SierraGenerator, + test::{jit_enum, jit_struct, run_sierra_program}, + }, values::Value, }; - use cairo_lang_sierra::program::Program; + use cairo_lang_sierra::{ + extensions::int::unsigned256::{ + Uint256DivmodLibfunc, Uint256InvModNLibfunc, Uint256IsZeroLibfunc, + Uint256SquareRootLibfunc, + }, + program::Program, + }; use lazy_static::lazy_static; use num_bigint::BigUint; use num_traits::One; - use starknet_types_core::felt::Felt; use std::ops::Shl; lazy_static! { - static ref U256_IS_ZERO: (String, Program) = load_cairo! { - use zeroable::IsZeroResult; + static ref U256_IS_ZERO: Program = { + let generator = SierraGenerator::::default(); - extern fn u256_is_zero(a: u256) -> IsZeroResult implicits() nopanic; - - fn run_test(value: u256) -> bool { - match u256_is_zero(value) { - IsZeroResult::Zero(_) => true, - IsZeroResult::NonZero(_) => false, - } - } + generator.build(&[]) }; - static ref U256_SAFE_DIVMOD: (String, Program) = load_cairo! { - fn run_test(lhs: u256, rhs: u256) -> (u256, u256) { - let q = lhs / rhs; - let r = lhs % rhs; + static ref U256_SAFE_DIVMOD: Program = { + let generator = SierraGenerator::::default(); - (q, r) - } + generator.build(&[]) }; - static ref U256_SQRT: (String, Program) = load_cairo! { - use core::num::traits::Sqrt; + static ref U256_SQRT: Program = { + let generator = SierraGenerator::::default(); - fn run_test(value: u256) -> u128 { - value.sqrt() - } + generator.build(&[]) }; - static ref U256_INV_MOD_N: (String, Program) = load_cairo! { - use core::math::u256_inv_mod; + static ref U256_INV_MOD_N: Program = { + let generator = SierraGenerator::::default(); - fn run_test(a: u256, n: NonZero) -> Option> { - u256_inv_mod(a, n) - } + generator.build(&[]) }; } @@ -1007,119 +1001,119 @@ mod test { #[test] fn u256_is_zero() { - run_program_assert_output( - &U256_IS_ZERO, - "run_test", - &[u256(0u32.into())], - jit_enum!(1, jit_struct!()), - ); - run_program_assert_output( - &U256_IS_ZERO, - "run_test", - &[u256(1u32.into())], - jit_enum!(0, jit_struct!()), - ); - run_program_assert_output( - &U256_IS_ZERO, - "run_test", - &[u256(BigUint::one() << 128u32)], - jit_enum!(0, jit_struct!()), - ); - run_program_assert_output( - &U256_IS_ZERO, - "run_test", - &[u256((BigUint::one() << 128u32) + 1u32)], - jit_enum!(0, jit_struct!()), + let result = run_sierra_program(&U256_IS_ZERO, &[u256(0u32.into())]).return_value; + + assert_eq!(jit_enum!(0, jit_struct!()), result); + + let result = run_sierra_program(&U256_IS_ZERO, &[u256(1u32.into())]).return_value; + + assert_eq!(jit_enum!(1, u256(1u32.into())), result); + + let result = + run_sierra_program(&U256_IS_ZERO, &[u256(BigUint::one() << 128u32)]).return_value; + + assert_eq!(jit_enum!(1, u256(BigUint::one() << 128u32)), result); + + let result = run_sierra_program(&U256_IS_ZERO, &[u256((BigUint::one() << 128u32) + 1u32)]) + .return_value; + + assert_eq!( + jit_enum!(1, u256((BigUint::one() << 128u32) + 1u32)), + result ); } #[test] fn u256_safe_divmod() { #[track_caller] - fn run(lhs: (u128, u128), rhs: (u128, u128), result: Value) { - run_program_assert_output( + fn run(lhs: (u128, u128), rhs: (u128, u128), expected: Value) { + let result = run_sierra_program( &U256_SAFE_DIVMOD, - "run_test", &[ jit_struct!(lhs.1.into(), lhs.0.into()), jit_struct!(rhs.1.into(), rhs.0.into()), ], - result, ) + .return_value; + + assert_eq!(expected, result); } - let u256_is_zero = Felt::from_bytes_be_slice(b"Division by 0"); let max_value = 0xFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFFu128; + let struct_result = |val, rem| jit_struct!(val, rem, Value::Null); - run((0, 0), (0, 0), jit_panic!(u256_is_zero)); + run( + (0, 0), + (0, 0), + struct_result( + jit_struct!(0u128.into(), 0u128.into()), + jit_struct!(0u128.into(), 0u128.into()), + ), + ); run( (0, 0), (0, 1), - jit_enum!( - 0, - jit_struct!(jit_struct!( - jit_struct!(0u128.into(), 0u128.into()), - jit_struct!(0u128.into(), 0u128.into()), - )) + struct_result( + jit_struct!(0u128.into(), 0u128.into()), + jit_struct!(0u128.into(), 0u128.into()), ), ); run( (0, 0), (max_value, max_value), - jit_enum!( - 0, - jit_struct!(jit_struct!( - jit_struct!(0u128.into(), 0u128.into()), - jit_struct!(0u128.into(), 0u128.into()), - )) + struct_result( + jit_struct!(0u128.into(), 0u128.into()), + jit_struct!(0u128.into(), 0u128.into()), ), ); - run((0, 1), (0, 0), jit_panic!(u256_is_zero)); + run( + (0, 1), + (0, 0), + struct_result( + jit_struct!(0u128.into(), 0u128.into()), + jit_struct!(1u128.into(), 0u128.into()), + ), + ); run( (0, 1), (0, 1), - jit_enum!( - 0, - jit_struct!(jit_struct!( - jit_struct!(1u128.into(), 0u128.into()), - jit_struct!(0u128.into(), 0u128.into()), - )) + struct_result( + jit_struct!(1u128.into(), 0u128.into()), + jit_struct!(0u128.into(), 0u128.into()), ), ); run( (0, 1), (max_value, max_value), - jit_enum!( - 0, - jit_struct!(jit_struct!( - jit_struct!(0u128.into(), 0u128.into()), - jit_struct!(1u128.into(), 0u128.into()), - )) + struct_result( + jit_struct!(0u128.into(), 0u128.into()), + jit_struct!(1u128.into(), 0u128.into()), + ), + ); + run( + (max_value, max_value), + (0, 0), + struct_result( + jit_struct!(0u128.into(), 0u128.into()), + jit_struct!(max_value.into(), max_value.into()), ), ); - run((max_value, max_value), (0, 0), jit_panic!(u256_is_zero)); run( (max_value, max_value), (0, 1), - jit_enum!( - 0, - jit_struct!(jit_struct!( - jit_struct!(max_value.into(), max_value.into()), - jit_struct!(0u128.into(), 0u128.into()), - )) + struct_result( + jit_struct!(max_value.into(), max_value.into()), + jit_struct!(0u128.into(), 0u128.into()), ), ); run( (max_value, max_value), (max_value, max_value), - jit_enum!( - 0, - jit_struct!(jit_struct!( - jit_struct!(1u128.into(), 0u128.into()), - jit_struct!(0u128.into(), 0u128.into()), - )) + struct_result( + jit_struct!(1u128.into(), 0u128.into()), + jit_struct!(0u128.into(), 0u128.into()), ), ); } @@ -1127,13 +1121,12 @@ mod test { #[test] fn u256_sqrt() { #[track_caller] - fn run(value: (u128, u128), result: Value) { - run_program_assert_output( - &U256_SQRT, - "run_test", - &[jit_struct!(value.1.into(), value.0.into())], - result, - ) + fn run(value: (u128, u128), expected: Value) { + let result = + run_sierra_program(&U256_SQRT, &[jit_struct!(value.1.into(), value.0.into())]) + .return_value; + + assert_eq!(expected, result); } run((0u128, 0u128), 0u128.into()); @@ -1165,19 +1158,34 @@ mod test { #[test] fn u256_inv_mod_n() { #[track_caller] - fn run(a: (u128, u128), n: (u128, u128), result: Value) { - run_program_assert_output( + fn run(a: (u128, u128), n: (u128, u128), expected: Value) { + let result = run_sierra_program( &U256_INV_MOD_N, - "run_test", &[ jit_struct!(a.0.into(), a.1.into()), jit_struct!(n.0.into(), n.1.into()), ], - result, ) + .return_value; + + assert_eq!(expected, result); } - let none = jit_enum!(1, jit_struct!()); + // guarantees are represented as Value::Null + let struct_ok_result = |value| { + jit_struct!( + value, + Value::Null, + Value::Null, + Value::Null, + Value::Null, + Value::Null, + Value::Null, + Value::Null, + Value::Null, + ) + }; + let none = jit_enum!(1, jit_struct!(Value::Null, Value::Null)); // Not invertible. run((0, 0), (0, 0), none.clone()); @@ -1215,27 +1223,27 @@ mod test { run( (5, 0), (24, 0), - jit_enum!(0, jit_struct!(5u128.into(), 0u128.into())), + jit_enum!(0, struct_ok_result(jit_struct!(5u128.into(), 0u128.into()))), ); run( (29, 0), (24, 0), - jit_enum!(0, jit_struct!(5u128.into(), 0u128.into())), + jit_enum!(0, struct_ok_result(jit_struct!(5u128.into(), 0u128.into()))), ); run( (1, 0), (24, 0), - jit_enum!(0, jit_struct!(1u128.into(), 0u128.into())), + jit_enum!(0, struct_ok_result(jit_struct!(1u128.into(), 0u128.into()))), ); run( (1, 0), (5, 0), - jit_enum!(0, jit_struct!(1u128.into(), 0u128.into())), + jit_enum!(0, struct_ok_result(jit_struct!(1u128.into(), 0u128.into()))), ); run( (2, 0), (5, 0), - jit_enum!(0, jit_struct!(3u128.into(), 0u128.into())), + jit_enum!(0, struct_ok_result(jit_struct!(3u128.into(), 0u128.into()))), ); } } diff --git a/src/libfuncs/uint512.rs b/src/libfuncs/uint512.rs index 3ba0c23ed..95e421783 100644 --- a/src/libfuncs/uint512.rs +++ b/src/libfuncs/uint512.rs @@ -160,22 +160,24 @@ pub fn build_divmod_u256<'ctx, 'this>( #[cfg(test)] mod test { use crate::{ - utils::test::{jit_struct, load_cairo, run_program_assert_output}, + utils::{ + sierra_gen::SierraGenerator, + test::{jit_struct, run_sierra_program}, + }, values::Value, }; - use cairo_lang_sierra::program::Program; + use cairo_lang_sierra::{ + extensions::int::unsigned512::Uint512DivmodU256Libfunc, program::Program, + }; use lazy_static::lazy_static; use num_bigint::BigUint; use num_traits::One; lazy_static! { - static ref UINT512_DIVMOD_U256: (String, Program) = load_cairo! { - use core::integer::{u512, u512_safe_divmod_by_u256}; + static ref UINT512_DIVMOD_U256: Program = { + let generator = SierraGenerator::::default(); - fn run_test(lhs: u512, rhs: NonZero) -> (u512, u256) { - let (lhs, rhs, _, _, _, _, _) = u512_safe_divmod_by_u256(lhs, rhs); - (lhs, rhs) - } + generator.build(&[]) }; } @@ -205,11 +207,20 @@ mod test { let rhs = u256(rhs); let output_u512 = u512(output_u512); let output_u256 = u256(output_u256); - run_program_assert_output( - &UINT512_DIVMOD_U256, - "run_test", - &[lhs, rhs], - jit_struct!(output_u512, output_u256), + + let result = run_sierra_program(&UINT512_DIVMOD_U256, &[lhs, rhs]).return_value; + + assert_eq!( + result, + jit_struct!( + output_u512, + output_u256, + Value::Null, + Value::Null, + Value::Null, + Value::Null, + Value::Null + ) ); } diff --git a/src/utils.rs b/src/utils.rs index 1dda89185..cd918c362 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -622,6 +622,34 @@ pub mod test { .unwrap() } + // This function receives a sierra program and runs its first entrypoint + // It is used primarely along with the sierra generator + // The difference between this function and run_program is that the latter + // also receives the name of the entrypoint to run + pub fn run_sierra_program(program: &Program, args: &[Value]) -> ExecutionResult { + let entry_point_id = &program + .funcs + .first() + .expect("program entry point not found.") + .id; + + let context = NativeContext::new(); + + let module = context + .compile(program, false, Some(Default::default())) + .expect("Could not compile test program to MLIR."); + + let executor = JitNativeExecutor::from_native_module(module, OptLevel::Less).unwrap(); + executor + .invoke_dynamic_with_syscall_handler( + entry_point_id, + args, + Some(u64::MAX), + &mut StubSyscallHandler::default(), + ) + .unwrap() + } + #[track_caller] pub fn run_program_assert_output( program: &(String, Program), diff --git a/src/values.rs b/src/values.rs index 7e7c8ecf9..36e9af130 100644 --- a/src/values.rs +++ b/src/values.rs @@ -170,6 +170,16 @@ impl Value { ) -> Result, Error> { let ty = registry.get_type(type_id)?; + match ty { + CoreTypeConcrete::Box(info) + | CoreTypeConcrete::NonZero(info) + | CoreTypeConcrete::Nullable(info) + | CoreTypeConcrete::Snapshot(info) => { + return self.to_ptr(arena, registry, &info.ty, find_dict_drop_override); + } + _ => {} + } + Ok(unsafe { match self { Self::Felt252(value) => { @@ -747,9 +757,7 @@ impl Value { CoreTypeConcrete::Uint32(_) => Self::Uint32(*ptr.cast::().as_ref()), CoreTypeConcrete::Uint64(_) => Self::Uint64(*ptr.cast::().as_ref()), CoreTypeConcrete::Uint128(_) => Self::Uint128(*ptr.cast::().as_ref()), - CoreTypeConcrete::Uint128MulGuarantee(_) => { - native_panic!("todo: implement uint128mulguarantee from_ptr") - } + CoreTypeConcrete::Uint128MulGuarantee(_) => Self::Null, CoreTypeConcrete::Sint8(_) => Self::Sint8(*ptr.cast::().as_ref()), CoreTypeConcrete::Sint16(_) => Self::Sint16(*ptr.cast::().as_ref()), CoreTypeConcrete::Sint32(_) => Self::Sint32(*ptr.cast::().as_ref()),