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}