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