cairo_lang_sierra/extensions/modules/
boxing.rs

1use super::snapshot::snapshot_ty;
2use super::utils::reinterpret_cast_signature;
3use crate::define_libfunc_hierarchy;
4use crate::extensions::lib_func::{
5    DeferredOutputKind, LibfuncSignature, OutputVarInfo, SierraApChange,
6    SignatureAndTypeGenericLibfunc, SignatureSpecializationContext,
7    WrapSignatureAndTypeGenericLibfunc,
8};
9use crate::extensions::type_specialization_context::TypeSpecializationContext;
10use crate::extensions::types::{
11    GenericTypeArgGenericType, GenericTypeArgGenericTypeWrapper, TypeInfo,
12};
13use crate::extensions::{NamedType, OutputVarReferenceInfo, SpecializationError};
14use crate::ids::{ConcreteTypeId, GenericTypeId};
15
16/// Type wrapping a value.
17#[derive(Default)]
18pub struct BoxTypeWrapped {}
19impl GenericTypeArgGenericType for BoxTypeWrapped {
20    const ID: GenericTypeId = GenericTypeId::new_inline("Box");
21
22    fn calc_info(
23        &self,
24        _context: &dyn TypeSpecializationContext,
25        long_id: crate::program::ConcreteTypeLongId,
26        TypeInfo { storable, droppable, duplicatable, .. }: TypeInfo,
27    ) -> Result<TypeInfo, SpecializationError> {
28        if storable {
29            Ok(TypeInfo { long_id, zero_sized: false, storable, droppable, duplicatable })
30        } else {
31            Err(SpecializationError::UnsupportedGenericArg)
32        }
33    }
34}
35pub type BoxType = GenericTypeArgGenericTypeWrapper<BoxTypeWrapped>;
36
37define_libfunc_hierarchy! {
38    pub enum BoxLibfunc {
39        Into(IntoBoxLibfunc),
40        Unbox(UnboxLibfunc),
41        ForwardSnapshot(BoxForwardSnapshotLibfunc),
42    }, BoxConcreteLibfunc
43}
44
45/// Helper for getting the `Box<T>` type.
46pub fn box_ty(
47    context: &dyn SignatureSpecializationContext,
48    ty: ConcreteTypeId,
49) -> Result<ConcreteTypeId, SpecializationError> {
50    context.get_wrapped_concrete_type(BoxType::id(), ty)
51}
52
53/// Libfunc for wrapping an object of type T into a box.
54#[derive(Default)]
55pub struct IntoBoxLibfuncWrapped {}
56impl SignatureAndTypeGenericLibfunc for IntoBoxLibfuncWrapped {
57    const STR_ID: &'static str = "into_box";
58
59    fn specialize_signature(
60        &self,
61        context: &dyn SignatureSpecializationContext,
62        ty: ConcreteTypeId,
63    ) -> Result<LibfuncSignature, SpecializationError> {
64        Ok(LibfuncSignature::new_non_branch(
65            vec![ty.clone()],
66            vec![OutputVarInfo {
67                ty: box_ty(context, ty)?,
68                ref_info: OutputVarReferenceInfo::NewTempVar { idx: 0 },
69            }],
70            SierraApChange::Known { new_vars_only: true },
71        ))
72    }
73}
74pub type IntoBoxLibfunc = WrapSignatureAndTypeGenericLibfunc<IntoBoxLibfuncWrapped>;
75
76/// Libfunc for unboxing a `Box<T>` back into a T.
77#[derive(Default)]
78pub struct UnboxLibfuncWrapped {}
79impl SignatureAndTypeGenericLibfunc for UnboxLibfuncWrapped {
80    const STR_ID: &'static str = "unbox";
81
82    fn specialize_signature(
83        &self,
84        context: &dyn SignatureSpecializationContext,
85        ty: ConcreteTypeId,
86    ) -> Result<LibfuncSignature, SpecializationError> {
87        Ok(LibfuncSignature::new_non_branch(
88            vec![box_ty(context, ty.clone())?],
89            vec![OutputVarInfo {
90                ty: ty.clone(),
91                ref_info: if context.get_type_info(ty)?.zero_sized {
92                    OutputVarReferenceInfo::ZeroSized
93                } else {
94                    OutputVarReferenceInfo::Deferred(DeferredOutputKind::Generic)
95                },
96            }],
97            SierraApChange::Known { new_vars_only: true },
98        ))
99    }
100}
101pub type UnboxLibfunc = WrapSignatureAndTypeGenericLibfunc<UnboxLibfuncWrapped>;
102
103/// Libfunc for converting `@Box<T>` into `Box<@T>`.
104#[derive(Default)]
105pub struct BoxForwardSnapshotLibfuncWrapped {}
106impl SignatureAndTypeGenericLibfunc for BoxForwardSnapshotLibfuncWrapped {
107    const STR_ID: &'static str = "box_forward_snapshot";
108    fn specialize_signature(
109        &self,
110        context: &dyn SignatureSpecializationContext,
111        ty: ConcreteTypeId,
112    ) -> Result<LibfuncSignature, SpecializationError> {
113        Ok(reinterpret_cast_signature(
114            snapshot_ty(context, box_ty(context, ty.clone())?)?,
115            box_ty(context, snapshot_ty(context, ty)?)?,
116        ))
117    }
118}
119
120pub type BoxForwardSnapshotLibfunc =
121    WrapSignatureAndTypeGenericLibfunc<BoxForwardSnapshotLibfuncWrapped>;