array.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 crate::{Expression, IntegerType, Literal, LiteralVariant, Type}; 18 use snarkvm::console::program::ArrayType as ConsoleArrayType; 19 20 use adl_span::{Span, Symbol}; 21 use serde::{Deserialize, Serialize}; 22 use snarkvm::prelude::Network; 23 use std::fmt; 24 25 /// An array type. 26 #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] 27 pub struct ArrayType { 28 pub element_type: Box<Type>, 29 pub length: Box<Expression>, 30 } 31 32 impl ArrayType { 33 /// Creates a new array type. 34 pub fn new(element: Type, length: Expression) -> Self { 35 Self { element_type: Box::new(element), length: Box::new(length) } 36 } 37 38 /// Creates a new bit array type. 39 pub fn bit_array(length: u32) -> Self { 40 Self { 41 element_type: Box::new(Type::Boolean), 42 length: Box::new(Expression::Literal(Literal { 43 variant: LiteralVariant::Integer(IntegerType::U32, length.to_string()), 44 id: Default::default(), 45 span: Span::default(), 46 })), 47 } 48 } 49 50 /// Returns the element type of the array. 51 pub fn element_type(&self) -> &Type { 52 &self.element_type 53 } 54 55 /// Returns the base element type of the array. 56 pub fn base_element_type(&self) -> &Type { 57 match self.element_type.as_ref() { 58 Type::Array(array_type) => array_type.base_element_type(), 59 type_ => type_, 60 } 61 } 62 63 pub fn from_snarkvm<N: Network>(array_type: &ConsoleArrayType<N>, program: Option<Symbol>) -> Self { 64 Self { 65 element_type: Box::new(Type::from_snarkvm(array_type.next_element_type(), program)), 66 length: Box::new(Expression::Literal(Literal { 67 variant: LiteralVariant::Integer(IntegerType::U32, array_type.length().to_string().replace("u32", "")), 68 id: Default::default(), 69 span: Span::default(), 70 })), 71 } 72 } 73 74 pub fn to_snarkvm<N: Network>(&self) -> anyhow::Result<ConsoleArrayType<N>> { 75 let length = if let Expression::Literal(literal) = &*self.length { 76 match &literal.variant { 77 LiteralVariant::Integer(_, s) => s.parse::<u32>().unwrap(), 78 LiteralVariant::Unsuffixed(s) => s.parse::<u32>().unwrap(), 79 _ => anyhow::bail!("Array length must be an integer literal"), 80 } 81 } else { 82 anyhow::bail!("Array length must be an integer literal") 83 }; 84 85 ConsoleArrayType::new(self.element_type.to_snarkvm()?, vec![snarkvm::console::types::U32::new(length)]) 86 } 87 } 88 89 impl fmt::Display for ArrayType { 90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 91 // For display purposes (in error messages for example.), do not include the type suffix. 92 if let Expression::Literal(literal) = &*self.length 93 && let LiteralVariant::Integer(_, s) = &literal.variant 94 { 95 return write!(f, "[{}; {s}]", self.element_type); 96 } 97 98 write!(f, "[{}; {}]", self.element_type, self.length) 99 } 100 } 101 102 impl From<ArrayType> for Type { 103 fn from(value: ArrayType) -> Self { 104 Type::Array(value) 105 } 106 }