1use super::*;
18
19use leo_ast::{
20 AssertVariant,
21 BinaryOperation,
22 Block,
23 CoreConstant,
24 CoreFunction,
25 DefinitionPlace,
26 Expression,
27 FromStrRadix as _,
28 Function,
29 IntegerType,
30 Literal,
31 LiteralVariant,
32 Statement,
33 Type,
34 UnaryOperation,
35 Variant,
36};
37use leo_errors::{InterpreterHalt, Result};
38use leo_span::{Span, Symbol, sym};
39
40use snarkvm::prelude::{
41 Closure as SvmClosure,
42 Double as _,
43 Finalize as SvmFinalize,
44 Function as SvmFunctionParam,
45 Inverse as _,
46 Pow as _,
47 ProgramID,
48 Square as _,
49 SquareRoot as _,
50 TestnetV0,
51};
52
53use indexmap::{IndexMap, IndexSet};
54use rand_chacha::{ChaCha20Rng, rand_core::SeedableRng};
55use std::{cmp::Ordering, collections::HashMap, fmt, mem, str::FromStr as _};
56
57pub type Closure = SvmClosure<TestnetV0>;
58pub type Finalize = SvmFinalize<TestnetV0>;
59pub type SvmFunction = SvmFunctionParam<TestnetV0>;
60
61#[derive(Clone, Debug)]
63pub struct FunctionContext {
64 program: Symbol,
65 pub caller: SvmAddress,
66 names: HashMap<Symbol, Value>,
67 accumulated_futures: Future,
68 is_async: bool,
69}
70
71#[derive(Clone, Debug, Default)]
73pub struct ContextStack {
74 contexts: Vec<FunctionContext>,
75 current_len: usize,
76}
77
78impl ContextStack {
79 fn len(&self) -> usize {
80 self.current_len
81 }
82
83 fn push(&mut self, program: Symbol, caller: SvmAddress, is_async: bool) {
84 if self.current_len == self.contexts.len() {
85 self.contexts.push(FunctionContext {
86 program,
87 caller,
88 names: HashMap::new(),
89 accumulated_futures: Default::default(),
90 is_async,
91 });
92 }
93 self.contexts[self.current_len].accumulated_futures.0.clear();
94 self.contexts[self.current_len].names.clear();
95 self.contexts[self.current_len].caller = caller;
96 self.contexts[self.current_len].program = program;
97 self.contexts[self.current_len].is_async = is_async;
98 self.current_len += 1;
99 }
100
101 pub fn pop(&mut self) {
102 assert!(self.len() > 0);
106 self.current_len -= 1;
107 self.contexts[self.current_len].names.clear();
108 }
109
110 fn get_future(&mut self) -> Future {
115 assert!(self.len() > 0);
116 mem::take(&mut self.contexts[self.current_len - 1].accumulated_futures)
117 }
118
119 fn set(&mut self, symbol: Symbol, value: Value) {
120 assert!(self.current_len > 0);
121 self.last_mut().unwrap().names.insert(symbol, value);
122 }
123
124 pub fn add_future(&mut self, future: Future) {
125 assert!(self.current_len > 0);
126 self.contexts[self.current_len - 1].accumulated_futures.0.extend(future.0);
127 }
128
129 fn is_async(&self) -> bool {
131 assert!(self.current_len > 0);
132 self.last().unwrap().is_async
133 }
134
135 pub fn current_program(&self) -> Option<Symbol> {
136 self.last().map(|c| c.program)
137 }
138
139 pub fn last(&self) -> Option<&FunctionContext> {
140 self.len().checked_sub(1).and_then(|i| self.contexts.get(i))
141 }
142
143 fn last_mut(&mut self) -> Option<&mut FunctionContext> {
144 self.len().checked_sub(1).and_then(|i| self.contexts.get_mut(i))
145 }
146}
147
148#[derive(Clone, Debug)]
149pub enum AleoContext {
150 Closure(Closure),
151 Function(SvmFunction),
152 Finalize(Finalize),
153}
154
155#[derive(Clone, Debug)]
157pub enum Element {
158 Statement(Statement),
160
161 Expression(Expression),
163
164 Block {
173 block: Block,
174 function_body: bool,
175 },
176
177 AleoExecution {
178 context: Box<AleoContext>,
179 registers: IndexMap<u64, Value>,
180 instruction_index: usize,
181 },
182
183 DelayedCall(GlobalId),
184}
185
186impl Element {
187 pub fn span(&self) -> Span {
188 use Element::*;
189 match self {
190 Statement(statement) => statement.span(),
191 Expression(expression) => expression.span(),
192 Block { block, .. } => block.span(),
193 AleoExecution { .. } | DelayedCall(..) => Default::default(),
194 }
195 }
196}
197
198#[derive(Clone, Debug)]
201pub struct Frame {
202 pub step: usize,
203 pub element: Element,
204 pub user_initiated: bool,
205}
206
207#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
210pub struct GlobalId {
211 pub program: Symbol,
212 pub name: Symbol,
213}
214
215impl fmt::Display for GlobalId {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 write!(f, "{}.aleo/{}", self.program, self.name)
218 }
219}
220
221#[derive(Clone, Debug)]
222pub enum FunctionVariant {
223 Leo(Function),
224 AleoClosure(Closure),
225 AleoFunction(SvmFunction),
226}
227
228#[derive(Clone, Debug)]
230pub struct Cursor {
231 pub frames: Vec<Frame>,
233
234 pub values: Vec<Value>,
238
239 pub functions: HashMap<GlobalId, FunctionVariant>,
241
242 pub globals: HashMap<GlobalId, Value>,
244
245 pub user_values: HashMap<Symbol, Value>,
246
247 pub mappings: HashMap<GlobalId, HashMap<Value, Value>>,
248
249 pub structs: HashMap<GlobalId, IndexSet<Symbol>>,
251
252 pub futures: Vec<Future>,
253
254 pub contexts: ContextStack,
255
256 pub signer: SvmAddress,
257
258 pub rng: ChaCha20Rng,
259
260 pub block_height: u32,
261
262 pub really_async: bool,
263
264 pub program: Option<Symbol>,
265}
266
267impl CoreFunctionHelper for Cursor {
268 fn pop_value_impl(&mut self) -> Option<Value> {
269 self.values.pop()
270 }
271
272 fn set_block_height(&mut self, height: u32) {
273 self.block_height = height;
274 }
275
276 fn lookup_mapping(&self, program: Option<Symbol>, name: Symbol) -> Option<&HashMap<Value, Value>> {
277 Cursor::lookup_mapping(self, program, name)
278 }
279
280 fn lookup_mapping_mut(&mut self, program: Option<Symbol>, name: Symbol) -> Option<&mut HashMap<Value, Value>> {
281 Cursor::lookup_mapping_mut(self, program, name)
282 }
283
284 fn rng(&mut self) -> Option<&mut ChaCha20Rng> {
285 Some(&mut self.rng)
286 }
287}
288
289impl Cursor {
290 pub fn new(really_async: bool, signer: SvmAddress, block_height: u32) -> Self {
292 Cursor {
293 frames: Default::default(),
294 values: Default::default(),
295 functions: Default::default(),
296 globals: Default::default(),
297 user_values: Default::default(),
298 mappings: Default::default(),
299 structs: Default::default(),
300 contexts: Default::default(),
301 futures: Default::default(),
302 rng: ChaCha20Rng::from_entropy(),
303 signer,
304 block_height,
305 really_async,
306 program: None,
307 }
308 }
309
310 pub fn set_program(&mut self, program: &str) {
311 let p = program.strip_suffix(".aleo").unwrap_or(program);
312 self.program = Some(Symbol::intern(p));
313 }
314
315 pub fn current_program(&self) -> Option<Symbol> {
316 self.contexts.current_program().or(self.program)
317 }
318
319 pub fn increment_step(&mut self) {
320 let Some(Frame { step, .. }) = self.frames.last_mut() else {
321 panic!("frame expected");
322 };
323 *step += 1;
324 }
325
326 fn new_caller(&self) -> SvmAddress {
327 if let Some(function_context) = self.contexts.last() {
328 let program_id = ProgramID::<TestnetV0>::from_str(&format!("{}.aleo", function_context.program))
329 .expect("should be able to create ProgramID");
330 program_id.to_address().expect("should be able to convert to address")
331 } else {
332 self.signer
333 }
334 }
335
336 fn pop_value(&mut self) -> Result<Value> {
337 match self.values.pop() {
338 Some(v) => Ok(v),
339 None => {
340 Err(InterpreterHalt::new("value expected - this may be a bug in the Leo interpreter".to_string())
341 .into())
342 }
343 }
344 }
345
346 fn lookup(&self, name: Symbol) -> Option<Value> {
347 if let Some(context) = self.contexts.last() {
348 let option_value =
349 context.names.get(&name).or_else(|| self.globals.get(&GlobalId { program: context.program, name }));
350 if option_value.is_some() {
351 return option_value.cloned();
352 }
353 };
354
355 self.user_values.get(&name).cloned()
356 }
357
358 pub fn lookup_mapping(&self, program: Option<Symbol>, name: Symbol) -> Option<&HashMap<Value, Value>> {
359 let Some(program) = program.or_else(|| self.current_program()) else {
360 panic!("no program for mapping lookup");
361 };
362 self.mappings.get(&GlobalId { program, name })
363 }
364
365 pub fn lookup_mapping_mut(&mut self, program: Option<Symbol>, name: Symbol) -> Option<&mut HashMap<Value, Value>> {
366 let Some(program) = program.or_else(|| self.current_program()) else {
367 panic!("no program for mapping lookup");
368 };
369 self.mappings.get_mut(&GlobalId { program, name })
370 }
371
372 fn lookup_function(&self, program: Symbol, name: Symbol) -> Option<FunctionVariant> {
373 self.functions.get(&GlobalId { program, name }).cloned()
374 }
375
376 fn set_variable(&mut self, symbol: Symbol, value: Value) {
377 if self.contexts.len() > 0 {
378 self.contexts.set(symbol, value);
379 } else {
380 self.user_values.insert(symbol, value);
381 }
382 }
383
384 pub fn whole_step(&mut self) -> Result<StepResult> {
389 let frames_len = self.frames.len();
390 let initial_result = self.step()?;
391 if !initial_result.finished {
392 while self.frames.len() > frames_len {
393 self.step()?;
394 }
395 }
396 Ok(initial_result)
397 }
398
399 pub fn over(&mut self) -> Result<StepResult> {
403 let frames_len = self.frames.len();
404 loop {
405 match self.frames.len().cmp(&frames_len) {
406 Ordering::Greater => {
407 self.step()?;
408 }
409 Ordering::Equal => {
410 let result = self.step()?;
411 if result.finished {
412 return Ok(result);
413 }
414 }
415 Ordering::Less => {
416 return Ok(StepResult { finished: true, value: None });
420 }
421 }
422 }
423 }
424
425 pub fn step_block(&mut self, block: &Block, function_body: bool, step: usize) -> bool {
426 let len = self.frames.len();
427
428 let done = match step {
429 0 => {
430 for statement in block.statements.iter().rev() {
431 self.frames.push(Frame {
432 element: Element::Statement(statement.clone()),
433 step: 0,
434 user_initiated: false,
435 });
436 }
437 false
438 }
439 1 if function_body => {
440 self.values.push(Value::Unit);
441 self.contexts.pop();
442 true
443 }
444 1 => true,
445 _ => unreachable!(),
446 };
447
448 if done {
449 assert_eq!(len, self.frames.len());
450 self.frames.pop();
451 } else {
452 self.frames[len - 1].step += 1;
453 }
454
455 done
456 }
457
458 fn step_statement(&mut self, statement: &Statement, step: usize) -> Result<bool> {
459 let len = self.frames.len();
460
461 let mut push = |expression: &Expression| {
462 self.frames.push(Frame { element: Element::Expression(expression.clone()), step: 0, user_initiated: false })
463 };
464
465 let done = match statement {
466 Statement::Assert(assert) if step == 0 => {
467 match &assert.variant {
468 AssertVariant::Assert(x) => push(x),
469 AssertVariant::AssertEq(x, y) | AssertVariant::AssertNeq(x, y) => {
470 push(y);
471 push(x);
472 }
473 };
474 false
475 }
476 Statement::Assert(assert) if step == 1 => {
477 match &assert.variant {
478 AssertVariant::Assert(..) => {
479 let value = self.pop_value()?;
480 match value {
481 Value::Bool(true) => {}
482 Value::Bool(false) => halt!(assert.span(), "assert failure"),
483 _ => tc_fail!(),
484 }
485 }
486 AssertVariant::AssertEq(..) | AssertVariant::AssertNeq(..) => {
487 let x = self.pop_value()?;
488 let y = self.pop_value()?;
489 let b =
490 if matches!(assert.variant, AssertVariant::AssertEq(..)) { x.eq(&y)? } else { x.neq(&y)? };
491 if !b {
492 halt!(assert.span(), "assert failure");
493 }
494 }
495 };
496 true
497 }
498 Statement::Assign(assign) if step == 0 => {
499 push(&assign.value);
500 false
501 }
502 Statement::Assign(assign) if step == 1 => {
503 let value = self.values.pop().unwrap();
504 match &assign.place {
505 Expression::Identifier(name) => self.set_variable(name.name, value),
506 Expression::TupleAccess(tuple_access) => {
507 let Expression::Identifier(identifier) = tuple_access.tuple else {
508 halt!(assign.span(), "tuple assignments must refer to identifiers.");
509 };
510 let mut current_tuple = self.lookup(identifier.name).expect_tc(identifier.span())?;
511 let Value::Tuple(tuple) = &mut current_tuple else {
512 halt!(tuple_access.span(), "Type error: this must be a tuple.");
513 };
514 tuple[tuple_access.index.value()] = value;
515 self.set_variable(identifier.name, current_tuple);
516 }
517 _ => halt!(assign.span(), "Invalid assignment place."),
518 }
519 true
520 }
521 Statement::Block(block) => return Ok(self.step_block(block, false, step)),
522 Statement::Conditional(conditional) if step == 0 => {
523 push(&conditional.condition);
524 false
525 }
526 Statement::Conditional(conditional) if step == 1 => {
527 match self.pop_value()? {
528 Value::Bool(true) => self.frames.push(Frame {
529 step: 0,
530 element: Element::Block { block: conditional.then.clone(), function_body: false },
531 user_initiated: false,
532 }),
533 Value::Bool(false) => {
534 if let Some(otherwise) = conditional.otherwise.as_ref() {
535 self.frames.push(Frame {
536 step: 0,
537 element: Element::Statement(Statement::clone(otherwise)),
538 user_initiated: false,
539 })
540 }
541 }
542 _ => tc_fail!(),
543 };
544 false
545 }
546 Statement::Conditional(_) if step == 2 => true,
547 Statement::Const(const_) if step == 0 => {
548 push(&const_.value);
549 false
550 }
551 Statement::Const(const_) if step == 1 => {
552 let value = self.pop_value()?;
553 self.set_variable(const_.place.name, value);
554 true
555 }
556 Statement::Definition(definition) if step == 0 => {
557 push(&definition.value);
558 false
559 }
560 Statement::Definition(definition) if step == 1 => {
561 let value = self.pop_value()?;
562 match &definition.place {
563 DefinitionPlace::Single(id) => self.set_variable(id.name, value),
564 DefinitionPlace::Multiple(ids) => {
565 let Value::Tuple(rhs) = value else {
566 tc_fail!();
567 };
568 for (id, val) in ids.iter().zip(rhs.into_iter()) {
569 self.set_variable(id.name, val);
570 }
571 }
572 }
573 true
574 }
575 Statement::Expression(expression) if step == 0 => {
576 push(&expression.expression);
577 false
578 }
579 Statement::Expression(_) if step == 1 => {
580 self.values.pop();
581 true
582 }
583 Statement::Iteration(iteration) if step == 0 => {
584 assert!(!iteration.inclusive);
585 push(&iteration.stop);
586 push(&iteration.start);
587 false
588 }
589 Statement::Iteration(iteration) => {
590 let stop = self.pop_value()?;
592 let start = self.pop_value()?;
593 if start.eq(&stop)? {
594 true
595 } else {
596 let new_start = start.inc_wrapping();
597 self.set_variable(iteration.variable.name, start);
598 self.frames.push(Frame {
599 step: 0,
600 element: Element::Block { block: iteration.block.clone(), function_body: false },
601 user_initiated: false,
602 });
603 self.values.push(new_start);
604 self.values.push(stop);
605 false
606 }
607 }
608 Statement::Return(return_) if step == 0 => {
609 push(&return_.expression);
610 false
611 }
612 Statement::Return(_) if step == 1 => loop {
613 let last_frame = self.frames.last().expect("a frame should be present");
614 match last_frame.element {
615 Element::Expression(Expression::Call(_)) | Element::DelayedCall(_) => {
616 if self.contexts.is_async() {
617 self.values.pop();
619 self.values.push(Value::Future(self.contexts.get_future()));
620 }
621 self.contexts.pop();
622 return Ok(true);
623 }
624 _ => {
625 self.frames.pop();
626 }
627 }
628 },
629 _ => unreachable!(),
630 };
631
632 if done {
633 assert_eq!(len, self.frames.len());
634 self.frames.pop();
635 } else {
636 self.frames[len - 1].step += 1;
637 }
638
639 Ok(done)
640 }
641
642 fn step_expression(&mut self, expression: &Expression, step: usize) -> Result<bool> {
643 let len = self.frames.len();
644
645 macro_rules! push {
646 () => {
647 |expression: &Expression| {
648 self.frames.push(Frame {
649 element: Element::Expression(expression.clone()),
650 step: 0,
651 user_initiated: false,
652 })
653 }
654 };
655 }
656
657 if let Some(value) = match expression {
658 Expression::ArrayAccess(array) if step == 0 => {
659 push!()(&array.index);
660 push!()(&array.array);
661 None
662 }
663 Expression::ArrayAccess(array) if step == 1 => {
664 let span = array.span();
665 let array = self.pop_value()?;
666 let index = self.pop_value()?;
667
668 let index_usize: usize = match index {
669 Value::U8(x) => x.into(),
670 Value::U16(x) => x.into(),
671 Value::U32(x) => x.try_into().expect_tc(span)?,
672 Value::U64(x) => x.try_into().expect_tc(span)?,
673 Value::U128(x) => x.try_into().expect_tc(span)?,
674 Value::I8(x) => x.try_into().expect_tc(span)?,
675 Value::I16(x) => x.try_into().expect_tc(span)?,
676 Value::I32(x) => x.try_into().expect_tc(span)?,
677 Value::I64(x) => x.try_into().expect_tc(span)?,
678 Value::I128(x) => x.try_into().expect_tc(span)?,
679 _ => halt!(expression.span(), "invalid array index {index}"),
680 };
681 let Value::Array(vec_array) = array else { tc_fail!() };
682 Some(vec_array.get(index_usize).expect_tc(span)?.clone())
683 }
684 Expression::MemberAccess(access) => match &access.inner {
685 Expression::Identifier(identifier) if identifier.name == sym::SelfLower => match access.name.name {
686 sym::signer => Some(Value::Address(self.signer)),
687 sym::caller => {
688 if let Some(function_context) = self.contexts.last() {
689 Some(Value::Address(function_context.caller))
690 } else {
691 Some(Value::Address(self.signer))
692 }
693 }
694 _ => halt!(access.span(), "unknown member of self"),
695 },
696 Expression::Identifier(identifier) if identifier.name == sym::block => match access.name.name {
697 sym::height => Some(Value::U32(self.block_height)),
698 _ => halt!(access.span(), "unknown member of block"),
699 },
700
701 _ if step == 0 => {
703 push!()(&access.inner);
704 None
705 }
706 _ if step == 1 => {
707 let Some(Value::Struct(struct_)) = self.values.pop() else {
708 tc_fail!();
709 };
710 let value = struct_.contents.get(&access.name.name).cloned();
711 if value.is_none() {
712 tc_fail!();
713 }
714 value
715 }
716 _ => unreachable!("we've actually covered all possible patterns above"),
717 },
718 Expression::TupleAccess(tuple_access) if step == 0 => {
719 push!()(&tuple_access.tuple);
720 None
721 }
722 Expression::TupleAccess(tuple_access) if step == 1 => {
723 let Some(value) = self.values.pop() else { tc_fail!() };
724 let Value::Tuple(tuple) = value else {
725 halt!(tuple_access.span(), "Type error");
726 };
727 if let Some(result) = tuple.get(tuple_access.index.value()) {
728 Some(result.clone())
729 } else {
730 halt!(tuple_access.span(), "Tuple index out of range");
731 }
732 }
733 Expression::Array(array) if step == 0 => {
734 array.elements.iter().rev().for_each(push!());
735 None
736 }
737 Expression::Array(array) if step == 1 => {
738 let len = self.values.len();
739 let array_values = self.values.drain(len - array.elements.len()..).collect();
740 Some(Value::Array(array_values))
741 }
742 Expression::AssociatedConstant(constant) if step == 0 => {
743 let Type::Identifier(type_ident) = constant.ty else {
744 tc_fail!();
745 };
746 let Some(core_constant) = CoreConstant::from_symbols(type_ident.name, constant.name.name) else {
747 halt!(constant.span(), "Unknown constant {constant}");
748 };
749 match core_constant {
750 CoreConstant::GroupGenerator => Some(Value::generator()),
751 }
752 }
753 Expression::AssociatedFunction(function) if step == 0 => {
754 let Some(core_function) = CoreFunction::from_symbols(function.variant.name, function.name.name) else {
755 halt!(function.span(), "Unkown core function {function}");
756 };
757
758 match core_function {
761 CoreFunction::MappingGet | CoreFunction::MappingRemove | CoreFunction::MappingContains => {
762 push!()(&function.arguments[1]);
763 }
764 CoreFunction::MappingGetOrUse | CoreFunction::MappingSet => {
765 push!()(&function.arguments[2]);
766 push!()(&function.arguments[1]);
767 }
768 CoreFunction::CheatCodePrintMapping => {
769 }
771 _ => function.arguments.iter().rev().for_each(push!()),
772 }
773 None
774 }
775 Expression::AssociatedFunction(function) if step == 1 => {
776 let Some(core_function) = CoreFunction::from_symbols(function.variant.name, function.name.name) else {
777 halt!(function.span(), "Unkown core function {function}");
778 };
779
780 let span = function.span();
781
782 if let CoreFunction::FutureAwait = core_function {
783 let value = self.pop_value()?;
784 let Value::Future(future) = value else {
785 halt!(span, "Invalid value for await: {value}");
786 };
787 for async_execution in future.0 {
788 self.values.extend(async_execution.arguments.into_iter());
789 self.frames.push(Frame {
790 step: 0,
791 element: Element::DelayedCall(async_execution.function),
792 user_initiated: false,
793 });
794 }
795 None
797 } else {
798 let value = crate::evaluate_core_function(self, core_function.clone(), &function.arguments, span)?;
799 assert!(value.is_some());
800 value
801 }
802 }
803 Expression::AssociatedFunction(function) if step == 2 => {
804 let Some(core_function) = CoreFunction::from_symbols(function.variant.name, function.name.name) else {
805 halt!(function.span(), "Unkown core function {function}");
806 };
807 assert!(core_function == CoreFunction::FutureAwait);
808 Some(Value::Unit)
809 }
810 Expression::Binary(binary) if step == 0 => {
811 push!()(&binary.right);
812 push!()(&binary.left);
813 None
814 }
815 Expression::Binary(binary) if step == 1 => {
816 let rhs = self.pop_value()?;
817 let lhs = self.pop_value()?;
818 Some(evaluate_binary(binary.span, binary.op, &lhs, &rhs)?)
819 }
820 Expression::Call(call) if step == 0 => {
821 call.arguments.iter().rev().for_each(push!());
822 None
823 }
824 Expression::Call(call) if step == 1 => {
825 let len = self.values.len();
826 let (program, name) = match &call.function {
827 Expression::Identifier(id) => {
828 let maybe_program = call.program.or_else(|| self.current_program());
829 if let Some(program) = maybe_program {
830 (program, id.name)
831 } else {
832 halt!(call.span, "No current program");
833 }
834 }
835 Expression::Locator(locator) => (locator.program.name.name, locator.name),
836 _ => tc_fail!(),
837 };
838 let arguments: Vec<Value> = self.values.drain(len - call.arguments.len()..).collect();
841 self.do_call(
842 program,
843 name,
844 arguments.into_iter(),
845 false, call.span(),
847 )?;
848 None
849 }
850 Expression::Call(_call) if step == 2 => Some(self.pop_value()?),
851 Expression::Cast(cast) if step == 0 => {
852 push!()(&cast.expression);
853 None
854 }
855 Expression::Cast(cast) if step == 1 => {
856 let span = cast.span();
857 let arg = self.pop_value()?;
858 match arg.cast(&cast.type_) {
859 Some(value) => Some(value),
860 None => return Err(InterpreterHalt::new_spanned("cast failure".to_string(), span).into()),
861 }
862 }
863 Expression::Err(_) => todo!(),
864 Expression::Identifier(identifier) if step == 0 => {
865 Some(self.lookup(identifier.name).expect_tc(identifier.span())?)
866 }
867 Expression::Literal(literal) if step == 0 => Some(literal_to_value(literal)?),
868 Expression::Locator(_locator) => todo!(),
869 Expression::Struct(struct_) if step == 0 => {
870 struct_.members.iter().flat_map(|init| init.expression.as_ref()).for_each(push!());
871 None
872 }
873 Expression::Struct(struct_) if step == 1 => {
874 let mut contents_tmp = HashMap::with_capacity(struct_.members.len());
876 for initializer in struct_.members.iter() {
877 let name = initializer.identifier.name;
878 let value = if initializer.expression.is_some() {
879 self.pop_value()?
880 } else {
881 self.lookup(name).expect_tc(struct_.span())?
882 };
883 contents_tmp.insert(name, value);
884 }
885
886 let program = self.current_program().expect("there should be a current program");
888 let id = GlobalId { program, name: struct_.name.name };
889 let struct_type = self.structs.get(&id).expect_tc(struct_.span())?;
890 let contents = struct_type
891 .iter()
892 .map(|sym| (*sym, contents_tmp.remove(sym).expect("we just inserted this")))
893 .collect();
894
895 Some(Value::Struct(StructContents { name: struct_.name.name, contents }))
896 }
897 Expression::Ternary(ternary) if step == 0 => {
898 push!()(&ternary.condition);
899 None
900 }
901 Expression::Ternary(ternary) if step == 1 => {
902 let condition = self.pop_value()?;
903 match condition {
904 Value::Bool(true) => push!()(&ternary.if_true),
905 Value::Bool(false) => push!()(&ternary.if_false),
906 _ => halt!(ternary.span(), "Invalid type for ternary expression {ternary}"),
907 }
908 None
909 }
910 Expression::Ternary(_) if step == 2 => Some(self.pop_value()?),
911 Expression::Tuple(tuple) if step == 0 => {
912 tuple.elements.iter().rev().for_each(push!());
913 None
914 }
915 Expression::Tuple(tuple) if step == 1 => {
916 let len = self.values.len();
917 let tuple_values = self.values.drain(len - tuple.elements.len()..).collect();
918 Some(Value::Tuple(tuple_values))
919 }
920 Expression::Unary(unary) if step == 0 => {
921 push!()(&unary.receiver);
922 None
923 }
924 Expression::Unary(unary) if step == 1 => {
925 let value = self.pop_value()?;
926 Some(evaluate_unary(unary.span, unary.op, &value)?)
927 }
928 Expression::Unit(_) if step == 0 => Some(Value::Unit),
929 x => unreachable!("Unexpected expression {x}"),
930 } {
931 assert_eq!(self.frames.len(), len);
932 self.frames.pop();
933 self.values.push(value);
934 Ok(true)
935 } else {
936 self.frames[len - 1].step += 1;
937 Ok(false)
938 }
939 }
940
941 pub fn step(&mut self) -> Result<StepResult> {
949 if self.frames.is_empty() {
950 return Err(InterpreterHalt::new("no execution frames available".into()).into());
951 }
952
953 let Frame { element, step, user_initiated } = self.frames.last().expect("there should be a frame").clone();
954 match element {
955 Element::Block { block, function_body } => {
956 let finished = self.step_block(&block, function_body, step);
957 Ok(StepResult { finished, value: None })
958 }
959 Element::Statement(statement) => {
960 let finished = self.step_statement(&statement, step)?;
961 Ok(StepResult { finished, value: None })
962 }
963 Element::Expression(expression) => {
964 let finished = self.step_expression(&expression, step)?;
965 let value = match (finished, user_initiated) {
966 (false, _) => None,
967 (true, false) => self.values.last().cloned(),
968 (true, true) => self.values.pop(),
969 };
970 let maybe_future = if let Some(Value::Tuple(vals)) = &value { vals.last() } else { value.as_ref() };
971
972 if let Some(Value::Future(future)) = &maybe_future {
973 if user_initiated && !future.0.is_empty() {
974 self.futures.push(future.clone());
975 }
976 }
977 Ok(StepResult { finished, value })
978 }
979 Element::AleoExecution { .. } => {
980 self.step_aleo()?;
981 Ok(StepResult { finished: true, value: None })
982 }
983 Element::DelayedCall(gid) if step == 0 => {
984 match self.lookup_function(gid.program, gid.name).expect("function should exist") {
985 FunctionVariant::Leo(function) => {
986 assert!(function.variant == Variant::AsyncFunction);
987 let len = self.values.len();
988 let values: Vec<Value> = self.values.drain(len - function.input.len()..).collect();
989 self.contexts.push(
990 gid.program,
991 self.signer,
992 true, );
994 let param_names = function.input.iter().map(|input| input.identifier.name);
995 for (name, value) in param_names.zip(values) {
996 self.set_variable(name, value);
997 }
998 self.frames.last_mut().unwrap().step = 1;
999 self.frames.push(Frame {
1000 step: 0,
1001 element: Element::Block { block: function.block.clone(), function_body: true },
1002 user_initiated: false,
1003 });
1004 Ok(StepResult { finished: false, value: None })
1005 }
1006 FunctionVariant::AleoFunction(function) => {
1007 let Some(finalize_f) = function.finalize_logic() else {
1008 panic!("must have finalize logic for a delayed call");
1009 };
1010 let len = self.values.len();
1011 let values_iter = self.values.drain(len - finalize_f.inputs().len()..);
1012 self.contexts.push(
1013 gid.program,
1014 self.signer,
1015 true, );
1017 self.frames.last_mut().unwrap().step = 1;
1018 self.frames.push(Frame {
1019 step: 0,
1020 element: Element::AleoExecution {
1021 context: AleoContext::Finalize(finalize_f.clone()).into(),
1022 registers: values_iter.enumerate().map(|(i, v)| (i as u64, v)).collect(),
1023 instruction_index: 0,
1024 },
1025 user_initiated: false,
1026 });
1027 Ok(StepResult { finished: false, value: None })
1028 }
1029 FunctionVariant::AleoClosure(..) => panic!("A call to a closure can't be delayed"),
1030 }
1031 }
1032 Element::DelayedCall(_gid) => {
1033 assert_eq!(step, 1);
1034 let value = self.values.pop();
1035 self.frames.pop();
1036 Ok(StepResult { finished: true, value })
1037 }
1038 }
1039 }
1040
1041 pub fn do_call(
1042 &mut self,
1043 function_program: Symbol,
1044 function_name: Symbol,
1045 arguments: impl Iterator<Item = Value>,
1046 finalize: bool,
1047 span: Span,
1048 ) -> Result<()> {
1049 let Some(function_variant) = self.lookup_function(function_program, function_name) else {
1050 halt!(span, "unknown function {function_program}.aleo/{function_name}");
1051 };
1052 match function_variant {
1053 FunctionVariant::Leo(function) => {
1054 let caller = if matches!(function.variant, Variant::Transition | Variant::AsyncTransition) {
1055 self.new_caller()
1056 } else {
1057 self.signer
1058 };
1059 if self.really_async && function.variant == Variant::AsyncFunction {
1060 let async_ex = AsyncExecution {
1062 function: GlobalId { name: function_name, program: function_program },
1063 arguments: arguments.collect(),
1064 };
1065 self.values.push(Value::Future(Future(vec![async_ex])));
1066 } else {
1067 let is_async = function.variant == Variant::AsyncFunction;
1068 self.contexts.push(function_program, caller, is_async);
1069 let param_names = function.input.iter().map(|input| input.identifier.name);
1070 for (name, value) in param_names.zip(arguments) {
1071 self.set_variable(name, value);
1072 }
1073 self.frames.push(Frame {
1074 step: 0,
1075 element: Element::Block { block: function.block.clone(), function_body: true },
1076 user_initiated: false,
1077 });
1078 }
1079 }
1080 FunctionVariant::AleoClosure(closure) => {
1081 self.contexts.push(function_program, self.signer, false);
1082 let context = AleoContext::Closure(closure);
1083 self.frames.push(Frame {
1084 step: 0,
1085 element: Element::AleoExecution {
1086 context: context.into(),
1087 registers: arguments.enumerate().map(|(i, v)| (i as u64, v)).collect(),
1088 instruction_index: 0,
1089 },
1090 user_initiated: false,
1091 });
1092 }
1093 FunctionVariant::AleoFunction(function) => {
1094 let caller = self.new_caller();
1095 self.contexts.push(function_program, caller, false);
1096 let context = if finalize {
1097 let Some(finalize_f) = function.finalize_logic() else {
1098 panic!("finalize call with no finalize logic");
1099 };
1100 AleoContext::Finalize(finalize_f.clone())
1101 } else {
1102 AleoContext::Function(function)
1103 };
1104 self.frames.push(Frame {
1105 step: 0,
1106 element: Element::AleoExecution {
1107 context: context.into(),
1108 registers: arguments.enumerate().map(|(i, v)| (i as u64, v)).collect(),
1109 instruction_index: 0,
1110 },
1111 user_initiated: false,
1112 });
1113 }
1114 }
1115
1116 Ok(())
1117 }
1118}
1119
1120#[derive(Clone, Debug)]
1121pub struct StepResult {
1122 pub finished: bool,
1124
1125 pub value: Option<Value>,
1127}
1128
1129pub fn evaluate_binary(span: Span, op: BinaryOperation, lhs: &Value, rhs: &Value) -> Result<Value> {
1131 let value = match op {
1132 BinaryOperation::Add => {
1133 let Some(value) = (match (lhs, rhs) {
1134 (Value::U8(x), Value::U8(y)) => x.checked_add(*y).map(Value::U8),
1135 (Value::U16(x), Value::U16(y)) => x.checked_add(*y).map(Value::U16),
1136 (Value::U32(x), Value::U32(y)) => x.checked_add(*y).map(Value::U32),
1137 (Value::U64(x), Value::U64(y)) => x.checked_add(*y).map(Value::U64),
1138 (Value::U128(x), Value::U128(y)) => x.checked_add(*y).map(Value::U128),
1139 (Value::I8(x), Value::I8(y)) => x.checked_add(*y).map(Value::I8),
1140 (Value::I16(x), Value::I16(y)) => x.checked_add(*y).map(Value::I16),
1141 (Value::I32(x), Value::I32(y)) => x.checked_add(*y).map(Value::I32),
1142 (Value::I64(x), Value::I64(y)) => x.checked_add(*y).map(Value::I64),
1143 (Value::I128(x), Value::I128(y)) => x.checked_add(*y).map(Value::I128),
1144 (Value::Group(x), Value::Group(y)) => Some(Value::Group(*x + *y)),
1145 (Value::Field(x), Value::Field(y)) => Some(Value::Field(*x + *y)),
1146 (Value::Scalar(x), Value::Scalar(y)) => Some(Value::Scalar(*x + *y)),
1147 _ => halt!(span, "Type error"),
1148 }) else {
1149 halt!(span, "add overflow");
1150 };
1151 value
1152 }
1153 BinaryOperation::AddWrapped => match (lhs, rhs) {
1154 (Value::U8(x), Value::U8(y)) => Value::U8(x.wrapping_add(*y)),
1155 (Value::U16(x), Value::U16(y)) => Value::U16(x.wrapping_add(*y)),
1156 (Value::U32(x), Value::U32(y)) => Value::U32(x.wrapping_add(*y)),
1157 (Value::U64(x), Value::U64(y)) => Value::U64(x.wrapping_add(*y)),
1158 (Value::U128(x), Value::U128(y)) => Value::U128(x.wrapping_add(*y)),
1159 (Value::I8(x), Value::I8(y)) => Value::I8(x.wrapping_add(*y)),
1160 (Value::I16(x), Value::I16(y)) => Value::I16(x.wrapping_add(*y)),
1161 (Value::I32(x), Value::I32(y)) => Value::I32(x.wrapping_add(*y)),
1162 (Value::I64(x), Value::I64(y)) => Value::I64(x.wrapping_add(*y)),
1163 (Value::I128(x), Value::I128(y)) => Value::I128(x.wrapping_add(*y)),
1164 _ => halt!(span, "Type error"),
1165 },
1166 BinaryOperation::And => match (lhs, rhs) {
1167 (Value::Bool(x), Value::Bool(y)) => Value::Bool(*x && *y),
1168 _ => halt!(span, "Type error"),
1169 },
1170 BinaryOperation::BitwiseAnd => match (lhs, rhs) {
1171 (Value::Bool(x), Value::Bool(y)) => Value::Bool(x & y),
1172 (Value::U8(x), Value::U8(y)) => Value::U8(x & y),
1173 (Value::U16(x), Value::U16(y)) => Value::U16(x & y),
1174 (Value::U32(x), Value::U32(y)) => Value::U32(x & y),
1175 (Value::U64(x), Value::U64(y)) => Value::U64(x & y),
1176 (Value::U128(x), Value::U128(y)) => Value::U128(x & y),
1177 (Value::I8(x), Value::I8(y)) => Value::I8(x & y),
1178 (Value::I16(x), Value::I16(y)) => Value::I16(x & y),
1179 (Value::I32(x), Value::I32(y)) => Value::I32(x & y),
1180 (Value::I64(x), Value::I64(y)) => Value::I64(x & y),
1181 (Value::I128(x), Value::I128(y)) => Value::I128(x & y),
1182 _ => halt!(span, "Type error"),
1183 },
1184 BinaryOperation::Div => {
1185 let Some(value) = (match (lhs, rhs) {
1186 (Value::U8(x), Value::U8(y)) => x.checked_div(*y).map(Value::U8),
1187 (Value::U16(x), Value::U16(y)) => x.checked_div(*y).map(Value::U16),
1188 (Value::U32(x), Value::U32(y)) => x.checked_div(*y).map(Value::U32),
1189 (Value::U64(x), Value::U64(y)) => x.checked_div(*y).map(Value::U64),
1190 (Value::U128(x), Value::U128(y)) => x.checked_div(*y).map(Value::U128),
1191 (Value::I8(x), Value::I8(y)) => x.checked_div(*y).map(Value::I8),
1192 (Value::I16(x), Value::I16(y)) => x.checked_div(*y).map(Value::I16),
1193 (Value::I32(x), Value::I32(y)) => x.checked_div(*y).map(Value::I32),
1194 (Value::I64(x), Value::I64(y)) => x.checked_div(*y).map(Value::I64),
1195 (Value::I128(x), Value::I128(y)) => x.checked_div(*y).map(Value::I128),
1196 (Value::Field(x), Value::Field(y)) => y.inverse().map(|y| Value::Field(*x * y)).ok(),
1197 _ => halt!(span, "Type error"),
1198 }) else {
1199 halt!(span, "div overflow");
1200 };
1201 value
1202 }
1203 BinaryOperation::DivWrapped => match (lhs, rhs) {
1204 (Value::U8(_), Value::U8(0))
1205 | (Value::U16(_), Value::U16(0))
1206 | (Value::U32(_), Value::U32(0))
1207 | (Value::U64(_), Value::U64(0))
1208 | (Value::U128(_), Value::U128(0))
1209 | (Value::I8(_), Value::I8(0))
1210 | (Value::I16(_), Value::I16(0))
1211 | (Value::I32(_), Value::I32(0))
1212 | (Value::I64(_), Value::I64(0))
1213 | (Value::I128(_), Value::I128(0)) => halt!(span, "divide by 0"),
1214 (Value::U8(x), Value::U8(y)) => Value::U8(x.wrapping_div(*y)),
1215 (Value::U16(x), Value::U16(y)) => Value::U16(x.wrapping_div(*y)),
1216 (Value::U32(x), Value::U32(y)) => Value::U32(x.wrapping_div(*y)),
1217 (Value::U64(x), Value::U64(y)) => Value::U64(x.wrapping_div(*y)),
1218 (Value::U128(x), Value::U128(y)) => Value::U128(x.wrapping_div(*y)),
1219 (Value::I8(x), Value::I8(y)) => Value::I8(x.wrapping_div(*y)),
1220 (Value::I16(x), Value::I16(y)) => Value::I16(x.wrapping_div(*y)),
1221 (Value::I32(x), Value::I32(y)) => Value::I32(x.wrapping_div(*y)),
1222 (Value::I64(x), Value::I64(y)) => Value::I64(x.wrapping_div(*y)),
1223 (Value::I128(x), Value::I128(y)) => Value::I128(x.wrapping_div(*y)),
1224 _ => halt!(span, "Type error"),
1225 },
1226 BinaryOperation::Eq => Value::Bool(lhs.eq(rhs)?),
1227 BinaryOperation::Gte => Value::Bool(lhs.gte(rhs)?),
1228 BinaryOperation::Gt => Value::Bool(lhs.gt(rhs)?),
1229 BinaryOperation::Lte => Value::Bool(lhs.lte(rhs)?),
1230 BinaryOperation::Lt => Value::Bool(lhs.lt(rhs)?),
1231 BinaryOperation::Mod => {
1232 let Some(value) = (match (lhs, rhs) {
1233 (Value::U8(x), Value::U8(y)) => x.checked_rem(*y).map(Value::U8),
1234 (Value::U16(x), Value::U16(y)) => x.checked_rem(*y).map(Value::U16),
1235 (Value::U32(x), Value::U32(y)) => x.checked_rem(*y).map(Value::U32),
1236 (Value::U64(x), Value::U64(y)) => x.checked_rem(*y).map(Value::U64),
1237 (Value::U128(x), Value::U128(y)) => x.checked_rem(*y).map(Value::U128),
1238 (Value::I8(x), Value::I8(y)) => x.checked_rem(*y).map(Value::I8),
1239 (Value::I16(x), Value::I16(y)) => x.checked_rem(*y).map(Value::I16),
1240 (Value::I32(x), Value::I32(y)) => x.checked_rem(*y).map(Value::I32),
1241 (Value::I64(x), Value::I64(y)) => x.checked_rem(*y).map(Value::I64),
1242 (Value::I128(x), Value::I128(y)) => x.checked_rem(*y).map(Value::I128),
1243 _ => halt!(span, "Type error"),
1244 }) else {
1245 halt!(span, "mod overflow");
1246 };
1247 value
1248 }
1249 BinaryOperation::Mul => {
1250 let Some(value) = (match (lhs, rhs) {
1251 (Value::U8(x), Value::U8(y)) => x.checked_mul(*y).map(Value::U8),
1252 (Value::U16(x), Value::U16(y)) => x.checked_mul(*y).map(Value::U16),
1253 (Value::U32(x), Value::U32(y)) => x.checked_mul(*y).map(Value::U32),
1254 (Value::U64(x), Value::U64(y)) => x.checked_mul(*y).map(Value::U64),
1255 (Value::U128(x), Value::U128(y)) => x.checked_mul(*y).map(Value::U128),
1256 (Value::I8(x), Value::I8(y)) => x.checked_mul(*y).map(Value::I8),
1257 (Value::I16(x), Value::I16(y)) => x.checked_mul(*y).map(Value::I16),
1258 (Value::I32(x), Value::I32(y)) => x.checked_mul(*y).map(Value::I32),
1259 (Value::I64(x), Value::I64(y)) => x.checked_mul(*y).map(Value::I64),
1260 (Value::I128(x), Value::I128(y)) => x.checked_mul(*y).map(Value::I128),
1261 (Value::Field(x), Value::Field(y)) => Some(Value::Field(*x * *y)),
1262 (Value::Group(x), Value::Scalar(y)) => Some(Value::Group(*x * *y)),
1263 (Value::Scalar(x), Value::Group(y)) => Some(Value::Group(*x * *y)),
1264 _ => halt!(span, "Type error"),
1265 }) else {
1266 halt!(span, "mul overflow");
1267 };
1268 value
1269 }
1270 BinaryOperation::MulWrapped => match (lhs, rhs) {
1271 (Value::U8(x), Value::U8(y)) => Value::U8(x.wrapping_mul(*y)),
1272 (Value::U16(x), Value::U16(y)) => Value::U16(x.wrapping_mul(*y)),
1273 (Value::U32(x), Value::U32(y)) => Value::U32(x.wrapping_mul(*y)),
1274 (Value::U64(x), Value::U64(y)) => Value::U64(x.wrapping_mul(*y)),
1275 (Value::U128(x), Value::U128(y)) => Value::U128(x.wrapping_mul(*y)),
1276 (Value::I8(x), Value::I8(y)) => Value::I8(x.wrapping_mul(*y)),
1277 (Value::I16(x), Value::I16(y)) => Value::I16(x.wrapping_mul(*y)),
1278 (Value::I32(x), Value::I32(y)) => Value::I32(x.wrapping_mul(*y)),
1279 (Value::I64(x), Value::I64(y)) => Value::I64(x.wrapping_mul(*y)),
1280 (Value::I128(x), Value::I128(y)) => Value::I128(x.wrapping_mul(*y)),
1281 _ => halt!(span, "Type error"),
1282 },
1283
1284 BinaryOperation::Nand => match (lhs, rhs) {
1285 (Value::Bool(x), Value::Bool(y)) => Value::Bool(!(x & y)),
1286 _ => halt!(span, "Type error"),
1287 },
1288 BinaryOperation::Neq => Value::Bool(lhs.neq(rhs)?),
1289 BinaryOperation::Nor => match (lhs, rhs) {
1290 (Value::Bool(x), Value::Bool(y)) => Value::Bool(!(x | y)),
1291 _ => halt!(span, "Type error"),
1292 },
1293 BinaryOperation::Or => match (lhs, rhs) {
1294 (Value::Bool(x), Value::Bool(y)) => Value::Bool(x | y),
1295 _ => halt!(span, "Type error"),
1296 },
1297 BinaryOperation::BitwiseOr => match (lhs, rhs) {
1298 (Value::Bool(x), Value::Bool(y)) => Value::Bool(x | y),
1299 (Value::U8(x), Value::U8(y)) => Value::U8(x | y),
1300 (Value::U16(x), Value::U16(y)) => Value::U16(x | y),
1301 (Value::U32(x), Value::U32(y)) => Value::U32(x | y),
1302 (Value::U64(x), Value::U64(y)) => Value::U64(x | y),
1303 (Value::U128(x), Value::U128(y)) => Value::U128(x | y),
1304 (Value::I8(x), Value::I8(y)) => Value::I8(x | y),
1305 (Value::I16(x), Value::I16(y)) => Value::I16(x | y),
1306 (Value::I32(x), Value::I32(y)) => Value::I32(x | y),
1307 (Value::I64(x), Value::I64(y)) => Value::I64(x | y),
1308 (Value::I128(x), Value::I128(y)) => Value::I128(x | y),
1309 _ => halt!(span, "Type error"),
1310 },
1311 BinaryOperation::Pow => {
1312 if let (Value::Field(x), Value::Field(y)) = (&lhs, &rhs) {
1313 Value::Field(x.pow(y))
1314 } else {
1315 let rhs: u32 = match rhs {
1316 Value::U8(y) => (*y).into(),
1317 Value::U16(y) => (*y).into(),
1318 Value::U32(y) => *y,
1319 _ => tc_fail!(),
1320 };
1321
1322 let Some(value) = (match lhs {
1323 Value::U8(x) => x.checked_pow(rhs).map(Value::U8),
1324 Value::U16(x) => x.checked_pow(rhs).map(Value::U16),
1325 Value::U32(x) => x.checked_pow(rhs).map(Value::U32),
1326 Value::U64(x) => x.checked_pow(rhs).map(Value::U64),
1327 Value::U128(x) => x.checked_pow(rhs).map(Value::U128),
1328 Value::I8(x) => x.checked_pow(rhs).map(Value::I8),
1329 Value::I16(x) => x.checked_pow(rhs).map(Value::I16),
1330 Value::I32(x) => x.checked_pow(rhs).map(Value::I32),
1331 Value::I64(x) => x.checked_pow(rhs).map(Value::I64),
1332 Value::I128(x) => x.checked_pow(rhs).map(Value::I128),
1333 _ => halt!(span, "Type error"),
1334 }) else {
1335 halt!(span, "pow overflow");
1336 };
1337 value
1338 }
1339 }
1340 BinaryOperation::PowWrapped => {
1341 let rhs: u32 = match rhs {
1342 Value::U8(y) => (*y).into(),
1343 Value::U16(y) => (*y).into(),
1344 Value::U32(y) => *y,
1345 _ => halt!(span, "Type error"),
1346 };
1347
1348 match lhs {
1349 Value::U8(x) => Value::U8(x.wrapping_pow(rhs)),
1350 Value::U16(x) => Value::U16(x.wrapping_pow(rhs)),
1351 Value::U32(x) => Value::U32(x.wrapping_pow(rhs)),
1352 Value::U64(x) => Value::U64(x.wrapping_pow(rhs)),
1353 Value::U128(x) => Value::U128(x.wrapping_pow(rhs)),
1354 Value::I8(x) => Value::I8(x.wrapping_pow(rhs)),
1355 Value::I16(x) => Value::I16(x.wrapping_pow(rhs)),
1356 Value::I32(x) => Value::I32(x.wrapping_pow(rhs)),
1357 Value::I64(x) => Value::I64(x.wrapping_pow(rhs)),
1358 Value::I128(x) => Value::I128(x.wrapping_pow(rhs)),
1359 _ => halt!(span, "Type error"),
1360 }
1361 }
1362 BinaryOperation::Rem => {
1363 let Some(value) = (match (lhs, rhs) {
1364 (Value::U8(x), Value::U8(y)) => x.checked_rem(*y).map(Value::U8),
1365 (Value::U16(x), Value::U16(y)) => x.checked_rem(*y).map(Value::U16),
1366 (Value::U32(x), Value::U32(y)) => x.checked_rem(*y).map(Value::U32),
1367 (Value::U64(x), Value::U64(y)) => x.checked_rem(*y).map(Value::U64),
1368 (Value::U128(x), Value::U128(y)) => x.checked_rem(*y).map(Value::U128),
1369 (Value::I8(x), Value::I8(y)) => x.checked_rem(*y).map(Value::I8),
1370 (Value::I16(x), Value::I16(y)) => x.checked_rem(*y).map(Value::I16),
1371 (Value::I32(x), Value::I32(y)) => x.checked_rem(*y).map(Value::I32),
1372 (Value::I64(x), Value::I64(y)) => x.checked_rem(*y).map(Value::I64),
1373 (Value::I128(x), Value::I128(y)) => x.checked_rem(*y).map(Value::I128),
1374 _ => halt!(span, "Type error"),
1375 }) else {
1376 halt!(span, "rem error");
1377 };
1378 value
1379 }
1380 BinaryOperation::RemWrapped => match (lhs, rhs) {
1381 (Value::U8(_), Value::U8(0))
1382 | (Value::U16(_), Value::U16(0))
1383 | (Value::U32(_), Value::U32(0))
1384 | (Value::U64(_), Value::U64(0))
1385 | (Value::U128(_), Value::U128(0))
1386 | (Value::I8(_), Value::I8(0))
1387 | (Value::I16(_), Value::I16(0))
1388 | (Value::I32(_), Value::I32(0))
1389 | (Value::I64(_), Value::I64(0))
1390 | (Value::I128(_), Value::I128(0)) => halt!(span, "rem by 0"),
1391 (Value::U8(x), Value::U8(y)) => Value::U8(x.wrapping_rem(*y)),
1392 (Value::U16(x), Value::U16(y)) => Value::U16(x.wrapping_rem(*y)),
1393 (Value::U32(x), Value::U32(y)) => Value::U32(x.wrapping_rem(*y)),
1394 (Value::U64(x), Value::U64(y)) => Value::U64(x.wrapping_rem(*y)),
1395 (Value::U128(x), Value::U128(y)) => Value::U128(x.wrapping_rem(*y)),
1396 (Value::I8(x), Value::I8(y)) => Value::I8(x.wrapping_rem(*y)),
1397 (Value::I16(x), Value::I16(y)) => Value::I16(x.wrapping_rem(*y)),
1398 (Value::I32(x), Value::I32(y)) => Value::I32(x.wrapping_rem(*y)),
1399 (Value::I64(x), Value::I64(y)) => Value::I64(x.wrapping_rem(*y)),
1400 (Value::I128(x), Value::I128(y)) => Value::I128(x.wrapping_rem(*y)),
1401 _ => halt!(span, "Type error"),
1402 },
1403 BinaryOperation::Shl => {
1404 let rhs: u32 = match rhs {
1405 Value::U8(y) => (*y).into(),
1406 Value::U16(y) => (*y).into(),
1407 Value::U32(y) => *y,
1408 _ => halt!(span, "Type error"),
1409 };
1410 match lhs {
1411 Value::U8(_) | Value::I8(_) if rhs >= 8 => halt!(span, "shl overflow"),
1412 Value::U16(_) | Value::I16(_) if rhs >= 16 => halt!(span, "shl overflow"),
1413 Value::U32(_) | Value::I32(_) if rhs >= 32 => halt!(span, "shl overflow"),
1414 Value::U64(_) | Value::I64(_) if rhs >= 64 => halt!(span, "shl overflow"),
1415 Value::U128(_) | Value::I128(_) if rhs >= 128 => halt!(span, "shl overflow"),
1416 _ => {}
1417 }
1418
1419 let shifted = lhs.simple_shl(rhs);
1421 let reshifted = shifted.simple_shr(rhs);
1422 if lhs.eq(&reshifted)? {
1423 shifted
1424 } else {
1425 halt!(span, "shl overflow");
1426 }
1427 }
1428
1429 BinaryOperation::ShlWrapped => {
1430 let rhs: u32 = match rhs {
1431 Value::U8(y) => (*y).into(),
1432 Value::U16(y) => (*y).into(),
1433 Value::U32(y) => *y,
1434 _ => halt!(span, "Type error"),
1435 };
1436 match lhs {
1437 Value::U8(x) => Value::U8(x.wrapping_shl(rhs)),
1438 Value::U16(x) => Value::U16(x.wrapping_shl(rhs)),
1439 Value::U32(x) => Value::U32(x.wrapping_shl(rhs)),
1440 Value::U64(x) => Value::U64(x.wrapping_shl(rhs)),
1441 Value::U128(x) => Value::U128(x.wrapping_shl(rhs)),
1442 Value::I8(x) => Value::I8(x.wrapping_shl(rhs)),
1443 Value::I16(x) => Value::I16(x.wrapping_shl(rhs)),
1444 Value::I32(x) => Value::I32(x.wrapping_shl(rhs)),
1445 Value::I64(x) => Value::I64(x.wrapping_shl(rhs)),
1446 Value::I128(x) => Value::I128(x.wrapping_shl(rhs)),
1447 _ => halt!(span, "Type error"),
1448 }
1449 }
1450
1451 BinaryOperation::Shr => {
1452 let rhs: u32 = match rhs {
1453 Value::U8(y) => (*y).into(),
1454 Value::U16(y) => (*y).into(),
1455 Value::U32(y) => *y,
1456 _ => halt!(span, "Type error"),
1457 };
1458
1459 match lhs {
1460 Value::U8(_) | Value::I8(_) if rhs >= 8 => halt!(span, "shr overflow"),
1461 Value::U16(_) | Value::I16(_) if rhs >= 16 => halt!(span, "shr overflow"),
1462 Value::U32(_) | Value::I32(_) if rhs >= 32 => halt!(span, "shr overflow"),
1463 Value::U64(_) | Value::I64(_) if rhs >= 64 => halt!(span, "shr overflow"),
1464 Value::U128(_) | Value::I128(_) if rhs >= 128 => halt!(span, "shr overflow"),
1465 _ => {}
1466 }
1467
1468 lhs.simple_shr(rhs)
1469 }
1470
1471 BinaryOperation::ShrWrapped => {
1472 let rhs: u32 = match rhs {
1473 Value::U8(y) => (*y).into(),
1474 Value::U16(y) => (*y).into(),
1475 Value::U32(y) => *y,
1476 _ => halt!(span, "Type error"),
1477 };
1478
1479 match lhs {
1480 Value::U8(x) => Value::U8(x.wrapping_shr(rhs)),
1481 Value::U16(x) => Value::U16(x.wrapping_shr(rhs)),
1482 Value::U32(x) => Value::U32(x.wrapping_shr(rhs)),
1483 Value::U64(x) => Value::U64(x.wrapping_shr(rhs)),
1484 Value::U128(x) => Value::U128(x.wrapping_shr(rhs)),
1485 Value::I8(x) => Value::I8(x.wrapping_shr(rhs)),
1486 Value::I16(x) => Value::I16(x.wrapping_shr(rhs)),
1487 Value::I32(x) => Value::I32(x.wrapping_shr(rhs)),
1488 Value::I64(x) => Value::I64(x.wrapping_shr(rhs)),
1489 Value::I128(x) => Value::I128(x.wrapping_shr(rhs)),
1490 _ => halt!(span, "Type error"),
1491 }
1492 }
1493
1494 BinaryOperation::Sub => {
1495 let Some(value) = (match (lhs, rhs) {
1496 (Value::U8(x), Value::U8(y)) => x.checked_sub(*y).map(Value::U8),
1497 (Value::U16(x), Value::U16(y)) => x.checked_sub(*y).map(Value::U16),
1498 (Value::U32(x), Value::U32(y)) => x.checked_sub(*y).map(Value::U32),
1499 (Value::U64(x), Value::U64(y)) => x.checked_sub(*y).map(Value::U64),
1500 (Value::U128(x), Value::U128(y)) => x.checked_sub(*y).map(Value::U128),
1501 (Value::I8(x), Value::I8(y)) => x.checked_sub(*y).map(Value::I8),
1502 (Value::I16(x), Value::I16(y)) => x.checked_sub(*y).map(Value::I16),
1503 (Value::I32(x), Value::I32(y)) => x.checked_sub(*y).map(Value::I32),
1504 (Value::I64(x), Value::I64(y)) => x.checked_sub(*y).map(Value::I64),
1505 (Value::I128(x), Value::I128(y)) => x.checked_sub(*y).map(Value::I128),
1506 (Value::Group(x), Value::Group(y)) => Some(Value::Group(*x - *y)),
1507 (Value::Field(x), Value::Field(y)) => Some(Value::Field(*x - *y)),
1508 _ => halt!(span, "Type error"),
1509 }) else {
1510 halt!(span, "sub overflow");
1511 };
1512 value
1513 }
1514
1515 BinaryOperation::SubWrapped => match (lhs, rhs) {
1516 (Value::U8(x), Value::U8(y)) => Value::U8(x.wrapping_sub(*y)),
1517 (Value::U16(x), Value::U16(y)) => Value::U16(x.wrapping_sub(*y)),
1518 (Value::U32(x), Value::U32(y)) => Value::U32(x.wrapping_sub(*y)),
1519 (Value::U64(x), Value::U64(y)) => Value::U64(x.wrapping_sub(*y)),
1520 (Value::U128(x), Value::U128(y)) => Value::U128(x.wrapping_sub(*y)),
1521 (Value::I8(x), Value::I8(y)) => Value::I8(x.wrapping_sub(*y)),
1522 (Value::I16(x), Value::I16(y)) => Value::I16(x.wrapping_sub(*y)),
1523 (Value::I32(x), Value::I32(y)) => Value::I32(x.wrapping_sub(*y)),
1524 (Value::I64(x), Value::I64(y)) => Value::I64(x.wrapping_sub(*y)),
1525 (Value::I128(x), Value::I128(y)) => Value::I128(x.wrapping_sub(*y)),
1526 _ => halt!(span, "Type error"),
1527 },
1528
1529 BinaryOperation::Xor => match (lhs, rhs) {
1530 (Value::Bool(x), Value::Bool(y)) => Value::Bool(*x ^ *y),
1531 (Value::U8(x), Value::U8(y)) => Value::U8(*x ^ *y),
1532 (Value::U16(x), Value::U16(y)) => Value::U16(*x ^ *y),
1533 (Value::U32(x), Value::U32(y)) => Value::U32(*x ^ *y),
1534 (Value::U64(x), Value::U64(y)) => Value::U64(*x ^ *y),
1535 (Value::U128(x), Value::U128(y)) => Value::U128(*x ^ *y),
1536 (Value::I8(x), Value::I8(y)) => Value::I8(*x ^ *y),
1537 (Value::I16(x), Value::I16(y)) => Value::I16(*x ^ *y),
1538 (Value::I32(x), Value::I32(y)) => Value::I32(*x ^ *y),
1539 (Value::I64(x), Value::I64(y)) => Value::I64(*x ^ *y),
1540 (Value::I128(x), Value::I128(y)) => Value::I128(*x ^ *y),
1541 _ => halt!(span, "Type error"),
1542 },
1543 };
1544 Ok(value)
1545}
1546
1547pub fn evaluate_unary(span: Span, op: UnaryOperation, value: &Value) -> Result<Value> {
1549 let value_result = match op {
1550 UnaryOperation::Abs => match value {
1551 Value::I8(x) => {
1552 if *x == i8::MIN {
1553 halt!(span, "abs overflow");
1554 } else {
1555 Value::I8(x.abs())
1556 }
1557 }
1558 Value::I16(x) => {
1559 if *x == i16::MIN {
1560 halt!(span, "abs overflow");
1561 } else {
1562 Value::I16(x.abs())
1563 }
1564 }
1565 Value::I32(x) => {
1566 if *x == i32::MIN {
1567 halt!(span, "abs overflow");
1568 } else {
1569 Value::I32(x.abs())
1570 }
1571 }
1572 Value::I64(x) => {
1573 if *x == i64::MIN {
1574 halt!(span, "abs overflow");
1575 } else {
1576 Value::I64(x.abs())
1577 }
1578 }
1579 Value::I128(x) => {
1580 if *x == i128::MIN {
1581 halt!(span, "abs overflow");
1582 } else {
1583 Value::I128(x.abs())
1584 }
1585 }
1586 _ => halt!(span, "Type error"),
1587 },
1588 UnaryOperation::AbsWrapped => match value {
1589 Value::I8(x) => Value::I8(x.unsigned_abs() as i8),
1590 Value::I16(x) => Value::I16(x.unsigned_abs() as i16),
1591 Value::I32(x) => Value::I32(x.unsigned_abs() as i32),
1592 Value::I64(x) => Value::I64(x.unsigned_abs() as i64),
1593 Value::I128(x) => Value::I128(x.unsigned_abs() as i128),
1594 _ => halt!(span, "Type error"),
1595 },
1596 UnaryOperation::Double => match value {
1597 Value::Field(x) => Value::Field(x.double()),
1598 Value::Group(x) => Value::Group(x.double()),
1599 _ => halt!(span, "Type error"),
1600 },
1601 UnaryOperation::Inverse => match value {
1602 Value::Field(x) => {
1603 let Ok(y) = x.inverse() else {
1604 halt!(span, "attempt to invert 0field");
1605 };
1606 Value::Field(y)
1607 }
1608 _ => halt!(span, "Can only invert fields"),
1609 },
1610 UnaryOperation::Negate => match value {
1611 Value::I8(x) => match x.checked_neg() {
1612 None => halt!(span, "negation overflow"),
1613 Some(y) => Value::I8(y),
1614 },
1615 Value::I16(x) => match x.checked_neg() {
1616 None => halt!(span, "negation overflow"),
1617 Some(y) => Value::I16(y),
1618 },
1619 Value::I32(x) => match x.checked_neg() {
1620 None => halt!(span, "negation overflow"),
1621 Some(y) => Value::I32(y),
1622 },
1623 Value::I64(x) => match x.checked_neg() {
1624 None => halt!(span, "negation overflow"),
1625 Some(y) => Value::I64(y),
1626 },
1627 Value::I128(x) => match x.checked_neg() {
1628 None => halt!(span, "negation overflow"),
1629 Some(y) => Value::I128(y),
1630 },
1631 Value::Group(x) => Value::Group(-*x),
1632 Value::Field(x) => Value::Field(-*x),
1633 _ => halt!(span, "Type error"),
1634 },
1635 UnaryOperation::Not => match value {
1636 Value::Bool(x) => Value::Bool(!x),
1637 Value::U8(x) => Value::U8(!x),
1638 Value::U16(x) => Value::U16(!x),
1639 Value::U32(x) => Value::U32(!x),
1640 Value::U64(x) => Value::U64(!x),
1641 Value::U128(x) => Value::U128(!x),
1642 Value::I8(x) => Value::I8(!x),
1643 Value::I16(x) => Value::I16(!x),
1644 Value::I32(x) => Value::I32(!x),
1645 Value::I64(x) => Value::I64(!x),
1646 Value::I128(x) => Value::I128(!x),
1647 _ => halt!(span, "Type error"),
1648 },
1649 UnaryOperation::Square => match value {
1650 Value::Field(x) => Value::Field(x.square()),
1651 _ => halt!(span, "Can only square fields"),
1652 },
1653 UnaryOperation::SquareRoot => match value {
1654 Value::Field(x) => {
1655 let Ok(y) = x.square_root() else {
1656 halt!(span, "square root failure");
1657 };
1658 Value::Field(y)
1659 }
1660 _ => halt!(span, "Can only apply square_root to fields"),
1661 },
1662 UnaryOperation::ToXCoordinate => match value {
1663 Value::Group(x) => Value::Field(x.to_x_coordinate()),
1664 _ => tc_fail!(),
1665 },
1666 UnaryOperation::ToYCoordinate => match value {
1667 Value::Group(x) => Value::Field(x.to_y_coordinate()),
1668 _ => tc_fail!(),
1669 },
1670 };
1671
1672 Ok(value_result)
1673}
1674
1675pub fn literal_to_value(literal: &Literal) -> Result<Value> {
1676 fn prepare_snarkvm_string(s: &str, suffix: &str) -> String {
1679 let (neg, rest) = s.strip_prefix("-").map(|rest| ("-", rest)).unwrap_or(("", s));
1681 let mut rest = rest.trim_start_matches('0');
1683 if rest.is_empty() {
1684 rest = "0";
1685 }
1686 format!("{neg}{rest}{suffix}")
1687 }
1688
1689 let value = match &literal.variant {
1690 LiteralVariant::Boolean(b) => Value::Bool(*b),
1691 LiteralVariant::Integer(IntegerType::U8, s, ..) => {
1692 let s = s.replace("_", "");
1693 Value::U8(u8::from_str_by_radix(&s).expect("Parsing guarantees this works."))
1694 }
1695 LiteralVariant::Integer(IntegerType::U16, s, ..) => {
1696 let s = s.replace("_", "");
1697 Value::U16(u16::from_str_by_radix(&s).expect("Parsing guarantees this works."))
1698 }
1699 LiteralVariant::Integer(IntegerType::U32, s, ..) => {
1700 let s = s.replace("_", "");
1701 Value::U32(u32::from_str_by_radix(&s).expect("Parsing guarantees this works."))
1702 }
1703 LiteralVariant::Integer(IntegerType::U64, s, ..) => {
1704 let s = s.replace("_", "");
1705 Value::U64(u64::from_str_by_radix(&s).expect("Parsing guarantees this works."))
1706 }
1707 LiteralVariant::Integer(IntegerType::U128, s, ..) => {
1708 let s = s.replace("_", "");
1709 Value::U128(u128::from_str_by_radix(&s).expect("Parsing guarantees this works."))
1710 }
1711 LiteralVariant::Integer(IntegerType::I8, s, ..) => {
1712 let s = s.replace("_", "");
1713 Value::I8(i8::from_str_by_radix(&s).expect("Parsing guarantees this works."))
1714 }
1715 LiteralVariant::Integer(IntegerType::I16, s, ..) => {
1716 let s = s.replace("_", "");
1717 Value::I16(i16::from_str_by_radix(&s).expect("Parsing guarantees this works."))
1718 }
1719 LiteralVariant::Integer(IntegerType::I32, s, ..) => {
1720 let s = s.replace("_", "");
1721 Value::I32(i32::from_str_by_radix(&s).expect("Parsing guarantees this works."))
1722 }
1723 LiteralVariant::Integer(IntegerType::I64, s, ..) => {
1724 let s = s.replace("_", "");
1725 Value::I64(i64::from_str_by_radix(&s).expect("Parsing guarantees this works."))
1726 }
1727 LiteralVariant::Integer(IntegerType::I128, s, ..) => {
1728 let s = s.replace("_", "");
1729 Value::I128(i128::from_str_by_radix(&s).expect("Parsing guarantees this works."))
1730 }
1731 LiteralVariant::Field(s) => Value::Field(prepare_snarkvm_string(s, "field").parse().expect_tc(literal.span())?),
1732 LiteralVariant::Group(s) => Value::Group(prepare_snarkvm_string(s, "group").parse().expect_tc(literal.span())?),
1733 LiteralVariant::Address(s) => {
1734 if s.ends_with(".aleo") {
1735 let program_id = ProgramID::from_str(s)?;
1736 Value::Address(program_id.to_address()?)
1737 } else {
1738 Value::Address(s.parse().expect_tc(literal.span())?)
1739 }
1740 }
1741 LiteralVariant::Scalar(s) => {
1742 Value::Scalar(prepare_snarkvm_string(s, "scalar").parse().expect_tc(literal.span())?)
1743 }
1744 LiteralVariant::String(..) => tc_fail!(),
1745 };
1746
1747 Ok(value)
1748}