1use super::*;
18
19use leo_ast::{
20 ArrayType,
21 AssertVariant,
22 AsyncExpression,
23 BinaryOperation,
24 Block,
25 CoreConstant,
26 CoreFunction,
27 DefinitionPlace,
28 Expression,
29 Function,
30 Location,
31 NodeID,
32 Statement,
33 StructVariableInitializer,
34 Type,
35 UnaryOperation,
36 Variant,
37 interpreter_value::{
38 AsyncExecution,
39 CoreFunctionHelper,
40 Value,
41 evaluate_binary,
42 evaluate_core_function,
43 evaluate_unary,
44 literal_to_value,
45 },
46};
47use leo_errors::{InterpreterHalt, Result};
48use leo_span::{Span, Symbol, sym};
49
50use snarkvm::prelude::{
51 Address,
52 CanaryV0,
53 Closure as SvmClosure,
54 Finalize as SvmFinalize,
55 Function as SvmFunctionParam,
56 MainnetV0,
57 Network,
58 PrivateKey,
59 ProgramID,
60 TestnetV0,
61};
62
63use indexmap::IndexMap;
64use itertools::Itertools;
65use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
66use std::{cmp::Ordering, collections::HashMap, mem, str::FromStr as _};
67
68pub type Closure = SvmClosure<TestnetV0>;
69pub type Finalize = SvmFinalize<TestnetV0>;
70pub type SvmFunction = SvmFunctionParam<TestnetV0>;
71
72#[derive(Clone, Debug)]
74pub struct FunctionContext {
75 path: Vec<Symbol>,
76 program: Symbol,
77 pub caller: Value,
78 names: HashMap<Vec<Symbol>, Value>,
79 accumulated_futures: Vec<AsyncExecution>,
80 is_async: bool,
81}
82
83#[derive(Clone, Debug, Default)]
85pub struct ContextStack {
86 contexts: Vec<FunctionContext>,
87 current_len: usize,
88}
89
90impl ContextStack {
91 fn len(&self) -> usize {
92 self.current_len
93 }
94
95 fn push(
96 &mut self,
97 path: &[Symbol],
98 program: Symbol,
99 caller: Value,
100 is_async: bool,
101 names: HashMap<Vec<Symbol>, Value>, ) {
103 if self.current_len == self.contexts.len() {
104 self.contexts.push(FunctionContext {
105 path: path.to_vec(),
106 program,
107 caller: caller.clone(),
108 names: HashMap::new(),
109 accumulated_futures: Default::default(),
110 is_async,
111 });
112 }
113
114 self.contexts[self.current_len].path = path.to_vec();
115 self.contexts[self.current_len].program = program;
116 self.contexts[self.current_len].caller = caller;
117 self.contexts[self.current_len].names = names;
118 self.contexts[self.current_len].accumulated_futures.clear();
119 self.contexts[self.current_len].is_async = is_async;
120 self.current_len += 1;
121 }
122
123 pub fn pop(&mut self) {
124 assert!(self.len() > 0);
128 self.current_len -= 1;
129 self.contexts[self.current_len].names.clear();
130 }
131
132 fn get_future(&mut self) -> Vec<AsyncExecution> {
137 assert!(self.len() > 0);
138 mem::take(&mut self.contexts[self.current_len - 1].accumulated_futures)
139 }
140
141 fn set(&mut self, path: &[Symbol], value: Value) {
142 assert!(self.current_len > 0);
143 self.last_mut().unwrap().names.insert(path.to_vec(), value);
144 }
145
146 pub fn add_future(&mut self, future: Vec<AsyncExecution>) {
147 assert!(self.current_len > 0);
148 self.contexts[self.current_len - 1].accumulated_futures.extend(future);
149 }
150
151 fn is_async(&self) -> bool {
153 assert!(self.current_len > 0);
154 self.last().unwrap().is_async
155 }
156
157 pub fn current_program(&self) -> Option<Symbol> {
158 self.last().map(|c| c.program)
159 }
160
161 pub fn last(&self) -> Option<&FunctionContext> {
162 self.len().checked_sub(1).and_then(|i| self.contexts.get(i))
163 }
164
165 fn last_mut(&mut self) -> Option<&mut FunctionContext> {
166 self.len().checked_sub(1).and_then(|i| self.contexts.get_mut(i))
167 }
168}
169
170#[derive(Clone, Debug)]
171pub enum AleoContext {
172 Closure(Closure),
173 Function(SvmFunction),
174 Finalize(Finalize),
175}
176
177#[derive(Clone, Debug)]
179pub enum Element {
180 Statement(Statement),
182
183 Expression(Expression, Option<Type>),
186
187 Block {
196 block: Block,
197 function_body: bool,
198 },
199
200 AleoExecution {
201 context: Box<AleoContext>,
202 registers: IndexMap<u64, Value>,
203 instruction_index: usize,
204 },
205
206 DelayedCall(Location),
207 DelayedAsyncBlock {
208 program: Symbol,
209 block: NodeID,
210 names: HashMap<Vec<Symbol>, Value>,
211 },
212}
213
214impl Element {
215 pub fn span(&self) -> Span {
216 use Element::*;
217 match self {
218 Statement(statement) => statement.span(),
219 Expression(expression, _) => expression.span(),
220 Block { block, .. } => block.span(),
221 AleoExecution { .. } | DelayedCall(..) | DelayedAsyncBlock { .. } => Default::default(),
222 }
223 }
224}
225
226#[derive(Clone, Debug)]
229pub struct Frame {
230 pub step: usize,
231 pub element: Element,
232 pub user_initiated: bool,
233}
234
235#[derive(Clone, Debug)]
236pub enum FunctionVariant {
237 Leo(Function),
238 AleoClosure(Closure),
239 AleoFunction(SvmFunction),
240}
241
242#[derive(Clone, Debug)]
244pub struct Cursor {
245 pub frames: Vec<Frame>,
247
248 pub values: Vec<Value>,
252
253 pub functions: HashMap<Location, FunctionVariant>,
255
256 pub async_blocks: HashMap<NodeID, Block>,
258
259 pub globals: HashMap<Location, Value>,
261
262 pub user_values: HashMap<Vec<Symbol>, Value>,
263
264 pub mappings: HashMap<Location, HashMap<Value, Value>>,
265
266 pub structs: HashMap<Vec<Symbol>, IndexMap<Symbol, Type>>,
268
269 pub records: HashMap<(Symbol, Vec<Symbol>), IndexMap<Symbol, Type>>,
272
273 pub futures: Vec<AsyncExecution>,
274
275 pub contexts: ContextStack,
276
277 pub signer: Value,
279
280 pub rng: ChaCha20Rng,
281
282 pub block_height: u32,
283
284 pub really_async: bool,
285
286 pub program: Option<Symbol>,
287
288 pub network: NetworkName,
289
290 pub private_key: String,
291}
292
293impl CoreFunctionHelper for Cursor {
294 fn pop_value_impl(&mut self) -> Option<Value> {
295 self.values.pop()
296 }
297
298 fn set_block_height(&mut self, height: u32) {
299 self.block_height = height;
300 }
301
302 fn set_signer(&mut self, private_key: String) -> Result<()> {
303 let address = match PrivateKey::<TestnetV0>::from_str(&private_key.replace("\"", ""))
305 .and_then(|pk| Address::<TestnetV0>::try_from(&pk))
306 {
307 Ok(address) => address.into(),
308 Err(_) => halt_no_span!("Invalid private key provided for signer."),
309 };
310 self.private_key = private_key;
312 self.signer = address;
314
315 Ok(())
316 }
317
318 fn lookup_mapping(&self, program: Option<Symbol>, name: Symbol) -> Option<&HashMap<Value, Value>> {
319 Cursor::lookup_mapping(self, program, name)
320 }
321
322 fn lookup_mapping_mut(&mut self, program: Option<Symbol>, name: Symbol) -> Option<&mut HashMap<Value, Value>> {
323 Cursor::lookup_mapping_mut(self, program, name)
324 }
325
326 fn rng(&mut self) -> Option<&mut ChaCha20Rng> {
327 Some(&mut self.rng)
328 }
329}
330
331impl Cursor {
332 pub fn new(really_async: bool, private_key: String, block_height: u32, network: NetworkName) -> Self {
334 let mut cursor = Cursor {
335 frames: Default::default(),
336 values: Default::default(),
337 functions: Default::default(),
338 async_blocks: Default::default(),
339 globals: Default::default(),
340 user_values: Default::default(),
341 mappings: Default::default(),
342 structs: Default::default(),
343 records: Default::default(),
344 contexts: Default::default(),
345 futures: Default::default(),
346 rng: ChaCha20Rng::from_entropy(),
347 signer: Default::default(),
348 block_height,
349 really_async,
350 program: None,
351 network,
352 private_key: Default::default(),
353 };
354
355 cursor.set_signer(private_key).expect("The default private key should be valid.");
357
358 cursor
359 }
360
361 pub fn clear(&mut self) {
363 self.frames.clear();
364 self.values.clear();
365 self.mappings.iter_mut().for_each(|(_, map)| map.clear());
366 self.contexts = Default::default();
367 self.futures.clear();
368 }
369
370 fn set_place(
371 new_value: Value,
372 this_value: &mut Value,
373 places: &mut dyn Iterator<Item = &Expression>,
374 indices: &mut dyn Iterator<Item = Value>,
375 ) -> Result<()> {
376 match places.next() {
377 None => *this_value = new_value,
378 Some(Expression::ArrayAccess(_access)) => {
379 let index = indices.next().unwrap();
380 let index = index.as_u32().unwrap() as usize;
381
382 let mut index_value = this_value.array_index(index).expect("Type");
383 Self::set_place(new_value, &mut index_value, places, indices)?;
384
385 if this_value.array_index_set(index, index_value).is_none() {
386 halt_no_span!("Invalid array assignment");
387 }
388 }
389 Some(Expression::TupleAccess(access)) => {
390 let index = access.index.value();
391 let mut index_value = this_value.tuple_index(index).expect("Type");
392 Self::set_place(new_value, &mut index_value, places, indices)?;
393 if this_value.tuple_index_set(index, index_value).is_none() {
394 halt_no_span!("Invalid tuple assignment");
395 }
396 }
397 Some(Expression::MemberAccess(access)) => {
398 let mut access_value = this_value.member_access(access.name.name).expect("Type");
399 Self::set_place(new_value, &mut access_value, places, indices)?;
400 if this_value.member_set(access.name.name, access_value).is_none() {
401 halt_no_span!("Invalid member set");
402 }
403 }
404 Some(Expression::Path(_path)) => {
405 Self::set_place(new_value, this_value, places, indices)?;
406 }
407 Some(place) => halt_no_span!("Invalid place for assignment: {place}"),
408 }
409
410 Ok(())
411 }
412
413 pub fn assign(&mut self, value: Value, place: &Expression, indices: &mut dyn Iterator<Item = Value>) -> Result<()> {
414 let mut places = vec![place];
415 let indices: Vec<Value> = indices.collect();
416
417 let path: &Path;
418
419 loop {
420 match places.last().unwrap() {
421 Expression::ArrayAccess(access) => places.push(&access.array),
422 Expression::TupleAccess(access) => places.push(&access.tuple),
423 Expression::MemberAccess(access) => places.push(&access.inner),
424 Expression::Path(path_) => {
425 path = path_;
426 break;
427 }
428 place @ (Expression::AssociatedConstant(..)
429 | Expression::AssociatedFunction(..)
430 | Expression::Async(..)
431 | Expression::Array(..)
432 | Expression::Binary(..)
433 | Expression::Call(..)
434 | Expression::Cast(..)
435 | Expression::Err(..)
436 | Expression::Literal(..)
437 | Expression::Locator(..)
438 | Expression::Repeat(..)
439 | Expression::Struct(..)
440 | Expression::Ternary(..)
441 | Expression::Tuple(..)
442 | Expression::Unary(..)
443 | Expression::Unit(..)) => halt_no_span!("Invalid place for assignment: {place}"),
444 }
445 }
446
447 let full_name = self.to_absolute_path(&path.as_symbols());
448
449 let mut leo_value = self.lookup(&full_name).unwrap_or(Value::make_unit());
450
451 let mut temp_value = leo_value.clone();
453 let mut indices_iter = indices.iter();
454
455 for place in places.iter().rev() {
456 match place {
457 Expression::ArrayAccess(_access) => {
458 let next_index = indices_iter.next().unwrap();
459 temp_value = temp_value.array_index(next_index.as_u32().unwrap() as usize).unwrap();
460 }
461 Expression::TupleAccess(access) => {
462 temp_value = temp_value.tuple_index(access.index.value()).unwrap();
463 }
464 Expression::MemberAccess(access) => {
465 temp_value = temp_value.member_access(access.name.name).unwrap();
466 }
467 Expression::Path(_path) =>
468 {}
470 _ => panic!("Can't happen."),
471 }
472 }
473
474 let ty = temp_value.get_numeric_type();
475 let value = value.resolve_if_unsuffixed(&ty, place.span())?;
476
477 Self::set_place(value, &mut leo_value, &mut places.into_iter().rev(), &mut indices.into_iter())?;
478 self.set_variable(&full_name, leo_value);
479 Ok(())
480 }
481
482 pub fn set_program(&mut self, program: &str) {
483 let p = program.strip_suffix(".aleo").unwrap_or(program);
484 self.program = Some(Symbol::intern(p));
485 }
486
487 pub fn current_program(&self) -> Option<Symbol> {
488 self.contexts.current_program().or(self.program)
489 }
490
491 pub fn increment_step(&mut self) {
492 let Some(Frame { step, .. }) = self.frames.last_mut() else {
493 panic!("frame expected");
494 };
495 *step += 1;
496 }
497
498 fn new_caller(&self) -> Value {
499 if let Some(function_context) = self.contexts.last() {
500 let program_id = ProgramID::<TestnetV0>::from_str(&format!("{}.aleo", function_context.program))
501 .expect("should be able to create ProgramID");
502 program_id.to_address().expect("should be able to convert to address").into()
503 } else {
504 self.signer.clone()
505 }
506 }
507
508 fn pop_value(&mut self) -> Result<Value> {
509 match self.values.pop() {
510 Some(v) => Ok(v),
511 None => {
512 Err(InterpreterHalt::new("value expected - this may be a bug in the Leo interpreter".to_string())
513 .into())
514 }
515 }
516 }
517
518 fn lookup(&self, name: &[Symbol]) -> Option<Value> {
519 if let Some(context) = self.contexts.last() {
520 let option_value =
521 context.names.get(name).or_else(|| self.globals.get(&Location::new(context.program, name.to_vec())));
522 if option_value.is_some() {
523 return option_value.cloned();
524 }
525 };
526
527 self.user_values.get(name).cloned()
528 }
529
530 pub fn lookup_mapping(&self, program: Option<Symbol>, name: Symbol) -> Option<&HashMap<Value, Value>> {
531 let Some(program) = program.or_else(|| self.current_program()) else {
532 panic!("no program for mapping lookup");
533 };
534 self.mappings.get(&Location::new(program, vec![name]))
536 }
537
538 pub fn lookup_mapping_mut(&mut self, program: Option<Symbol>, name: Symbol) -> Option<&mut HashMap<Value, Value>> {
539 let Some(program) = program.or_else(|| self.current_program()) else {
540 panic!("no program for mapping lookup");
541 };
542 self.mappings.get_mut(&Location::new(program, vec![name]))
544 }
545
546 fn lookup_function(&self, program: Symbol, name: &[Symbol]) -> Option<FunctionVariant> {
547 self.functions.get(&Location::new(program, name.to_vec())).cloned()
548 }
549
550 fn set_variable(&mut self, path: &[Symbol], value: Value) {
551 if self.contexts.len() > 0 {
552 self.contexts.set(path, value);
553 } else {
554 self.user_values.insert(path.to_vec(), value);
555 }
556 }
557
558 pub fn whole_step(&mut self) -> Result<StepResult> {
563 let frames_len = self.frames.len();
564 let initial_result = self.step()?;
565 if !initial_result.finished {
566 while self.frames.len() > frames_len {
567 self.step()?;
568 }
569 }
570 Ok(initial_result)
571 }
572
573 pub fn over(&mut self) -> Result<StepResult> {
577 let frames_len = self.frames.len();
578 loop {
579 match self.frames.len().cmp(&frames_len) {
580 Ordering::Greater => {
581 self.step()?;
582 }
583 Ordering::Equal => {
584 let result = self.step()?;
585 if result.finished {
586 return Ok(result);
587 }
588 }
589 Ordering::Less => {
590 return Ok(StepResult { finished: true, value: None });
594 }
595 }
596 }
597 }
598
599 pub fn step_block(&mut self, block: &Block, function_body: bool, step: usize) -> bool {
600 let len = self.frames.len();
601
602 let done = match step {
603 0 => {
604 for statement in block.statements.iter().rev() {
605 self.frames.push(Frame {
606 element: Element::Statement(statement.clone()),
607 step: 0,
608 user_initiated: false,
609 });
610 }
611 false
612 }
613 1 if function_body => {
614 self.values.push(Value::make_unit());
615 self.contexts.pop();
616 true
617 }
618 1 => true,
619 _ => unreachable!(),
620 };
621
622 if done {
623 assert_eq!(len, self.frames.len());
624 self.frames.pop();
625 } else {
626 self.frames[len - 1].step += 1;
627 }
628
629 done
630 }
631
632 fn to_absolute_path(&self, name: &[Symbol]) -> Vec<Symbol> {
635 if let Some(context) = self.contexts.last() {
636 let mut full_name = context.path.clone();
637 full_name.pop(); full_name.extend(name);
639 full_name
640 } else {
641 name.to_vec()
642 }
643 }
644
645 fn step_statement(&mut self, statement: &Statement, step: usize) -> Result<bool> {
646 let len = self.frames.len();
647 let mut push = |expression: &Expression, ty: &Option<Type>| {
649 self.frames.push(Frame {
650 element: Element::Expression(expression.clone(), ty.clone()),
651 step: 0,
652 user_initiated: false,
653 })
654 };
655
656 let done = match statement {
657 Statement::Assert(assert) if step == 0 => {
658 match &assert.variant {
659 AssertVariant::Assert(x) => push(x, &Some(Type::Boolean)),
660 AssertVariant::AssertEq(x, y) | AssertVariant::AssertNeq(x, y) => {
661 push(y, &None);
662 push(x, &None);
663 }
664 };
665 false
666 }
667 Statement::Assert(assert) if step == 1 => {
668 match &assert.variant {
669 AssertVariant::Assert(..) => {
670 let value = self.pop_value()?;
671 match value.try_into() {
672 Ok(true) => {}
673 Ok(false) => halt!(assert.span(), "assert failure"),
674 _ => tc_fail!(),
675 }
676 }
677 AssertVariant::AssertEq(..) => {
678 let x = self.pop_value()?;
679 let y = self.pop_value()?;
680 if !x.eq(&y)? {
681 halt!(assert.span(), "assert failure: {} != {}", y, x);
682 }
683 }
684
685 AssertVariant::AssertNeq(..) => {
686 let x = self.pop_value()?;
687 let y = self.pop_value()?;
688 if x.eq(&y)? {
689 halt!(assert.span(), "assert failure: {} == {}", y, x);
690 }
691 }
692 };
693 true
694 }
695 Statement::Assign(assign) if step == 0 => {
696 push(&assign.value, &None);
698 let mut place = &assign.place;
699 loop {
700 match place {
701 leo_ast::Expression::ArrayAccess(access) => {
702 push(&access.index, &None);
703 place = &access.array;
704 }
705 leo_ast::Expression::Path(..) => break,
706 leo_ast::Expression::MemberAccess(access) => {
707 place = &access.inner;
708 }
709 leo_ast::Expression::TupleAccess(access) => {
710 place = &access.tuple;
711 }
712 _ => panic!("Can't happen"),
713 }
714 }
715 false
716 }
717 Statement::Assign(assign) if step == 1 => {
718 let mut index_count = 0;
720 let mut place = &assign.place;
721 loop {
722 match place {
723 leo_ast::Expression::ArrayAccess(access) => {
724 index_count += 1;
725 place = &access.array;
726 }
727 leo_ast::Expression::Path(..) => break,
728 leo_ast::Expression::MemberAccess(access) => {
729 place = &access.inner;
730 }
731 leo_ast::Expression::TupleAccess(access) => {
732 place = &access.tuple;
733 }
734 _ => panic!("Can't happen"),
735 }
736 }
737
738 let value = self.pop_value()?;
740 let len = self.values.len();
741
742 let indices: Vec<Value> = self.values.drain(len - index_count..len).collect();
744
745 self.assign(value, &assign.place, &mut indices.into_iter())?;
746
747 true
748 }
749 Statement::Block(block) => return Ok(self.step_block(block, false, step)),
750 Statement::Conditional(conditional) if step == 0 => {
751 push(&conditional.condition, &Some(Type::Boolean));
752 false
753 }
754 Statement::Conditional(conditional) if step == 1 => {
755 match self.pop_value()?.try_into() {
756 Ok(true) => self.frames.push(Frame {
757 step: 0,
758 element: Element::Block { block: conditional.then.clone(), function_body: false },
759 user_initiated: false,
760 }),
761 Ok(false) => {
762 if let Some(otherwise) = conditional.otherwise.as_ref() {
763 self.frames.push(Frame {
764 step: 0,
765 element: Element::Statement(Statement::clone(otherwise)),
766 user_initiated: false,
767 })
768 }
769 }
770 _ => tc_fail!(),
771 };
772 false
773 }
774 Statement::Conditional(_) if step == 2 => true,
775 Statement::Const(const_) if step == 0 => {
776 push(&const_.value, &Some(const_.type_.clone()));
777 false
778 }
779 Statement::Const(const_) if step == 1 => {
780 let value = self.pop_value()?;
781 self.set_variable(&self.to_absolute_path(&[const_.place.name]), value);
782 true
783 }
784 Statement::Definition(definition) if step == 0 => {
785 push(&definition.value, &definition.type_);
786 false
787 }
788 Statement::Definition(definition) if step == 1 => {
789 let value = self.pop_value()?;
790 match &definition.place {
791 DefinitionPlace::Single(id) => self.set_variable(&self.to_absolute_path(&[id.name]), value),
792 DefinitionPlace::Multiple(ids) => {
793 for (i, id) in ids.iter().enumerate() {
794 self.set_variable(
795 &self.to_absolute_path(&[id.name]),
796 value.tuple_index(i).expect("Place for definition should be a tuple."),
797 );
798 }
799 }
800 }
801 true
802 }
803 Statement::Expression(expression) if step == 0 => {
804 push(&expression.expression, &None);
805 false
806 }
807 Statement::Expression(_) if step == 1 => {
808 self.values.pop();
809 true
810 }
811 Statement::Iteration(iteration) if step == 0 => {
812 assert!(!iteration.inclusive);
813 push(&iteration.stop, &iteration.type_.clone());
814 push(&iteration.start, &iteration.type_.clone());
815 false
816 }
817 Statement::Iteration(iteration) => {
818 let stop = self.pop_value()?;
820 let start = self.pop_value()?;
821 if start.eq(&stop)? {
822 true
823 } else {
824 let new_start = start.inc_wrapping().expect_tc(iteration.span())?;
825 self.set_variable(&self.to_absolute_path(&[iteration.variable.name]), start);
826 self.frames.push(Frame {
827 step: 0,
828 element: Element::Block { block: iteration.block.clone(), function_body: false },
829 user_initiated: false,
830 });
831 self.values.push(new_start);
832 self.values.push(stop);
833 false
834 }
835 }
836 Statement::Return(return_) if step == 0 => {
837 let output_type = self.contexts.last().and_then(|ctx| {
840 self.lookup_function(ctx.program, &ctx.path).and_then(|variant| match variant {
841 FunctionVariant::Leo(function) => Some(function.output_type.clone()),
842 _ => None,
843 })
844 });
845
846 self.frames.push(Frame {
847 element: Element::Expression(return_.expression.clone(), output_type),
848 step: 0,
849 user_initiated: false,
850 });
851
852 false
853 }
854 Statement::Return(_) if step == 1 => loop {
855 let last_frame = self.frames.last().expect("a frame should be present");
856 match last_frame.element {
857 Element::Expression(Expression::Call(_), _) | Element::DelayedCall(_) => {
858 if self.contexts.is_async() {
859 self.values.pop();
861 self.values.push(self.contexts.get_future().into());
862 }
863 self.contexts.pop();
864 return Ok(true);
865 }
866 _ => {
867 self.frames.pop();
868 }
869 }
870 },
871 _ => unreachable!(),
872 };
873
874 if done {
875 assert_eq!(len, self.frames.len());
876 self.frames.pop();
877 } else {
878 self.frames[len - 1].step += 1;
879 }
880
881 Ok(done)
882 }
883
884 fn step_expression(&mut self, expression: &Expression, expected_ty: &Option<Type>, step: usize) -> Result<bool> {
885 let len = self.frames.len();
886
887 macro_rules! push {
888 () => {
889 |expression: &Expression, expected_ty: &Option<Type>| {
890 self.frames.push(Frame {
891 element: Element::Expression(expression.clone(), expected_ty.clone()),
892 step: 0,
893 user_initiated: false,
894 })
895 }
896 };
897 }
898
899 if let Some(value) = match expression {
900 Expression::ArrayAccess(array) if step == 0 => {
901 push!()(&array.index, &None);
902 push!()(&array.array, &None);
903 None
904 }
905 Expression::ArrayAccess(array_expr) if step == 1 => {
906 let span = array_expr.span();
907 let index = self.pop_value()?;
908 let array = self.pop_value()?;
909
910 fn to_usize(value: &Value, span: Span) -> Result<usize> {
912 let value = value.resolve_if_unsuffixed(&Some(Type::Integer(leo_ast::IntegerType::U32)), span)?;
913 Ok(value.as_u32().expect_tc(span)? as usize)
914 }
915
916 let index_usize = to_usize(&index, span)?;
917
918 Some(array.array_index(index_usize).expect_tc(span)?)
919 }
920
921 Expression::Async(AsyncExpression { block, .. }) if step == 0 => {
922 self.async_blocks.insert(block.id, block.clone());
924 None
925 }
926 Expression::Async(AsyncExpression { block, .. }) if step == 1 => {
927 if let Some(context) = self.contexts.last() {
930 let async_ex = AsyncExecution::AsyncBlock {
931 containing_function: Location::new(context.program, context.path.clone()),
932 block: block.id,
933 names: context.names.clone().into_iter().collect(),
934 };
935 self.values.push(vec![async_ex].into());
936 }
937 None
938 }
939 Expression::Async(_) if step == 2 => Some(self.pop_value()?),
940
941 Expression::MemberAccess(access) => match &access.inner {
942 Expression::Path(path) if *path.as_symbols() == vec![sym::SelfLower] => match access.name.name {
943 sym::signer => Some(self.signer.clone()),
944 sym::caller => {
945 if let Some(function_context) = self.contexts.last() {
946 Some(function_context.caller.clone())
947 } else {
948 Some(self.signer.clone())
949 }
950 }
951 sym::address => {
952 fn program_to_address<N: Network>(program_id: &str) -> Result<Value> {
954 let Ok(program_id) = ProgramID::<N>::from_str(&format!("{program_id}.aleo")) else {
955 halt_no_span!("Failed to parse program ID");
956 };
957 let Ok(address) = program_id.to_address() else {
958 halt_no_span!("Failed to convert program ID to address");
959 };
960 let Ok(value) = Value::from_str(&address.to_string()) else {
961 halt_no_span!("Failed to convert address to value");
962 };
963 Ok(value)
964 }
965 let Some(program) = self.current_program() else {
967 halt_no_span!("No program context for address");
968 };
969 let result = match self.network {
970 NetworkName::TestnetV0 => program_to_address::<TestnetV0>(&program.to_string())?,
971 NetworkName::MainnetV0 => program_to_address::<MainnetV0>(&program.to_string())?,
972 NetworkName::CanaryV0 => program_to_address::<CanaryV0>(&program.to_string())?,
973 };
974 Some(result)
975 }
976 _ => halt!(access.span(), "unknown member of self"),
977 },
978 Expression::Path(path) if *path.as_symbols() == vec![sym::block] => match access.name.name {
979 sym::height => Some(self.block_height.into()),
980 _ => halt!(access.span(), "unknown member of block"),
981 },
982
983 _ if step == 0 => {
985 push!()(&access.inner, &None);
986 None
987 }
988 _ if step == 1 => {
989 let struct_ = self.values.pop().expect_tc(access.span())?;
990 let value = struct_.member_access(access.name.name).expect_tc(access.span())?;
991 Some(value)
992 }
993 _ => unreachable!("we've actually covered all possible patterns above"),
994 },
995 Expression::TupleAccess(tuple_access) if step == 0 => {
996 push!()(&tuple_access.tuple, &None);
997 None
998 }
999 Expression::TupleAccess(tuple_access) if step == 1 => {
1000 let Some(value) = self.values.pop() else { tc_fail!() };
1001 if let Some(result) = value.tuple_index(tuple_access.index.value()) {
1002 Some(result)
1003 } else {
1004 halt!(tuple_access.span(), "Tuple index out of range");
1005 }
1006 }
1007 Expression::Array(array) if step == 0 => {
1008 let element_type = expected_ty.clone().and_then(|ty| match ty {
1009 Type::Array(ArrayType { element_type, .. }) => Some(*element_type),
1010 _ => None,
1011 });
1012
1013 array.elements.iter().rev().for_each(|array| push!()(array, &element_type));
1014 None
1015 }
1016 Expression::Array(array) if step == 1 => {
1017 let len = self.values.len();
1018 let array_values = self.values.drain(len - array.elements.len()..);
1019 Some(Value::make_array(array_values))
1020 }
1021 Expression::Repeat(repeat) if step == 0 => {
1022 let element_type = expected_ty.clone().and_then(|ty| match ty {
1023 Type::Array(ArrayType { element_type, .. }) => Some(*element_type),
1024 _ => None,
1025 });
1026
1027 push!()(&repeat.count, &None);
1028 push!()(&repeat.expr, &element_type);
1029 None
1030 }
1031 Expression::Repeat(repeat) if step == 1 => {
1032 let count = self.pop_value()?;
1033 let expr = self.pop_value()?;
1034 let count_resolved = count
1035 .resolve_if_unsuffixed(&Some(Type::Integer(leo_ast::IntegerType::U32)), repeat.count.span())?;
1036 Some(Value::make_array(std::iter::repeat_n(
1037 expr,
1038 count_resolved.as_u32().expect_tc(repeat.span())? as usize,
1039 )))
1040 }
1041 Expression::AssociatedConstant(constant) if step == 0 => {
1042 let Type::Identifier(type_ident) = constant.ty else {
1043 tc_fail!();
1044 };
1045 let Some(core_constant) = CoreConstant::from_symbols(type_ident.name, constant.name.name) else {
1046 halt!(constant.span(), "Unknown constant {constant}");
1047 };
1048 match core_constant {
1049 CoreConstant::GroupGenerator => Some(Value::generator()),
1050 }
1051 }
1052 Expression::AssociatedFunction(function) if step == 0 => {
1053 let Some(core_function) = CoreFunction::try_from(function).ok() else {
1054 halt!(function.span(), "Unkown core function {function}");
1055 };
1056
1057 match core_function {
1060 CoreFunction::Get | CoreFunction::MappingRemove | CoreFunction::MappingContains => {
1061 push!()(&function.arguments[1], &None);
1062 }
1063 CoreFunction::MappingGetOrUse | CoreFunction::Set => {
1064 push!()(&function.arguments[2], &None);
1065 push!()(&function.arguments[1], &None);
1066 }
1067 CoreFunction::CheatCodePrintMapping => {
1068 }
1070 _ => function.arguments.iter().rev().for_each(|arg| push!()(arg, &None)),
1071 }
1072 None
1073 }
1074 Expression::AssociatedFunction(function) if step == 1 => {
1075 let Some(core_function) = CoreFunction::try_from(function).ok() else {
1076 halt!(function.span(), "Unkown core function {function}");
1077 };
1078
1079 let span = function.span();
1080
1081 if let CoreFunction::FutureAwait = core_function {
1082 let value = self.pop_value()?;
1083 let Some(asyncs) = value.as_future() else {
1084 halt!(span, "Invalid value for await: {value}");
1085 };
1086 for async_execution in asyncs {
1087 match async_execution {
1088 AsyncExecution::AsyncFunctionCall { function, arguments } => {
1089 self.values.extend(arguments.iter().cloned());
1090 self.frames.push(Frame {
1091 step: 0,
1092 element: Element::DelayedCall(function.clone()),
1093 user_initiated: false,
1094 });
1095 }
1096 AsyncExecution::AsyncBlock { containing_function, block, names, .. } => {
1097 self.frames.push(Frame {
1098 step: 0,
1099 element: Element::DelayedAsyncBlock {
1100 program: containing_function.program,
1101 block: *block,
1102 names: names.clone().into_iter().collect(),
1105 },
1106 user_initiated: false,
1107 });
1108 }
1109 }
1110 }
1111 None
1113 } else {
1114 let value = evaluate_core_function(self, core_function.clone(), &function.arguments, span)?;
1115 assert!(value.is_some());
1116 value
1117 }
1118 }
1119 Expression::AssociatedFunction(function) if step == 2 => {
1120 let Some(core_function) = CoreFunction::try_from(function).ok() else {
1121 halt!(function.span(), "Unkown core function {function}");
1122 };
1123 assert!(core_function == CoreFunction::FutureAwait);
1124 Some(Value::make_unit())
1125 }
1126 Expression::Binary(binary) if step == 0 => {
1127 use BinaryOperation::*;
1128
1129 let (right_ty, left_ty) = match binary.op {
1131 Mul if matches!(expected_ty, Some(Type::Group)) => (None, None),
1134
1135 And | Or | Nand | Nor | Eq | Neq | Lt | Gt | Lte | Gte => (None, None),
1137
1138 Pow => {
1140 let right_ty = if matches!(expected_ty, Some(Type::Field)) {
1141 Some(Type::Field) } else {
1143 None };
1145 (right_ty, expected_ty.clone()) }
1147
1148 Shl | ShlWrapped | Shr | ShrWrapped | PowWrapped => (None, expected_ty.clone()),
1151
1152 _ => (expected_ty.clone(), expected_ty.clone()),
1154 };
1155
1156 push!()(&binary.right, &right_ty);
1158 push!()(&binary.left, &left_ty);
1159
1160 None
1161 }
1162 Expression::Binary(binary) if step == 1 => {
1163 let rhs = self.pop_value()?;
1164 let lhs = self.pop_value()?;
1165 Some(evaluate_binary(binary.span, binary.op, &lhs, &rhs, expected_ty)?)
1166 }
1167
1168 Expression::Call(call) if step == 0 => {
1169 let (function_program, function_path) = {
1171 let maybe_program = call.program.or_else(|| self.current_program());
1172 if let Some(program) = maybe_program {
1173 (program, self.to_absolute_path(&call.function.as_symbols()))
1174 } else {
1175 halt!(call.span, "No current program");
1176 }
1177 };
1178
1179 let Some(function_variant) = self.lookup_function(function_program, &function_path) else {
1181 halt!(call.span, "unknown function {function_program}.aleo/{}", function_path.iter().format("::"));
1182 };
1183
1184 let (const_param_types, input_types) = match function_variant {
1186 FunctionVariant::Leo(function) => (
1187 function.const_parameters.iter().map(|p| p.type_.clone()).collect::<Vec<_>>(),
1188 function.input.iter().map(|p| p.type_.clone()).collect::<Vec<_>>(),
1189 ),
1190 FunctionVariant::AleoClosure(closure) => {
1191 let function = leo_ast::FunctionStub::from_closure(&closure, function_program);
1192 (vec![], function.input.iter().map(|p| p.type_.clone()).collect::<Vec<_>>())
1193 }
1194 FunctionVariant::AleoFunction(svm_function) => {
1195 let function = leo_ast::FunctionStub::from_function_core(&svm_function, function_program);
1196 (vec![], function.input.iter().map(|p| p.type_.clone()).collect::<Vec<_>>())
1197 }
1198 };
1199
1200 call.arguments
1202 .iter()
1203 .rev()
1204 .zip(input_types.iter().rev())
1205 .for_each(|(arg, ty)| push!()(arg, &Some(ty.clone())));
1206
1207 call.const_arguments
1209 .iter()
1210 .rev()
1211 .zip(const_param_types.iter().rev())
1212 .for_each(|(arg, ty)| push!()(arg, &Some(ty.clone())));
1213
1214 None
1215 }
1216
1217 Expression::Call(call) if step == 1 => {
1218 let len = self.values.len();
1219 let (program, path) = {
1220 let maybe_program = call.program.or_else(|| self.current_program());
1221 if let Some(program) = maybe_program {
1222 (program, call.function.as_symbols())
1223 } else {
1224 halt!(call.span, "No current program");
1225 }
1226 };
1227 let arguments: Vec<Value> =
1230 self.values.drain(len - call.arguments.len() - call.const_arguments.len()..).collect();
1231 self.do_call(
1232 program,
1233 &self.to_absolute_path(&path),
1234 arguments.into_iter(),
1235 false, call.span(),
1237 )?;
1238 None
1239 }
1240 Expression::Call(_call) if step == 2 => Some(self.pop_value()?),
1241 Expression::Cast(cast) if step == 0 => {
1242 push!()(&cast.expression, &None);
1243 None
1244 }
1245 Expression::Cast(cast) if step == 1 => {
1246 let span = cast.span();
1247 let arg = self.pop_value()?;
1248 match arg.cast(&cast.type_) {
1249 Some(value) => Some(value),
1250 None => return Err(InterpreterHalt::new_spanned("cast failure".to_string(), span).into()),
1251 }
1252 }
1253 Expression::Err(_) => todo!(),
1254 Expression::Path(path) if step == 0 => {
1255 Some(self.lookup(&self.to_absolute_path(&path.as_symbols())).expect_tc(path.span())?)
1256 }
1257 Expression::Literal(literal) if step == 0 => Some(literal_to_value(literal, expected_ty)?),
1258 Expression::Locator(_locator) => todo!(),
1259 Expression::Struct(struct_) if step == 0 => {
1260 let members =
1261 self.structs.get(&self.to_absolute_path(&struct_.path.as_symbols())).expect_tc(struct_.span())?;
1262 for StructVariableInitializer { identifier: field_init_name, expression: init, .. } in &struct_.members
1263 {
1264 let Some(type_) = members.get(&field_init_name.name) else { tc_fail!() };
1265 push!()(
1266 init.as_ref().unwrap_or(&Expression::Path(Path::from(*field_init_name))),
1267 &Some(type_.clone()),
1268 )
1269 }
1270
1271 None
1272 }
1273 Expression::Struct(struct_) if step == 1 => {
1274 let mut contents_tmp = HashMap::with_capacity(struct_.members.len());
1276 for initializer in struct_.members.iter() {
1277 let name = initializer.identifier.name;
1278 let value = self.pop_value()?;
1279 contents_tmp.insert(name, value);
1280 }
1281
1282 let members =
1284 self.structs.get(&self.to_absolute_path(&struct_.path.as_symbols())).expect_tc(struct_.span())?;
1285 let contents = members.iter().map(|(identifier, _)| {
1286 (*identifier, contents_tmp.remove(identifier).expect("we just inserted this"))
1287 });
1288
1289 Some(Value::make_struct(contents, self.current_program().unwrap(), struct_.path.as_symbols()))
1292 }
1293 Expression::Ternary(ternary) if step == 0 => {
1294 push!()(&ternary.condition, &None);
1295 None
1296 }
1297 Expression::Ternary(ternary) if step == 1 => {
1298 let condition = self.pop_value()?;
1299 match condition.try_into() {
1300 Ok(true) => push!()(&ternary.if_true, &None),
1301 Ok(false) => push!()(&ternary.if_false, &None),
1302 _ => halt!(ternary.span(), "Invalid type for ternary expression {ternary}"),
1303 }
1304 None
1305 }
1306 Expression::Ternary(_) if step == 2 => Some(self.pop_value()?),
1307 Expression::Tuple(tuple) if step == 0 => {
1308 tuple.elements.iter().rev().for_each(|t| push!()(t, &None));
1309 None
1310 }
1311 Expression::Tuple(tuple) if step == 1 => {
1312 let len = self.values.len();
1313 let tuple_values = self.values.drain(len - tuple.elements.len()..);
1314 Some(Value::make_tuple(tuple_values))
1315 }
1316 Expression::Unary(unary) if step == 0 => {
1317 use UnaryOperation::*;
1318
1319 let ty = match unary.op {
1321 Inverse | Square | SquareRoot => Some(Type::Field), ToXCoordinate | ToYCoordinate => Some(Type::Group), _ => expected_ty.clone(), };
1325
1326 push!()(&unary.receiver, &ty);
1328
1329 None
1330 }
1331 Expression::Unary(unary) if step == 1 => {
1332 let value = self.pop_value()?;
1333 Some(evaluate_unary(unary.span, unary.op, &value, expected_ty)?)
1334 }
1335 Expression::Unit(_) if step == 0 => Some(Value::make_unit()),
1336 x => unreachable!("Unexpected expression {x}"),
1337 } {
1338 assert_eq!(self.frames.len(), len);
1339 self.frames.pop();
1340 self.values.push(value);
1341 Ok(true)
1342 } else {
1343 self.frames[len - 1].step += 1;
1344 Ok(false)
1345 }
1346 }
1347
1348 pub fn step(&mut self) -> Result<StepResult> {
1356 if self.frames.is_empty() {
1357 return Err(InterpreterHalt::new("no execution frames available".into()).into());
1358 }
1359
1360 let Frame { element, step, user_initiated } = self.frames.last().expect("there should be a frame").clone();
1361 match element {
1362 Element::Block { block, function_body } => {
1363 let finished = self.step_block(&block, function_body, step);
1364 Ok(StepResult { finished, value: None })
1365 }
1366 Element::Statement(statement) => {
1367 let finished = self.step_statement(&statement, step)?;
1368 Ok(StepResult { finished, value: None })
1369 }
1370 Element::Expression(expression, expected_ty) => {
1371 let finished = self.step_expression(&expression, &expected_ty, step)?;
1372 let value = match (finished, user_initiated) {
1373 (false, _) => None,
1374 (true, false) => self.values.last().cloned(),
1375 (true, true) => self.values.pop(),
1376 };
1377
1378 let maybe_future = if let Some(len) = value.as_ref().and_then(|val| val.tuple_len()) {
1379 value.as_ref().unwrap().tuple_index(len - 1)
1380 } else {
1381 value.clone()
1382 };
1383
1384 if let Some(asyncs) = maybe_future.as_ref().and_then(|fut| fut.as_future())
1385 && user_initiated
1386 {
1387 self.futures.extend(asyncs.iter().cloned());
1388 }
1389
1390 Ok(StepResult { finished, value })
1391 }
1392 Element::AleoExecution { .. } => {
1393 self.step_aleo()?;
1394 Ok(StepResult { finished: true, value: None })
1395 }
1396 Element::DelayedCall(gid) if step == 0 => {
1397 match self.lookup_function(gid.program, &gid.path).expect("function should exist") {
1398 FunctionVariant::Leo(function) => {
1399 assert!(function.variant == Variant::AsyncFunction);
1400 let len = self.values.len();
1401 let values: Vec<Value> = self.values.drain(len - function.input.len()..).collect();
1402 self.contexts.push(
1403 &gid.path,
1404 gid.program,
1405 self.signer.clone(),
1406 true, HashMap::new(),
1408 );
1409 let param_names = function.input.iter().map(|input| input.identifier.name);
1410 for (name, value) in param_names.zip(values) {
1411 self.set_variable(&self.to_absolute_path(&[name]), value);
1412 }
1413 self.frames.last_mut().unwrap().step = 1;
1414 self.frames.push(Frame {
1415 step: 0,
1416 element: Element::Block { block: function.block.clone(), function_body: true },
1417 user_initiated: false,
1418 });
1419 Ok(StepResult { finished: false, value: None })
1420 }
1421 FunctionVariant::AleoFunction(function) => {
1422 let Some(finalize_f) = function.finalize_logic() else {
1423 panic!("must have finalize logic for a delayed call");
1424 };
1425 let len = self.values.len();
1426 let values_iter = self.values.drain(len - finalize_f.inputs().len()..);
1427 self.contexts.push(
1428 &gid.path,
1429 gid.program,
1430 self.signer.clone(),
1431 true, HashMap::new(),
1433 );
1434 self.frames.last_mut().unwrap().step = 1;
1435 self.frames.push(Frame {
1436 step: 0,
1437 element: Element::AleoExecution {
1438 context: AleoContext::Finalize(finalize_f.clone()).into(),
1439 registers: values_iter.enumerate().map(|(i, v)| (i as u64, v)).collect(),
1440 instruction_index: 0,
1441 },
1442 user_initiated: false,
1443 });
1444 Ok(StepResult { finished: false, value: None })
1445 }
1446 FunctionVariant::AleoClosure(..) => panic!("A call to a closure can't be delayed"),
1447 }
1448 }
1449 Element::DelayedCall(_gid) => {
1450 assert_eq!(step, 1);
1451 let value = self.values.pop();
1452 self.frames.pop();
1453 Ok(StepResult { finished: true, value })
1454 }
1455 Element::DelayedAsyncBlock { program, block, names } if step == 0 => {
1456 self.contexts.push(
1457 &[Symbol::intern("")],
1458 program,
1459 self.signer.clone(),
1460 true,
1461 names.clone().into_iter().collect(), );
1463 self.frames.last_mut().unwrap().step = 1;
1464 self.frames.push(Frame {
1465 step: 0,
1466 element: Element::Block {
1467 block: self.async_blocks.get(&block).unwrap().clone(),
1468 function_body: true,
1469 },
1470 user_initiated: false,
1471 });
1472 Ok(StepResult { finished: false, value: None })
1473 }
1474 Element::DelayedAsyncBlock { .. } => {
1475 assert_eq!(step, 1);
1476 let value = self.values.pop();
1477 self.frames.pop();
1478 Ok(StepResult { finished: true, value })
1479 }
1480 }
1481 }
1482
1483 pub fn do_call(
1484 &mut self,
1485 function_program: Symbol,
1486 function_path: &[Symbol],
1487 arguments: impl Iterator<Item = Value>,
1488 finalize: bool,
1489 span: Span,
1490 ) -> Result<()> {
1491 let Some(function_variant) = self.lookup_function(function_program, function_path) else {
1492 halt!(span, "unknown function {function_program}.aleo/{}", function_path.iter().format("::"));
1493 };
1494 match function_variant {
1495 FunctionVariant::Leo(function) => {
1496 let caller = if matches!(function.variant, Variant::Transition | Variant::AsyncTransition) {
1497 self.new_caller()
1498 } else {
1499 self.signer.clone()
1500 };
1501 if self.really_async && function.variant == Variant::AsyncFunction {
1502 let async_ex = AsyncExecution::AsyncFunctionCall {
1504 function: Location::new(function_program, function_path.to_vec()),
1505 arguments: arguments.collect(),
1506 };
1507 self.values.push(vec![async_ex].into());
1508 } else {
1509 let is_async = function.variant == Variant::AsyncFunction;
1510 self.contexts.push(function_path, function_program, caller, is_async, HashMap::new());
1511 let param_names = function
1513 .const_parameters
1514 .iter()
1515 .map(|param| param.identifier.name)
1516 .chain(function.input.iter().map(|input| input.identifier.name));
1517 for (name, value) in param_names.zip(arguments) {
1518 self.set_variable(&self.to_absolute_path(&[name]), value);
1519 }
1520 self.frames.push(Frame {
1521 step: 0,
1522 element: Element::Block { block: function.block.clone(), function_body: true },
1523 user_initiated: false,
1524 });
1525 }
1526 }
1527 FunctionVariant::AleoClosure(closure) => {
1528 self.contexts.push(function_path, function_program, self.signer.clone(), false, HashMap::new());
1529 let context = AleoContext::Closure(closure);
1530 self.frames.push(Frame {
1531 step: 0,
1532 element: Element::AleoExecution {
1533 context: context.into(),
1534 registers: arguments.enumerate().map(|(i, v)| (i as u64, v)).collect(),
1535 instruction_index: 0,
1536 },
1537 user_initiated: false,
1538 });
1539 }
1540 FunctionVariant::AleoFunction(function) => {
1541 let caller = self.new_caller();
1542 self.contexts.push(function_path, function_program, caller, false, HashMap::new());
1543 let context = if finalize {
1544 let Some(finalize_f) = function.finalize_logic() else {
1545 panic!("finalize call with no finalize logic");
1546 };
1547 AleoContext::Finalize(finalize_f.clone())
1548 } else {
1549 AleoContext::Function(function)
1550 };
1551 self.frames.push(Frame {
1552 step: 0,
1553 element: Element::AleoExecution {
1554 context: context.into(),
1555 registers: arguments.enumerate().map(|(i, v)| (i as u64, v)).collect(),
1556 instruction_index: 0,
1557 },
1558 user_initiated: false,
1559 });
1560 }
1561 }
1562
1563 Ok(())
1564 }
1565}
1566
1567#[derive(Clone, Debug)]
1568pub struct StepResult {
1569 pub finished: bool,
1571
1572 pub value: Option<Value>,
1574}