1use crate::prelude::InstantiationCache;
2use crate::{
3 AssociatedImpls, ExternalFunctionDefinition, Function, FunctionScopeState,
4 InternalFunctionDefinition, LocalIdentifier, SemanticError,
5};
6use seq_map::SeqMap;
7use std::rc::Rc;
8use swamp_script_node::Node;
9use swamp_script_types::{
10 AnonymousStructType, NamedStructType, ParameterizedTypeBlueprint,
11 ParameterizedTypeBlueprintInfo, ParameterizedTypeKind, Signature, StructTypeField, Type,
12 TypeForParameter, all_types_are_concrete, all_types_are_concrete_or_unit,
13};
14
15#[derive(Debug)]
16pub struct TypeVariableScope {
17 pub type_variables: SeqMap<String, Type>,
18}
19
20impl TypeVariableScope {
21 #[must_use]
22 pub const fn new(scope: SeqMap<String, Type>) -> Self {
23 Self {
24 type_variables: scope,
25 }
26 }
27
28 pub(crate) fn variables(&self) -> Vec<Type> {
29 self.type_variables.values().cloned().collect()
30 }
31}
32#[derive(Clone, Debug)]
33pub struct Instantiator {
34 pub associated_impls: AssociatedImpls,
35 pub instantiation_cache: InstantiationCache,
36}
37
38impl Instantiator {
39 pub fn new() -> Self {
40 Self {
41 associated_impls: AssociatedImpls::new(),
42 instantiation_cache: InstantiationCache::new(),
43 }
44 }
45 pub fn instantiate_blueprint_and_members(
46 &mut self,
47 blueprint: &ParameterizedTypeBlueprint,
48 analyzed_type_parameters: &[Type],
49 ) -> Result<Type, SemanticError> {
50 assert!(all_types_are_concrete_or_unit(analyzed_type_parameters));
51
52 if let Some(existing) = self.instantiation_cache.get(
53 &blueprint.defined_in_module_path,
54 &blueprint.name(),
55 analyzed_type_parameters,
56 ) {
57 return Ok(existing.clone());
58 }
59
60 let scope = Self::create_type_parameter_scope_from_variables(
61 &blueprint.type_variables,
62 analyzed_type_parameters,
63 )?;
64 let (_ignore_if_changed, instantiated_type) =
65 self.instantiate_base_type_from_blueprint(blueprint, &scope)?;
66
67 let new_impls = {
68 let mut new_impls = SeqMap::new();
69 let maybe_member_functions = self
70 .associated_impls
71 .functions
72 .get(&Type::Blueprint(blueprint.clone()))
73 .cloned();
74 if let Some(found_member_functions) = maybe_member_functions {
75 for (func_name, func_ref) in &found_member_functions.functions {
76 let (_replaced, new_signature) = self.instantiate_signature(
77 &instantiated_type,
78 func_ref.signature(),
79 &scope,
80 )?;
81 let new_func = match &**func_ref {
82 Function::Internal(internal) => {
83 let func_ref = Rc::new(InternalFunctionDefinition {
84 body: internal.body.clone(),
85 name: LocalIdentifier(Node::default()),
86 assigned_name: format!("instantiated {func_name}"),
87 signature: new_signature.clone(),
88 variable_scopes: FunctionScopeState::new(
89 *new_signature.return_type.clone(),
90 ), function_scope_state: Vec::new(), program_unique_id: internal.program_unique_id,
93 });
94 Function::Internal(func_ref)
95 }
96 Function::External(blueprint_external) => {
97 let func_ref = Rc::new(ExternalFunctionDefinition {
98 name: None,
99 assigned_name: String::new(),
100 signature: new_signature,
101 id: blueprint_external.id,
102 });
103 Function::External(func_ref)
104 }
105 };
106 new_impls.insert(func_name.clone(), new_func).unwrap();
107 }
108 }
109 new_impls
110 };
111
112 self.associated_impls.prepare(&instantiated_type);
113 for (name, func) in &new_impls {
114 self.associated_impls.add_member_function(
115 &instantiated_type,
116 name,
117 func.clone().into(),
118 )?;
119 }
120
121 self.instantiation_cache
122 .add(
123 &blueprint.defined_in_module_path,
124 &blueprint.name(),
125 instantiated_type.clone(),
126 analyzed_type_parameters,
127 )
128 .unwrap();
129
130 Ok(instantiated_type)
131 }
132
133 fn create_type_parameter_scope(
134 parameters: &[Type],
135 concrete: &[Type],
136 ) -> Result<TypeVariableScope, SemanticError> {
137 assert_eq!(parameters.len(), concrete.len(), "wrong parameter count");
138
139 let mut scope = SeqMap::new();
140 for (param, concrete) in parameters.iter().zip(concrete) {
141 if let Type::Variable(type_variable_name) = param {
142 scope
143 .insert(type_variable_name.clone(), concrete.clone())
144 .unwrap();
145 };
146 }
147
148 Ok(TypeVariableScope::new(scope))
149 }
150
151 fn create_type_parameter_scope_from_variables(
152 variables: &[String],
153 concrete_types: &[Type],
154 ) -> Result<TypeVariableScope, SemanticError> {
155 assert_eq!(
156 variables.len(),
157 concrete_types.len(),
158 "wrong parameter count"
159 );
160
161 assert!(all_types_are_concrete_or_unit(concrete_types));
162
163 let mut scope = SeqMap::new();
164 for (param, concrete) in variables.iter().zip(concrete_types) {
165 scope.insert(param.clone(), concrete.clone()).unwrap();
166 }
167
168 Ok(TypeVariableScope::new(scope))
169 }
170
171 fn instantiate_base_type_from_blueprint(
172 &mut self,
173 blueprint: &ParameterizedTypeBlueprint,
174 scope: &TypeVariableScope,
175 ) -> Result<(bool, Type), SemanticError> {
176 match &blueprint.kind {
177 ParameterizedTypeKind::Struct(struct_ref) => self.instantiate_struct(
178 Some(&Type::Blueprint(blueprint.clone())),
179 struct_ref,
180 scope,
181 ),
182 ParameterizedTypeKind::Enum(_) => todo!(),
183 }
184 }
185
186 fn instantiate_type_in_signature(
187 &mut self,
188 current_self: &Type,
189 ty: &Type,
190 type_variables: &TypeVariableScope,
191 ) -> Result<(bool, Type), SemanticError> {
192 match ty {
193 Type::Blueprint(_) => {
194 Ok((false, current_self.clone()))
196 }
197 _ => self.instantiate_type_if_needed(Some(current_self), ty, type_variables),
198 }
199 }
200
201 pub fn instantiate_signature(
202 &mut self,
203 self_type: &Type,
204 signature: &Signature,
205 scope: &TypeVariableScope,
206 ) -> Result<(bool, Signature), SemanticError> {
207 let mut was_replaced = false;
208 let mut instantiated_type_for_parameters = Vec::new();
209 for type_for_parameter in &signature.parameters {
210 let (type_was_replaced, resolved) = self.instantiate_type_in_signature(
211 self_type,
212 &type_for_parameter.resolved_type,
213 scope,
214 )?;
215
216 if type_was_replaced {
217 was_replaced = true;
218 }
219 instantiated_type_for_parameters.push(TypeForParameter {
220 name: type_for_parameter.name.clone(),
221 resolved_type: resolved,
222 is_mutable: type_for_parameter.is_mutable,
223 node: type_for_parameter.node.clone(),
224 });
225 }
226
227 let (return_type_was_replaced, instantiated_return_type) =
228 self.instantiate_type_in_signature(self_type, &signature.return_type, scope)?;
229 if return_type_was_replaced {
230 was_replaced = true;
231 }
232
233 let new_signature = Signature {
234 parameters: instantiated_type_for_parameters,
235 return_type: Box::new(instantiated_return_type),
236 };
237
238 Ok((was_replaced, new_signature))
239 }
240
241 fn instantiate_types_if_needed(
242 &mut self,
243 current_self: Option<&Type>,
244
245 types: &[Type],
246 type_variables: &TypeVariableScope,
247 ) -> Result<(bool, Vec<Type>), SemanticError> {
248 let mut converted = Vec::new();
249
250 for ty in types {
251 let (_was_converted, instantiated_type) =
252 self.instantiate_type_if_needed(current_self, ty, type_variables)?;
253
254 converted.push(instantiated_type);
255 }
256
257 Ok((true, converted))
258 }
259
260 fn extract_blueprint_info(ty: &Type) -> Option<ParameterizedTypeBlueprintInfo> {
262 match ty {
263 Type::Blueprint(bp) => Some(bp.info()),
264 Type::NamedStruct(named) => Some(named.blueprint_info.clone().unwrap()),
265 Type::Generic(bp, _) => Some(bp.info()),
266 _ => None,
267 }
268 }
269
270 fn instantiate_type_if_needed(
271 &mut self,
272 current_self: Option<&Type>,
273 ty: &Type,
274 type_variables: &TypeVariableScope,
275 ) -> Result<(bool, Type), SemanticError> {
276 if let Some(cs) = current_self {
277 if let Some(cs_bp) = Self::extract_blueprint_info(cs) {
278 let other = Self::extract_blueprint_info(&ty);
279 if let Some(found_other) = other {
280 if found_other == cs_bp {
281 return Ok((false, cs.clone()));
282 }
283 }
284 }
285 }
286
287 let (replaced, result_type) = match ty {
288 Type::Generic(parameterized_type, arguments) => {
289 let (_was_replaced, new_arguments) =
290 self.instantiate_types_if_needed(current_self, arguments, type_variables)?;
291 if all_types_are_concrete(&new_arguments) {
292 let new_type =
293 self.instantiate_blueprint_and_members(parameterized_type, &new_arguments)?;
294 (true, new_type)
295 } else {
296 panic!("Cannot instantiate generics with unresolved parameters")
297 }
298 }
299
300 Type::Variable(type_variable) => {
301 let found_type = type_variables
302 .type_variables
303 .get(type_variable)
304 .ok_or(SemanticError::UnknownTypeVariable)?;
305 assert!(found_type.is_concrete());
306 (true, found_type.clone())
307 }
308
309 Type::Blueprint(_blueprint) => {
310 panic!("not allowed with blueprints here for types")
312 }
313
314 Type::Tuple(types) => {
315 let (was_replaced, new_types) =
316 self.instantiate_types_if_needed(current_self, types, type_variables)?;
317 (was_replaced, Type::Tuple(new_types))
318 }
319
320 Type::Optional(inner_type) => {
321 let (was_replaced, new_type) =
322 self.instantiate_type_if_needed(current_self, inner_type, type_variables)?;
323 (was_replaced, Type::Optional(Box::new(new_type)))
324 }
325
326 Type::Slice(inner_type) => {
327 let (was_replaced, new_type) =
328 self.instantiate_type_if_needed(current_self, inner_type, type_variables)?;
329 (was_replaced, Type::Slice(Box::new(new_type)))
330 }
331
332 Type::SlicePair(key_type, value_type) => {
333 let (key_type_was_replaced, new_key_type) =
334 self.instantiate_type_if_needed(current_self, key_type, type_variables)?;
335 let (value_type_was_replaced, new_value_type) =
336 self.instantiate_type_if_needed(current_self, value_type, type_variables)?;
337 (
338 key_type_was_replaced || value_type_was_replaced,
339 Type::SlicePair(Box::new(new_key_type), Box::new(new_value_type)),
340 )
341 }
342
343 _ => (false, ty.clone()),
344 };
345
346 Ok((replaced, result_type))
347 }
348
349 fn parameterized_name(name: &str, parameters: &[Type]) -> String {
350 let type_strings: Vec<String> = parameters
351 .iter()
352 .map(std::string::ToString::to_string)
353 .collect();
354
355 format!("{}<{}>", name, type_strings.join(","))
356 }
357
358 fn instantiate_struct(
359 &mut self,
360 current_self: Option<&Type>,
361 struct_type: &NamedStructType,
362 type_variables: &TypeVariableScope,
363 ) -> Result<(bool, Type), SemanticError> {
364 let mut was_any_replaced = false;
365 let mut new_fields = SeqMap::new();
366 for (name, field) in &struct_type.anon_struct_type.field_name_sorted_fields {
367 let (was_replaced, new_type) =
368 self.instantiate_type_if_needed(current_self, &field.field_type, type_variables)?;
369 was_any_replaced |= was_replaced;
370 let new_field = StructTypeField {
371 identifier: field.identifier.clone(),
372 field_type: new_type,
373 };
374 new_fields.insert(name.clone(), new_field).unwrap();
375 }
376
377 let new_assigned_name =
378 Self::parameterized_name(&struct_type.assigned_name, &type_variables.variables());
379
380 let Type::Blueprint(blueprint) = current_self.unwrap() else {
381 panic!("must be blueprint");
382 };
383
384 let new_struct = NamedStructType {
385 name: struct_type.name.clone(),
386 assigned_name: new_assigned_name,
387 anon_struct_type: AnonymousStructType {
388 field_name_sorted_fields: new_fields,
389 },
390 module_path: struct_type.module_path.clone(),
391 instantiated_type_parameters: type_variables
392 .type_variables
393 .values()
394 .cloned()
395 .collect::<Vec<_>>(),
396 blueprint_info: Some(blueprint.info()),
397 };
398
399 Ok((was_any_replaced, Type::NamedStruct(new_struct)))
400 }
401}