cairo_vm/
utils.rs

1use crate::stdlib::prelude::*;
2use crate::types::relocatable::Relocatable;
3use lazy_static::lazy_static;
4use num_bigint::BigUint;
5use num_traits::Num;
6
7pub const PRIME_STR: &str = "0x800000000000011000000000000000000000000000000000000000000000001";
8
9#[macro_export]
10macro_rules! relocatable {
11    ($val1 : expr, $val2 : expr) => {
12        Relocatable {
13            segment_index: $val1,
14            offset: $val2,
15        }
16    };
17}
18
19lazy_static! {
20    pub static ref CAIRO_PRIME: BigUint = BigUint::from_str_radix(&PRIME_STR[2..], 16).unwrap();
21}
22
23#[macro_export]
24macro_rules! any_box {
25    ($val : expr) => {
26        $crate::stdlib::boxed::Box::new($val) as $crate::stdlib::boxed::Box<dyn core::any::Any>
27    };
28}
29
30pub fn is_subsequence<T: PartialEq>(subsequence: &[T], mut sequence: &[T]) -> bool {
31    for search in subsequence {
32        if let Some(index) = sequence.iter().position(|element| search == element) {
33            sequence = &sequence[index + 1..];
34        } else {
35            return false;
36        }
37    }
38    true
39}
40
41pub fn from_relocatable_to_indexes(relocatable: Relocatable) -> (usize, usize) {
42    if relocatable.segment_index.is_negative() {
43        (
44            -(relocatable.segment_index + 1) as usize,
45            relocatable.offset,
46        )
47    } else {
48        (relocatable.segment_index as usize, relocatable.offset)
49    }
50}
51
52#[cfg(test)]
53#[macro_use]
54pub mod test_utils {
55    use crate::types::exec_scope::ExecutionScopes;
56    use crate::types::relocatable::MaybeRelocatable;
57    use crate::vm::trace::trace_entry::TraceEntry;
58
59    #[macro_export]
60    macro_rules! felt_hex {
61        ($val: expr) => {
62            $crate::Felt252::from_hex($val).expect("Couldn't parse bytes")
63        };
64    }
65
66    #[macro_export]
67    macro_rules! felt_str {
68        ($val: expr) => {
69            $crate::Felt252::from_dec_str($val).expect("Couldn't parse bytes")
70        };
71    }
72
73    #[macro_export]
74    macro_rules! bigint {
75        ($val : expr) => {
76            Into::<num_bigint::BigInt>::into($val)
77        };
78    }
79    pub(crate) use bigint;
80
81    #[macro_export]
82    macro_rules! bigint_str {
83        ($val: expr) => {
84            num_bigint::BigInt::parse_bytes($val.as_bytes(), 10).expect("Couldn't parse bytes")
85        };
86        ($val: expr, $opt: expr) => {
87            num_bigint::BigInt::parse_bytes($val.as_bytes(), $opt).expect("Couldn't parse bytes")
88        };
89    }
90    pub(crate) use bigint_str;
91
92    #[macro_export]
93    macro_rules! biguint {
94        ($val : expr) => {
95            Into::<num_bigint::BigUint>::into($val as u128)
96        };
97    }
98    pub(crate) use biguint;
99
100    #[macro_export]
101    macro_rules! biguint_str {
102        ($val: expr) => {
103            num_bigint::BigUint::parse_bytes($val.as_bytes(), 10).expect("Couldn't parse bytes")
104        };
105        ($val: expr, $opt: expr) => {
106            num_bigint::BigUint::parse_bytes($val.as_bytes(), $opt).expect("Couldn't parse bytes")
107        };
108    }
109    pub(crate) use biguint_str;
110
111    impl From<(&str, u8)> for MaybeRelocatable {
112        fn from((string, radix): (&str, u8)) -> Self {
113            match radix {
114                16 => MaybeRelocatable::Int(crate::felt_hex!(string)),
115                10 => MaybeRelocatable::Int(crate::felt_str!(string)),
116                _ => panic!(" Invalid radix"),
117            }
118        }
119    }
120
121    macro_rules! segments {
122        ($( (($si:expr, $off:expr), $val:tt) ),* $(,)? ) => {
123            {
124                let mut segments = $crate::vm::vm_memory::memory_segments::MemorySegmentManager::new();
125                segments.memory = memory!($( (($si, $off), $val) ),*);
126                segments
127            }
128
129        };
130    }
131    pub(crate) use segments;
132
133    macro_rules! memory {
134        ( $( (($si:expr, $off:expr), $val:tt) ),* ) => {
135            {
136                let mut memory = $crate::vm::vm_memory::memory::Memory::new();
137                memory_from_memory!(memory, ( $( (($si, $off), $val) ),* ));
138                memory
139            }
140        };
141    }
142    pub(crate) use memory;
143
144    macro_rules! memory_from_memory {
145        ($mem: expr, ( $( (($si:expr, $off:expr), $val:tt) ),* )) => {
146            {
147                $(
148                    memory_inner!($mem, ($si, $off), $val);
149                )*
150            }
151        };
152    }
153    pub(crate) use memory_from_memory;
154
155    macro_rules! memory_inner {
156        ($mem:expr, ($si:expr, $off:expr), ($sival:expr, $offval: expr)) => {
157            let (k, v) = (($si, $off).into(), &mayberelocatable!($sival, $offval));
158            let mut res = $mem.insert(k, v);
159            while matches!(
160                res,
161                Err($crate::vm::errors::memory_errors::MemoryError::UnallocatedSegment(_))
162            ) {
163                if $si < 0 {
164                    $mem.temp_data.push($crate::stdlib::vec::Vec::new())
165                } else {
166                    $mem.data.push($crate::stdlib::vec::Vec::new());
167                }
168                res = $mem.insert(k, v);
169            }
170        };
171        ($mem:expr, ($si:expr, $off:expr), $val:expr) => {
172            let (k, v) = (($si, $off).into(), &mayberelocatable!($val));
173            let mut res = $mem.insert(k, v);
174            while matches!(
175                res,
176                Err($crate::vm::errors::memory_errors::MemoryError::UnallocatedSegment(_))
177            ) {
178                if $si < 0 {
179                    $mem.temp_data.push($crate::stdlib::vec::Vec::new())
180                } else {
181                    $mem.data.push($crate::stdlib::vec::Vec::new());
182                }
183                res = $mem.insert(k, v);
184            }
185        };
186    }
187    pub(crate) use memory_inner;
188
189    macro_rules! check_memory {
190        ( $mem: expr, $( (($si:expr, $off:expr), $val:tt) ),* $(,)? ) => {
191            $(
192                check_memory_address!($mem, ($si, $off), $val);
193            )*
194        };
195    }
196    pub(crate) use check_memory;
197
198    macro_rules! check_memory_address {
199        ($mem:expr, ($si:expr, $off:expr), ($sival:expr, $offval: expr)) => {
200            assert_eq!(
201                $mem.get(&mayberelocatable!($si, $off)).unwrap().as_ref(),
202                &mayberelocatable!($sival, $offval)
203            )
204        };
205        ($mem:expr, ($si:expr, $off:expr), $val:expr) => {
206            assert_eq!(
207                $mem.get(&mayberelocatable!($si, $off)).unwrap().as_ref(),
208                &mayberelocatable!($val)
209            )
210        };
211    }
212    pub(crate) use check_memory_address;
213
214    macro_rules! mayberelocatable {
215        ($val1 : expr, $val2 : expr) => {
216            $crate::types::relocatable::MaybeRelocatable::from(($val1, $val2))
217        };
218        ($val1 : expr) => {
219            $crate::types::relocatable::MaybeRelocatable::from(crate::Felt252::from($val1 as i128))
220        };
221    }
222    pub(crate) use mayberelocatable;
223
224    macro_rules! references {
225        ($num: expr) => {{
226            let mut references = crate::stdlib::collections::HashMap::<usize, HintReference>::new();
227            for i in 0..$num {
228                references.insert(i as usize, HintReference::new_simple((i as i32 - $num)));
229            }
230            references
231        }};
232    }
233    pub(crate) use references;
234
235    macro_rules! vm_with_range_check {
236        () => {{
237            let mut vm = VirtualMachine::new(false, false);
238            vm.builtin_runners = vec![
239                $crate::vm::runners::builtin_runner::RangeCheckBuiltinRunner::<8>::new(
240                    Some(8),
241                    true,
242                )
243                .into(),
244            ];
245            vm
246        }};
247    }
248    pub(crate) use vm_with_range_check;
249
250    macro_rules! cairo_runner {
251        ($program:expr) => {
252            crate::vm::runners::cairo_runner::CairoRunner::new(
253                &$program,
254                crate::types::layout_name::LayoutName::all_cairo,
255                None,
256                false,
257                false,
258                false,
259            )
260            .unwrap()
261        };
262        ($program:expr, $layout:expr) => {
263            crate::vm::runners::cairo_runner::CairoRunner::new(
264                &$program, $layout, None, false, false, false,
265            )
266            .unwrap()
267        };
268        ($program:expr, $layout:expr, $proof_mode:expr) => {
269            crate::vm::runners::cairo_runner::CairoRunner::new(
270                &$program,
271                $layout,
272                None,
273                $proof_mode,
274                false,
275                false,
276            )
277            .unwrap()
278        };
279        ($program:expr, $layout:expr, $proof_mode:expr, $trace_enabled:expr) => {
280            crate::vm::runners::cairo_runner::CairoRunner::new(
281                &$program,
282                $layout,
283                None,
284                $proof_mode,
285                $trace_enabled,
286                false,
287            )
288            .unwrap()
289        };
290    }
291    pub(crate) use cairo_runner;
292
293    pub(crate) use crate::stdlib::{collections::BTreeMap, sync::Arc};
294    pub(crate) use crate::types::program::HintsCollection;
295    pub(crate) use crate::types::program::Program;
296    pub(crate) use crate::types::program::SharedProgramData;
297    macro_rules! program {
298        //Empty program
299        () => {
300            Program::default()
301        };
302        //Program with builtins
303        ( $( $builtin_name: expr ),* ) => {{
304            let shared_program_data = SharedProgramData {
305                data: crate::stdlib::vec::Vec::new(),
306                hints_collection: HintsCollection::new(&BTreeMap::new(), 0).unwrap(),
307                main: None,
308                start: None,
309                end: None,
310                error_message_attributes: crate::stdlib::vec::Vec::new(),
311                instruction_locations: None,
312                identifiers: crate::stdlib::collections::HashMap::new(),
313                reference_manager: Program::get_reference_list(&ReferenceManager {
314                    references: crate::stdlib::vec::Vec::new(),
315                }),
316            };
317            Program {
318                shared_program_data: Arc::new(shared_program_data),
319                constants: crate::stdlib::collections::HashMap::new(),
320                builtins: vec![$( $builtin_name ),*],
321            }
322        }};
323        ($($field:ident = $value:expr),* $(,)?) => {{
324
325            let program_flat = crate::utils::test_utils::ProgramFlat {
326                $(
327                    $field: $value,
328                )*
329                ..Default::default()
330            };
331
332            Into::<Program>::into(program_flat)
333        }};
334    }
335
336    pub(crate) use program;
337
338    pub(crate) struct ProgramFlat {
339        pub(crate) data: crate::utils::Vec<MaybeRelocatable>,
340        pub(crate) hints: crate::stdlib::collections::BTreeMap<
341            usize,
342            crate::utils::Vec<crate::serde::deserialize_program::HintParams>,
343        >,
344        pub(crate) main: Option<usize>,
345        //start and end labels will only be used in proof-mode
346        pub(crate) start: Option<usize>,
347        pub(crate) end: Option<usize>,
348        pub(crate) error_message_attributes:
349            crate::utils::Vec<crate::serde::deserialize_program::Attribute>,
350        pub(crate) instruction_locations: Option<
351            crate::stdlib::collections::HashMap<
352                usize,
353                crate::serde::deserialize_program::InstructionLocation,
354            >,
355        >,
356        pub(crate) identifiers: crate::stdlib::collections::HashMap<
357            crate::stdlib::string::String,
358            crate::serde::deserialize_program::Identifier,
359        >,
360        pub(crate) constants:
361            crate::stdlib::collections::HashMap<crate::stdlib::string::String, crate::Felt252>,
362        pub(crate) builtins: crate::utils::Vec<crate::types::builtin_name::BuiltinName>,
363        pub(crate) reference_manager: crate::serde::deserialize_program::ReferenceManager,
364    }
365
366    impl Default for ProgramFlat {
367        fn default() -> Self {
368            Self {
369                data: Default::default(),
370                hints: Default::default(),
371                main: Default::default(),
372                start: Default::default(),
373                end: Default::default(),
374                error_message_attributes: Default::default(),
375                instruction_locations: Default::default(),
376                identifiers: Default::default(),
377                constants: Default::default(),
378                builtins: Default::default(),
379                reference_manager: crate::serde::deserialize_program::ReferenceManager {
380                    references: crate::utils::Vec::new(),
381                },
382            }
383        }
384    }
385
386    impl From<ProgramFlat> for Program {
387        fn from(val: ProgramFlat) -> Self {
388            // NOTE: panics if hints have PCs higher than the program length
389            let hints_collection =
390                HintsCollection::new(&val.hints, val.data.len()).expect("hints are valid");
391            Program {
392                shared_program_data: Arc::new(SharedProgramData {
393                    data: val.data,
394                    hints_collection,
395                    main: val.main,
396                    start: val.start,
397                    end: val.end,
398                    error_message_attributes: val.error_message_attributes,
399                    instruction_locations: val.instruction_locations,
400                    identifiers: val.identifiers,
401                    reference_manager: Program::get_reference_list(&val.reference_manager),
402                }),
403                constants: val.constants,
404                builtins: val.builtins,
405            }
406        }
407    }
408
409    macro_rules! vm {
410        () => {{
411            crate::vm::vm_core::VirtualMachine::new(false, false)
412        }};
413
414        ($use_trace:expr) => {{
415            crate::vm::vm_core::VirtualMachine::new($use_trace, false)
416        }};
417    }
418    pub(crate) use vm;
419
420    macro_rules! run_context {
421        ( $vm: expr, $pc: expr, $ap: expr, $fp: expr ) => {
422            $vm.run_context.pc = Relocatable::from((0, $pc));
423            $vm.run_context.ap = $ap;
424            $vm.run_context.fp = $fp;
425        };
426    }
427    pub(crate) use run_context;
428
429    macro_rules! ids_data {
430        ( $( $name: expr ),* ) => {
431            {
432                let ids_names = vec![$( $name ),*];
433                let references = references!(ids_names.len() as i32);
434                let mut ids_data = crate::stdlib::collections::HashMap::<crate::stdlib::string::String, HintReference>::new();
435                for (i, name) in ids_names.iter().enumerate() {
436                    ids_data.insert(crate::stdlib::string::ToString::to_string(name), references.get(&i).unwrap().clone());
437                }
438                ids_data
439            }
440        };
441    }
442    pub(crate) use ids_data;
443
444    macro_rules! non_continuous_ids_data {
445        ( $( ($name: expr, $offset:expr) ),* $(,)? ) => {
446            {
447                let mut ids_data = crate::stdlib::collections::HashMap::<crate::stdlib::string::String, HintReference>::new();
448                $(
449                    ids_data.insert(crate::stdlib::string::String::from($name), HintReference::new_simple($offset));
450                )*
451                ids_data
452            }
453        };
454    }
455    pub(crate) use non_continuous_ids_data;
456
457    #[track_caller]
458    pub(crate) fn trace_check(
459        actual: &[TraceEntry],
460        expected: &[(crate::utils::Relocatable, usize, usize)],
461    ) {
462        assert_eq!(actual.len(), expected.len());
463        for (entry, expected) in actual.iter().zip(expected.iter()) {
464            assert_eq!(&(entry.pc, entry.ap, entry.fp), expected);
465        }
466    }
467
468    macro_rules! exec_scopes_ref {
469        () => {
470            &mut crate::types::exec_scope::ExecutionScopes::new()
471        };
472    }
473    pub(crate) use exec_scopes_ref;
474
475    macro_rules! run_hint {
476        ($vm:expr, $ids_data:expr, $hint_code:expr, $exec_scopes:expr, $constants:expr) => {{
477            let hint_data = HintProcessorData::new_default($hint_code.to_string(), $ids_data);
478            let mut hint_processor = BuiltinHintProcessor::new_empty();
479            hint_processor.execute_hint(&mut $vm, $exec_scopes, &any_box!(hint_data), $constants)
480        }};
481        ($vm:expr, $ids_data:expr, $hint_code:expr, $exec_scopes:expr) => {{
482            let hint_data = HintProcessorData::new_default(
483                crate::stdlib::string::ToString::to_string($hint_code),
484                $ids_data,
485            );
486            let mut hint_processor = BuiltinHintProcessor::new_empty();
487            hint_processor.execute_hint(
488                &mut $vm,
489                $exec_scopes,
490                &any_box!(hint_data),
491                &crate::stdlib::collections::HashMap::new(),
492            )
493        }};
494        ($vm:expr, $ids_data:expr, $hint_code:expr) => {{
495            let hint_data = HintProcessorData::new_default(
496                crate::stdlib::string::ToString::to_string($hint_code),
497                $ids_data,
498            );
499            let mut hint_processor = BuiltinHintProcessor::new_empty();
500            hint_processor.execute_hint(
501                &mut $vm,
502                exec_scopes_ref!(),
503                &any_box!(hint_data),
504                &crate::stdlib::collections::HashMap::new(),
505            )
506        }};
507    }
508    pub(crate) use run_hint;
509
510    macro_rules! add_segments {
511        ($vm:expr, $n:expr) => {
512            for _ in 0..$n {
513                $vm.segments.add();
514            }
515        };
516    }
517    pub(crate) use add_segments;
518
519    macro_rules! check_scope {
520        ( $exec_scope: expr, [ $( ($name: expr, $val: expr)),*$(,)? ] $(,)? ) => {
521            $(
522                check_scope_value($exec_scope, $name, $val);
523            )*
524        };
525    }
526    pub(crate) use check_scope;
527
528    macro_rules! scope {
529        () => { ExecutionScopes::new() };
530        (  $( ($name: expr, $val: expr)),* $(,)?  ) => {
531            {
532                let mut exec_scopes = ExecutionScopes::new();
533                $(
534                    exec_scopes.assign_or_update_variable(
535                        $name,
536                        any_box!($val),
537                    );
538                )*
539                exec_scopes
540            }
541        };
542    }
543    pub(crate) use scope;
544
545    macro_rules! check_dictionary {
546        ( $exec_scopes: expr, $tracker_num:expr, $( ($key:expr, $val:expr )),* ) => {
547            $(
548                assert_matches::assert_matches!(
549                    $exec_scopes
550                        .get_dict_manager()
551                        .unwrap()
552                        .borrow_mut()
553                        .trackers
554                        .get_mut(&$tracker_num)
555                        .unwrap()
556                        .get_value(&MaybeRelocatable::from($key)),
557                    Ok(x) if x == &MaybeRelocatable::from($val)
558                ));
559            *
560        };
561    }
562    pub(crate) use check_dictionary;
563
564    macro_rules! check_dict_ptr {
565        ($exec_scopes: expr, $tracker_num: expr, ($i:expr, $off:expr)) => {
566            assert_eq!(
567                $exec_scopes
568                    .get_dict_manager()
569                    .unwrap()
570                    .borrow()
571                    .trackers
572                    .get(&$tracker_num)
573                    .unwrap()
574                    .current_ptr,
575                relocatable!($i, $off)
576            );
577        };
578    }
579    pub(crate) use check_dict_ptr;
580
581    macro_rules! dict_manager {
582        ($exec_scopes:expr, $tracker_num:expr, $( ($key:expr, $val:expr )),* ) => {
583            let mut tracker = DictTracker::new_empty(relocatable!($tracker_num, 0));
584            $(
585            tracker.insert_value(&MaybeRelocatable::from($key), &MaybeRelocatable::from($val));
586            )*
587            let mut dict_manager = DictManager::new();
588            dict_manager.trackers.insert(2, tracker);
589            $exec_scopes.insert_value("dict_manager", crate::stdlib::rc::Rc::new(core::cell::RefCell::new(dict_manager)))
590        };
591        ($exec_scopes:expr, $tracker_num:expr) => {
592            let  tracker = DictTracker::new_empty(relocatable!($tracker_num, 0));
593            let mut dict_manager = DictManager::new();
594            dict_manager.trackers.insert(2, tracker);
595            $exec_scopes.insert_value("dict_manager", crate::stdlib::rc::Rc::new(core::cell::RefCell::new(dict_manager)))
596        };
597
598    }
599    pub(crate) use dict_manager;
600
601    macro_rules! dict_manager_default {
602        ($exec_scopes:expr, $tracker_num:expr,$default:expr, $( ($key:expr, $val:expr )),* ) => {
603            let mut tracker = DictTracker::new_default_dict(relocatable!($tracker_num, 0), &MaybeRelocatable::from($default), None);
604            $(
605            tracker.insert_value(&MaybeRelocatable::from($key), &MaybeRelocatable::from($val));
606            )*
607            let mut dict_manager = DictManager::new();
608            dict_manager.trackers.insert(2, tracker);
609            $exec_scopes.insert_value("dict_manager", crate::stdlib::rc::Rc::new(core::cell::RefCell::new(dict_manager)))
610        };
611        ($exec_scopes:expr, $tracker_num:expr,$default:expr) => {
612            let tracker = DictTracker::new_default_dict(relocatable!($tracker_num, 0), &MaybeRelocatable::from($default), None);
613            let mut dict_manager = DictManager::new();
614            dict_manager.trackers.insert(2, tracker);
615            $exec_scopes.insert_value("dict_manager", crate::stdlib::rc::Rc::new(core::cell::RefCell::new(dict_manager)))
616        };
617    }
618    pub(crate) use dict_manager_default;
619
620    macro_rules! vec_data {
621        ( $( ($val:tt) ),* ) => {
622            vec![$( vec_data_inner!($val) ),*]
623        };
624    }
625    pub(crate) use vec_data;
626
627    macro_rules! vec_data_inner {
628        (( $val1:expr, $val2:expr )) => {
629            mayberelocatable!($val1, $val2)
630        };
631        ( $val:expr ) => {
632            mayberelocatable!($val)
633        };
634    }
635    pub(crate) use vec_data_inner;
636
637    pub fn check_scope_value<T: core::fmt::Debug + core::cmp::PartialEq + 'static>(
638        scopes: &ExecutionScopes,
639        name: &str,
640        value: T,
641    ) {
642        let scope_value = scopes.get_any_boxed_ref(name).unwrap();
643        assert_eq!(scope_value.downcast_ref::<T>(), Some(&value));
644    }
645}
646
647#[cfg(test)]
648mod test {
649    use crate::hint_processor::hint_processor_definition::HintProcessorLogic;
650    use crate::stdlib::{cell::RefCell, collections::HashMap, rc::Rc, string::String, vec::Vec};
651    use crate::types::builtin_name::BuiltinName;
652    use crate::types::program::HintsCollection;
653    use crate::{
654        hint_processor::{
655            builtin_hint_processor::{
656                builtin_hint_processor_definition::{BuiltinHintProcessor, HintProcessorData},
657                dict_manager::{DictManager, DictTracker},
658            },
659            hint_processor_definition::HintReference,
660        },
661        serde::deserialize_program::ReferenceManager,
662        types::{exec_scope::ExecutionScopes, program::Program, relocatable::MaybeRelocatable},
663        utils::test_utils::*,
664        vm::{trace::trace_entry::TraceEntry, vm_memory::memory::Memory},
665    };
666
667    #[cfg(target_arch = "wasm32")]
668    use wasm_bindgen_test::*;
669
670    use super::*;
671
672    #[test]
673    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
674    fn memory_macro_test() {
675        let mut memory = Memory::new();
676        for _ in 0..2 {
677            memory.data.push(Vec::new());
678        }
679        memory
680            .insert(
681                Relocatable::from((1, 2)),
682                &MaybeRelocatable::from(crate::Felt252::ONE),
683            )
684            .unwrap();
685        memory
686            .insert(Relocatable::from((1, 1)), &MaybeRelocatable::from((1, 0)))
687            .unwrap();
688        let mem = memory![((1, 2), 1), ((1, 1), (1, 0))];
689        assert_eq!(memory.data, mem.data);
690    }
691
692    #[test]
693    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
694    fn check_memory_macro_test() {
695        let mut memory = Memory::new();
696        for _ in 0..2 {
697            memory.data.push(Vec::new());
698        }
699        memory
700            .insert(Relocatable::from((1, 1)), &MaybeRelocatable::from((1, 0)))
701            .unwrap();
702
703        memory
704            .insert(
705                Relocatable::from((1, 2)),
706                &MaybeRelocatable::from(crate::Felt252::ONE),
707            )
708            .unwrap();
709
710        check_memory![memory, ((1, 1), (1, 0)), ((1, 2), 1)];
711    }
712
713    #[test]
714    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
715    fn check_memory_address_macro_test() {
716        let mut memory = Memory::new();
717        for _ in 0..2 {
718            memory.data.push(Vec::new());
719        }
720        memory
721            .insert(Relocatable::from((1, 1)), &MaybeRelocatable::from((1, 0)))
722            .unwrap();
723
724        memory
725            .insert(
726                Relocatable::from((1, 2)),
727                &MaybeRelocatable::from(crate::Felt252::ONE),
728            )
729            .unwrap();
730
731        check_memory_address!(memory, (1, 1), (1, 0));
732        check_memory_address!(memory, (1, 2), 1);
733    }
734
735    #[test]
736    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
737    fn create_run_context() {
738        let mut vm = vm!();
739        run_context!(vm, 2, 6, 10);
740
741        assert_eq!(vm.run_context.pc, Relocatable::from((0, 2)));
742        assert_eq!(vm.run_context.ap, 6);
743        assert_eq!(vm.run_context.fp, 10);
744    }
745
746    #[test]
747    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
748    fn assert_trace() {
749        let trace = vec![
750            TraceEntry {
751                pc: (0, 2).into(),
752                ap: 7,
753                fp: 1,
754            },
755            TraceEntry {
756                pc: (0, 5).into(),
757                ap: 1,
758                fp: 0,
759            },
760            TraceEntry {
761                pc: (0, 9).into(),
762                ap: 5,
763                fp: 7,
764            },
765        ];
766        trace_check(
767            &trace,
768            &[
769                ((0, 2).into(), 7, 1),
770                ((0, 5).into(), 1, 0),
771                ((0, 9).into(), 5, 7),
772            ],
773        );
774    }
775
776    #[test]
777    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
778    fn test_non_continuous_ids_data() {
779        let ids_data_macro = non_continuous_ids_data![("a", -2), ("", -6)];
780        let ids_data_verbose = HashMap::from([
781            ("a".to_string(), HintReference::new_simple(-2)),
782            ("".to_string(), HintReference::new_simple(-6)),
783        ]);
784        assert_eq!(ids_data_macro, ids_data_verbose);
785    }
786
787    #[test]
788    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
789    fn run_hint_alloc() {
790        let hint_code = "memory[ap] = segments.add()";
791        let mut vm = vm!();
792        add_segments!(vm, 1);
793        assert_matches::assert_matches!(run_hint!(vm, HashMap::new(), hint_code), Ok(()));
794        //A segment is added
795        assert_eq!(vm.segments.memory.data.len(), 2);
796    }
797
798    #[test]
799    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
800    fn check_scope_test_pass() {
801        let mut exec_scopes = ExecutionScopes::new();
802        exec_scopes.assign_or_update_variable("a", any_box!(String::from("Hello")));
803        exec_scopes.assign_or_update_variable(
804            "",
805            any_box!(Rc::new(RefCell::new(HashMap::<usize, Vec<usize>>::new()))),
806        );
807        exec_scopes.assign_or_update_variable("c", any_box!(vec![1, 2, 3, 4]));
808        check_scope!(
809            &exec_scopes,
810            [
811                ("a", String::from("Hello")),
812                (
813                    "",
814                    Rc::new(RefCell::new(HashMap::<usize, Vec<usize>>::new()))
815                ),
816                ("c", vec![1, 2, 3, 4])
817            ]
818        );
819    }
820
821    #[test]
822    #[should_panic]
823    fn check_scope_test_fail() {
824        let mut exec_scopes = ExecutionScopes::new();
825        exec_scopes.assign_or_update_variable("a", any_box!(String::from("Hello")));
826        exec_scopes.assign_or_update_variable(
827            "",
828            any_box!(Rc::new(RefCell::new(HashMap::<usize, Vec<usize>>::new()))),
829        );
830        exec_scopes.assign_or_update_variable("c", any_box!(vec![1, 2, 3, 4]));
831        check_scope!(
832            &exec_scopes,
833            [
834                ("a", String::from("Hello")),
835                (
836                    "",
837                    Rc::new(RefCell::new(HashMap::<usize, Vec<usize>>::new()))
838                ),
839                ("c", vec![1, 2, 3, 5])
840            ]
841        );
842    }
843
844    #[test]
845    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
846    fn scope_macro_test() {
847        let scope_from_macro = scope![("a", crate::Felt252::ONE)];
848        let mut scope_verbose = ExecutionScopes::new();
849        scope_verbose.assign_or_update_variable("a", any_box!(crate::Felt252::ONE));
850        assert_eq!(scope_from_macro.data.len(), scope_verbose.data.len());
851        assert_eq!(scope_from_macro.data[0].len(), scope_verbose.data[0].len());
852        assert_eq!(
853            scope_from_macro.data[0].get("a").unwrap().downcast_ref(),
854            Some(&crate::Felt252::ONE)
855        );
856    }
857
858    #[test]
859    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
860    fn check_dictionary_pass() {
861        let mut tracker = DictTracker::new_empty(relocatable!(2, 0));
862        tracker.insert_value(
863            &MaybeRelocatable::from(crate::Felt252::from(5)),
864            &MaybeRelocatable::from(crate::Felt252::from(10)),
865        );
866        let mut dict_manager = DictManager::new();
867        dict_manager.trackers.insert(2, tracker);
868        let mut exec_scopes = ExecutionScopes::new();
869        exec_scopes.assign_or_update_variable(
870            "dict_manager",
871            any_box!(Rc::new(RefCell::new(dict_manager))),
872        );
873        check_dictionary!(&exec_scopes, 2, (5, 10));
874    }
875
876    #[test]
877    #[should_panic]
878    fn check_dictionary_fail() {
879        let mut tracker = DictTracker::new_empty(relocatable!(2, 0));
880        tracker.insert_value(&MaybeRelocatable::from(5), &MaybeRelocatable::from(10));
881        let mut dict_manager = DictManager::new();
882        dict_manager.trackers.insert(2, tracker);
883        let mut exec_scopes = ExecutionScopes::new();
884        exec_scopes.assign_or_update_variable(
885            "dict_manager",
886            any_box!(Rc::new(RefCell::new(dict_manager))),
887        );
888        check_dictionary!(&exec_scopes, 2, (5, 11));
889    }
890
891    #[test]
892    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
893    fn check_dict_ptr_pass() {
894        let tracker = DictTracker::new_empty(relocatable!(2, 0));
895        let mut dict_manager = DictManager::new();
896        dict_manager.trackers.insert(2, tracker);
897        let mut exec_scopes = ExecutionScopes::new();
898        exec_scopes.assign_or_update_variable(
899            "dict_manager",
900            any_box!(Rc::new(RefCell::new(dict_manager))),
901        );
902        check_dict_ptr!(&exec_scopes, 2, (2, 0));
903    }
904
905    #[test]
906    #[should_panic]
907    fn check_dict_ptr_fail() {
908        let tracker = DictTracker::new_empty(relocatable!(2, 0));
909        let mut dict_manager = DictManager::new();
910        dict_manager.trackers.insert(2, tracker);
911        let mut exec_scopes = ExecutionScopes::new();
912        exec_scopes.assign_or_update_variable(
913            "dict_manager",
914            any_box!(Rc::new(RefCell::new(dict_manager))),
915        );
916        check_dict_ptr!(&exec_scopes, 2, (3, 0));
917    }
918
919    #[test]
920    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
921    fn dict_manager_macro() {
922        let tracker = DictTracker::new_empty(relocatable!(2, 0));
923        let mut dict_manager = DictManager::new();
924        dict_manager.trackers.insert(2, tracker);
925        let mut exec_scopes = ExecutionScopes::new();
926        dict_manager!(exec_scopes, 2);
927        assert_matches::assert_matches!(
928            exec_scopes.get_dict_manager(),
929            Ok(x) if x == Rc::new(RefCell::new(dict_manager))
930        );
931    }
932
933    #[test]
934    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
935    fn dict_manager_default_macro() {
936        let tracker = DictTracker::new_default_dict(
937            relocatable!(2, 0),
938            &MaybeRelocatable::from(crate::Felt252::from(17)),
939            None,
940        );
941        let mut dict_manager = DictManager::new();
942        dict_manager.trackers.insert(2, tracker);
943        let mut exec_scopes = ExecutionScopes::new();
944        dict_manager_default!(exec_scopes, 2, 17);
945        assert_matches::assert_matches!(
946            exec_scopes.get_dict_manager(),
947            Ok(x) if x == Rc::new(RefCell::new(dict_manager))
948        );
949    }
950
951    #[test]
952    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
953    fn data_vec_test() {
954        let data = vec_data!((1), ((2, 2)), (("49128305", 10)), (("3b6f00a9", 16)));
955        assert_eq!(data[0], mayberelocatable!(1));
956        assert_eq!(data[1], mayberelocatable!(2, 2));
957        assert_eq!(data[2], mayberelocatable!(49128305));
958        assert_eq!(data[3], mayberelocatable!(997130409));
959    }
960    #[test]
961    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
962    fn from_relocatable_to_indexes_test() {
963        let reloc_1 = relocatable!(1, 5);
964        let reloc_2 = relocatable!(0, 5);
965        let reloc_3 = relocatable!(-1, 5);
966        assert_eq!((1, 5), from_relocatable_to_indexes(reloc_1));
967        assert_eq!((0, 5), from_relocatable_to_indexes(reloc_2));
968        assert_eq!((0, 5), from_relocatable_to_indexes(reloc_3));
969    }
970
971    #[test]
972    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
973    fn program_macro() {
974        let shared_data = SharedProgramData {
975            data: Vec::new(),
976            hints_collection: HintsCollection::new(&BTreeMap::new(), 0).unwrap(),
977            main: None,
978            start: None,
979            end: None,
980            error_message_attributes: Vec::new(),
981            instruction_locations: None,
982            identifiers: HashMap::new(),
983            reference_manager: Program::get_reference_list(&ReferenceManager {
984                references: Vec::new(),
985            }),
986        };
987        let program = Program {
988            shared_program_data: Arc::new(shared_data),
989            constants: HashMap::new(),
990            builtins: Vec::new(),
991        };
992        assert_eq!(program, program!())
993    }
994
995    #[test]
996    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
997    fn program_macro_with_builtin() {
998        let shared_data = SharedProgramData {
999            data: Vec::new(),
1000            hints_collection: HintsCollection::new(&BTreeMap::new(), 0).unwrap(),
1001            main: None,
1002            start: None,
1003            end: None,
1004            error_message_attributes: Vec::new(),
1005            instruction_locations: None,
1006            identifiers: HashMap::new(),
1007            reference_manager: Program::get_reference_list(&ReferenceManager {
1008                references: Vec::new(),
1009            }),
1010        };
1011        let program = Program {
1012            shared_program_data: Arc::new(shared_data),
1013            constants: HashMap::new(),
1014            builtins: vec![BuiltinName::range_check],
1015        };
1016
1017        assert_eq!(program, program![BuiltinName::range_check])
1018    }
1019
1020    #[test]
1021    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1022    fn program_macro_custom_definition() {
1023        let shared_data = SharedProgramData {
1024            data: Vec::new(),
1025            hints_collection: HintsCollection::new(&BTreeMap::new(), 0).unwrap(),
1026            main: Some(2),
1027            start: None,
1028            end: None,
1029            error_message_attributes: Vec::new(),
1030            instruction_locations: None,
1031            identifiers: HashMap::new(),
1032            reference_manager: Program::get_reference_list(&ReferenceManager {
1033                references: Vec::new(),
1034            }),
1035        };
1036        let program = Program {
1037            shared_program_data: Arc::new(shared_data),
1038            constants: HashMap::new(),
1039            builtins: vec![BuiltinName::range_check],
1040        };
1041
1042        assert_eq!(
1043            program,
1044            program!(builtins = vec![BuiltinName::range_check], main = Some(2),)
1045        )
1046    }
1047}