cairo_lang_sierra/extensions/modules/
felt252_dict.rsuse super::enm::EnumType;
use super::felt252::Felt252Type;
use super::gas::GasBuiltinType;
use super::int::unsigned::{Uint16Type, Uint32Type, Uint64Type, Uint8Type};
use super::int::unsigned128::Uint128Type;
use super::nullable::NullableType;
use super::range_check::RangeCheckType;
use super::segment_arena::SegmentArenaType;
use super::squashed_felt252_dict::SquashedFelt252DictType;
use crate::define_libfunc_hierarchy;
use crate::extensions::lib_func::{
DeferredOutputKind, LibfuncSignature, OutputVarInfo, ParamSignature, SierraApChange,
SignatureAndTypeGenericLibfunc, SignatureOnlyGenericLibfunc, SignatureSpecializationContext,
WrapSignatureAndTypeGenericLibfunc,
};
use crate::extensions::type_specialization_context::TypeSpecializationContext;
use crate::extensions::types::{
GenericTypeArgGenericType, GenericTypeArgGenericTypeWrapper, TypeInfo,
};
use crate::extensions::{
args_as_single_type, NamedType, OutputVarReferenceInfo, SpecializationError,
};
use crate::ids::{ConcreteTypeId, GenericTypeId};
use crate::program::{ConcreteTypeLongId, GenericArg};
#[derive(Default)]
pub struct Felt252DictTypeWrapped {}
impl GenericTypeArgGenericType for Felt252DictTypeWrapped {
const ID: GenericTypeId = GenericTypeId::new_inline("Felt252Dict");
fn calc_info(
&self,
context: &dyn TypeSpecializationContext,
long_id: crate::program::ConcreteTypeLongId,
wrapped_type_info: TypeInfo,
) -> Result<TypeInfo, SpecializationError> {
specialize_with_dict_value_param(context, long_id, wrapped_type_info)
}
}
fn specialize_with_dict_value_param(
context: &dyn TypeSpecializationContext,
long_id: ConcreteTypeLongId,
TypeInfo {
long_id: ConcreteTypeLongId { generic_id, generic_args },
storable,
droppable,
duplicatable: _,
zero_sized: _,
}: TypeInfo,
) -> Result<TypeInfo, SpecializationError> {
let allowed = match generic_id {
id if id == Felt252Type::id() => generic_args.is_empty(),
id if id == Uint8Type::id() => generic_args.is_empty(),
id if id == Uint16Type::id() => generic_args.is_empty(),
id if id == Uint32Type::id() => generic_args.is_empty(),
id if id == Uint64Type::id() => generic_args.is_empty(),
id if id == Uint128Type::id() => generic_args.is_empty(),
id if id == NullableType::id() => generic_args.len() == 1,
id if id == EnumType::id() => {
!generic_args.is_empty()
&& generic_args.len() <= 3
&& generic_args.into_iter().skip(1).all(|arg| {
let GenericArg::Type(ty) = arg else {
return false;
};
let Ok(info) = context.get_type_info(ty) else {
return false;
};
info.zero_sized
})
}
_ => false,
};
if allowed && storable && droppable {
Ok(TypeInfo {
long_id,
duplicatable: false,
droppable: false,
storable: true,
zero_sized: false,
})
} else {
Err(SpecializationError::UnsupportedGenericArg)
}
}
pub type Felt252DictType = GenericTypeArgGenericTypeWrapper<Felt252DictTypeWrapped>;
define_libfunc_hierarchy! {
pub enum Felt252DictLibfunc {
New(Felt252DictNewLibfunc),
Squash(Felt252DictSquashLibfunc),
}, Felt252DictConcreteLibfunc
}
#[derive(Default)]
pub struct Felt252DictNewLibfunc {}
impl SignatureOnlyGenericLibfunc for Felt252DictNewLibfunc {
const STR_ID: &'static str = "felt252_dict_new";
fn specialize_signature(
&self,
context: &dyn SignatureSpecializationContext,
args: &[GenericArg],
) -> Result<LibfuncSignature, SpecializationError> {
let ty = args_as_single_type(args)?;
let segment_arena_ty = context.get_concrete_type(SegmentArenaType::id(), &[])?;
Ok(LibfuncSignature::new_non_branch_ex(
vec![ParamSignature::new(segment_arena_ty.clone()).with_allow_add_const()],
vec![
OutputVarInfo::new_builtin(segment_arena_ty, 0),
OutputVarInfo {
ty: context.get_wrapped_concrete_type(Felt252DictType::id(), ty)?,
ref_info: OutputVarReferenceInfo::Deferred(DeferredOutputKind::Generic),
},
],
SierraApChange::Known { new_vars_only: false },
))
}
}
#[derive(Default)]
pub struct Felt252DictSquashLibfunc {}
impl SignatureOnlyGenericLibfunc for Felt252DictSquashLibfunc {
const STR_ID: &'static str = "felt252_dict_squash";
fn specialize_signature(
&self,
context: &dyn SignatureSpecializationContext,
args: &[GenericArg],
) -> Result<LibfuncSignature, SpecializationError> {
let generic_ty = args_as_single_type(args)?;
let dict_ty =
context.get_wrapped_concrete_type(Felt252DictType::id(), generic_ty.clone())?;
let squashed_dict_ty =
context.get_wrapped_concrete_type(SquashedFelt252DictType::id(), generic_ty)?;
let range_check_type = context.get_concrete_type(RangeCheckType::id(), &[])?;
let gas_builtin_type = context.get_concrete_type(GasBuiltinType::id(), &[])?;
let segment_arena_ty = context.get_concrete_type(SegmentArenaType::id(), &[])?;
Ok(LibfuncSignature::new_non_branch(
vec![
range_check_type.clone(),
gas_builtin_type.clone(),
segment_arena_ty.clone(),
dict_ty,
],
vec![
OutputVarInfo {
ty: range_check_type,
ref_info: OutputVarReferenceInfo::NewTempVar { idx: 0 },
},
OutputVarInfo {
ty: gas_builtin_type,
ref_info: OutputVarReferenceInfo::NewTempVar { idx: 1 },
},
OutputVarInfo {
ty: segment_arena_ty,
ref_info: OutputVarReferenceInfo::NewTempVar { idx: 2 },
},
OutputVarInfo {
ty: squashed_dict_ty,
ref_info: OutputVarReferenceInfo::NewTempVar { idx: 3 },
},
],
SierraApChange::Unknown,
))
}
}
#[derive(Default)]
pub struct Felt252DictEntryTypeWrapped {}
impl GenericTypeArgGenericType for Felt252DictEntryTypeWrapped {
const ID: GenericTypeId = GenericTypeId::new_inline("Felt252DictEntry");
fn calc_info(
&self,
context: &dyn TypeSpecializationContext,
long_id: crate::program::ConcreteTypeLongId,
wrapped_type_info: TypeInfo,
) -> Result<TypeInfo, SpecializationError> {
specialize_with_dict_value_param(context, long_id, wrapped_type_info)
}
}
pub type Felt252DictEntryType = GenericTypeArgGenericTypeWrapper<Felt252DictEntryTypeWrapped>;
define_libfunc_hierarchy! {
pub enum Felt252DictEntryLibfunc {
Get(Felt252DictEntryGetLibfunc),
Finalize(Felt252DictEntryFinalizeLibfunc),
}, Felt252DictEntryConcreteLibfunc
}
#[derive(Default)]
pub struct Felt252DictEntryGetLibfuncWrapped {}
impl SignatureAndTypeGenericLibfunc for Felt252DictEntryGetLibfuncWrapped {
const STR_ID: &'static str = "felt252_dict_entry_get";
fn specialize_signature(
&self,
context: &dyn SignatureSpecializationContext,
ty: ConcreteTypeId,
) -> Result<LibfuncSignature, SpecializationError> {
let dict_ty = context.get_wrapped_concrete_type(Felt252DictType::id(), ty.clone())?;
let dict_entry_ty =
context.get_wrapped_concrete_type(Felt252DictEntryType::id(), ty.clone())?;
let felt252_ty = context.get_concrete_type(Felt252Type::id(), &[])?;
Ok(LibfuncSignature::new_non_branch_ex(
vec![
ParamSignature::new(dict_ty).with_allow_add_const(),
ParamSignature::new(felt252_ty),
],
vec![
OutputVarInfo {
ty: dict_entry_ty,
ref_info: OutputVarReferenceInfo::Deferred(DeferredOutputKind::AddConst {
param_idx: 0,
}),
},
OutputVarInfo {
ty,
ref_info: OutputVarReferenceInfo::Deferred(DeferredOutputKind::Generic),
},
],
SierraApChange::Known { new_vars_only: true },
))
}
}
pub type Felt252DictEntryGetLibfunc =
WrapSignatureAndTypeGenericLibfunc<Felt252DictEntryGetLibfuncWrapped>;
#[derive(Default)]
pub struct Felt252DictEntryFinalizeLibfuncWrapped {}
impl SignatureAndTypeGenericLibfunc for Felt252DictEntryFinalizeLibfuncWrapped {
const STR_ID: &'static str = "felt252_dict_entry_finalize";
fn specialize_signature(
&self,
context: &dyn SignatureSpecializationContext,
ty: ConcreteTypeId,
) -> Result<LibfuncSignature, SpecializationError> {
let dict_ty = context.get_wrapped_concrete_type(Felt252DictType::id(), ty.clone())?;
let dict_entry_ty =
context.get_wrapped_concrete_type(Felt252DictEntryType::id(), ty.clone())?;
Ok(LibfuncSignature::new_non_branch_ex(
vec![
ParamSignature::new(dict_entry_ty).with_allow_add_const(),
ParamSignature::new(ty),
],
vec![OutputVarInfo {
ty: dict_ty,
ref_info: OutputVarReferenceInfo::SameAsParam { param_idx: 0 },
}],
SierraApChange::Known { new_vars_only: true },
))
}
}
pub type Felt252DictEntryFinalizeLibfunc =
WrapSignatureAndTypeGenericLibfunc<Felt252DictEntryFinalizeLibfuncWrapped>;