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