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