1#![no_std]
2#![deny(warnings)]
3
4extern crate alloc;
5
6mod alignable;
7mod array_type;
8mod function_type;
9mod layout;
10mod pointer_type;
11mod struct_type;
12
13use alloc::{boxed::Box, sync::Arc};
14use core::fmt;
15
16use miden_formatting::prettier::PrettyPrint;
17
18pub use self::{
19    alignable::Alignable, array_type::ArrayType, function_type::*, pointer_type::*, struct_type::*,
20};
21
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25pub enum Type {
26    Unknown,
28    Never,
30    I1,
34    I8,
36    U8,
38    I16,
40    U16,
42    I32,
44    U32,
46    I64,
48    U64,
50    I128,
52    U128,
54    U256,
56    F64,
60    Felt,
62    Ptr(Arc<PointerType>),
67    Struct(Arc<StructType>),
69    Array(Arc<ArrayType>),
71    List(Arc<Type>),
77    Function(Arc<FunctionType>),
79}
80impl Type {
81    pub fn is_zst(&self) -> bool {
88        match self {
89            Self::Unknown => false,
90            Self::Never => true,
91            Self::Array(ref ty) => ty.is_zst(),
92            Self::Struct(ref struct_ty) => struct_ty.fields.iter().all(|f| f.ty.is_zst()),
93            Self::I1
94            | Self::I8
95            | Self::U8
96            | Self::I16
97            | Self::U16
98            | Self::I32
99            | Self::U32
100            | Self::I64
101            | Self::U64
102            | Self::I128
103            | Self::U128
104            | Self::U256
105            | Self::F64
106            | Self::Felt
107            | Self::Ptr(_)
108            | Self::List(_)
109            | Self::Function(_) => false,
110        }
111    }
112
113    pub fn is_numeric(&self) -> bool {
115        matches!(
116            self,
117            Self::I1
118                | Self::I8
119                | Self::U8
120                | Self::I16
121                | Self::U16
122                | Self::I32
123                | Self::U32
124                | Self::I64
125                | Self::U64
126                | Self::I128
127                | Self::U128
128                | Self::U256
129                | Self::F64
130                | Self::Felt
131        )
132    }
133
134    pub fn is_integer(&self) -> bool {
136        matches!(
137            self,
138            Self::I1
139                | Self::I8
140                | Self::U8
141                | Self::I16
142                | Self::U16
143                | Self::I32
144                | Self::U32
145                | Self::I64
146                | Self::U64
147                | Self::I128
148                | Self::U128
149                | Self::U256
150                | Self::Felt
151        )
152    }
153
154    pub fn is_signed_integer(&self) -> bool {
156        matches!(self, Self::I8 | Self::I16 | Self::I32 | Self::I64 | Self::I128)
157    }
158
159    pub fn is_unsigned_integer(&self) -> bool {
161        matches!(self, Self::I1 | Self::U8 | Self::U16 | Self::U32 | Self::U64 | Self::U128)
162    }
163
164    pub fn as_unsigned(&self) -> Type {
169        match self {
170            Self::I8 | Self::U8 => Self::U8,
171            Self::I16 | Self::U16 => Self::U16,
172            Self::I32 | Self::U32 => Self::U32,
173            Self::I64 | Self::U64 => Self::U64,
174            Self::I128 | Self::U128 => Self::U128,
175            Self::Felt => Self::Felt,
176            ty => panic!("invalid conversion to unsigned integer type: {ty} is not an integer"),
177        }
178    }
179
180    pub fn as_signed(&self) -> Type {
184        match self {
185            Self::I8 | Self::U8 => Self::I8,
186            Self::I16 | Self::U16 => Self::I16,
187            Self::I32 | Self::U32 => Self::I32,
188            Self::I64 | Self::U64 => Self::I64,
189            Self::I128 | Self::U128 => Self::I128,
190            Self::Felt => {
191                panic!("invalid conversion to signed integer type: felt has no signed equivalent")
192            }
193            ty => panic!("invalid conversion to signed integer type: {ty} is not an integer"),
194        }
195    }
196
197    #[inline]
199    pub fn is_float(&self) -> bool {
200        matches!(self, Self::F64)
201    }
202
203    #[inline]
205    pub fn is_felt(&self) -> bool {
206        matches!(self, Self::Felt)
207    }
208
209    #[inline]
211    pub fn is_pointer(&self) -> bool {
212        matches!(self, Self::Ptr(_))
213    }
214
215    #[inline]
217    pub fn pointee(&self) -> Option<&Type> {
218        match self {
219            Self::Ptr(ty) => Some(ty.pointee()),
220            _ => None,
221        }
222    }
223
224    #[inline]
226    pub fn is_struct(&self) -> bool {
227        matches!(self, Self::Struct(_))
228    }
229
230    #[inline]
232    pub fn is_array(&self) -> bool {
233        matches!(self, Self::Array(_))
234    }
235
236    #[inline]
238    pub fn is_list(&self) -> bool {
239        matches!(self, Self::List(_))
240    }
241
242    #[inline]
244    pub fn is_function(&self) -> bool {
245        matches!(self, Self::Function(_))
246    }
247}
248
249impl From<StructType> for Type {
250    #[inline]
251    fn from(ty: StructType) -> Type {
252        Type::Struct(Arc::new(ty))
253    }
254}
255
256impl From<Box<StructType>> for Type {
257    #[inline]
258    fn from(ty: Box<StructType>) -> Type {
259        Type::Struct(Arc::from(ty))
260    }
261}
262
263impl From<Arc<StructType>> for Type {
264    #[inline]
265    fn from(ty: Arc<StructType>) -> Type {
266        Type::Struct(ty)
267    }
268}
269
270impl From<ArrayType> for Type {
271    #[inline]
272    fn from(ty: ArrayType) -> Type {
273        Type::Array(Arc::new(ty))
274    }
275}
276
277impl From<Box<ArrayType>> for Type {
278    #[inline]
279    fn from(ty: Box<ArrayType>) -> Type {
280        Type::Array(Arc::from(ty))
281    }
282}
283
284impl From<Arc<ArrayType>> for Type {
285    #[inline]
286    fn from(ty: Arc<ArrayType>) -> Type {
287        Type::Array(ty)
288    }
289}
290
291impl From<PointerType> for Type {
292    #[inline]
293    fn from(ty: PointerType) -> Type {
294        Type::Ptr(Arc::new(ty))
295    }
296}
297
298impl From<Box<PointerType>> for Type {
299    #[inline]
300    fn from(ty: Box<PointerType>) -> Type {
301        Type::Ptr(Arc::from(ty))
302    }
303}
304
305impl From<Arc<PointerType>> for Type {
306    #[inline]
307    fn from(ty: Arc<PointerType>) -> Type {
308        Type::Ptr(ty)
309    }
310}
311
312impl From<FunctionType> for Type {
313    #[inline]
314    fn from(ty: FunctionType) -> Type {
315        Type::Function(Arc::new(ty))
316    }
317}
318
319impl From<Box<FunctionType>> for Type {
320    #[inline]
321    fn from(ty: Box<FunctionType>) -> Type {
322        Type::Function(Arc::from(ty))
323    }
324}
325
326impl From<Arc<FunctionType>> for Type {
327    #[inline]
328    fn from(ty: Arc<FunctionType>) -> Type {
329        Type::Function(ty)
330    }
331}
332
333impl fmt::Display for Type {
334    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
336        self.pretty_print(f)
337    }
338}
339
340impl PrettyPrint for Type {
341    fn render(&self) -> miden_formatting::prettier::Document {
342        use miden_formatting::prettier::*;
343
344        match self {
345            Self::Unknown => const_text("?"),
346            Self::Never => const_text("!"),
347            Self::I1 => const_text("i1"),
348            Self::I8 => const_text("i8"),
349            Self::U8 => const_text("u8"),
350            Self::I16 => const_text("i16"),
351            Self::U16 => const_text("u16"),
352            Self::I32 => const_text("i32"),
353            Self::U32 => const_text("u32"),
354            Self::I64 => const_text("i64"),
355            Self::U64 => const_text("u64"),
356            Self::I128 => const_text("i128"),
357            Self::U128 => const_text("u128"),
358            Self::U256 => const_text("u256"),
359            Self::F64 => const_text("f64"),
360            Self::Felt => const_text("felt"),
361            Self::Ptr(ptr_ty) => ptr_ty.render(),
362            Self::Struct(struct_ty) => struct_ty.render(),
363            Self::Array(array_ty) => array_ty.render(),
364            Self::List(ty) => const_text("list<") + ty.render() + const_text(">"),
365            Self::Function(ty) => ty.render(),
366        }
367    }
368}