slang_types/
registry.rs

1use crate::{FunctionType, PrimitiveType, TypeId, TypeInfo, TypeKind};
2use std::collections::HashMap;
3
4/// Registry that stores all available types in the language
5pub struct TypeRegistry {
6    /// Map from TypeId to TypeInfo
7    types: HashMap<TypeId, TypeInfo>,
8    /// Map from function signatures to TypeIds for fast function type deduplication
9    function_type_cache: HashMap<FunctionType, TypeId>,
10}
11
12impl TypeRegistry {
13    /// Creates a new TypeRegistry with built-in types registered.
14    pub fn new_instance() -> Self {
15        let mut registry = TypeRegistry {
16            types: HashMap::new(),
17            function_type_cache: HashMap::new(),
18        };
19        registry.register_built_in_types();
20        registry
21    }
22
23    /// Registers all built-in types in the type registry
24    fn register_built_in_types(&mut self) {
25        for ptype in PrimitiveType::iter() {
26            self.register_primitive_type(
27                ptype.name(),
28                ptype.to_type_kind(),
29                TypeId::from_primitive(ptype),
30            );
31        }
32    }
33
34    /// Registers a new type in the registry
35    ///
36    /// ### Arguments
37    ///
38    /// * `name` - The name of the type
39    /// * `kind` - The kind of the type (e.g., Integer, Float, etc.)
40    ///
41    /// ### Returns
42    /// A TypeId representing the newly registered type
43    pub fn register_type(&mut self, name: &str, kind: TypeKind) -> TypeId {
44        let id = TypeId::new();
45        let type_info = TypeInfo {
46            id: id.clone(),
47            name: name.to_string(),
48            kind,
49        };
50        self.types.insert(id.clone(), type_info);
51        id
52    }
53
54    /// Registers a primitive type in the registry
55    ///
56    /// ### Arguments
57    ///
58    /// * `name` - The name of the primitive type
59    /// * `kind` - The kind of the primitive type (e.g., Integer, Float, etc.)
60    /// * `id` - The TypeId for the primitive type
61    fn register_primitive_type(&mut self, name: &str, kind: TypeKind, id: TypeId) {
62        let type_info = TypeInfo {
63            id: id.clone(),
64            name: name.to_string(),
65            kind,
66        };
67        self.types.insert(id, type_info);
68    }
69
70    /// Gets type information for a given TypeId
71    ///
72    /// ### Arguments
73    /// * `id` - The TypeId to look up
74    ///
75    /// ### Returns
76    /// An Option containing the TypeInfo if found, or None if not found
77    pub fn get_type_info(&self, id: &TypeId) -> Option<&TypeInfo> {
78        self.types.get(id)
79    }
80
81    /// Try to get the primitive type for a given TypeId
82    ///
83    /// ### Arguments
84    /// * `id` - The TypeId to look up
85    ///
86    /// ### Returns
87    /// An Option containing the PrimitiveType if found, or None if not found
88    pub fn get_primitive_type(&self, id: &TypeId) -> Option<PrimitiveType> {
89        self.get_type_info(id)
90            .and_then(|info| PrimitiveType::from_str(&info.name))
91    }
92
93    /// Check if a type is a primitive type
94    ///
95    /// ### Arguments
96    /// * `id` - The TypeId to check
97    ///
98    /// ### Returns
99    /// A boolean indicating whether the type is a primitive type
100    pub fn is_primitive_type(&self, id: &TypeId) -> bool {
101        self.get_primitive_type(id).is_some()
102    }
103
104    /// Checks if a value is within the valid range for a given type
105    ///
106    /// ### Arguments
107    /// * `value` - The value to check
108    /// * `type_id` - The TypeId of the type to check against
109    ///
110    /// ### Returns
111    /// A boolean indicating whether the value is within the valid range
112    pub fn check_value_in_range(&self, value: &i64, type_id: &TypeId) -> bool {
113        let type_info = match self.get_type_info(type_id) {
114            Some(info) => info,
115            None => return false,
116        };
117
118        match &type_info.kind {
119            TypeKind::Integer(int_type) => match (int_type.signed, int_type.bits) {
120                (true, 32) => *value >= i32::MIN as i64 && *value <= i32::MAX as i64,
121                (true, 64) => true,
122                (false, 32) => *value >= 0 && *value <= u32::MAX as i64,
123                (false, 64) => *value >= 0,
124                _ => false,
125            },
126            TypeKind::Float(float_type) => match float_type.bits {
127                32 => *value >= f32::MIN as i64 && *value <= f32::MAX as i64,
128                64 => true,
129                _ => *value >= f64::MIN as i64 && *value <= f64::MAX as i64,
130            },
131            _ => false,
132        }
133    }
134
135    /// Checks if a float value is within the valid range for a given type
136    ///
137    /// ### Arguments
138    /// * `value` - The float value to check
139    /// * `type_id` - The TypeId of the type to check against
140    ///
141    /// ### Returns
142    /// A boolean indicating whether the float value is within the valid range
143    pub fn check_float_value_in_range(&self, value: &f64, type_id: &TypeId) -> bool {
144        let type_info = match self.get_type_info(type_id) {
145            Some(info) => info,
146            None => return false,
147        };
148
149        match &type_info.kind {
150            TypeKind::Float(float_type) => match float_type.bits {
151                32 => *value >= f32::MIN as f64 && *value <= f32::MAX as f64,
152                64 => true,
153                _ => false,
154            },
155            _ => false,
156        }
157    }
158
159    /// Registers a function type in the registry
160    ///
161    /// ### Arguments
162    /// * `param_types` - The parameter types of the function
163    /// * `return_type` - The return type of the function
164    ///
165    /// ### Returns
166    /// A TypeId representing the function type (either existing or newly registered)
167    pub fn register_function_type(
168        &mut self,
169        param_types: Vec<TypeId>,
170        return_type: TypeId,
171    ) -> TypeId {
172        // Create a function type signature for lookup
173        let function_signature = FunctionType::new(param_types.clone(), return_type.clone());
174
175        if let Some(&existing_type_id) = self.function_type_cache.get(&function_signature) {
176            return existing_type_id;
177        }
178
179        let kind = TypeKind::Function(function_signature.clone());
180
181        let param_type_names: Vec<&str> = param_types
182            .iter()
183            .filter_map(|id| self.get_type_info(id).map(|info| info.name.as_str()))
184            .collect();
185
186        let return_type_name = self
187            .get_type_info(&return_type)
188            .map(|info| info.name.as_str())
189            .unwrap_or("UnknownType");
190
191        let name = format!(
192            "fn({}) -> {}",
193            param_type_names.join(", "),
194            return_type_name
195        );
196
197        let type_id = self.register_type(&name, kind);
198
199        self.function_type_cache.insert(function_signature, type_id);
200
201        type_id
202    }
203
204    /// Checks if a type is a function type
205    ///
206    /// ### Arguments
207    /// * `id` - The TypeId to check
208    ///
209    /// ### Returns
210    /// A boolean indicating whether the type is a function type
211    pub fn is_function_type(&self, id: &TypeId) -> bool {
212        self.get_type_info(id)
213            .map(|info| matches!(info.kind, TypeKind::Function(_)))
214            .unwrap_or(false)
215    }
216
217    /// Gets the function type information for a given TypeId
218    ///
219    /// ### Arguments
220    /// * `id` - The TypeId to look up
221    ///
222    /// ### Returns
223    /// An Option containing the FunctionType if found, or None if not found or not a function
224    pub fn get_function_type(&self, id: &TypeId) -> Option<&FunctionType> {
225        self.get_type_info(id).and_then(|info| match &info.kind {
226            TypeKind::Function(func_type) => Some(func_type),
227            _ => None,
228        })
229    }
230}