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