1use std::{
18 collections::BTreeMap,
19 fmt,
20 hash::{Hash, Hasher},
21 str::FromStr,
22};
23
24use itertools::Itertools as _;
25
26use crate::Location;
27
28use snarkvm::prelude::{
29 Access,
30 Address as SvmAddress,
31 Argument,
32 Boolean as SvmBoolean,
33 Entry,
34 Field as SvmField,
35 Future as FutureParam,
36 Group as SvmGroup,
37 LiteralType,
38 Owner,
39 ProgramID as ProgramIDParam,
40 Record,
41 Scalar as SvmScalar,
42};
43pub(crate) use snarkvm::prelude::{
44 Identifier as SvmIdentifierParam,
45 Literal as SvmLiteralParam,
46 Plaintext,
47 Signature as SvmSignature,
48 TestnetV0,
49 Value as SvmValueParam,
50};
51
52use leo_errors::Result;
53use leo_span::{Span, Symbol};
54
55use crate::{Expression, IntegerType, NodeBuilder, Type};
56
57pub(crate) type CurrentNetwork = TestnetV0;
58
59pub(crate) type SvmValue = SvmValueParam<CurrentNetwork>;
60pub(crate) type ProgramID = ProgramIDParam<CurrentNetwork>;
61pub(crate) type SvmPlaintext = Plaintext<CurrentNetwork>;
62pub(crate) type SvmLiteral = SvmLiteralParam<CurrentNetwork>;
63pub(crate) type SvmIdentifier = SvmIdentifierParam<CurrentNetwork>;
64pub(crate) type Group = SvmGroup<CurrentNetwork>;
65pub(crate) type Field = SvmField<CurrentNetwork>;
66pub(crate) type Scalar = SvmScalar<CurrentNetwork>;
67pub(crate) type Address = SvmAddress<CurrentNetwork>;
68pub(crate) type Boolean = SvmBoolean<CurrentNetwork>;
69pub(crate) type Future = FutureParam<CurrentNetwork>;
70pub(crate) type Signature = SvmSignature<CurrentNetwork>;
71
72#[derive(Clone, Debug, Eq, PartialEq)]
73pub struct StructContents {
74 pub path: Vec<Symbol>,
75}
76
77#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
78pub struct Value {
79 pub id: Option<Location>,
80 pub(crate) contents: ValueVariants,
81}
82
83#[derive(Clone, Default, Debug, Eq, PartialEq)]
84#[allow(clippy::large_enum_variant)]
86pub(crate) enum ValueVariants {
87 #[default]
88 Unit,
89 Svm(SvmValue),
90 Tuple(Vec<Value>),
91 Unsuffixed(String),
92 Future(Vec<AsyncExecution>),
93 String(String),
94}
95
96#[derive(Clone, Debug, Eq, PartialEq, Hash)]
97pub enum AsyncExecution {
98 AsyncFunctionCall {
99 function: Location,
100 arguments: Vec<Value>,
101 },
102 AsyncBlock {
103 containing_function: Location, block: crate::NodeID,
105 names: BTreeMap<Vec<Symbol>, Value>, },
107}
108
109impl fmt::Display for AsyncExecution {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 write!(f, " async call to ")?;
112
113 match self {
114 AsyncExecution::AsyncFunctionCall { function, .. } => {
115 write!(f, "{function}")
116 }
117 AsyncExecution::AsyncBlock { containing_function, .. } => {
118 write!(f, "{containing_function}/<async block>")
119 }
120 }
121 }
122}
123
124fn hash_plaintext<H>(pt: &SvmPlaintext, state: &mut H)
125where
126 H: Hasher,
127{
128 match pt {
129 Plaintext::Literal(literal, ..) => {
130 6u8.hash(state);
131 literal.hash(state);
132 }
133 Plaintext::Struct(index_map, ..) => {
134 7u8.hash(state);
135 index_map.len().hash(state);
136 index_map.iter().for_each(|(key, value)| {
139 key.hash(state);
140 hash_plaintext(value, state);
141 });
142 }
143 Plaintext::Array(vec, ..) => {
144 8u8.hash(state);
145 vec.len().hash(state);
146 vec.iter().for_each(|pt0| hash_plaintext(pt0, state));
147 }
148 }
149}
150
151impl Hash for ValueVariants {
152 fn hash<H>(&self, state: &mut H)
153 where
154 H: Hasher,
155 {
156 use ValueVariants::*;
157
158 match self {
159 Unit => 0u8.hash(state),
160 Tuple(vec) => {
161 1u8.hash(state);
162 vec.len().hash(state);
163 }
164 Unsuffixed(s) => {
165 2u8.hash(state);
166 s.hash(state);
167 }
168 Future(async_executions) => {
169 3u8.hash(state);
170 async_executions.hash(state);
171 }
172 Svm(value) => match value {
173 SvmValueParam::Record(record) => {
174 4u8.hash(state);
175 (**record.version()).hash(state);
176 record.nonce().hash(state);
177 }
182 SvmValueParam::Future(future) => {
183 5u8.hash(state);
184 future.program_id().hash(state);
185 future.function_name().hash(state);
186 }
188 SvmValueParam::Plaintext(plaintext) => {
189 hash_plaintext(plaintext, state);
190 }
191 },
192 String(s) => {
193 9u8.hash(state);
194 s.hash(state);
195 }
196 }
197 }
198}
199
200impl From<ValueVariants> for Value {
201 fn from(contents: ValueVariants) -> Self {
202 Value { id: None, contents }
203 }
204}
205
206pub trait TryAsRef<T>
207where
208 T: ?Sized,
209{
210 fn try_as_ref(&self) -> Option<&T>;
211}
212
213macro_rules! impl_from_integer {
214 ($($int_type: ident $variant: ident);* $(;)?) => {
215 $(
216 impl From<$int_type> for Value {
217 fn from(value: $int_type) -> Self {
218 ValueVariants::Svm(
219 SvmValueParam::Plaintext(
220 Plaintext::Literal(
221 snarkvm::prelude::$variant::new(value).into(),
222 Default::default(),
223 )
224 )
225 ).into()
226 }
227 }
228
229 impl From<snarkvm::prelude::$variant<CurrentNetwork>> for Value {
230 fn from(x: snarkvm::prelude::$variant<CurrentNetwork>) -> Self {
231 ValueVariants::Svm(SvmValueParam::Plaintext(
232 Plaintext::Literal(
233 SvmLiteralParam::$variant(x),
234 Default::default()
235 )
236 )).into()
237 }
238 }
239
240 impl TryFrom<Value> for $int_type {
241 type Error = ();
242
243 fn try_from(value: Value) -> Result<$int_type, Self::Error> {
244 match value.contents {
245 ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(SvmLiteralParam::$variant(x), _))) => Ok(*x),
246 _ => Err(()),
247 }
248 }
249 }
250
251 impl TryAsRef<$int_type> for Value {
252 fn try_as_ref(&self) -> Option<&$int_type> {
253 match &self.contents {
254 ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(SvmLiteralParam::$variant(x), _))) => Some(&*x),
255 _ => None,
256 }
257 }
258 }
259 )*
260 };
261}
262
263impl_from_integer! {
264 u8 U8;
265 u16 U16;
266 u32 U32;
267 u64 U64;
268 u128 U128;
269 i8 I8;
270 i16 I16;
271 i32 I32;
272 i64 I64;
273 i128 I128;
274 bool Boolean;
275}
276
277macro_rules! impl_from_literal {
278 ($($type_: ident);* $(;)?) => {
279 $(
280 impl From<snarkvm::prelude::$type_<CurrentNetwork>> for Value {
281 fn from(x: snarkvm::prelude::$type_<CurrentNetwork>) -> Self {
282 let literal: SvmLiteral = x.into();
283 ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(literal, Default::default()))).into()
284 }
285 }
286
287 impl TryFrom<Value> for snarkvm::prelude::$type_<CurrentNetwork> {
288 type Error = ();
289
290 fn try_from(x: Value) -> Result<Self, Self::Error> {
291 if let ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(SvmLiteralParam::$type_(val), ..))) = x.contents {
292 Ok(val)
293 } else {
294 Err(())
295 }
296 }
297 }
298 )*
299 };
300}
301
302impl_from_literal! {
303 Field; Group; Scalar; Address;
304}
305
306impl TryFrom<Value> for snarkvm::prelude::Signature<CurrentNetwork> {
307 type Error = ();
308
309 fn try_from(x: Value) -> Result<Self, Self::Error> {
310 if let ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(SvmLiteralParam::Signature(val), ..))) =
311 x.contents
312 {
313 Ok(*val)
314 } else {
315 Err(())
316 }
317 }
318}
319
320impl From<Future> for Value {
321 fn from(value: Future) -> Self {
322 SvmValueParam::Future(value).into()
323 }
324}
325
326impl TryAsRef<SvmLiteral> for Value {
327 fn try_as_ref(&self) -> Option<&SvmLiteral> {
328 match &self.contents {
329 ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(literal, ..))) => Some(literal),
330 _ => None,
331 }
332 }
333}
334
335impl From<SvmLiteral> for Value {
336 fn from(x: SvmLiteral) -> Self {
337 ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(x, Default::default()))).into()
338 }
339}
340
341impl TryFrom<Value> for SvmValue {
342 type Error = ();
343
344 fn try_from(value: Value) -> Result<Self, Self::Error> {
345 if let ValueVariants::Svm(x) = value.contents { Ok(x) } else { Err(()) }
346 }
347}
348
349impl TryFrom<Value> for SvmPlaintext {
350 type Error = ();
351
352 fn try_from(value: Value) -> Result<Self, Self::Error> {
353 if let ValueVariants::Svm(SvmValueParam::Plaintext(x)) = value.contents { Ok(x) } else { Err(()) }
354 }
355}
356
357impl TryAsRef<SvmPlaintext> for Value {
358 fn try_as_ref(&self) -> Option<&SvmPlaintext> {
359 if let ValueVariants::Svm(SvmValueParam::Plaintext(x)) = &self.contents { Some(x) } else { None }
360 }
361}
362
363impl From<SvmPlaintext> for Value {
364 fn from(x: SvmPlaintext) -> Self {
365 ValueVariants::Svm(SvmValueParam::Plaintext(x)).into()
366 }
367}
368
369impl From<SvmValue> for Value {
370 fn from(x: SvmValue) -> Self {
371 ValueVariants::Svm(x).into()
372 }
373}
374
375impl From<Vec<AsyncExecution>> for Value {
376 fn from(x: Vec<AsyncExecution>) -> Self {
377 ValueVariants::Future(x).into()
378 }
379}
380
381impl TryFrom<Value> for String {
382 type Error = ();
383
384 fn try_from(value: Value) -> Result<Self, Self::Error> {
385 if let ValueVariants::String(s) = value.contents { Ok(s) } else { Err(()) }
386 }
387}
388
389impl fmt::Display for Value {
390 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
391 match &self.contents {
392 ValueVariants::Unit => "()".fmt(f),
393 ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Struct(struct_, ..))) => {
394 if let Some(id) = &self.id {
395 write!(f, "{id} ")?
396 }
397 let mut debug_map = f.debug_map();
398 for (key, value) in struct_ {
399 debug_map.entry(key, value);
400 }
401 debug_map.finish()
402 }
403 ValueVariants::Svm(value) => value.fmt(f),
404 ValueVariants::Tuple(vec) => write!(f, "({})", vec.iter().format(", ")),
405 ValueVariants::Unsuffixed(s) => s.fmt(f),
406 ValueVariants::Future(_async_executions) => "Future".fmt(f),
407 ValueVariants::String(s) => write!(f, "\"{s}\""),
408 }
409 }
410}
411
412impl Value {
413 pub fn lt(&self, rhs: &Self) -> Option<bool> {
414 use SvmLiteralParam::*;
415
416 let literal0: &SvmLiteral = self.try_as_ref()?;
417 let literal1: &SvmLiteral = rhs.try_as_ref()?;
418
419 let value = match (literal0, literal1) {
420 (I8(val0), I8(val1)) => val0 < val1,
421 (I16(val0), I16(val1)) => val0 < val1,
422 (I32(val0), I32(val1)) => val0 < val1,
423 (I64(val0), I64(val1)) => val0 < val1,
424 (I128(val0), I128(val1)) => val0 < val1,
425 (U8(val0), U8(val1)) => val0 < val1,
426 (U16(val0), U16(val1)) => val0 < val1,
427 (U32(val0), U32(val1)) => val0 < val1,
428 (U64(val0), U64(val1)) => val0 < val1,
429 (U128(val0), U128(val1)) => val0 < val1,
430 (Field(val0), Field(val1)) => val0 < val1,
431 _ => return None,
432 };
433
434 Some(value)
435 }
436
437 pub fn lte(&self, rhs: &Self) -> Option<bool> {
438 use SvmLiteralParam::*;
439
440 let literal0: &SvmLiteral = self.try_as_ref()?;
441 let literal1: &SvmLiteral = rhs.try_as_ref()?;
442
443 let value = match (literal0, literal1) {
444 (I8(val0), I8(val1)) => val0 <= val1,
445 (I16(val0), I16(val1)) => val0 <= val1,
446 (I32(val0), I32(val1)) => val0 <= val1,
447 (I64(val0), I64(val1)) => val0 <= val1,
448 (I128(val0), I128(val1)) => val0 <= val1,
449 (U8(val0), U8(val1)) => val0 <= val1,
450 (U16(val0), U16(val1)) => val0 <= val1,
451 (U32(val0), U32(val1)) => val0 <= val1,
452 (U64(val0), U64(val1)) => val0 <= val1,
453 (U128(val0), U128(val1)) => val0 <= val1,
454 (Field(val0), Field(val1)) => val0 <= val1,
455 _ => return None,
456 };
457
458 Some(value)
459 }
460
461 pub fn gt(&self, rhs: &Self) -> Option<bool> {
462 rhs.lt(self)
463 }
464
465 pub fn gte(&self, rhs: &Self) -> Option<bool> {
466 rhs.lte(self)
467 }
468
469 pub fn inc_wrapping(&self) -> Option<Self> {
470 let literal: &SvmLiteral = self.try_as_ref()?;
471
472 let value = match literal {
473 SvmLiteralParam::U8(x) => x.wrapping_add(1).into(),
474 SvmLiteralParam::U16(x) => x.wrapping_add(1).into(),
475 SvmLiteralParam::U32(x) => x.wrapping_add(1).into(),
476 SvmLiteralParam::U64(x) => x.wrapping_add(1).into(),
477 SvmLiteralParam::U128(x) => x.wrapping_add(1).into(),
478 SvmLiteralParam::I8(x) => x.wrapping_add(1).into(),
479 SvmLiteralParam::I16(x) => x.wrapping_add(1).into(),
480 SvmLiteralParam::I32(x) => x.wrapping_add(1).into(),
481 SvmLiteralParam::I64(x) => x.wrapping_add(1).into(),
482 SvmLiteralParam::I128(x) => x.wrapping_add(1).into(),
483 _ => return None,
484 };
485 Some(value)
486 }
487
488 pub fn add(&self, i: usize) -> Option<Self> {
489 let literal: &SvmLiteral = self.try_as_ref()?;
490
491 macro_rules! sum {
492 ($ty: ident, $int: ident) => {{
493 let rhs: $ty = i.try_into().ok()?;
494 (**$int + rhs).into()
495 }};
496 }
497
498 let value = match literal {
499 SvmLiteralParam::I8(int) => sum!(i8, int),
500 SvmLiteralParam::I16(int) => sum!(i16, int),
501 SvmLiteralParam::I32(int) => sum!(i32, int),
502 SvmLiteralParam::I64(int) => sum!(i64, int),
503 SvmLiteralParam::I128(int) => sum!(i128, int),
504 SvmLiteralParam::U8(int) => sum!(u8, int),
505 SvmLiteralParam::U16(int) => sum!(u16, int),
506 SvmLiteralParam::U32(int) => sum!(u32, int),
507 SvmLiteralParam::U64(int) => sum!(u64, int),
508 SvmLiteralParam::U128(int) => sum!(u128, int),
509 SvmLiteralParam::Address(..)
510 | SvmLiteralParam::Boolean(..)
511 | SvmLiteralParam::Field(..)
512 | SvmLiteralParam::Group(..)
513 | SvmLiteralParam::Scalar(..)
514 | SvmLiteralParam::Signature(..)
515 | SvmLiteralParam::String(..) => return None,
516 };
517 Some(value)
518 }
519
520 pub fn cast(&self, ty: &Type) -> Option<Self> {
521 let literal_ty = match ty {
522 Type::Address => LiteralType::Address,
523 Type::Boolean => LiteralType::Boolean,
524 Type::Field => LiteralType::Field,
525 Type::Group => LiteralType::Group,
526 Type::Integer(IntegerType::U8) => LiteralType::U8,
527 Type::Integer(IntegerType::U16) => LiteralType::U16,
528 Type::Integer(IntegerType::U32) => LiteralType::U32,
529 Type::Integer(IntegerType::U64) => LiteralType::U64,
530 Type::Integer(IntegerType::U128) => LiteralType::U128,
531 Type::Integer(IntegerType::I8) => LiteralType::I8,
532 Type::Integer(IntegerType::I16) => LiteralType::I16,
533 Type::Integer(IntegerType::I32) => LiteralType::I32,
534 Type::Integer(IntegerType::I64) => LiteralType::I64,
535 Type::Integer(IntegerType::I128) => LiteralType::I128,
536 Type::Scalar => LiteralType::Scalar,
537 Type::Signature => LiteralType::Signature,
538 Type::String => LiteralType::String,
539 _ => return None,
540 };
541
542 let literal: &SvmLiteral = self.try_as_ref()?;
543
544 Some(literal.cast(literal_ty).ok()?.into())
545 }
546
547 pub fn cast_lossy(&self, ty: &LiteralType) -> Option<Self> {
548 let ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(literal, ..))) = &self.contents else {
549 return None;
550 };
551 literal.cast_lossy(*ty).ok().map(|lit| lit.into())
552 }
553
554 pub fn generator() -> Self {
556 Group::generator().into()
557 }
558
559 pub fn as_u32(&self) -> Option<u32> {
560 let literal = self.try_as_ref()?;
561 let value = match literal {
562 SvmLiteralParam::U8(x) => **x as u32,
563 SvmLiteralParam::U16(x) => **x as u32,
564 SvmLiteralParam::U32(x) => **x,
565 SvmLiteralParam::U64(x) => (**x).try_into().ok()?,
566 SvmLiteralParam::U128(x) => (**x).try_into().ok()?,
567 SvmLiteralParam::I8(x) => (**x).try_into().ok()?,
568 SvmLiteralParam::I16(x) => (**x).try_into().ok()?,
569 SvmLiteralParam::I32(x) => (**x).try_into().ok()?,
570 SvmLiteralParam::I64(x) => (**x).try_into().ok()?,
571 SvmLiteralParam::I128(x) => (**x).try_into().ok()?,
572 _ => return None,
573 };
574 Some(value)
575 }
576
577 pub fn as_i128(&self) -> Option<i128> {
578 let literal = self.try_as_ref()?;
579 let value = match literal {
580 SvmLiteralParam::U8(x) => **x as i128,
581 SvmLiteralParam::U16(x) => **x as i128,
582 SvmLiteralParam::U32(x) => **x as i128,
583 SvmLiteralParam::U64(x) => **x as i128,
584 SvmLiteralParam::U128(x) => (**x).try_into().ok()?,
585 SvmLiteralParam::I8(x) => **x as i128,
586 SvmLiteralParam::I16(x) => **x as i128,
587 SvmLiteralParam::I32(x) => **x as i128,
588 SvmLiteralParam::I64(x) => **x as i128,
589 SvmLiteralParam::I128(x) => **x,
590 _ => return None,
591 };
592 Some(value)
593 }
594
595 pub fn array_index(&self, i: usize) -> Option<Self> {
596 let plaintext: &SvmPlaintext = self.try_as_ref()?;
597 let Plaintext::Array(array, ..) = plaintext else {
598 return None;
599 };
600
601 Some(array[i].clone().into())
602 }
603
604 pub fn array_index_set(&mut self, i: usize, value: Self) -> Option<()> {
605 let plaintext_rhs: SvmPlaintext = value.try_into().ok()?;
606
607 let ValueVariants::Svm(SvmValue::Plaintext(Plaintext::Array(arr, once_cell))) = &mut self.contents else {
608 return None;
609 };
610 *once_cell = Default::default();
611
612 *arr.get_mut(i)? = plaintext_rhs;
613
614 Some(())
615 }
616
617 pub fn tuple_len(&self) -> Option<usize> {
618 let ValueVariants::Tuple(tuple) = &self.contents else {
619 return None;
620 };
621
622 Some(tuple.len())
623 }
624
625 pub fn tuple_index(&self, i: usize) -> Option<Self> {
626 let ValueVariants::Tuple(tuple) = &self.contents else {
627 return None;
628 };
629
630 Some(tuple[i].clone())
631 }
632
633 pub fn tuple_index_set(&mut self, i: usize, value: Self) -> Option<()> {
634 let ValueVariants::Tuple(tuple) = &mut self.contents else {
635 return None;
636 };
637
638 *tuple.get_mut(i)? = value;
639
640 Some(())
641 }
642
643 pub fn as_future(&self) -> Option<&[AsyncExecution]> {
644 if let ValueVariants::Future(asyncs) = &self.contents { Some(asyncs) } else { None }
645 }
646
647 pub fn accesses(&self, accesses: impl IntoIterator<Item = Access<CurrentNetwork>>) -> Option<Value> {
648 self.accesses_impl(&mut accesses.into_iter())
649 }
650
651 fn accesses_impl(&self, accesses: &mut dyn Iterator<Item = Access<CurrentNetwork>>) -> Option<Value> {
652 let ValueVariants::Svm(SvmValueParam::Plaintext(current)) = &self.contents else {
653 return None;
654 };
655
656 let mut current = current;
657
658 for access in accesses {
659 current = match (access, current) {
660 (Access::Member(identifier), Plaintext::Struct(struct_, ..)) => struct_.get(&identifier)?,
661 (Access::Index(integer), Plaintext::Array(array, ..)) => array.get(*integer as usize)?,
662 _ => return None,
663 };
664 }
665
666 Some(current.clone().into())
667 }
668
669 pub fn member_access(&self, member: Symbol) -> Option<Self> {
670 match &self.contents {
671 ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Struct(map, ..))) => {
672 let identifier: SvmIdentifier =
673 member.to_string().parse().expect("Member name should be valid identifier");
674 Some(map.get(&identifier)?.clone().into())
675 }
676 _ => None,
677 }
678 }
679
680 pub fn member_set(&mut self, member: Symbol, value: Value) -> Option<()> {
681 let plaintext: SvmPlaintext = value.try_into().ok()?;
682 match &mut self.contents {
683 ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Struct(map, once_cell))) => {
684 *once_cell = Default::default();
685 let identifier: SvmIdentifier = member.to_string().parse().ok()?;
686 *map.get_mut(&identifier)? = plaintext;
687 Some(())
688 }
689
690 _ => None,
691 }
692 }
693
694 pub fn make_future(
695 program_name: Symbol,
696 function: Symbol,
697 arguments: impl IntoIterator<Item = Value>,
698 ) -> Option<Value> {
699 Self::make_future_impl(program_name, function, &mut arguments.into_iter())
700 }
701
702 fn make_future_impl(
703 program_name: Symbol,
704 function: Symbol,
705 arguments: &mut dyn Iterator<Item = Value>,
706 ) -> Option<Value> {
707 let program = ProgramID::try_from(format!("{program_name}.aleo")).ok()?;
708
709 let function_identifier: SvmIdentifier = function.to_string().parse().ok()?;
710
711 let arguments_vec = arguments
712 .map(|value| match value.contents {
713 ValueVariants::Svm(SvmValueParam::Plaintext(plaintext)) => Some(Argument::Plaintext(plaintext)),
714 ValueVariants::Svm(SvmValueParam::Future(future)) => Some(Argument::Future(future)),
715 _ => None,
716 })
717 .collect::<Option<Vec<_>>>()?;
718
719 Some(Future::new(program, function_identifier, arguments_vec).into())
720 }
721
722 pub fn make_unit() -> Self {
723 Value { id: None, contents: ValueVariants::Unit }
724 }
725
726 pub fn make_struct(contents: impl Iterator<Item = (Symbol, Value)>, program: Symbol, path: Vec<Symbol>) -> Self {
727 let id = Some(Location { program, path });
728
729 let contents = Plaintext::Struct(
730 contents
731 .map(|(symbol, value)| {
732 let identifier =
733 symbol.to_string().parse().expect("Invalid identifiers shouldn't have been allowed.");
734 let plaintext = value.try_into().expect("Invalid struct members shouldn't have been allowed.");
735 (identifier, plaintext)
736 })
737 .collect(),
738 Default::default(),
739 );
740
741 Value { id, contents: ValueVariants::Svm(contents.into()) }
742 }
743
744 pub fn make_record(contents: impl Iterator<Item = (Symbol, Value)>, program: Symbol, path: Vec<Symbol>) -> Self {
745 let id = Some(Location { program, path });
746
747 let mut non_owners = Vec::new();
749 let symbol_owner = Symbol::intern("owner");
751 let mut opt_owner_value = None;
752 for (symbol, value) in contents {
753 if symbol == symbol_owner {
754 let owner: Address = value.try_into().expect("Owner should be an address.");
755 opt_owner_value = Some(owner);
756 } else {
757 let identifier: SvmIdentifier = symbol.to_string().parse().expect("Can't parse identifier.");
758 let plaintext: SvmPlaintext = value.try_into().expect("Record member not plaintext.");
759 non_owners.push((identifier, Entry::Public(plaintext)));
760 }
761 }
762
763 let Some(owner_value) = opt_owner_value else {
764 panic!("No owner in record.");
765 };
766
767 let contents = SvmValueParam::Record(
768 Record::<CurrentNetwork, SvmPlaintext>::from_plaintext(
769 Owner::Public(owner_value),
770 non_owners.into_iter().collect(),
771 Group::generator(), snarkvm::prelude::U8::new(1u8),
773 )
774 .expect("Failed to make record."),
775 );
776
777 Value { id, contents: ValueVariants::Svm(contents) }
778 }
779
780 pub fn make_array(contents: impl Iterator<Item = Value>) -> Self {
781 let vec = contents
782 .map(|value| {
783 let plaintext: SvmPlaintext =
784 value.try_into().expect("Invalid array members shouldn't have been allowed.");
785 plaintext
786 })
787 .collect();
788 SvmPlaintext::Array(vec, Default::default()).into()
789 }
790
791 pub fn make_tuple(contents: impl IntoIterator<Item = Value>) -> Self {
792 ValueVariants::Tuple(contents.into_iter().collect()).into()
793 }
794
795 pub fn make_string(s: String) -> Self {
796 ValueVariants::String(s).into()
797 }
798
799 pub fn get_numeric_type(&self) -> Option<Type> {
802 use IntegerType::*;
803 use Type::*;
804 let ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(literal, ..))) = &self.contents else {
805 return None;
806 };
807 match literal {
808 SvmLiteralParam::U8(_) => Some(Integer(U8)),
809 SvmLiteralParam::U16(_) => Some(Integer(U16)),
810 SvmLiteralParam::U32(_) => Some(Integer(U32)),
811 SvmLiteralParam::U64(_) => Some(Integer(U64)),
812 SvmLiteralParam::U128(_) => Some(Integer(U128)),
813 SvmLiteralParam::I8(_) => Some(Integer(I8)),
814 SvmLiteralParam::I16(_) => Some(Integer(I16)),
815 SvmLiteralParam::I32(_) => Some(Integer(I32)),
816 SvmLiteralParam::I64(_) => Some(Integer(I64)),
817 SvmLiteralParam::I128(_) => Some(Integer(I128)),
818 SvmLiteralParam::Field(_) => Some(Field),
819 SvmLiteralParam::Group(_) => Some(Group),
820 SvmLiteralParam::Scalar(_) => Some(Scalar),
821 _ => None,
822 }
823 }
824
825 #[allow(clippy::type_complexity)]
826 pub fn to_expression(
827 &self,
828 span: Span,
829 node_builder: &NodeBuilder,
830 ty: &Type,
831 struct_lookup: &dyn Fn(&[Symbol]) -> Vec<(Symbol, Type)>,
832 ) -> Option<Expression> {
833 use crate::{Literal, TupleExpression, UnitExpression};
834
835 let id = node_builder.next_id();
836 let expression = match &self.contents {
837 ValueVariants::Unit => UnitExpression { span, id }.into(),
838 ValueVariants::Tuple(vec) => {
839 let Type::Tuple(tuple_type) = ty else {
840 return None;
841 };
842
843 if vec.len() != tuple_type.elements().len() {
844 return None;
845 }
846
847 TupleExpression {
848 span,
849 id,
850 elements: vec
851 .iter()
852 .zip(tuple_type.elements())
853 .map(|(val, ty)| val.to_expression(span, node_builder, ty, struct_lookup))
854 .collect::<Option<Vec<_>>>()?,
855 }
856 .into()
857 }
858 ValueVariants::Unsuffixed(s) => Literal::unsuffixed(s.clone(), span, id).into(),
859 ValueVariants::Svm(value) => match value {
860 SvmValueParam::Plaintext(plaintext) => {
861 plaintext_to_expression(plaintext, span, node_builder, ty, &struct_lookup)?
862 }
863 SvmValueParam::Record(..) => return None,
864 SvmValueParam::Future(..) => return None,
865 },
866 ValueVariants::Future(..) => return None,
867 ValueVariants::String(..) => return None,
868 };
869
870 Some(expression)
871 }
872}
873
874#[allow(clippy::type_complexity)]
875fn plaintext_to_expression(
876 plaintext: &SvmPlaintext,
877 span: Span,
878 node_builder: &NodeBuilder,
879 ty: &Type,
880 struct_lookup: &dyn Fn(&[Symbol]) -> Vec<(Symbol, Type)>,
881) -> Option<Expression> {
882 use crate::{ArrayExpression, Identifier, IntegerType, Literal, StructExpression, StructVariableInitializer};
883
884 let id = node_builder.next_id();
885
886 let expression = match plaintext {
887 Plaintext::Literal(literal, ..) => match literal {
888 SvmLiteralParam::Address(address) => {
889 Literal::address(address.to_string(), span, node_builder.next_id()).into()
890 }
891 SvmLiteralParam::Boolean(boolean) => Literal::boolean(**boolean, span, node_builder.next_id()).into(),
892 SvmLiteralParam::Field(field) => {
893 let mut s = field.to_string();
894 s.truncate(s.len() - 5);
896 Literal::field(s, span, id).into()
897 }
898 SvmLiteralParam::Group(group) => {
899 let mut s = group.to_string();
900 s.truncate(s.len() - 5);
902 Literal::group(s, span, id).into()
903 }
904 SvmLiteralParam::Scalar(scalar) => {
905 let mut s = scalar.to_string();
906 s.truncate(s.len() - 6);
908 Literal::scalar(s, span, id).into()
909 }
910 SvmLiteralParam::I8(int) => Literal::integer(IntegerType::I8, (**int).to_string(), span, id).into(),
911 SvmLiteralParam::I16(int) => Literal::integer(IntegerType::I16, (**int).to_string(), span, id).into(),
912 SvmLiteralParam::I32(int) => Literal::integer(IntegerType::I32, (**int).to_string(), span, id).into(),
913 SvmLiteralParam::I64(int) => Literal::integer(IntegerType::I64, (**int).to_string(), span, id).into(),
914 SvmLiteralParam::I128(int) => Literal::integer(IntegerType::I128, (**int).to_string(), span, id).into(),
915 SvmLiteralParam::U8(int) => Literal::integer(IntegerType::U8, (**int).to_string(), span, id).into(),
916 SvmLiteralParam::U16(int) => Literal::integer(IntegerType::U16, (**int).to_string(), span, id).into(),
917 SvmLiteralParam::U32(int) => Literal::integer(IntegerType::U32, (**int).to_string(), span, id).into(),
918 SvmLiteralParam::U64(int) => Literal::integer(IntegerType::U64, (**int).to_string(), span, id).into(),
919 SvmLiteralParam::U128(int) => Literal::integer(IntegerType::U128, (**int).to_string(), span, id).into(),
920 SvmLiteralParam::Signature(..) => todo!(),
921 SvmLiteralParam::String(..) => return None,
922 },
923 Plaintext::Struct(index_map, ..) => {
924 let Type::Composite(composite_type) = ty else {
925 return None;
926 };
927 let symbols = composite_type.path.as_symbols();
928 let iter_members = struct_lookup(&symbols);
929 StructExpression {
930 span,
931 id,
932 path: composite_type.path.clone(),
933 const_arguments: Vec::new(),
936 members: iter_members
937 .into_iter()
938 .map(|(sym, ty)| {
939 let svm_identifier: snarkvm::prelude::Identifier<CurrentNetwork> =
940 sym.to_string().parse().ok()?;
941 Some(StructVariableInitializer {
942 span,
943 id: node_builder.next_id(),
944 identifier: Identifier::new(sym, node_builder.next_id()),
945 expression: Some(plaintext_to_expression(
946 index_map.get(&svm_identifier)?,
947 span,
948 node_builder,
949 &ty,
950 &struct_lookup,
951 )?),
952 })
953 })
954 .collect::<Option<Vec<_>>>()?,
955 }
956 .into()
957 }
958 Plaintext::Array(vec, ..) => {
959 let Type::Array(array_ty) = ty else {
960 return None;
961 };
962 ArrayExpression {
963 span,
964 id,
965 elements: vec
966 .iter()
967 .map(|pt| plaintext_to_expression(pt, span, node_builder, &array_ty.element_type, &struct_lookup))
968 .collect::<Option<Vec<_>>>()?,
969 }
970 .into()
971 }
972 };
973
974 Some(expression)
975}
976
977impl FromStr for Value {
978 type Err = ();
979
980 fn from_str(s: &str) -> Result<Self, Self::Err> {
981 if s == "()" {
983 return Ok(Value::make_unit());
984 }
985
986 if let Some(s) = s.strip_prefix("(")
988 && let Some(s) = s.strip_suffix(")")
989 {
990 let mut results = Vec::new();
991 for item in s.split(',') {
992 let item = item.trim();
993 let value: Value = item.parse().map_err(|_| ())?;
994 results.push(value);
995 }
996
997 return Ok(Value::make_tuple(results));
998 }
999
1000 if s.chars().all(|c| c == '_' || c.is_ascii_digit()) {
1002 return Ok(ValueVariants::Unsuffixed(s.to_string()).into());
1003 }
1004
1005 let value: SvmValue = s.parse().map_err(|_| ())?;
1007 Ok(value.into())
1008 }
1009}