cairo_lang_sierra/extensions/modules/
felt252_dict.rs1use super::enm::EnumType;
2use super::felt252::Felt252Type;
3use super::gas::GasBuiltinType;
4use super::int::unsigned::{Uint8Type, Uint16Type, Uint32Type, Uint64Type};
5use super::int::unsigned128::Uint128Type;
6use super::nullable::NullableType;
7use super::range_check::RangeCheckType;
8use super::segment_arena::SegmentArenaType;
9use super::squashed_felt252_dict::SquashedFelt252DictType;
10use crate::define_libfunc_hierarchy;
11use crate::extensions::lib_func::{
12 DeferredOutputKind, LibfuncSignature, OutputVarInfo, ParamSignature, SierraApChange,
13 SignatureAndTypeGenericLibfunc, SignatureOnlyGenericLibfunc, SignatureSpecializationContext,
14 WrapSignatureAndTypeGenericLibfunc,
15};
16use crate::extensions::type_specialization_context::TypeSpecializationContext;
17use crate::extensions::types::{
18 GenericTypeArgGenericType, GenericTypeArgGenericTypeWrapper, TypeInfo,
19};
20use crate::extensions::{
21 NamedType, OutputVarReferenceInfo, SpecializationError, args_as_single_type,
22};
23use crate::ids::{ConcreteTypeId, GenericTypeId};
24use crate::program::{ConcreteTypeLongId, GenericArg};
25
26#[derive(Default)]
32pub struct Felt252DictTypeWrapped {}
33impl GenericTypeArgGenericType for Felt252DictTypeWrapped {
34 const ID: GenericTypeId = GenericTypeId::new_inline("Felt252Dict");
35
36 fn calc_info(
37 &self,
38 context: &dyn TypeSpecializationContext,
39 long_id: crate::program::ConcreteTypeLongId,
40 wrapped_type_info: TypeInfo,
41 ) -> Result<TypeInfo, SpecializationError> {
42 specialize_with_dict_value_param(context, long_id, wrapped_type_info)
43 }
44}
45
46fn specialize_with_dict_value_param(
49 context: &dyn TypeSpecializationContext,
50 long_id: ConcreteTypeLongId,
51 TypeInfo {
52 long_id: ConcreteTypeLongId { generic_id, generic_args },
53 storable,
54 droppable,
55 duplicatable: _,
56 zero_sized: _,
57 }: TypeInfo,
58) -> Result<TypeInfo, SpecializationError> {
59 let allowed = match generic_id {
64 id if id == Felt252Type::id() => generic_args.is_empty(),
65 id if id == Uint8Type::id() => generic_args.is_empty(),
66 id if id == Uint16Type::id() => generic_args.is_empty(),
67 id if id == Uint32Type::id() => generic_args.is_empty(),
68 id if id == Uint64Type::id() => generic_args.is_empty(),
69 id if id == Uint128Type::id() => generic_args.is_empty(),
70 id if id == NullableType::id() => generic_args.len() == 1,
71 id if id == EnumType::id() => {
72 !generic_args.is_empty()
74 && generic_args.len() <= 3
78 && generic_args.into_iter().skip(1).all(|arg| {
80 let GenericArg::Type(ty) = arg else {
81 return false;
82 };
83 let Ok(info) = context.get_type_info(ty) else {
84 return false;
85 };
86 info.zero_sized
87 })
88 }
89 _ => false,
90 };
91 if allowed && storable && droppable {
92 Ok(TypeInfo {
93 long_id,
94 duplicatable: false,
95 droppable: false,
96 storable: true,
97 zero_sized: false,
98 })
99 } else {
100 Err(SpecializationError::UnsupportedGenericArg)
101 }
102}
103pub type Felt252DictType = GenericTypeArgGenericTypeWrapper<Felt252DictTypeWrapped>;
104
105define_libfunc_hierarchy! {
106 pub enum Felt252DictLibfunc {
107 New(Felt252DictNewLibfunc),
108 Squash(Felt252DictSquashLibfunc),
109 }, Felt252DictConcreteLibfunc
110}
111
112#[derive(Default)]
114pub struct Felt252DictNewLibfunc {}
115impl SignatureOnlyGenericLibfunc for Felt252DictNewLibfunc {
116 const STR_ID: &'static str = "felt252_dict_new";
117
118 fn specialize_signature(
119 &self,
120 context: &dyn SignatureSpecializationContext,
121 args: &[GenericArg],
122 ) -> Result<LibfuncSignature, SpecializationError> {
123 let ty = args_as_single_type(args)?;
124 let segment_arena_ty = context.get_concrete_type(SegmentArenaType::id(), &[])?;
125 Ok(LibfuncSignature::new_non_branch_ex(
126 vec![ParamSignature::new(segment_arena_ty.clone()).with_allow_add_const()],
127 vec![
128 OutputVarInfo::new_builtin(segment_arena_ty, 0),
129 OutputVarInfo {
130 ty: context.get_wrapped_concrete_type(Felt252DictType::id(), ty)?,
131 ref_info: OutputVarReferenceInfo::Deferred(DeferredOutputKind::Generic),
132 },
133 ],
134 SierraApChange::Known { new_vars_only: false },
135 ))
136 }
137}
138
139#[derive(Default)]
141pub struct Felt252DictSquashLibfunc {}
142impl SignatureOnlyGenericLibfunc for Felt252DictSquashLibfunc {
143 const STR_ID: &'static str = "felt252_dict_squash";
144
145 fn specialize_signature(
146 &self,
147 context: &dyn SignatureSpecializationContext,
148 args: &[GenericArg],
149 ) -> Result<LibfuncSignature, SpecializationError> {
150 let generic_ty = args_as_single_type(args)?;
151 let dict_ty =
152 context.get_wrapped_concrete_type(Felt252DictType::id(), generic_ty.clone())?;
153 let squashed_dict_ty =
154 context.get_wrapped_concrete_type(SquashedFelt252DictType::id(), generic_ty)?;
155 let range_check_type = context.get_concrete_type(RangeCheckType::id(), &[])?;
156 let gas_builtin_type = context.get_concrete_type(GasBuiltinType::id(), &[])?;
157 let segment_arena_ty = context.get_concrete_type(SegmentArenaType::id(), &[])?;
158 Ok(LibfuncSignature::new_non_branch(
159 vec![
160 range_check_type.clone(),
161 gas_builtin_type.clone(),
162 segment_arena_ty.clone(),
163 dict_ty,
164 ],
165 vec![
166 OutputVarInfo {
167 ty: range_check_type,
168 ref_info: OutputVarReferenceInfo::NewTempVar { idx: 0 },
169 },
170 OutputVarInfo {
171 ty: gas_builtin_type,
172 ref_info: OutputVarReferenceInfo::NewTempVar { idx: 1 },
173 },
174 OutputVarInfo {
175 ty: segment_arena_ty,
176 ref_info: OutputVarReferenceInfo::NewTempVar { idx: 2 },
177 },
178 OutputVarInfo {
179 ty: squashed_dict_ty,
180 ref_info: OutputVarReferenceInfo::NewTempVar { idx: 3 },
181 },
182 ],
183 SierraApChange::Unknown,
184 ))
185 }
186}
187
188#[derive(Default)]
190pub struct Felt252DictEntryTypeWrapped {}
191impl GenericTypeArgGenericType for Felt252DictEntryTypeWrapped {
192 const ID: GenericTypeId = GenericTypeId::new_inline("Felt252DictEntry");
193
194 fn calc_info(
195 &self,
196 context: &dyn TypeSpecializationContext,
197 long_id: crate::program::ConcreteTypeLongId,
198 wrapped_type_info: TypeInfo,
199 ) -> Result<TypeInfo, SpecializationError> {
200 specialize_with_dict_value_param(context, long_id, wrapped_type_info)
201 }
202}
203pub type Felt252DictEntryType = GenericTypeArgGenericTypeWrapper<Felt252DictEntryTypeWrapped>;
204
205define_libfunc_hierarchy! {
206 pub enum Felt252DictEntryLibfunc {
207 Get(Felt252DictEntryGetLibfunc),
208 Finalize(Felt252DictEntryFinalizeLibfunc),
209 }, Felt252DictEntryConcreteLibfunc
210}
211
212#[derive(Default)]
214pub struct Felt252DictEntryGetLibfuncWrapped {}
215impl SignatureAndTypeGenericLibfunc for Felt252DictEntryGetLibfuncWrapped {
216 const STR_ID: &'static str = "felt252_dict_entry_get";
217
218 fn specialize_signature(
219 &self,
220 context: &dyn SignatureSpecializationContext,
221 ty: ConcreteTypeId,
222 ) -> Result<LibfuncSignature, SpecializationError> {
223 let dict_ty = context.get_wrapped_concrete_type(Felt252DictType::id(), ty.clone())?;
224 let dict_entry_ty =
225 context.get_wrapped_concrete_type(Felt252DictEntryType::id(), ty.clone())?;
226 let felt252_ty = context.get_concrete_type(Felt252Type::id(), &[])?;
227 Ok(LibfuncSignature::new_non_branch_ex(
228 vec![
229 ParamSignature::new(dict_ty).with_allow_add_const(),
230 ParamSignature::new(felt252_ty),
232 ],
233 vec![
234 OutputVarInfo {
235 ty: dict_entry_ty,
236 ref_info: OutputVarReferenceInfo::Deferred(DeferredOutputKind::AddConst {
237 param_idx: 0,
238 }),
239 },
240 OutputVarInfo {
242 ty,
243 ref_info: OutputVarReferenceInfo::Deferred(DeferredOutputKind::Generic),
244 },
245 ],
246 SierraApChange::Known { new_vars_only: true },
247 ))
248 }
249}
250pub type Felt252DictEntryGetLibfunc =
251 WrapSignatureAndTypeGenericLibfunc<Felt252DictEntryGetLibfuncWrapped>;
252
253#[derive(Default)]
255pub struct Felt252DictEntryFinalizeLibfuncWrapped {}
256impl SignatureAndTypeGenericLibfunc for Felt252DictEntryFinalizeLibfuncWrapped {
257 const STR_ID: &'static str = "felt252_dict_entry_finalize";
258
259 fn specialize_signature(
260 &self,
261 context: &dyn SignatureSpecializationContext,
262 ty: ConcreteTypeId,
263 ) -> Result<LibfuncSignature, SpecializationError> {
264 let dict_ty = context.get_wrapped_concrete_type(Felt252DictType::id(), ty.clone())?;
265 let dict_entry_ty =
266 context.get_wrapped_concrete_type(Felt252DictEntryType::id(), ty.clone())?;
267 Ok(LibfuncSignature::new_non_branch_ex(
268 vec![
269 ParamSignature::new(dict_entry_ty).with_allow_add_const(),
270 ParamSignature::new(ty),
272 ],
273 vec![OutputVarInfo {
274 ty: dict_ty,
275 ref_info: OutputVarReferenceInfo::SameAsParam { param_idx: 0 },
276 }],
277 SierraApChange::Known { new_vars_only: true },
278 ))
279 }
280}
281
282pub type Felt252DictEntryFinalizeLibfunc =
283 WrapSignatureAndTypeGenericLibfunc<Felt252DictEntryFinalizeLibfuncWrapped>;