py_ir/
types.rs

1use std::collections::HashMap;
2
3#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq)]
4pub enum PrimitiveType {
5    Bool, // boolean
6    I8,
7    U8,
8    I16,
9    U16,
10    I32,
11    U32, // char
12    I64,
13    U64,
14    I128,
15    U128,
16    Usize,
17    Isize,
18    F32,
19    F64,
20}
21
22impl PrimitiveType {
23    pub fn char() -> Self {
24        Self::U32
25    }
26
27    pub fn is_float(&self) -> bool {
28        matches!(self, Self::F32 | Self::F64)
29    }
30
31    pub fn is_integer(&self) -> bool {
32        !self.is_float() && self != &Self::Bool
33    }
34
35    pub fn is_signed(&self) -> bool {
36        matches!(
37            self,
38            Self::I8 | Self::I16 | Self::I32 | Self::I64 | Self::I128 | Self::Isize
39        )
40    }
41
42    pub fn is_unsigned(&self) -> bool {
43        matches!(
44            self,
45            Self::U8 | Self::U16 | Self::U32 | Self::U64 | Self::U128 | Self::Usize
46        )
47    }
48
49    pub fn width(&self) -> usize {
50        match self {
51            PrimitiveType::Bool => 1,
52            PrimitiveType::I8 | PrimitiveType::U8 => 8,
53            PrimitiveType::I16 | PrimitiveType::U16 => 16,
54            PrimitiveType::I32 | PrimitiveType::U32 => 32,
55            PrimitiveType::I64 | PrimitiveType::U64 => 64,
56            PrimitiveType::I128 | PrimitiveType::U128 => 128,
57            // !
58            PrimitiveType::Usize | PrimitiveType::Isize => 64,
59            PrimitiveType::F32 => 32,
60            PrimitiveType::F64 => 64,
61        }
62    }
63}
64
65impl std::fmt::Display for PrimitiveType {
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        // hmmm...
68        write!(f, "{}", format!("{self:?}").to_ascii_lowercase())
69    }
70}
71
72#[derive(Debug, Clone, PartialEq)]
73pub enum TypeDecorators {
74    // #[deprecated = "unclear semantics"]
75    Const,
76    // TODO: remove this varient
77    Array,
78    Reference,
79    Pointer,
80    SizedArray(usize),
81}
82
83mod serde_type_decorators {
84    use super::*;
85    struct Visitor;
86
87    impl serde::de::Visitor<'_> for Visitor {
88        type Value = TypeDecorators;
89
90        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
91            formatter.write_str("Const, Unigned, Array, Reference, Pointer...")
92        }
93
94        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
95        where
96            E: serde::de::Error,
97        {
98            match v {
99                "Const" => Ok(TypeDecorators::Const),
100                "Array" => Ok(TypeDecorators::Array),
101                "Reference" => Ok(TypeDecorators::Reference),
102                "Pointer" => Ok(TypeDecorators::Pointer),
103                a => a
104                    .parse::<usize>()
105                    .map(TypeDecorators::SizedArray)
106                    .map_err(E::custom),
107            }
108        }
109    }
110
111    impl serde::Serialize for TypeDecorators {
112        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
113        where
114            S: serde::Serializer,
115        {
116            match self {
117                TypeDecorators::Const => serializer.serialize_str("Const"),
118                TypeDecorators::Array => serializer.serialize_str("Array"),
119                TypeDecorators::Reference => serializer.serialize_str("Reference"),
120                TypeDecorators::Pointer => serializer.serialize_str("Pointer"),
121                TypeDecorators::SizedArray(v) => serializer.serialize_str(&format!("Array {v}")),
122            }
123        }
124    }
125
126    impl<'de> serde::Deserialize<'de> for TypeDecorators {
127        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
128        where
129            D: serde::Deserializer<'de>,
130        {
131            deserializer.deserialize_str(Visitor)
132        }
133    }
134}
135
136#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
137pub struct ComplexType {
138    /// use option to avoid memory allocation sometimes
139    #[serde(default)]
140    #[serde(skip_serializing_if = "Vec::is_empty")]
141    pub decorators: Vec<TypeDecorators>,
142    #[serde(rename = "type")]
143    pub ty: String,
144}
145
146impl ComplexType {
147    pub fn no_decorators(ty: String) -> Self {
148        Self {
149            decorators: Vec::new(),
150            ty,
151        }
152    }
153
154    pub fn string() -> Self {
155        Self {
156            decorators: vec![TypeDecorators::Array],
157            ty: "u8".into(),
158        }
159    }
160}
161
162impl std::fmt::Display for ComplexType {
163    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164        for dec in &self.decorators {
165            match dec {
166                TypeDecorators::Const => write!(f, "const "),
167                TypeDecorators::Array => write!(f, "[] "),
168                TypeDecorators::Reference => write!(f, "& "),
169                TypeDecorators::Pointer => write!(f, "* "),
170                TypeDecorators::SizedArray(s) => write!(f, "[{s}] "),
171            }?;
172        }
173
174        write!(f, "{}", self.ty)
175    }
176}
177
178#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
179pub enum TypeDefine {
180    Primitive(PrimitiveType),
181    Complex(ComplexType),
182}
183
184impl TypeDefine {
185    /// Returns `true` if the type define is [`Primitive`].
186    ///
187    /// [`Primitive`]: TypeDefine::Primitive
188    #[must_use]
189    pub fn is_primitive(&self) -> bool {
190        matches!(self, Self::Primitive(..))
191    }
192
193    /// Returns `true` if the type define is [`Complex`].
194    ///
195    /// [`Complex`]: TypeDefine::Complex
196    #[must_use]
197    pub fn is_complex(&self) -> bool {
198        matches!(self, Self::Complex(..))
199    }
200
201    pub fn as_primitive(&self) -> Option<&PrimitiveType> {
202        if let Self::Primitive(v) = self {
203            Some(v)
204        } else {
205            None
206        }
207    }
208}
209
210impl std::fmt::Display for TypeDefine {
211    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212        match self {
213            TypeDefine::Primitive(ty) => write!(f, "{}", ty),
214            TypeDefine::Complex(ty) => write!(f, "{}", ty),
215        }
216    }
217}
218
219impl From<ComplexType> for TypeDefine {
220    fn from(v: ComplexType) -> Self {
221        Self::Complex(v)
222    }
223}
224
225impl From<PrimitiveType> for TypeDefine {
226    fn from(v: PrimitiveType) -> Self {
227        Self::Primitive(v)
228    }
229}
230
231impl TryFrom<TypeDefine> for PrimitiveType {
232    type Error = TypeDefine;
233
234    fn try_from(value: TypeDefine) -> Result<Self, Self::Error> {
235        match value {
236            TypeDefine::Primitive(p) => Ok(p),
237            TypeDefine::Complex(_) => Err(value),
238        }
239    }
240}
241
242impl TryFrom<TypeDefine> for ComplexType {
243    type Error = TypeDefine;
244
245    fn try_from(value: TypeDefine) -> Result<Self, Self::Error> {
246        match value {
247            TypeDefine::Primitive(_) => Err(value),
248            TypeDefine::Complex(c) => Ok(c),
249        }
250    }
251}
252
253impl PartialEq<PrimitiveType> for TypeDefine {
254    fn eq(&self, other: &PrimitiveType) -> bool {
255        match self {
256            TypeDefine::Primitive(s) => s == other,
257            TypeDefine::Complex(_) => false,
258        }
259    }
260}
261
262#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
263pub enum Type {
264    Template(Template),
265    Primitive(PrimitiveType),
266    Custom(String),
267}
268
269impl From<Template> for Type {
270    fn from(v: Template) -> Self {
271        Self::Template(v)
272    }
273}
274
275impl From<PrimitiveType> for Type {
276    fn from(v: PrimitiveType) -> Self {
277        Self::Primitive(v)
278    }
279}
280
281impl From<String> for Type {
282    fn from(v: String) -> Self {
283        Self::Custom(v)
284    }
285}
286
287#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
288pub struct Template {
289    pub name: String,
290    pub generics: HashMap<String, Type>,
291}
292
293impl Template {
294    pub fn new<I>(name: I, generics: HashMap<String, Type>) -> Self
295    where
296        I: Into<String>,
297    {
298        Self {
299            name: name.into(),
300            generics,
301        }
302    }
303
304    pub fn reference(to: Type) -> Self {
305        Self::new("&", std::iter::once(("T".into(), to)).collect())
306    }
307}