1use crate::{ArrayType, CompositeType, FutureType, Identifier, IntegerType, MappingType, TupleType, common};
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, Hash, 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 {
78 match (self, other) {
79 (Type::Address, Type::Address)
80 | (Type::Boolean, Type::Boolean)
81 | (Type::Field, Type::Field)
82 | (Type::Group, Type::Group)
83 | (Type::Scalar, Type::Scalar)
84 | (Type::Signature, Type::Signature)
85 | (Type::String, Type::String)
86 | (Type::Unit, Type::Unit) => true,
87 (Type::Array(left), Type::Array(right)) => {
88 left.element_type().eq_flat_relaxed(right.element_type()) && left.length() == right.length()
89 }
90 (Type::Identifier(left), Type::Identifier(right)) => left.matches(right),
91 (Type::Integer(left), Type::Integer(right)) => left.eq(right),
92 (Type::Mapping(left), Type::Mapping(right)) => {
93 left.key.eq_flat_relaxed(&right.key) && left.value.eq_flat_relaxed(&right.value)
94 }
95 (Type::Tuple(left), Type::Tuple(right)) if left.length() == right.length() => left
96 .elements()
97 .iter()
98 .zip_eq(right.elements().iter())
99 .all(|(left_type, right_type)| left_type.eq_flat_relaxed(right_type)),
100 (Type::Composite(left), Type::Composite(right)) => left.id.name == right.id.name,
101 (Type::Future(left), Type::Future(right)) if !left.is_explicit || !right.is_explicit => true,
103 (Type::Future(left), Type::Future(right)) if left.inputs.len() == right.inputs.len() => left
104 .inputs()
105 .iter()
106 .zip_eq(right.inputs().iter())
107 .all(|(left_type, right_type)| left_type.eq_flat_relaxed(right_type)),
108 _ => false,
109 }
110 }
111
112 pub fn from_snarkvm<N: Network>(t: &PlaintextType<N>, program: Option<Symbol>) -> Self {
113 match t {
114 Literal(lit) => match lit {
115 snarkvm::prelude::LiteralType::Address => Type::Address,
116 snarkvm::prelude::LiteralType::Boolean => Type::Boolean,
117 snarkvm::prelude::LiteralType::Field => Type::Field,
118 snarkvm::prelude::LiteralType::Group => Type::Group,
119 snarkvm::prelude::LiteralType::U8 => Type::Integer(IntegerType::U8),
120 snarkvm::prelude::LiteralType::U16 => Type::Integer(IntegerType::U16),
121 snarkvm::prelude::LiteralType::U32 => Type::Integer(IntegerType::U32),
122 snarkvm::prelude::LiteralType::U64 => Type::Integer(IntegerType::U64),
123 snarkvm::prelude::LiteralType::U128 => Type::Integer(IntegerType::U128),
124 snarkvm::prelude::LiteralType::I8 => Type::Integer(IntegerType::I8),
125 snarkvm::prelude::LiteralType::I16 => Type::Integer(IntegerType::I16),
126 snarkvm::prelude::LiteralType::I32 => Type::Integer(IntegerType::I32),
127 snarkvm::prelude::LiteralType::I64 => Type::Integer(IntegerType::I64),
128 snarkvm::prelude::LiteralType::I128 => Type::Integer(IntegerType::I128),
129 snarkvm::prelude::LiteralType::Scalar => Type::Scalar,
130 snarkvm::prelude::LiteralType::Signature => Type::Signature,
131 snarkvm::prelude::LiteralType::String => Type::String,
132 },
133 Struct(s) => Type::Composite(CompositeType { id: common::Identifier::from(s), program }),
134 Array(array) => Type::Array(ArrayType::from_snarkvm(array, program)),
135 }
136 }
137}
138
139impl fmt::Display for Type {
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 match *self {
142 Type::Address => write!(f, "address"),
143 Type::Array(ref array_type) => write!(f, "{array_type}"),
144 Type::Boolean => write!(f, "bool"),
145 Type::Field => write!(f, "field"),
146 Type::Future(ref future_type) => write!(f, "{future_type}"),
147 Type::Group => write!(f, "group"),
148 Type::Identifier(ref variable) => write!(f, "{variable}"),
149 Type::Integer(ref integer_type) => write!(f, "{integer_type}"),
150 Type::Mapping(ref mapping_type) => write!(f, "{mapping_type}"),
151 Type::Scalar => write!(f, "scalar"),
152 Type::Signature => write!(f, "signature"),
153 Type::String => write!(f, "string"),
154 Type::Composite(ref struct_type) => write!(f, "{struct_type}"),
155 Type::Tuple(ref tuple) => write!(f, "{tuple}"),
156 Type::Numeric => write!(f, "numeric"),
157 Type::Unit => write!(f, "()"),
158 Type::Err => write!(f, "error"),
159 }
160 }
161}