cairo_lang_sierra/extensions/
types.rs1use super::args_as_single_type;
2use super::error::{ExtensionError, SpecializationError};
3use super::type_specialization_context::TypeSpecializationContext;
4use crate::ids::{ConcreteTypeId, GenericTypeId};
5use crate::program::{ConcreteTypeLongId, GenericArg};
6
7pub trait GenericType: Sized {
9 type Concrete: ConcreteType;
10
11 fn by_id(id: &GenericTypeId) -> Option<Self>;
13 fn specialize(
15 &self,
16 context: &dyn TypeSpecializationContext,
17 args: &[GenericArg],
18 ) -> Result<Self::Concrete, SpecializationError>;
19}
20
21pub trait GenericTypeEx: GenericType {
23 fn specialize_by_id(
24 context: &dyn TypeSpecializationContext,
25 type_id: &GenericTypeId,
26 args: &[GenericArg],
27 ) -> Result<Self::Concrete, ExtensionError>;
28}
29impl<TGenericType: GenericType> GenericTypeEx for TGenericType {
30 fn specialize_by_id(
31 context: &dyn TypeSpecializationContext,
32 type_id: &GenericTypeId,
33 args: &[GenericArg],
34 ) -> Result<TGenericType::Concrete, ExtensionError> {
35 Self::by_id(type_id)
36 .ok_or_else(move || ExtensionError::TypeSpecialization {
37 type_id: type_id.clone(),
38 error: SpecializationError::UnsupportedId(type_id.0.clone()),
39 })?
40 .specialize(context, args)
41 .map_err(move |error| ExtensionError::TypeSpecialization {
42 type_id: type_id.clone(),
43 error,
44 })
45 }
46}
47
48pub trait NamedType: Default {
50 type Concrete: ConcreteType;
51 const ID: GenericTypeId;
52 fn id() -> GenericTypeId {
54 Self::ID
55 }
56 fn concrete_type_long_id(generic_args: &[GenericArg]) -> ConcreteTypeLongId {
58 ConcreteTypeLongId { generic_id: Self::id(), generic_args: generic_args.to_vec() }
59 }
60 fn specialize(
62 &self,
63 context: &dyn TypeSpecializationContext,
64 args: &[GenericArg],
65 ) -> Result<Self::Concrete, SpecializationError>;
66}
67impl<TNamedType: NamedType> GenericType for TNamedType {
68 type Concrete = <Self as NamedType>::Concrete;
69
70 fn by_id(id: &GenericTypeId) -> Option<Self> {
71 if &Self::ID == id { Some(Self::default()) } else { None }
72 }
73
74 fn specialize(
75 &self,
76 context: &dyn TypeSpecializationContext,
77 args: &[GenericArg],
78 ) -> Result<Self::Concrete, SpecializationError> {
79 <Self as NamedType>::specialize(self, context, args)
80 }
81}
82
83pub trait NoGenericArgsGenericType: Default {
85 const ID: GenericTypeId;
86 const STORABLE: bool;
87 const DUPLICATABLE: bool;
88 const DROPPABLE: bool;
89 const ZERO_SIZED: bool;
90}
91impl<T: NoGenericArgsGenericType> NamedType for T {
92 type Concrete = InfoOnlyConcreteType;
93 const ID: GenericTypeId = <Self as NoGenericArgsGenericType>::ID;
94
95 fn specialize(
96 &self,
97 _context: &dyn TypeSpecializationContext,
98 args: &[GenericArg],
99 ) -> Result<Self::Concrete, SpecializationError> {
100 if args.is_empty() {
101 Ok(Self::Concrete {
102 info: TypeInfo {
103 long_id: Self::concrete_type_long_id(args),
104 storable: T::STORABLE,
105 droppable: T::DROPPABLE,
106 duplicatable: T::DUPLICATABLE,
107 zero_sized: T::ZERO_SIZED,
108 },
109 })
110 } else {
111 Err(SpecializationError::WrongNumberOfGenericArgs)
112 }
113 }
114}
115
116pub trait GenericTypeArgGenericType: Default {
118 const ID: GenericTypeId;
119
120 fn calc_info(
122 &self,
123 context: &dyn TypeSpecializationContext,
124 long_id: ConcreteTypeLongId,
125 wrapped_info: &TypeInfo,
126 ) -> Result<TypeInfo, SpecializationError>;
127}
128
129#[derive(Default)]
131pub struct GenericTypeArgGenericTypeWrapper<T: GenericTypeArgGenericType>(T);
132impl<T: GenericTypeArgGenericType> NamedType for GenericTypeArgGenericTypeWrapper<T> {
133 type Concrete = InfoAndTypeConcreteType;
134 const ID: GenericTypeId = T::ID;
135
136 fn specialize(
137 &self,
138 context: &dyn TypeSpecializationContext,
139 args: &[GenericArg],
140 ) -> Result<Self::Concrete, SpecializationError> {
141 let ty = args_as_single_type(args)?;
142 let long_id = Self::concrete_type_long_id(args);
143 let wrapped_info = context.get_type_info(ty)?;
144 Ok(Self::Concrete {
145 info: self.0.calc_info(context, long_id, wrapped_info)?,
146 ty: ty.clone(),
147 })
148 }
149}
150
151#[derive(Clone, Debug, Eq, PartialEq)]
153pub struct TypeInfo {
154 pub long_id: ConcreteTypeLongId,
156 pub storable: bool,
158 pub droppable: bool,
160 pub duplicatable: bool,
162 pub zero_sized: bool,
164}
165
166pub trait ConcreteType {
168 fn info(&self) -> &TypeInfo;
169}
170
171pub struct InfoOnlyConcreteType {
174 pub info: TypeInfo,
175}
176
177impl ConcreteType for InfoOnlyConcreteType {
178 fn info(&self) -> &TypeInfo {
179 &self.info
180 }
181}
182
183pub struct InfoAndTypeConcreteType {
185 pub info: TypeInfo,
186 pub ty: ConcreteTypeId,
187}
188
189impl ConcreteType for InfoAndTypeConcreteType {
190 fn info(&self) -> &TypeInfo {
191 &self.info
192 }
193}
194
195#[macro_export]
208macro_rules! define_type_hierarchy {
209 (pub enum $name:ident { $($variant_name:ident ($variant:ty),)* },
210 $concrete_name:ident) => {
211 #[allow(clippy::enum_variant_names)]
212 pub enum $name {
213 $($variant_name ($variant)),*
214 }
215
216 impl $crate::extensions::types::GenericType for $name {
217 type Concrete = $concrete_name;
218 fn by_id(id: &$crate::ids::GenericTypeId) -> Option<Self> {
219 $(
220 if let Some(res) = <$variant>::by_id(id){
221 return Some(Self::$variant_name(res));
222 }
223 )*
224 None
225 }
226 fn specialize(
227 &self,
228 context: &dyn $crate::extensions::type_specialization_context::TypeSpecializationContext,
229 args: &[$crate::program::GenericArg]
230 ) -> Result<Self::Concrete, $crate::extensions::SpecializationError>{
231 match self {
232 $(
233 Self::$variant_name(value) => {
234 Ok(Self::Concrete::$variant_name(
235 <$variant as $crate::extensions::GenericType>::specialize(
236 value, context, args,
237 )?
238 .into(),
239 ))
240 }
241 ),*
242 }
243 }
244 }
245
246 pub enum $concrete_name {
247 $($variant_name (<$variant as $crate::extensions::GenericType> ::Concrete),)*
248 }
249 impl $crate::extensions::ConcreteType for $concrete_name {
250 fn info(&self) -> &$crate::extensions::types::TypeInfo {
251 match self {
252 $(Self::$variant_name(value) => value.info()),*
253 }
254 }
255 }
256 }
257}