diff --git a/Cargo.lock b/Cargo.lock index 09e0016cd..8822815b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1228,9 +1228,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.34" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" +checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" dependencies = [ "clap_builder", "clap_derive", @@ -1238,9 +1238,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.34" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" +checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" dependencies = [ "anstream", "anstyle", @@ -1630,9 +1630,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", "miniz_oxide", @@ -2013,10 +2013,11 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -2934,9 +2935,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags", "errno", @@ -3142,6 +3143,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +[[package]] +name = "size-of" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e36eca171fddeda53901b0a436573b3f2391eaa9189d439b2bd8ea8cebd7e3" + [[package]] name = "slab" version = "0.4.9" @@ -3231,9 +3238,9 @@ dependencies = [ [[package]] name = "starknet-types-core" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1b9e01ccb217ab6d475c5cda05dbb22c30029f7bb52b192a010a00d77a3d74" +checksum = "4037bcb26ce7c508448d221e570d075196fd4f6912ae6380981098937af9522a" dependencies = [ "lambdaworks-crypto", "lambdaworks-math 0.10.0", @@ -3242,6 +3249,8 @@ dependencies = [ "num-integer", "num-traits", "serde", + "size-of", + "zeroize", ] [[package]] @@ -3727,23 +3736,24 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn 2.0.100", @@ -3752,9 +3762,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3762,9 +3772,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -3775,15 +3785,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/src/libfuncs/bool.rs b/src/libfuncs/bool.rs index c9ca75bf3..a422e4b0d 100644 --- a/src/libfuncs/bool.rs +++ b/src/libfuncs/bool.rs @@ -209,65 +209,64 @@ pub fn build_bool_to_felt252<'ctx, 'this>( #[cfg(test)] mod test { + use cairo_lang_sierra::extensions::boolean::{ + BoolAndLibfunc, BoolNotLibfunc, BoolOrLibfunc, BoolToFelt252Libfunc, BoolXorLibfunc, + }; + use crate::{ - utils::test::{jit_enum, jit_struct, load_cairo, run_program}, + utils::{ + sierra_gen::SierraGenerator, + test::{jit_enum, jit_struct, run_sierra_program}, + }, values::Value, }; #[test] fn run_not() { - let program = load_cairo!( - use array::ArrayTrait; + let program = { + let sierra_generator = SierraGenerator::::default(); - fn run_test(a: bool) -> bool { - !a - } - ); + sierra_generator.build(&[]) + }; - let result = run_program(&program, "run_test", &[jit_enum!(0, jit_struct!())]).return_value; + let result = run_sierra_program(&program, &[jit_enum!(0, jit_struct!())]).return_value; assert_eq!(result, jit_enum!(1, jit_struct!())); - let result = run_program(&program, "run_test", &[jit_enum!(1, jit_struct!())]).return_value; + let result = run_sierra_program(&program, &[jit_enum!(1, jit_struct!())]).return_value; assert_eq!(result, jit_enum!(0, jit_struct!())); } #[test] fn run_and() { - let program = load_cairo!( - use array::ArrayTrait; + let program = { + let sierra_generator = SierraGenerator::::default(); - fn run_test(a: bool, b: bool) -> bool { - a && b - } - ); + sierra_generator.build(&[]) + }; - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(1, jit_struct!()), jit_enum!(1, jit_struct!())], ) .return_value; assert_eq!(result, jit_enum!(1, jit_struct!())); - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(1, jit_struct!()), jit_enum!(0, jit_struct!())], ) .return_value; assert_eq!(result, jit_enum!(0, jit_struct!())); - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(0, jit_struct!()), jit_enum!(1, jit_struct!())], ) .return_value; assert_eq!(result, jit_enum!(0, jit_struct!())); - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(0, jit_struct!()), jit_enum!(0, jit_struct!())], ) .return_value; @@ -276,41 +275,35 @@ mod test { #[test] fn run_xor() { - let program = load_cairo!( - use array::ArrayTrait; + let program = { + let sierra_generator = SierraGenerator::::default(); - fn run_test(a: bool, b: bool) -> bool { - a ^ b - } - ); + sierra_generator.build(&[]) + }; - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(1, jit_struct!()), jit_enum!(1, jit_struct!())], ) .return_value; assert_eq!(result, jit_enum!(0, jit_struct!())); - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(1, jit_struct!()), jit_enum!(0, jit_struct!())], ) .return_value; assert_eq!(result, jit_enum!(1, jit_struct!())); - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(0, jit_struct!()), jit_enum!(1, jit_struct!())], ) .return_value; assert_eq!(result, jit_enum!(1, jit_struct!())); - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(0, jit_struct!()), jit_enum!(0, jit_struct!())], ) .return_value; @@ -319,41 +312,35 @@ mod test { #[test] fn run_or() { - let program = load_cairo!( - use array::ArrayTrait; + let program = { + let sierra_generator = SierraGenerator::::default(); - fn run_test(a: bool, b: bool) -> bool { - a || b - } - ); + sierra_generator.build(&[]) + }; - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(1, jit_struct!()), jit_enum!(1, jit_struct!())], ) .return_value; assert_eq!(result, jit_enum!(1, jit_struct!())); - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(1, jit_struct!()), jit_enum!(0, jit_struct!())], ) .return_value; assert_eq!(result, jit_enum!(1, jit_struct!())); - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(0, jit_struct!()), jit_enum!(1, jit_struct!())], ) .return_value; assert_eq!(result, jit_enum!(1, jit_struct!())); - let result = run_program( + let result = run_sierra_program( &program, - "run_test", &[jit_enum!(0, jit_struct!()), jit_enum!(0, jit_struct!())], ) .return_value; @@ -362,16 +349,16 @@ mod test { #[test] fn bool_to_felt252() { - let program = load_cairo!( - fn run_test(a: bool) -> felt252 { - bool_to_felt252(a) - } - ); + let program = { + let sierra_generator = SierraGenerator::::default(); + + sierra_generator.build(&[]) + }; - let result = run_program(&program, "run_test", &[jit_enum!(1, jit_struct!())]).return_value; + let result = run_sierra_program(&program, &[jit_enum!(1, jit_struct!())]).return_value; assert_eq!(result, Value::Felt252(1.into())); - let result = run_program(&program, "run_test", &[jit_enum!(0, jit_struct!())]).return_value; + let result = run_sierra_program(&program, &[jit_enum!(0, jit_struct!())]).return_value; assert_eq!(result, Value::Felt252(0.into())); } } diff --git a/src/libfuncs/bounded_int.rs b/src/libfuncs/bounded_int.rs index c50ee5201..ba8366027 100644 --- a/src/libfuncs/bounded_int.rs +++ b/src/libfuncs/bounded_int.rs @@ -817,134 +817,133 @@ fn build_wrap_non_zero<'ctx, 'this>( #[cfg(test)] mod test { - use cairo_vm::Felt252; + use cairo_lang_sierra::{ + extensions::{ + bounded_int::BoundedIntTrimLibfunc, + int::{ + signed::{Sint16Type, Sint8Type}, + unsigned::Uint32Type, + }, + utils::Range, + }, + program::GenericArg, + }; + use num_bigint::BigInt; use crate::{ - context::NativeContext, execution_result::ExecutionResult, executor::JitNativeExecutor, - utils::test::load_cairo, OptLevel, Value, + utils::{ + sierra_gen::SierraGenerator, + test::{jit_struct, run_sierra_program}, + }, + Value, }; #[test] fn test_trim_some_pos_i8() { - let (_, program) = load_cairo!( - use core::internal::{OptionRev, bounded_int::BoundedInt}; - use core::internal::bounded_int; - fn main() -> BoundedInt<-128, 126> { - let num = match bounded_int::trim_max::(1) { - OptionRev::Some(n) => n, - OptionRev::None => 0, - }; - - num + let program_trim = { + let mut generator = SierraGenerator::>::default(); + let i8_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(i8_ty)]) + }; + let Value::Enum { + tag: 1, + value, + debug_name: _, + } = run_sierra_program(&program_trim, &[Value::Sint8(1)]).return_value + else { + panic!("should be OptionRev::Some"); + }; + + assert_eq!( + *value, + Value::BoundedInt { + value: 1_u8.into(), + range: Range { + lower: BigInt::from(i8::MIN), + upper: BigInt::from(i8::MAX) + } } ); - let ctx = NativeContext::new(); - let module = ctx.compile(&program, false, None).unwrap(); - let executor = JitNativeExecutor::from_native_module(module, OptLevel::Default).unwrap(); - let ExecutionResult { - remaining_gas: _, - return_value, - builtin_stats: _, - } = executor - .invoke_dynamic(&program.funcs[0].id, &[], None) - .unwrap(); - - let Value::BoundedInt { value, range: _ } = return_value else { - panic!(); - }; - assert_eq!(value, Felt252::from(1_u8)); } #[test] fn test_trim_some_neg_i8() { - let (_, program) = load_cairo!( - use core::internal::{OptionRev, bounded_int::BoundedInt}; - use core::internal::bounded_int; - fn main() -> BoundedInt<-127, 127> { - let num = match bounded_int::trim_min::(1) { - OptionRev::Some(n) => n, - OptionRev::None => 1, - }; - - num + let program_trim = { + let mut generator = SierraGenerator::>::default(); + let i8_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(i8_ty)]) + }; + let Value::Enum { + tag: 1, + value, + debug_name: _, + } = run_sierra_program(&program_trim, &[Value::Sint8(-1)]).return_value + else { + panic!("should be OptionRev::Some"); + }; + + assert_eq!( + *value, + Value::BoundedInt { + value: (-1_i8).into(), + range: Range { + lower: BigInt::from(i8::MIN), + upper: BigInt::from(i8::MAX) + } } ); - let ctx = NativeContext::new(); - let module = ctx.compile(&program, false, None).unwrap(); - let executor = JitNativeExecutor::from_native_module(module, OptLevel::Default).unwrap(); - let ExecutionResult { - remaining_gas: _, - return_value, - builtin_stats: _, - } = executor - .invoke_dynamic(&program.funcs[0].id, &[], None) - .unwrap(); - - let Value::BoundedInt { value, range: _ } = return_value else { - panic!(); - }; - assert_eq!(value, Felt252::from(1_u8)); } #[test] fn test_trim_some_u32() { - let (_, program) = load_cairo!( - use core::internal::{OptionRev, bounded_int::BoundedInt}; - use core::internal::bounded_int; - fn main() -> BoundedInt<0, 4294967294> { - let num = match bounded_int::trim_max::(0xfffffffe) { - OptionRev::Some(n) => n, - OptionRev::None => 0, - }; - - num + let program_trim = { + let mut generator = SierraGenerator::>::default(); + let u32_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(u32_ty)]) + }; + + let Value::Enum { + tag: 1, + value, + debug_name: _, + } = run_sierra_program(&program_trim, &[Value::Uint32(0xfffffffe)]).return_value + else { + panic!("should be OptionRev::Some"); + }; + + assert_eq!( + *value, + Value::BoundedInt { + value: 0xfffffffeu32.into(), + range: Range { + lower: 0.into(), + upper: u32::MAX.into() + } } ); - let ctx = NativeContext::new(); - let module = ctx.compile(&program, false, None).unwrap(); - let executor = JitNativeExecutor::from_native_module(module, OptLevel::Default).unwrap(); - let ExecutionResult { - remaining_gas: _, - return_value, - builtin_stats: _, - } = executor - .invoke_dynamic(&program.funcs[0].id, &[], None) - .unwrap(); - - let Value::BoundedInt { value, range: _ } = return_value else { - panic!(); - }; - assert_eq!(value, Felt252::from(0xfffffffe_u32)); } #[test] fn test_trim_none() { - let (_, program) = load_cairo!( - use core::internal::{OptionRev, bounded_int::BoundedInt}; - use core::internal::bounded_int; - fn main() -> BoundedInt<-32767, 32767> { - let num = match bounded_int::trim_min::(-0x8000) { - OptionRev::Some(n) => n, - OptionRev::None => 0, - }; - - num - } - ); - let ctx = NativeContext::new(); - let module = ctx.compile(&program, false, None).unwrap(); - let executor = JitNativeExecutor::from_native_module(module, OptLevel::Default).unwrap(); - let ExecutionResult { - remaining_gas: _, - return_value, - builtin_stats: _, - } = executor - .invoke_dynamic(&program.funcs[0].id, &[], None) - .unwrap(); - - let Value::BoundedInt { value, range: _ } = return_value else { - panic!(); + let program_trim = { + let mut generator = SierraGenerator::>::default(); + let i16_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(i16_ty)]) }; - assert_eq!(value, Felt252::from(0)); + + let Value::Enum { + tag: 0, + value, + debug_name: _, + } = run_sierra_program(&program_trim, &[Value::Sint16(-0x8000)]).return_value + else { + panic!("should be OptionRev::None"); + }; + + assert_eq!(*value, jit_struct!()); } } diff --git a/src/libfuncs/box.rs b/src/libfuncs/box.rs index 96a50ef52..1769c241d 100644 --- a/src/libfuncs/box.rs +++ b/src/libfuncs/box.rs @@ -152,41 +152,58 @@ pub fn build_unbox<'ctx, 'this>( #[cfg(test)] mod test { + use cairo_lang_sierra::{ + extensions::{ + boxing::{IntoBoxLibfunc, UnboxLibfunc}, + int::unsigned::Uint32Type, + }, + program::GenericArg, + }; + use crate::{ - utils::test::{load_cairo, run_program_assert_output}, + utils::{ + sierra_gen::SierraGenerator, + test::{load_cairo, run_program_assert_output, run_sierra_program}, + }, values::Value, }; #[test] fn run_box_unbox() { - let program = load_cairo! { - use box::BoxTrait; - use box::BoxImpl; + let program_box = { + let mut generator = SierraGenerator::::default(); - fn run_test() -> u32 { - let x: u32 = 2_u32; - let box_x: Box = BoxTrait::new(x); - box_x.unbox() - } + let u32_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(u32_ty)]) }; + let program_unbox = { + let mut generator = SierraGenerator::::default(); + + let u32_ty = generator.push_type_declaration::(&[]).clone(); - run_program_assert_output(&program, "run_test", &[], Value::Uint32(2)); + generator.build(&[GenericArg::Type(u32_ty)]) + }; + + let result = run_sierra_program(&program_box, &[Value::Uint32(2)]).return_value; + let result = run_sierra_program(&program_unbox, &[result]).return_value; + + assert_eq!(result, Value::Uint32(2)); } #[test] fn run_box() { - let program = load_cairo! { - use box::BoxTrait; - use box::BoxImpl; + let program_box = { + let mut generator = SierraGenerator::::default(); - fn run_test() -> Box { - let x: u32 = 2_u32; - let box_x: Box = BoxTrait::new(x); - box_x - } + let u32_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(u32_ty)]) }; - run_program_assert_output(&program, "run_test", &[], Value::Uint32(2)); + let result = run_sierra_program(&program_box, &[Value::Uint32(2)]).return_value; + + assert_eq!(result, Value::Uint32(2)); } #[test] diff --git a/src/libfuncs/bytes31.rs b/src/libfuncs/bytes31.rs index 66006c87a..aee06a94e 100644 --- a/src/libfuncs/bytes31.rs +++ b/src/libfuncs/bytes31.rs @@ -162,39 +162,50 @@ pub fn build_from_felt252<'ctx, 'this>( #[cfg(test)] mod test { - use crate::utils::test::{ - jit_enum, jit_panic, jit_struct, load_cairo, run_program_assert_output, + use crate::{ + utils::{ + sierra_gen::SierraGenerator, + test::{jit_enum, jit_struct, run_sierra_program}, + }, + Value, + }; + use cairo_lang_sierra::{ + extensions::{ + bytes31::{Bytes31FromFelt252Trait, Bytes31ToFelt252Libfunc}, + try_from_felt252::TryFromFelt252Libfunc, + }, + program::Program, }; - use cairo_lang_sierra::program::Program; use lazy_static::lazy_static; use starknet_types_core::felt::Felt; lazy_static! { // TODO: Test `bytes31_const` once the compiler supports it. - static ref BYTES31_ROUNDTRIP: (String, Program) = load_cairo! { - use core::bytes_31::{bytes31_try_from_felt252, bytes31_to_felt252}; + static ref BYTES31_TRY_FROM_FELT: Program = { + let generator = SierraGenerator::>::default(); + + generator.build(&[]) + }; + static ref BYTES31_TO_FELT: Program = { + let generator = SierraGenerator::::default(); - fn run_test(value: felt252) -> felt252 { - let a: bytes31 = bytes31_try_from_felt252(value).unwrap(); - bytes31_to_felt252(a) - } + generator.build(&[]) }; } #[test] fn bytes31_roundtrip() { - run_program_assert_output( - &BYTES31_ROUNDTRIP, - "run_test", - &[Felt::from(2).into()], - jit_enum!(0, jit_struct!(Felt::from(2).into())), - ); - - run_program_assert_output( - &BYTES31_ROUNDTRIP, - "run_test", - &[Felt::MAX.into()], - jit_panic!(Felt::from_bytes_be_slice(b"Option::unwrap failed.")), - ); + let Value::Enum { value, .. } = + run_sierra_program(&BYTES31_TRY_FROM_FELT, &[Felt::from(2).into()]).return_value + else { + panic!("Invalid result type"); + }; + let result = run_sierra_program(&BYTES31_TO_FELT, &[*value]).return_value; + + assert_eq!(Value::Felt252(2.into()), result); + + let result = run_sierra_program(&BYTES31_TRY_FROM_FELT, &[Felt::MAX.into()]).return_value; + + assert_eq!(jit_enum!(1, jit_struct!()), result); } } diff --git a/src/libfuncs/cast.rs b/src/libfuncs/cast.rs index 8657ac08c..b036af1da 100644 --- a/src/libfuncs/cast.rs +++ b/src/libfuncs/cast.rs @@ -391,299 +391,265 @@ pub fn build_upcast<'ctx, 'this>( #[cfg(test)] mod test { use crate::{ - utils::test::{jit_enum, 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 lazy_static::lazy_static; - - lazy_static! { - static ref DOWNCAST: (String, Program) = load_cairo! { - use core::integer::downcast; - - fn run_test( - v8: u8, v16: u16, v32: u32, v64: u64, v128: u128 - ) -> ( - (Option, Option, Option, Option, Option), - (Option, Option, Option, Option), - (Option, Option, Option), - (Option, Option), - (Option,), - ) { - ( - (downcast(v128), downcast(v64), downcast(v32), downcast(v16), downcast(v8)), - (downcast(v128), downcast(v64), downcast(v32), downcast(v16)), - (downcast(v128), downcast(v64), downcast(v32)), - (downcast(v128), downcast(v64)), - (downcast(v128),), - ) - } - }; - static ref UPCAST: (String, Program) = load_cairo! { - use core::integer::upcast; - - fn run_test( - v8: u8, v16: u16, v32: u32, v64: u64, v128: u128, v248: bytes31 - ) -> ( - (u8,), - (u16, u16), - (u32, u32, u32), - (u64, u64, u64, u64), - (u128, u128, u128, u128, u128), - (bytes31, bytes31, bytes31, bytes31, bytes31, bytes31) - ) { - ( - (upcast(v8),), - (upcast(v8), upcast(v16)), - (upcast(v8), upcast(v16), upcast(v32)), - (upcast(v8), upcast(v16), upcast(v32), upcast(v64)), - (upcast(v8), upcast(v16), upcast(v32), upcast(v64), upcast(v128)), - (upcast(v8), upcast(v16), upcast(v32), upcast(v64), upcast(v128), upcast(v248)), - ) - } - }; + use cairo_lang_sierra::{ + extensions::{ + bytes31::Bytes31Type, + casts::{DowncastLibfunc, UpcastLibfunc}, + int::{ + unsigned::{Uint16Type, Uint32Type, Uint64Type, Uint8Type}, + unsigned128::Uint128Type, + }, + GenericLibfunc, NamedType, + }, + program::{GenericArg, Program}, + }; + + fn cast() -> Program { + let mut generator = SierraGenerator::::default(); + + let from_ty = generator.push_type_declaration::(&[]).clone(); + let to_ty = generator.push_type_declaration::(&[]).clone(); + + generator.build(&[GenericArg::Type(from_ty), GenericArg::Type(to_ty)]) + } + + fn bytes21_with_filled_u8_max(times: u8) -> Value { + let mut vec = [0; 31]; + + for i in 0..times { + vec[i as usize] = u8::MAX + } + + Value::Bytes31(vec) } #[test] fn downcast() { - run_program_assert_output( - &DOWNCAST, - "run_test", - &[ - u8::MAX.into(), - u16::MAX.into(), - u32::MAX.into(), - u64::MAX.into(), - u128::MAX.into(), - ], - jit_struct!( - jit_struct!( - jit_enum!(1, jit_struct!()), - jit_enum!(1, jit_struct!()), - jit_enum!(1, jit_struct!()), - jit_enum!(1, jit_struct!()), - jit_enum!(1, jit_struct!()), - ), - jit_struct!( - jit_enum!(1, jit_struct!()), - jit_enum!(1, jit_struct!()), - jit_enum!(1, jit_struct!()), - jit_enum!(1, jit_struct!()), - ), - jit_struct!( - jit_enum!(1, jit_struct!()), - jit_enum!(1, jit_struct!()), - jit_enum!(1, jit_struct!()), - ), - jit_struct!(jit_enum!(1, jit_struct!()), jit_enum!(1, jit_struct!())), - jit_struct!(jit_enum!(1, jit_struct!())), - ), - ); + let result = run_sierra_program( + &cast::(), + &[u128::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u128::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u128::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u128::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u128::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u64::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u64::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u64::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u64::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u32::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u32::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u32::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u16::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u16::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); + let result = run_sierra_program( + &cast::(), + &[u8::MAX.into()], + ) + .return_value; + assert_eq!(result, jit_enum!(1, jit_struct!())); } #[test] fn upcast() { - run_program_assert_output( - &UPCAST, - "run_test", - &[ - u8::MAX.into(), - u16::MAX.into(), - u32::MAX.into(), - u64::MAX.into(), - u128::MAX.into(), - Value::Bytes31([0xFF; 31]), - ], - jit_struct!( - jit_struct!(u8::MAX.into()), - jit_struct!((u8::MAX as u16).into(), u16::MAX.into()), - jit_struct!( - (u8::MAX as u32).into(), - (u16::MAX as u32).into(), - u32::MAX.into() - ), - jit_struct!( - (u8::MAX as u64).into(), - (u16::MAX as u64).into(), - (u32::MAX as u64).into(), - u64::MAX.into() - ), - jit_struct!( - (u8::MAX as u128).into(), - (u16::MAX as u128).into(), - (u32::MAX as u128).into(), - (u64::MAX as u128).into(), - u128::MAX.into() - ), - jit_struct!( - Value::Bytes31([ - u8::MAX, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ]), - Value::Bytes31([ - u8::MAX, - u8::MAX, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ]), - Value::Bytes31([ - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ]), - Value::Bytes31([ - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ]), - Value::Bytes31([ - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - u8::MAX, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ]), - Value::Bytes31([u8::MAX; 31]), - ), - ), - ); + let result = run_sierra_program( + &cast::(), + &[u128::MAX.into()], + ) + .return_value; + assert_eq!(result, u128::MAX.into()); + let result = run_sierra_program( + &cast::(), + &[u64::MAX.into()], + ) + .return_value; + assert_eq!(result, (u64::MAX as u128).into()); + let result = run_sierra_program( + &cast::(), + &[u64::MAX.into()], + ) + .return_value; + assert_eq!(result, u64::MAX.into()); + let result = run_sierra_program( + &cast::(), + &[u32::MAX.into()], + ) + .return_value; + assert_eq!(result, (u32::MAX as u128).into()); + let result = run_sierra_program( + &cast::(), + &[u32::MAX.into()], + ) + .return_value; + assert_eq!(result, (u32::MAX as u64).into()); + let result = run_sierra_program( + &cast::(), + &[u32::MAX.into()], + ) + .return_value; + assert_eq!(result, u32::MAX.into()); + let result = run_sierra_program( + &cast::(), + &[u16::MAX.into()], + ) + .return_value; + assert_eq!(result, (u16::MAX as u128).into()); + let result = run_sierra_program( + &cast::(), + &[u16::MAX.into()], + ) + .return_value; + assert_eq!(result, (u16::MAX as u64).into()); + let result = run_sierra_program( + &cast::(), + &[u16::MAX.into()], + ) + .return_value; + assert_eq!(result, (u16::MAX as u32).into()); + let result = run_sierra_program( + &cast::(), + &[u16::MAX.into()], + ) + .return_value; + assert_eq!(result, u16::MAX.into()); + let result = run_sierra_program( + &cast::(), + &[u8::MAX.into()], + ) + .return_value; + assert_eq!(result, (u8::MAX as u128).into()); + let result = run_sierra_program( + &cast::(), + &[u8::MAX.into()], + ) + .return_value; + assert_eq!(result, (u8::MAX as u64).into()); + let result = run_sierra_program( + &cast::(), + &[u8::MAX.into()], + ) + .return_value; + assert_eq!(result, (u8::MAX as u32).into()); + let result = run_sierra_program( + &cast::(), + &[u8::MAX.into()], + ) + .return_value; + assert_eq!(result, (u8::MAX as u16).into()); + let result = run_sierra_program( + &cast::(), + &[u8::MAX.into()], + ) + .return_value; + assert_eq!(result, u8::MAX.into()); + let result = run_sierra_program( + &cast::(), + &[Value::Bytes31([0xFF; 31])], + ) + .return_value; + assert_eq!(result, Value::Bytes31([0xFF; 31])); + let result = run_sierra_program( + &cast::(), + &[u128::MAX.into()], + ) + .return_value; + assert_eq!(result, bytes21_with_filled_u8_max(16)); + let result = run_sierra_program( + &cast::(), + &[u64::MAX.into()], + ) + .return_value; + assert_eq!(result, bytes21_with_filled_u8_max(8)); + let result = run_sierra_program( + &cast::(), + &[u32::MAX.into()], + ) + .return_value; + assert_eq!(result, bytes21_with_filled_u8_max(4)); + let result = run_sierra_program( + &cast::(), + &[u16::MAX.into()], + ) + .return_value; + assert_eq!(result, bytes21_with_filled_u8_max(2)); + let result = run_sierra_program( + &cast::(), + &[u8::MAX.into()], + ) + .return_value; + assert_eq!(result, bytes21_with_filled_u8_max(1)); } } diff --git a/src/libfuncs/const.rs b/src/libfuncs/const.rs index 92ec36d31..fa4748959 100644 --- a/src/libfuncs/const.rs +++ b/src/libfuncs/const.rs @@ -307,29 +307,78 @@ pub fn build_const_type_value<'ctx, 'this>( #[cfg(test)] pub mod test { + use cairo_lang_sierra::{ + extensions::{ + boxing::UnboxLibfunc, + const_type::{ConstAsBoxLibfunc, ConstType}, + int::signed::Sint32Type, + structure::StructType, + }, + ids::UserTypeId, + program::GenericArg, + }; + use crate::{ - utils::test::{jit_struct, load_cairo, run_program}, + utils::{ + sierra_gen::SierraGenerator, + test::{jit_struct, run_sierra_program}, + }, values::Value, }; #[test] fn run_const_as_box() { - let program = load_cairo!( - use core::box::BoxTrait; + let program_as_const = { + let mut generator = SierraGenerator::::default(); - struct Hello { - x: i32, - } + let i32_ty = generator.push_type_declaration::(&[]).clone(); - fn run_test() -> Hello { - let x = BoxTrait::new(Hello { - x: -2 - }); - x.unbox() - } - ); + let const_i32_ty = generator + .push_type_declaration::(&[ + GenericArg::Type(i32_ty.clone()), + GenericArg::Value((-2).into()), + ]) + .clone(); + + let struct_ty = generator + .push_type_declaration::(&[ + GenericArg::UserType(UserTypeId::from_string("Hello")), + GenericArg::Type(i32_ty), + ]) + .clone(); + + let const_struct_ty = generator + .push_type_declaration::(&[ + GenericArg::Type(struct_ty), + GenericArg::Type(const_i32_ty.clone()), + ]) + .clone(); + + generator.build(&[ + GenericArg::Type(const_struct_ty), + GenericArg::Value(0.into()), + ]) + }; + + let program_unbox = { + let mut generator = SierraGenerator::::default(); + + let i32_type = generator.push_type_declaration::(&[]).clone(); + + let struct_type = generator + .push_type_declaration::(&[ + GenericArg::UserType(UserTypeId::from_string("Hello")), + GenericArg::Type(i32_type), + ]) + .clone(); + + generator.build(&[GenericArg::Type(struct_type)]) + }; + + let result = run_sierra_program(&program_as_const, &[]).return_value; + + let result = run_sierra_program(&program_unbox, &[result]).return_value; - let result = run_program(&program, "run_test", &[]).return_value; assert_eq!(result, jit_struct!(Value::Sint32(-2))); } } diff --git a/src/utils.rs b/src/utils.rs index 35ffbe826..bfbf9a260 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -626,6 +626,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 a748145a8..449318e10 100644 --- a/src/values.rs +++ b/src/values.rs @@ -169,6 +169,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) => { @@ -746,9 +756,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()),