cairo_lang_sierra/extensions/modules/
consts.rsuse num_bigint::BigInt;
use num_traits::Signed;
use crate::extensions::lib_func::{
DeferredOutputKind, LibfuncSignature, OutputVarInfo, SierraApChange,
SignatureSpecializationContext, SpecializationContext,
};
use crate::extensions::{
NamedLibfunc, OutputVarReferenceInfo, SignatureBasedConcreteLibfunc, SpecializationError,
args_as_single_value,
};
use crate::ids::GenericTypeId;
use crate::program::GenericArg;
pub trait ConstGenLibfunc: Default {
const STR_ID: &'static str;
const GENERIC_TYPE_ID: GenericTypeId;
fn bound() -> BigInt;
}
#[derive(Default)]
pub struct WrapConstGenLibfunc<T: ConstGenLibfunc>(T);
impl<T: ConstGenLibfunc> NamedLibfunc for WrapConstGenLibfunc<T> {
const STR_ID: &'static str = <T as ConstGenLibfunc>::STR_ID;
type Concrete = SignatureAndConstConcreteLibfunc;
fn specialize_signature(
&self,
context: &dyn SignatureSpecializationContext,
_args: &[GenericArg],
) -> Result<LibfuncSignature, SpecializationError> {
Ok(LibfuncSignature::new_non_branch(
vec![],
vec![OutputVarInfo {
ty: context.get_concrete_type(<T as ConstGenLibfunc>::GENERIC_TYPE_ID, &[])?,
ref_info: OutputVarReferenceInfo::Deferred(DeferredOutputKind::Const),
}],
SierraApChange::Known { new_vars_only: true },
))
}
fn specialize(
&self,
context: &dyn SpecializationContext,
args: &[GenericArg],
) -> Result<Self::Concrete, SpecializationError> {
let c = args_as_single_value(args)?;
if c.is_negative() || c > (<T as ConstGenLibfunc>::bound()) {
return Err(SpecializationError::UnsupportedGenericArg);
}
Ok(SignatureAndConstConcreteLibfunc {
c: c.clone(),
signature: <Self as NamedLibfunc>::specialize_signature(self, context.upcast(), args)?,
})
}
}
pub struct SignatureAndConstConcreteLibfunc {
pub c: BigInt,
pub signature: LibfuncSignature,
}
impl SignatureBasedConcreteLibfunc for SignatureAndConstConcreteLibfunc {
fn signature(&self) -> &LibfuncSignature {
&self.signature
}
}