1use crate::{ArrayType, CompositeType, FutureType, Identifier, IntegerType, MappingType, Path, TupleType};
18
19use itertools::Itertools;
20use leo_span::Symbol;
21use serde::{Deserialize, Serialize};
22use snarkvm::prelude::{
23 Network,
24 PlaintextType,
25 PlaintextType::{Array, Literal, Struct},
26};
27use std::fmt;
28
29#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
31pub enum Type {
32 Address,
34 Array(ArrayType),
36 Boolean,
38 Composite(CompositeType),
40 Field,
42 Future(FutureType),
44 Group,
46 Identifier(Identifier),
48 Integer(IntegerType),
50 Mapping(MappingType),
52 Scalar,
54 Signature,
56 String,
58 Tuple(TupleType),
60 Numeric,
62 Unit,
64 #[default]
67 Err,
68}
69
70impl Type {
71 pub fn eq_flat_relaxed(&self, other: &Self) -> bool {
81 match (self, other) {
82 (Type::Address, Type::Address)
83 | (Type::Boolean, Type::Boolean)
84 | (Type::Field, Type::Field)
85 | (Type::Group, Type::Group)
86 | (Type::Scalar, Type::Scalar)
87 | (Type::Signature, Type::Signature)
88 | (Type::String, Type::String)
89 | (Type::Unit, Type::Unit) => true,
90 (Type::Array(left), Type::Array(right)) => {
91 (match (left.length.as_u32(), right.length.as_u32()) {
94 (Some(l1), Some(l2)) => l1 == l2,
95 _ => {
96 true
99 }
100 }) && left.element_type().eq_flat_relaxed(right.element_type())
101 }
102 (Type::Identifier(left), Type::Identifier(right)) => left.matches(right),
103 (Type::Integer(left), Type::Integer(right)) => left.eq(right),
104 (Type::Mapping(left), Type::Mapping(right)) => {
105 left.key.eq_flat_relaxed(&right.key) && left.value.eq_flat_relaxed(&right.value)
106 }
107 (Type::Tuple(left), Type::Tuple(right)) if left.length() == right.length() => left
108 .elements()
109 .iter()
110 .zip_eq(right.elements().iter())
111 .all(|(left_type, right_type)| left_type.eq_flat_relaxed(right_type)),
112 (Type::Composite(left), Type::Composite(right)) => {
113 if !left.const_arguments.is_empty() || !right.const_arguments.is_empty() {
116 return true;
117 }
118
119 (left.program == right.program)
123 && match (&left.path.try_absolute_path(), &right.path.try_absolute_path()) {
124 (Some(l), Some(r)) => l == r,
125 _ => false,
126 }
127 }
128 (Type::Future(left), Type::Future(right)) if !left.is_explicit || !right.is_explicit => true,
130 (Type::Future(left), Type::Future(right)) if left.inputs.len() == right.inputs.len() => left
131 .inputs()
132 .iter()
133 .zip_eq(right.inputs().iter())
134 .all(|(left_type, right_type)| left_type.eq_flat_relaxed(right_type)),
135 _ => false,
136 }
137 }
138
139 pub fn from_snarkvm<N: Network>(t: &PlaintextType<N>, program: Option<Symbol>) -> Self {
140 match t {
141 Literal(lit) => match lit {
142 snarkvm::prelude::LiteralType::Address => Type::Address,
143 snarkvm::prelude::LiteralType::Boolean => Type::Boolean,
144 snarkvm::prelude::LiteralType::Field => Type::Field,
145 snarkvm::prelude::LiteralType::Group => Type::Group,
146 snarkvm::prelude::LiteralType::U8 => Type::Integer(IntegerType::U8),
147 snarkvm::prelude::LiteralType::U16 => Type::Integer(IntegerType::U16),
148 snarkvm::prelude::LiteralType::U32 => Type::Integer(IntegerType::U32),
149 snarkvm::prelude::LiteralType::U64 => Type::Integer(IntegerType::U64),
150 snarkvm::prelude::LiteralType::U128 => Type::Integer(IntegerType::U128),
151 snarkvm::prelude::LiteralType::I8 => Type::Integer(IntegerType::I8),
152 snarkvm::prelude::LiteralType::I16 => Type::Integer(IntegerType::I16),
153 snarkvm::prelude::LiteralType::I32 => Type::Integer(IntegerType::I32),
154 snarkvm::prelude::LiteralType::I64 => Type::Integer(IntegerType::I64),
155 snarkvm::prelude::LiteralType::I128 => Type::Integer(IntegerType::I128),
156 snarkvm::prelude::LiteralType::Scalar => Type::Scalar,
157 snarkvm::prelude::LiteralType::Signature => Type::Signature,
158 snarkvm::prelude::LiteralType::String => Type::String,
159 },
160 Struct(s) => Type::Composite(CompositeType {
161 path: {
162 let ident = Identifier::from(s);
163 Path::from(ident).with_absolute_path(Some(vec![ident.name]))
164 },
165 const_arguments: Vec::new(),
166 program,
167 }),
168 Array(array) => Type::Array(ArrayType::from_snarkvm(array, program)),
169 }
170 }
171}
172
173impl fmt::Display for Type {
174 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175 match *self {
176 Type::Address => write!(f, "address"),
177 Type::Array(ref array_type) => write!(f, "{array_type}"),
178 Type::Boolean => write!(f, "bool"),
179 Type::Field => write!(f, "field"),
180 Type::Future(ref future_type) => write!(f, "{future_type}"),
181 Type::Group => write!(f, "group"),
182 Type::Identifier(ref variable) => write!(f, "{variable}"),
183 Type::Integer(ref integer_type) => write!(f, "{integer_type}"),
184 Type::Mapping(ref mapping_type) => write!(f, "{mapping_type}"),
185 Type::Scalar => write!(f, "scalar"),
186 Type::Signature => write!(f, "signature"),
187 Type::String => write!(f, "string"),
188 Type::Composite(ref struct_type) => write!(f, "{struct_type}"),
189 Type::Tuple(ref tuple) => write!(f, "{tuple}"),
190 Type::Numeric => write!(f, "numeric"),
191 Type::Unit => write!(f, "()"),
192 Type::Err => write!(f, "error"),
193 }
194 }
195}