ergotree_ir/types/
smethod.rs

1use crate::serialization::sigma_byte_reader::SigmaByteRead;
2use crate::serialization::sigma_byte_writer::SigmaByteWrite;
3use crate::serialization::types::TypeCode;
4use crate::serialization::SigmaParsingError;
5use std::collections::HashMap;
6use std::convert::TryFrom;
7
8use super::sfunc::SFunc;
9use super::stype::SType;
10use super::stype_companion::STypeCompanion;
11use super::stype_param::STypeVar;
12use super::type_unify::unify_many;
13use super::type_unify::TypeUnificationError;
14use crate::serialization::SigmaParsingError::UnknownMethodId;
15
16/// Method id unique among the methods of the same object
17#[derive(PartialEq, Eq, Debug, Clone)]
18pub struct MethodId(pub u8);
19
20impl MethodId {
21    pub(crate) fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> std::io::Result<()> {
22        w.put_u8(self.0)
23    }
24
25    pub(crate) fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> std::io::Result<Self> {
26        Ok(Self(r.get_u8()?))
27    }
28}
29
30/// Object method signature
31#[derive(PartialEq, Eq, Debug, Clone)]
32pub struct SMethod {
33    /// Object type companion
34    pub obj_type: STypeCompanion,
35    method_raw: SMethodDesc,
36}
37
38impl SMethod {
39    /// Create new SMethod
40    pub const fn new(obj_type: STypeCompanion, method_raw: SMethodDesc) -> SMethod {
41        SMethod {
42            obj_type,
43            method_raw,
44        }
45    }
46
47    /// Get method from type and method ids
48    pub(crate) fn from_ids(
49        type_id: TypeCode,
50        method_id: MethodId,
51    ) -> Result<Self, SigmaParsingError> {
52        let obj_type = STypeCompanion::try_from(type_id)?;
53        match obj_type.method_by_id(&method_id) {
54            Some(m) => Ok(m),
55            None => Err(UnknownMethodId(method_id, type_id.value())),
56        }
57    }
58
59    /// Type
60    pub fn tpe(&self) -> &SFunc {
61        &self.method_raw.tpe
62    }
63
64    /// Returns method name
65    pub fn name(&self) -> &'static str {
66        self.method_raw.name
67    }
68
69    /// Returns method id
70    pub fn method_id(&self) -> MethodId {
71        self.method_raw.method_id.clone()
72    }
73
74    /// Return new SMethod with type variables substituted
75    pub fn with_concrete_types(self, subst: &HashMap<STypeVar, SType>) -> Self {
76        let new_tpe = self.method_raw.tpe.clone().with_subst(subst);
77        Self {
78            method_raw: self.method_raw.with_tpe(new_tpe),
79            ..self
80        }
81    }
82
83    /// Specializes this instance by creating a new [`SMethod`] instance where signature
84    /// is specialized with respect to the given object and args types.
85    pub fn specialize_for(
86        self,
87        obj_tpe: SType,
88        args: Vec<SType>,
89    ) -> Result<SMethod, TypeUnificationError> {
90        let mut items2 = vec![obj_tpe];
91        let mut args = args;
92        items2.append(args.as_mut());
93        unify_many(self.tpe().t_dom.clone(), items2).map(|subst| self.with_concrete_types(&subst))
94    }
95}
96
97/// Object method description
98#[derive(PartialEq, Eq, Debug, Clone)]
99pub struct SMethodDesc {
100    pub(crate) name: &'static str,
101    pub(crate) method_id: MethodId,
102    pub(crate) tpe: SFunc,
103}
104
105impl SMethodDesc {
106    /// Initialize property method description
107    pub fn property(
108        obj_tpe: SType,
109        name: &'static str,
110        res_tpe: SType,
111        id: MethodId,
112    ) -> SMethodDesc {
113        SMethodDesc {
114            method_id: id,
115            name,
116            tpe: SFunc {
117                t_dom: vec![obj_tpe],
118                t_range: res_tpe.into(),
119                tpe_params: vec![],
120            },
121        }
122    }
123    pub(crate) fn as_method(&self, obj_type: STypeCompanion) -> SMethod {
124        SMethod {
125            obj_type,
126            method_raw: self.clone(),
127        }
128    }
129
130    pub(crate) fn with_tpe(self, tpe: SFunc) -> Self {
131        Self { tpe, ..self }
132    }
133}