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/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()),