semantic_analyzer/types/
types.rs

1//! # Semantic types
2//! Type-system types for Semantic analyzer State results.
3
4use super::{FunctionName, ValueName};
5use crate::ast::{self, GetName};
6#[cfg(feature = "codec")]
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use std::fmt::Display;
10
11/// `TypeAttributes` type attributes trait.
12/// Used for types declarations.
13pub trait TypeAttributes {
14    /// Get attribute index by value name for the parent type
15    fn get_attribute_index(&self, attr_name: &ValueName) -> Option<u32>;
16    /// Get attribute type by value name for the parent type
17    fn get_attribute_type(&self, attr_name: &ValueName) -> Option<Type>;
18    /// Get function name for the parent type by method name
19    fn get_method(&self, method_name: String) -> Option<FunctionName>;
20    /// Check is value attribute
21    fn is_attribute(&self, name: &ValueName) -> bool;
22    /// Check is name is method
23    fn is_method(&self, name: String) -> bool;
24}
25
26/// Type name representation
27#[derive(Debug, Clone, Eq, Hash, PartialEq)]
28#[cfg_attr(feature = "codec", derive(Serialize, Deserialize))]
29pub struct TypeName(String);
30
31impl GetName for TypeName {
32    fn name(&self) -> String {
33        self.0.clone()
34    }
35}
36
37impl From<String> for TypeName {
38    fn from(value: String) -> Self {
39        Self(value)
40    }
41}
42
43impl Display for TypeName {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        write!(f, "{}", self.0.clone())
46    }
47}
48
49/// # Type
50/// Basic representation of Type. Basic entities:
51/// - primitive type
52/// - struct type
53/// - array type
54#[derive(Debug, Clone, Eq, PartialEq)]
55#[cfg_attr(
56    feature = "codec",
57    derive(Serialize, Deserialize),
58    serde(tag = "type", content = "content")
59)]
60pub enum Type {
61    Primitive(PrimitiveTypes),
62    Struct(StructTypes),
63    Array(Box<Self>, u32),
64}
65
66impl Type {
67    /// Get type name
68    #[must_use]
69    pub fn name(&self) -> TypeName {
70        self.to_string().into()
71    }
72
73    /// Get structure type if it is
74    #[must_use]
75    pub fn get_struct(&self) -> Option<StructTypes> {
76        match self {
77            Self::Struct(ty) => Some(ty.clone()),
78            _ => None,
79        }
80    }
81}
82
83impl Display for Type {
84    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85        let str = match self {
86            Self::Primitive(primitive) => primitive.to_string(),
87            Self::Struct(struct_type) => struct_type.name.clone(),
88            Self::Array(array_type, size) => {
89                format!("[{:?};{:?}]", array_type.to_string(), size)
90            }
91        };
92        write!(f, "{str}")
93    }
94}
95
96impl TypeAttributes for Type {
97    fn get_attribute_index(&self, attr_name: &ValueName) -> Option<u32> {
98        match self {
99            Self::Struct(st) => st.get_attribute_index(attr_name),
100            _ => None,
101        }
102    }
103    fn get_attribute_type(&self, attr_name: &ValueName) -> Option<Type> {
104        match self {
105            Self::Struct(st) => st.get_attribute_type(attr_name),
106            _ => None,
107        }
108    }
109    fn get_method(&self, method_name: String) -> Option<FunctionName> {
110        match self {
111            Self::Struct(st) => st.get_method(method_name),
112            _ => None,
113        }
114    }
115    fn is_attribute(&self, attr_name: &ValueName) -> bool {
116        match self {
117            Self::Struct(st) => st.is_attribute(attr_name),
118            _ => false,
119        }
120    }
121    fn is_method(&self, method_name: String) -> bool {
122        match self {
123            Self::Struct(st) => st.is_method(method_name),
124            _ => false,
125        }
126    }
127}
128
129impl From<ast::Type<'_>> for Type {
130    fn from(value: ast::Type<'_>) -> Self {
131        match value {
132            ast::Type::Primitive(v) => Self::Primitive(v.into()),
133            ast::Type::Struct(v) => Self::Struct(v.into()),
134            ast::Type::Array(v, s) => Self::Array(Box::new(v.as_ref().clone().into()), s),
135        }
136    }
137}
138
139/// # Primitive types
140/// Most primitive type. It's basic elements for other types.
141#[derive(Debug, Clone, PartialEq, Eq)]
142#[cfg_attr(
143    feature = "codec",
144    derive(Serialize, Deserialize),
145    serde(tag = "type", content = "content")
146)]
147pub enum PrimitiveTypes {
148    U8,
149    U16,
150    U32,
151    U64,
152    I8,
153    I16,
154    I32,
155    I64,
156    F32,
157    F64,
158    Bool,
159    Char,
160    Ptr,
161    None,
162}
163
164impl Display for PrimitiveTypes {
165    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166        let s = match self {
167            Self::U8 => "u8",
168            Self::U16 => "u16",
169            Self::U32 => "u32",
170            Self::U64 => "u64",
171            Self::I8 => "i8",
172            Self::I16 => "i16",
173            Self::I32 => "i32",
174            Self::I64 => "i64",
175            Self::F32 => "f32",
176            Self::F64 => "f64",
177            Self::Bool => "bool",
178            Self::Char => "char",
179            Self::Ptr => "ptr",
180            Self::None => "()",
181        };
182        write!(f, "{s}")
183    }
184}
185
186impl From<ast::PrimitiveTypes> for PrimitiveTypes {
187    fn from(value: ast::PrimitiveTypes) -> Self {
188        match value {
189            ast::PrimitiveTypes::U8 => Self::U8,
190            ast::PrimitiveTypes::U16 => Self::U16,
191            ast::PrimitiveTypes::U32 => Self::U32,
192            ast::PrimitiveTypes::U64 => Self::U64,
193            ast::PrimitiveTypes::I8 => Self::I8,
194            ast::PrimitiveTypes::I16 => Self::I16,
195            ast::PrimitiveTypes::I32 => Self::I32,
196            ast::PrimitiveTypes::I64 => Self::I64,
197            ast::PrimitiveTypes::F32 => Self::F32,
198            ast::PrimitiveTypes::F64 => Self::F64,
199            ast::PrimitiveTypes::Bool => Self::Bool,
200            ast::PrimitiveTypes::Char => Self::Char,
201            ast::PrimitiveTypes::Ptr => Self::Ptr,
202            ast::PrimitiveTypes::None => Self::None,
203        }
204    }
205}
206
207/// # Struct types
208/// Basic entity for struct type itself.
209#[derive(Debug, Clone, Eq, PartialEq)]
210#[cfg_attr(feature = "codec", derive(Serialize, Deserialize))]
211pub struct StructTypes {
212    /// Type name
213    pub name: String,
214    /// Struct attributes
215    pub attributes: HashMap<ValueName, StructAttributeType>,
216    /// Struct methods
217    pub methods: HashMap<String, FunctionName>,
218}
219
220impl TypeAttributes for StructTypes {
221    fn get_attribute_index(&self, attr_name: &ValueName) -> Option<u32> {
222        self.attributes.get(attr_name).map(|attr| attr.attr_index)
223    }
224    fn get_attribute_type(&self, attr_name: &ValueName) -> Option<Type> {
225        self.attributes
226            .get(attr_name)
227            .map(|attr| attr.attr_type.clone())
228    }
229    fn get_method(&self, method_name: String) -> Option<FunctionName> {
230        self.methods.get(&method_name).cloned()
231    }
232    fn is_attribute(&self, attr_name: &ValueName) -> bool {
233        self.attributes.contains_key(attr_name)
234    }
235    fn is_method(&self, method_name: String) -> bool {
236        self.methods.contains_key(&method_name)
237    }
238}
239
240impl From<ast::StructTypes<'_>> for StructTypes {
241    fn from(value: ast::StructTypes<'_>) -> Self {
242        Self {
243            name: value.name(),
244            attributes: {
245                let mut res = HashMap::new();
246                for (index, val) in value.attributes.iter().enumerate() {
247                    let name = (*val.attr_name.fragment()).to_string();
248                    let mut v: StructAttributeType = val.clone().into();
249                    v.attr_index = u32::try_from(index).unwrap_or_default();
250                    res.insert(name.into(), v);
251                }
252                res
253            },
254            methods: HashMap::new(),
255        }
256    }
257}
258
259/// `StructAttributeType` is type for Struct attributes fields.
260#[derive(Debug, Clone, Eq, PartialEq)]
261#[cfg_attr(feature = "codec", derive(Serialize, Deserialize))]
262pub struct StructAttributeType {
263    /// Attribute name for struct type
264    pub attr_name: ValueName,
265    /// Attribute index representation for struct type
266    pub attr_index: u32,
267    /// Attribute type for struct type
268    pub attr_type: Type,
269}
270
271impl From<ast::StructType<'_>> for StructAttributeType {
272    fn from(value: ast::StructType<'_>) -> Self {
273        Self {
274            attr_name: value.name().into(),
275            attr_type: value.attr_type.into(),
276            attr_index: 0,
277        }
278    }
279}