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 () => {
300 Program::default()
301 };
302 ( $( $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 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 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 mut hint_data = HintProcessorData::new_default($hint_code.to_string(), $ids_data);
478 let constants: &HashMap<String, Felt252> = $constants;
479 hint_data.constants = crate::stdlib::rc::Rc::new(constants.clone());
480 let mut hint_processor = BuiltinHintProcessor::new_empty();
481 hint_processor.execute_hint(&mut $vm, $exec_scopes, &any_box!(hint_data))
482 }};
483 ($vm:expr, $ids_data:expr, $hint_code:expr, $exec_scopes:expr) => {{
484 let hint_data = HintProcessorData::new_default(
485 crate::stdlib::string::ToString::to_string($hint_code),
486 $ids_data,
487 );
488 let mut hint_processor = BuiltinHintProcessor::new_empty();
489 hint_processor.execute_hint(&mut $vm, $exec_scopes, &any_box!(hint_data))
490 }};
491 ($vm:expr, $ids_data:expr, $hint_code:expr) => {{
492 let hint_data = HintProcessorData::new_default(
493 crate::stdlib::string::ToString::to_string($hint_code),
494 $ids_data,
495 );
496 let mut hint_processor = BuiltinHintProcessor::new_empty();
497 hint_processor.execute_hint(&mut $vm, exec_scopes_ref!(), &any_box!(hint_data))
498 }};
499 }
500 pub(crate) use run_hint;
501
502 macro_rules! add_segments {
503 ($vm:expr, $n:expr) => {
504 for _ in 0..$n {
505 $vm.segments.add();
506 }
507 };
508 }
509 pub(crate) use add_segments;
510
511 macro_rules! check_scope {
512 ( $exec_scope: expr, [ $( ($name: expr, $val: expr)),*$(,)? ] $(,)? ) => {
513 $(
514 check_scope_value($exec_scope, $name, $val);
515 )*
516 };
517 }
518 pub(crate) use check_scope;
519
520 macro_rules! scope {
521 () => { ExecutionScopes::new() };
522 ( $( ($name: expr, $val: expr)),* $(,)? ) => {
523 {
524 let mut exec_scopes = ExecutionScopes::new();
525 $(
526 exec_scopes.assign_or_update_variable(
527 $name,
528 any_box!($val),
529 );
530 )*
531 exec_scopes
532 }
533 };
534 }
535 pub(crate) use scope;
536
537 macro_rules! check_dictionary {
538 ( $exec_scopes: expr, $tracker_num:expr, $( ($key:expr, $val:expr )),* ) => {
539 $(
540 assert_matches::assert_matches!(
541 $exec_scopes
542 .get_dict_manager()
543 .unwrap()
544 .borrow_mut()
545 .trackers
546 .get_mut(&$tracker_num)
547 .unwrap()
548 .get_value(&MaybeRelocatable::from($key)),
549 Ok(x) if x == &MaybeRelocatable::from($val)
550 ));
551 *
552 };
553 }
554 pub(crate) use check_dictionary;
555
556 macro_rules! check_dict_ptr {
557 ($exec_scopes: expr, $tracker_num: expr, ($i:expr, $off:expr)) => {
558 assert_eq!(
559 $exec_scopes
560 .get_dict_manager()
561 .unwrap()
562 .borrow()
563 .trackers
564 .get(&$tracker_num)
565 .unwrap()
566 .current_ptr,
567 relocatable!($i, $off)
568 );
569 };
570 }
571 pub(crate) use check_dict_ptr;
572
573 macro_rules! dict_manager {
574 ($exec_scopes:expr, $tracker_num:expr, $( ($key:expr, $val:expr )),* ) => {
575 let mut tracker = DictTracker::new_empty(relocatable!($tracker_num, 0));
576 $(
577 tracker.insert_value(&MaybeRelocatable::from($key), &MaybeRelocatable::from($val));
578 )*
579 let mut dict_manager = DictManager::new();
580 dict_manager.trackers.insert(2, tracker);
581 $exec_scopes.insert_value("dict_manager", crate::stdlib::rc::Rc::new(core::cell::RefCell::new(dict_manager)))
582 };
583 ($exec_scopes:expr, $tracker_num:expr) => {
584 let tracker = DictTracker::new_empty(relocatable!($tracker_num, 0));
585 let mut dict_manager = DictManager::new();
586 dict_manager.trackers.insert(2, tracker);
587 $exec_scopes.insert_value("dict_manager", crate::stdlib::rc::Rc::new(core::cell::RefCell::new(dict_manager)))
588 };
589
590 }
591 pub(crate) use dict_manager;
592
593 macro_rules! dict_manager_default {
594 ($exec_scopes:expr, $tracker_num:expr,$default:expr, $( ($key:expr, $val:expr )),* ) => {
595 let mut tracker = DictTracker::new_default_dict(relocatable!($tracker_num, 0), &MaybeRelocatable::from($default), None);
596 $(
597 tracker.insert_value(&MaybeRelocatable::from($key), &MaybeRelocatable::from($val));
598 )*
599 let mut dict_manager = DictManager::new();
600 dict_manager.trackers.insert(2, tracker);
601 $exec_scopes.insert_value("dict_manager", crate::stdlib::rc::Rc::new(core::cell::RefCell::new(dict_manager)))
602 };
603 ($exec_scopes:expr, $tracker_num:expr,$default:expr) => {
604 let tracker = DictTracker::new_default_dict(relocatable!($tracker_num, 0), &MaybeRelocatable::from($default), None);
605 let mut dict_manager = DictManager::new();
606 dict_manager.trackers.insert(2, tracker);
607 $exec_scopes.insert_value("dict_manager", crate::stdlib::rc::Rc::new(core::cell::RefCell::new(dict_manager)))
608 };
609 }
610 pub(crate) use dict_manager_default;
611
612 macro_rules! vec_data {
613 ( $( ($val:tt) ),* ) => {
614 vec![$( vec_data_inner!($val) ),*]
615 };
616 }
617 pub(crate) use vec_data;
618
619 macro_rules! vec_data_inner {
620 (( $val1:expr, $val2:expr )) => {
621 mayberelocatable!($val1, $val2)
622 };
623 ( $val:expr ) => {
624 mayberelocatable!($val)
625 };
626 }
627 pub(crate) use vec_data_inner;
628
629 pub fn check_scope_value<T: core::fmt::Debug + core::cmp::PartialEq + 'static>(
630 scopes: &ExecutionScopes,
631 name: &str,
632 value: T,
633 ) {
634 let scope_value = scopes.get_any_boxed_ref(name).unwrap();
635 assert_eq!(scope_value.downcast_ref::<T>(), Some(&value));
636 }
637}
638
639#[cfg(test)]
640mod test {
641 use crate::hint_processor::hint_processor_definition::HintProcessorLogic;
642 use crate::stdlib::{cell::RefCell, collections::HashMap, rc::Rc, string::String, vec::Vec};
643 use crate::types::builtin_name::BuiltinName;
644 use crate::types::program::HintsCollection;
645 use crate::{
646 hint_processor::{
647 builtin_hint_processor::{
648 builtin_hint_processor_definition::{BuiltinHintProcessor, HintProcessorData},
649 dict_manager::{DictManager, DictTracker},
650 },
651 hint_processor_definition::HintReference,
652 },
653 serde::deserialize_program::ReferenceManager,
654 types::{exec_scope::ExecutionScopes, program::Program, relocatable::MaybeRelocatable},
655 utils::test_utils::*,
656 vm::{trace::trace_entry::TraceEntry, vm_memory::memory::Memory},
657 };
658
659 #[cfg(target_arch = "wasm32")]
660 use wasm_bindgen_test::*;
661
662 use super::*;
663
664 #[test]
665 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
666 fn memory_macro_test() {
667 let mut memory = Memory::new();
668 for _ in 0..2 {
669 memory.data.push(Vec::new());
670 }
671 memory
672 .insert(
673 Relocatable::from((1, 2)),
674 &MaybeRelocatable::from(crate::Felt252::ONE),
675 )
676 .unwrap();
677 memory
678 .insert(Relocatable::from((1, 1)), &MaybeRelocatable::from((1, 0)))
679 .unwrap();
680 let mem = memory![((1, 2), 1), ((1, 1), (1, 0))];
681 assert_eq!(memory.data, mem.data);
682 }
683
684 #[test]
685 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
686 fn check_memory_macro_test() {
687 let mut memory = Memory::new();
688 for _ in 0..2 {
689 memory.data.push(Vec::new());
690 }
691 memory
692 .insert(Relocatable::from((1, 1)), &MaybeRelocatable::from((1, 0)))
693 .unwrap();
694
695 memory
696 .insert(
697 Relocatable::from((1, 2)),
698 &MaybeRelocatable::from(crate::Felt252::ONE),
699 )
700 .unwrap();
701
702 check_memory![memory, ((1, 1), (1, 0)), ((1, 2), 1)];
703 }
704
705 #[test]
706 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
707 fn check_memory_address_macro_test() {
708 let mut memory = Memory::new();
709 for _ in 0..2 {
710 memory.data.push(Vec::new());
711 }
712 memory
713 .insert(Relocatable::from((1, 1)), &MaybeRelocatable::from((1, 0)))
714 .unwrap();
715
716 memory
717 .insert(
718 Relocatable::from((1, 2)),
719 &MaybeRelocatable::from(crate::Felt252::ONE),
720 )
721 .unwrap();
722
723 check_memory_address!(memory, (1, 1), (1, 0));
724 check_memory_address!(memory, (1, 2), 1);
725 }
726
727 #[test]
728 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
729 fn create_run_context() {
730 let mut vm = vm!();
731 run_context!(vm, 2, 6, 10);
732
733 assert_eq!(vm.run_context.pc, Relocatable::from((0, 2)));
734 assert_eq!(vm.run_context.ap, 6);
735 assert_eq!(vm.run_context.fp, 10);
736 }
737
738 #[test]
739 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
740 fn assert_trace() {
741 let trace = vec![
742 TraceEntry {
743 pc: (0, 2).into(),
744 ap: 7,
745 fp: 1,
746 },
747 TraceEntry {
748 pc: (0, 5).into(),
749 ap: 1,
750 fp: 0,
751 },
752 TraceEntry {
753 pc: (0, 9).into(),
754 ap: 5,
755 fp: 7,
756 },
757 ];
758 trace_check(
759 &trace,
760 &[
761 ((0, 2).into(), 7, 1),
762 ((0, 5).into(), 1, 0),
763 ((0, 9).into(), 5, 7),
764 ],
765 );
766 }
767
768 #[test]
769 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
770 fn test_non_continuous_ids_data() {
771 let ids_data_macro = non_continuous_ids_data![("a", -2), ("", -6)];
772 let ids_data_verbose = HashMap::from([
773 ("a".to_string(), HintReference::new_simple(-2)),
774 ("".to_string(), HintReference::new_simple(-6)),
775 ]);
776 assert_eq!(ids_data_macro, ids_data_verbose);
777 }
778
779 #[test]
780 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
781 fn run_hint_alloc() {
782 let hint_code = "memory[ap] = segments.add()";
783 let mut vm = vm!();
784 add_segments!(vm, 1);
785 assert_matches::assert_matches!(run_hint!(vm, HashMap::new(), hint_code), Ok(()));
786 assert_eq!(vm.segments.memory.data.len(), 2);
788 }
789
790 #[test]
791 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
792 fn check_scope_test_pass() {
793 let mut exec_scopes = ExecutionScopes::new();
794 exec_scopes.assign_or_update_variable("a", any_box!(String::from("Hello")));
795 exec_scopes.assign_or_update_variable(
796 "",
797 any_box!(Rc::new(RefCell::new(HashMap::<usize, Vec<usize>>::new()))),
798 );
799 exec_scopes.assign_or_update_variable("c", any_box!(vec![1, 2, 3, 4]));
800 check_scope!(
801 &exec_scopes,
802 [
803 ("a", String::from("Hello")),
804 (
805 "",
806 Rc::new(RefCell::new(HashMap::<usize, Vec<usize>>::new()))
807 ),
808 ("c", vec![1, 2, 3, 4])
809 ]
810 );
811 }
812
813 #[test]
814 #[should_panic]
815 fn check_scope_test_fail() {
816 let mut exec_scopes = ExecutionScopes::new();
817 exec_scopes.assign_or_update_variable("a", any_box!(String::from("Hello")));
818 exec_scopes.assign_or_update_variable(
819 "",
820 any_box!(Rc::new(RefCell::new(HashMap::<usize, Vec<usize>>::new()))),
821 );
822 exec_scopes.assign_or_update_variable("c", any_box!(vec![1, 2, 3, 4]));
823 check_scope!(
824 &exec_scopes,
825 [
826 ("a", String::from("Hello")),
827 (
828 "",
829 Rc::new(RefCell::new(HashMap::<usize, Vec<usize>>::new()))
830 ),
831 ("c", vec![1, 2, 3, 5])
832 ]
833 );
834 }
835
836 #[test]
837 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
838 fn scope_macro_test() {
839 let scope_from_macro = scope![("a", crate::Felt252::ONE)];
840 let mut scope_verbose = ExecutionScopes::new();
841 scope_verbose.assign_or_update_variable("a", any_box!(crate::Felt252::ONE));
842 assert_eq!(scope_from_macro.data.len(), scope_verbose.data.len());
843 assert_eq!(scope_from_macro.data[0].len(), scope_verbose.data[0].len());
844 assert_eq!(
845 scope_from_macro.data[0].get("a").unwrap().downcast_ref(),
846 Some(&crate::Felt252::ONE)
847 );
848 }
849
850 #[test]
851 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
852 fn check_dictionary_pass() {
853 let mut tracker = DictTracker::new_empty(relocatable!(2, 0));
854 tracker.insert_value(
855 &MaybeRelocatable::from(crate::Felt252::from(5)),
856 &MaybeRelocatable::from(crate::Felt252::from(10)),
857 );
858 let mut dict_manager = DictManager::new();
859 dict_manager.trackers.insert(2, tracker);
860 let mut exec_scopes = ExecutionScopes::new();
861 exec_scopes.assign_or_update_variable(
862 "dict_manager",
863 any_box!(Rc::new(RefCell::new(dict_manager))),
864 );
865 check_dictionary!(&exec_scopes, 2, (5, 10));
866 }
867
868 #[test]
869 #[should_panic]
870 fn check_dictionary_fail() {
871 let mut tracker = DictTracker::new_empty(relocatable!(2, 0));
872 tracker.insert_value(&MaybeRelocatable::from(5), &MaybeRelocatable::from(10));
873 let mut dict_manager = DictManager::new();
874 dict_manager.trackers.insert(2, tracker);
875 let mut exec_scopes = ExecutionScopes::new();
876 exec_scopes.assign_or_update_variable(
877 "dict_manager",
878 any_box!(Rc::new(RefCell::new(dict_manager))),
879 );
880 check_dictionary!(&exec_scopes, 2, (5, 11));
881 }
882
883 #[test]
884 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
885 fn check_dict_ptr_pass() {
886 let tracker = DictTracker::new_empty(relocatable!(2, 0));
887 let mut dict_manager = DictManager::new();
888 dict_manager.trackers.insert(2, tracker);
889 let mut exec_scopes = ExecutionScopes::new();
890 exec_scopes.assign_or_update_variable(
891 "dict_manager",
892 any_box!(Rc::new(RefCell::new(dict_manager))),
893 );
894 check_dict_ptr!(&exec_scopes, 2, (2, 0));
895 }
896
897 #[test]
898 #[should_panic]
899 fn check_dict_ptr_fail() {
900 let tracker = DictTracker::new_empty(relocatable!(2, 0));
901 let mut dict_manager = DictManager::new();
902 dict_manager.trackers.insert(2, tracker);
903 let mut exec_scopes = ExecutionScopes::new();
904 exec_scopes.assign_or_update_variable(
905 "dict_manager",
906 any_box!(Rc::new(RefCell::new(dict_manager))),
907 );
908 check_dict_ptr!(&exec_scopes, 2, (3, 0));
909 }
910
911 #[test]
912 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
913 fn dict_manager_macro() {
914 let tracker = DictTracker::new_empty(relocatable!(2, 0));
915 let mut dict_manager = DictManager::new();
916 dict_manager.trackers.insert(2, tracker);
917 let mut exec_scopes = ExecutionScopes::new();
918 dict_manager!(exec_scopes, 2);
919 assert_matches::assert_matches!(
920 exec_scopes.get_dict_manager(),
921 Ok(x) if x == Rc::new(RefCell::new(dict_manager))
922 );
923 }
924
925 #[test]
926 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
927 fn dict_manager_default_macro() {
928 let tracker = DictTracker::new_default_dict(
929 relocatable!(2, 0),
930 &MaybeRelocatable::from(crate::Felt252::from(17)),
931 None,
932 );
933 let mut dict_manager = DictManager::new();
934 dict_manager.trackers.insert(2, tracker);
935 let mut exec_scopes = ExecutionScopes::new();
936 dict_manager_default!(exec_scopes, 2, 17);
937 assert_matches::assert_matches!(
938 exec_scopes.get_dict_manager(),
939 Ok(x) if x == Rc::new(RefCell::new(dict_manager))
940 );
941 }
942
943 #[test]
944 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
945 fn data_vec_test() {
946 let data = vec_data!((1), ((2, 2)), (("49128305", 10)), (("3b6f00a9", 16)));
947 assert_eq!(data[0], mayberelocatable!(1));
948 assert_eq!(data[1], mayberelocatable!(2, 2));
949 assert_eq!(data[2], mayberelocatable!(49128305));
950 assert_eq!(data[3], mayberelocatable!(997130409));
951 }
952 #[test]
953 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
954 fn from_relocatable_to_indexes_test() {
955 let reloc_1 = relocatable!(1, 5);
956 let reloc_2 = relocatable!(0, 5);
957 let reloc_3 = relocatable!(-1, 5);
958 assert_eq!((1, 5), from_relocatable_to_indexes(reloc_1));
959 assert_eq!((0, 5), from_relocatable_to_indexes(reloc_2));
960 assert_eq!((0, 5), from_relocatable_to_indexes(reloc_3));
961 }
962
963 #[test]
964 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
965 fn program_macro() {
966 let shared_data = SharedProgramData {
967 data: Vec::new(),
968 hints_collection: HintsCollection::new(&BTreeMap::new(), 0).unwrap(),
969 main: None,
970 start: None,
971 end: None,
972 error_message_attributes: Vec::new(),
973 instruction_locations: None,
974 identifiers: HashMap::new(),
975 reference_manager: Program::get_reference_list(&ReferenceManager {
976 references: Vec::new(),
977 }),
978 };
979 let program = Program {
980 shared_program_data: Arc::new(shared_data),
981 constants: HashMap::new(),
982 builtins: Vec::new(),
983 };
984 assert_eq!(program, program!())
985 }
986
987 #[test]
988 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
989 fn program_macro_with_builtin() {
990 let shared_data = SharedProgramData {
991 data: Vec::new(),
992 hints_collection: HintsCollection::new(&BTreeMap::new(), 0).unwrap(),
993 main: None,
994 start: None,
995 end: None,
996 error_message_attributes: Vec::new(),
997 instruction_locations: None,
998 identifiers: HashMap::new(),
999 reference_manager: Program::get_reference_list(&ReferenceManager {
1000 references: Vec::new(),
1001 }),
1002 };
1003 let program = Program {
1004 shared_program_data: Arc::new(shared_data),
1005 constants: HashMap::new(),
1006 builtins: vec![BuiltinName::range_check],
1007 };
1008
1009 assert_eq!(program, program![BuiltinName::range_check])
1010 }
1011
1012 #[test]
1013 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1014 fn program_macro_custom_definition() {
1015 let shared_data = SharedProgramData {
1016 data: Vec::new(),
1017 hints_collection: HintsCollection::new(&BTreeMap::new(), 0).unwrap(),
1018 main: Some(2),
1019 start: None,
1020 end: None,
1021 error_message_attributes: Vec::new(),
1022 instruction_locations: None,
1023 identifiers: HashMap::new(),
1024 reference_manager: Program::get_reference_list(&ReferenceManager {
1025 references: Vec::new(),
1026 }),
1027 };
1028 let program = Program {
1029 shared_program_data: Arc::new(shared_data),
1030 constants: HashMap::new(),
1031 builtins: vec![BuiltinName::range_check],
1032 };
1033
1034 assert_eq!(
1035 program,
1036 program!(builtins = vec![BuiltinName::range_check], main = Some(2),)
1037 )
1038 }
1039}