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