value.rs
1 // Copyright (C) 2019-2025 ADnet Contributors 2 // This file is part of the ADL library. 3 4 // The ADL library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 9 // The ADL library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 14 // You should have received a copy of the GNU General Public License 15 // along with the ADL library. If not, see <https://www.gnu.org/licenses/>. 16 17 use std::{ 18 collections::BTreeMap, 19 fmt, 20 hash::{Hash, Hasher}, 21 str::FromStr, 22 }; 23 24 use itertools::Itertools as _; 25 26 use crate::Location; 27 28 use 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 }; 43 pub(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 52 use adl_errors::Result; 53 use adl_span::{Span, Symbol}; 54 55 use crate::{Expression, IntegerType, NodeBuilder, Type}; 56 57 pub(crate) type CurrentNetwork = TestnetV0; 58 59 pub(crate) type SvmValue = SvmValueParam<CurrentNetwork>; 60 pub(crate) type ProgramID = ProgramIDParam<CurrentNetwork>; 61 pub(crate) type SvmPlaintext = Plaintext<CurrentNetwork>; 62 pub(crate) type SvmLiteral = SvmLiteralParam<CurrentNetwork>; 63 pub(crate) type SvmIdentifier = SvmIdentifierParam<CurrentNetwork>; 64 pub(crate) type Group = SvmGroup<CurrentNetwork>; 65 pub(crate) type Field = SvmField<CurrentNetwork>; 66 pub(crate) type Scalar = SvmScalar<CurrentNetwork>; 67 pub(crate) type Address = SvmAddress<CurrentNetwork>; 68 pub(crate) type Boolean = SvmBoolean<CurrentNetwork>; 69 pub(crate) type Future = FutureParam<CurrentNetwork>; 70 pub(crate) type Signature = SvmSignature<CurrentNetwork>; 71 72 #[derive(Clone, Debug, Eq, PartialEq)] 73 pub struct CompositeContents { 74 pub path: Vec<Symbol>, 75 } 76 77 #[derive(Clone, Debug, Default, Eq, PartialEq, Hash)] 78 pub struct Value { 79 pub id: Option<Location>, 80 pub(crate) contents: ValueVariants, 81 } 82 83 #[derive(Clone, Default, Debug, Eq, PartialEq)] 84 // SnarkVM's Value is large, but that's okay. 85 #[allow(clippy::large_enum_variant)] 86 pub(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)] 97 pub enum AsyncExecution { 98 AsyncFunctionCall { 99 function: Location, 100 arguments: Vec<Value>, 101 }, 102 AsyncBlock { 103 containing_function: Location, // The function that contains the async block. 104 block: crate::NodeID, 105 names: BTreeMap<Vec<Symbol>, Value>, // Use a `BTreeMap` here because `HashMap` does not implement `Hash`. 106 }, 107 } 108 109 impl 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 124 fn hash_plaintext<H>(pt: &SvmPlaintext, state: &mut H) 125 where 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 // The correctness of this hash depends on the members being 137 // in the same order for each type. 138 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 151 impl 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 // NOTE - we don't actually hash the data or owner. Thus this is 178 // a terrible hash function with many collisions. 179 // This shouldn't matter as the only place where we hash this is in 180 // keys for mappings, which cannot be records. 181 } 182 SvmValueParam::Future(future) => { 183 5u8.hash(state); 184 future.program_id().hash(state); 185 future.function_name().hash(state); 186 // Ditto - we don't hash the arguments. 187 } 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 200 impl From<ValueVariants> for Value { 201 fn from(contents: ValueVariants) -> Self { 202 Value { id: None, contents } 203 } 204 } 205 206 pub trait TryAsRef<T> 207 where 208 T: ?Sized, 209 { 210 fn try_as_ref(&self) -> Option<&T>; 211 } 212 213 macro_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 263 impl_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 277 macro_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 302 impl_from_literal! { 303 Field; Group; Scalar; Address; 304 } 305 306 impl 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 320 impl From<Future> for Value { 321 fn from(value: Future) -> Self { 322 SvmValueParam::Future(value).into() 323 } 324 } 325 326 impl 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 335 impl From<SvmLiteral> for Value { 336 fn from(x: SvmLiteral) -> Self { 337 ValueVariants::Svm(SvmValueParam::Plaintext(Plaintext::Literal(x, Default::default()))).into() 338 } 339 } 340 341 impl 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 349 impl 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 357 impl 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 363 impl From<SvmPlaintext> for Value { 364 fn from(x: SvmPlaintext) -> Self { 365 ValueVariants::Svm(SvmValueParam::Plaintext(x)).into() 366 } 367 } 368 369 impl From<SvmValue> for Value { 370 fn from(x: SvmValue) -> Self { 371 ValueVariants::Svm(x).into() 372 } 373 } 374 375 impl From<Vec<AsyncExecution>> for Value { 376 fn from(x: Vec<AsyncExecution>) -> Self { 377 ValueVariants::Future(x).into() 378 } 379 } 380 381 impl 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 389 impl 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 412 impl 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 /// Return the group generator. 555 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}.alpha")).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 // Find the owner, storing the other contents for later. 748 let mut non_owners = Vec::new(); 749 // let mut non_owners: Vec<(SvmIdentifier, SvmPlaintext)> = Vec::new(); 750 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(), // Just an arbitrary nonce. 772 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 /// Gets the type of a `Value` but only if it is an integer, a field, a group, or a scalar. 800 /// Return `None` otherwise. These are the only types that an unsuffixed literal can have. 801 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(value) => Literal::string(value.clone(), span, id).into(), 868 }; 869 870 Some(expression) 871 } 872 } 873 874 #[allow(clippy::type_complexity)] 875 fn 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, CompositeExpression, CompositeFieldInitializer, Identifier, IntegerType, Literal}; 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 // Strip off the `field` suffix. 895 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 // Strip off the `group` suffix. 901 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 // Strip off the `scalar` suffix. 907 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 CompositeExpression { 930 span, 931 id, 932 path: composite_type.path.clone(), 933 // If we were able to construct a Value, the const arguments must have already been resolved 934 // and inserted appropriately. 935 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(CompositeFieldInitializer { 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 977 impl FromStr for Value { 978 type Err = (); 979 980 fn from_str(s: &str) -> Result<Self, Self::Err> { 981 // Either it's a unit. 982 if s == "()" { 983 return Ok(Value::make_unit()); 984 } 985 986 // Or it's a tuple. 987 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 // Or it's an unsuffixed numeric literal. 1001 if s.chars().all(|c| c == '_' || c.is_ascii_digit()) { 1002 return Ok(ValueVariants::Unsuffixed(s.to_string()).into()); 1003 } 1004 1005 // Or it's a snarkvm value. 1006 let value: SvmValue = s.parse().map_err(|_| ())?; 1007 Ok(value.into()) 1008 } 1009 }