1use crate::{Analyzer, TypeContext};
6use seq_map::SeqMap;
7use seq_set::SeqSet;
8use source_map_node::Node;
9use std::collections::HashSet;
10use swamp_semantic::err::ErrorKind;
11use swamp_semantic::{
12 AnonymousStructLiteral, Expression, ExpressionKind, FunctionRef, Postfix, PostfixKind,
13 StartOfChain, StartOfChainKind,
14};
15use swamp_symbol::{Symbol, SymbolKind};
16use swamp_types::prelude::*;
17
18impl Analyzer<'_> {
19 fn analyze_struct_init_calling_default(
20 &mut self,
21 function: &FunctionRef,
22 super_type: &TypeRef,
23 anon_struct_type: &AnonymousStructType,
24 mut source_order_expressions: Vec<(usize, Option<Node>, Expression)>,
25 node: &swamp_ast::Node,
26 ) -> Expression {
27 let mut provided_field_indices = HashSet::new();
35 for (field_index, _, _) in &source_order_expressions {
36 provided_field_indices.insert(*field_index);
37 }
38
39 let default_call = self.create_default_static_call(node, super_type);
41 let default_struct_expr = self.create_expr(default_call, super_type.clone(), node);
42
43 for (field_index, (_field_name, field_info)) in
45 anon_struct_type.field_name_sorted_fields.iter().enumerate()
46 {
47 if !provided_field_indices.contains(&field_index) {
48 let start_of_chain = StartOfChain {
50 kind: StartOfChainKind::Expression(Box::new(default_struct_expr.clone())),
51 node: self.to_node(node),
52 };
53 let postfixes = vec![Postfix {
54 kind: PostfixKind::StructField(super_type.clone(), field_index),
55 ty: field_info.field_type.clone(),
56 node: self.to_node(node),
57 }];
58
59 let field_access_expr = self.create_expr(
60 ExpressionKind::PostfixChain(start_of_chain, postfixes),
61 field_info.field_type.clone(),
62 node,
63 );
64
65 source_order_expressions.push((
66 field_index,
67 field_info.identifier.clone(),
68 field_access_expr,
69 ));
70 }
71 }
72
73 self.create_expr(
75 ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
76 struct_like_type: Self::get_struct_like_type(super_type),
77 source_order_expressions,
78 }),
79 super_type.clone(),
80 node,
81 )
82 }
83
84 fn get_struct_like_type(ty: &TypeRef) -> TypeRef {
85 ty.clone()
86 }
87
88 fn analyze_struct_init_field_by_field(
89 &mut self,
90 borrowed_anon_type: &AnonymousStructType,
91 mut source_order_expressions: Vec<(usize, Option<Node>, Expression)>,
92 missing_fields: SeqSet<String>,
93 result_type: &TypeRef,
94 node: &swamp_ast::Node,
95 ) -> Expression {
96 {
97 for missing_field_name in missing_fields {
98 let field = borrowed_anon_type
99 .field_name_sorted_fields
100 .get(&missing_field_name)
101 .expect("verified");
102 let field_index = borrowed_anon_type
103 .field_name_sorted_fields
104 .get_index(&missing_field_name)
105 .expect("verified");
106
107 if let Some(expression) =
109 self.create_default_value_for_type(node, &field.field_type)
110 {
111 source_order_expressions.push((
112 field_index,
113 field.identifier.clone(),
114 expression,
115 ));
116 }
117 }
119 }
120
121 self.create_expr(
122 ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
123 struct_like_type: Self::get_struct_like_type(result_type),
124 source_order_expressions: source_order_expressions.clone(),
125 }),
126 result_type.clone(),
127 node,
128 )
129 }
130
131 pub fn deduce_the_anon_struct_type(
132 &mut self,
133 ast_fields: &Vec<swamp_ast::FieldExpression>,
134 context: &TypeContext,
135 ) -> AnonymousStructType {
136 let mut map_for_creating_type = SeqMap::new();
137
138 for field in ast_fields {
139 let field_name = self.get_text(&field.field_name.0).to_string();
140 let resolved_node = self.to_node(&field.field_name.0);
141
142 let field_type_context = TypeContext::new_anything_argument(true);
143 let resolved_expression =
144 self.analyze_expression(&field.expression, &field_type_context);
145
146 let expression_type = resolved_expression.ty.clone();
147
148 let symbol_id = self.shared.state.symbol_id_allocator.alloc_top_level();
149 self.shared.state.symbols.insert_top(symbol_id, Symbol {
150 id: symbol_id.into(),
151 kind: SymbolKind::AnonStructField,
152 source_map_node: Default::default(),
153 name: Default::default(),
154 });
155
156 let field = StructTypeField {
157 symbol_id,
158 identifier: Some(resolved_node),
159 field_type: expression_type,
160 };
161
162 map_for_creating_type
163 .insert(field_name.clone(), field)
164 .expect("insert");
165 }
166
167 AnonymousStructType::new_and_sort_fields(&map_for_creating_type)
170 }
171
172 pub fn analyze_anonymous_struct_literal(
177 &mut self,
178 node: &swamp_ast::Node,
179 ast_fields: &Vec<swamp_ast::FieldExpression>,
180 rest_was_specified: bool,
181 context: &TypeContext,
182 ) -> Expression {
183 let (super_type, anon_struct_type) = if let Some(expected_type) = context.expected_type {
186 match &*expected_type.kind {
187 TypeKind::NamedStruct(named_struct_type) => {
188 if let TypeKind::AnonymousStruct(anon_struct) =
190 &*named_struct_type.anon_struct_type.kind
191 {
192 (expected_type, anon_struct)
193 } else {
194 return self
195 .create_err(ErrorKind::CouldNotCoerceTo(expected_type.clone()), node);
196 }
197 }
198 TypeKind::AnonymousStruct(anonymous_struct_type) => {
199 (expected_type, anonymous_struct_type)
200 }
201 _ => {
202 return self
203 .create_err(ErrorKind::CouldNotCoerceTo(expected_type.clone()), node);
204 }
205 }
206 } else {
207 let deduced_anon_struct_type = self.deduce_the_anon_struct_type(ast_fields, context);
208 let anon_struct_type_ref = self
209 .shared
210 .state
211 .types
212 .anonymous_struct(deduced_anon_struct_type.clone());
213
214 self.add_default_functions(&anon_struct_type_ref, node);
216
217 return self.analyze_struct_init(
219 node,
220 &anon_struct_type_ref,
221 &deduced_anon_struct_type,
222 ast_fields,
223 rest_was_specified,
224 );
225 };
226
227 self.analyze_struct_init(
229 node,
230 super_type,
231 anon_struct_type,
232 ast_fields,
233 rest_was_specified,
234 )
235 }
236
237 pub(crate) fn analyze_named_struct_literal(
238 &mut self,
239 qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
240 ast_fields: &Vec<swamp_ast::FieldExpression>,
241 rest_was_specified: bool,
242 context: &TypeContext,
243 ) -> Expression {
244 if qualified_type_identifier.module_path.is_none()
245 && let Some(expected_type) = context.expected_type
246 && let TypeKind::Enum(found_enum_type) = &*expected_type.kind
247 {
248 let named_struct_or_variant = self.get_text(&qualified_type_identifier.name.0);
249 if let Some(found_variant) = found_enum_type.get_variant(named_struct_or_variant)
250 && matches!(
251 *found_variant.payload_type.kind,
252 TypeKind::AnonymousStruct(_)
253 )
254 {
255 return self.analyze_enum_variant_struct_literal(
256 found_variant,
257 expected_type,
258 ast_fields,
259 rest_was_specified,
260 &qualified_type_identifier.name.0,
261 );
262 }
263 }
264
265 let named_struct_type = self.get_struct_type(qualified_type_identifier);
266 let sem_node = self.to_node(&qualified_type_identifier.name.0);
267
268 self.shared.state.refs.add(named_struct_type.symbol_id.into(), sem_node);
269
270 let super_type = self
271 .shared
272 .state
273 .types
274 .named_struct(named_struct_type.clone());
275
276 if let TypeKind::AnonymousStruct(anon_struct) = &*named_struct_type.anon_struct_type.kind {
277 let anon_expr = self.analyze_struct_init(
278 &qualified_type_identifier.name.0,
279 &super_type,
280 anon_struct,
281 ast_fields,
282 rest_was_specified,
283 );
284 let ty = anon_expr.ty.clone();
285 self.create_expr(ExpressionKind::NamedStructLiteral(Box::from(anon_expr)), ty, &qualified_type_identifier.name.0)
286 } else {
287 self.create_err(
288 ErrorKind::UnknownStructTypeReference,
289 &qualified_type_identifier.name.0,
290 )
291 }
292 }
293
294 fn analyze_struct_init(
295 &mut self,
296 node: &swamp_ast::Node,
297 super_type: &TypeRef,
298 anon_struct_type: &AnonymousStructType,
299 ast_fields: &Vec<swamp_ast::FieldExpression>,
300 rest_was_specified: bool,
301 ) -> Expression {
302 let (source_order_expressions, missing_fields) = self
303 .place_anon_struct_fields_that_exist_and_return_missing(anon_struct_type, ast_fields);
304
305 if missing_fields.is_empty() {
306 self.create_expr(
308 ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
309 struct_like_type: Self::get_struct_like_type(super_type),
310 source_order_expressions,
311 }),
312 super_type.clone(),
313 node,
314 )
315 } else {
316 if rest_was_specified {
318 self.make_solution_for_missing_fields(
319 node,
320 super_type,
321 anon_struct_type,
322 source_order_expressions,
323 missing_fields,
324 )
325 } else {
326 self.create_err(
327 ErrorKind::MissingFieldInStructInstantiation(
328 missing_fields.to_vec(),
329 anon_struct_type.clone(),
330 ),
331 node,
332 )
333 }
334 }
335 }
336
337 fn make_solution_for_missing_fields(
380 &mut self,
381 node: &swamp_ast::Node,
382 super_type: &TypeRef,
383 anon_struct_type: &AnonymousStructType,
384 source_order_expressions: Vec<(usize, Option<Node>, Expression)>,
385 missing_fields: SeqSet<String>,
386 ) -> Expression {
387 let maybe_default = {
389 self.shared
390 .state
391 .associated_impls
392 .get_member_function(super_type, "default")
393 .cloned()
394 };
395
396 if let Some(function) = maybe_default {
399 self.analyze_struct_init_calling_default(
400 &function,
401 super_type,
402 anon_struct_type,
403 source_order_expressions,
404 node,
405 )
406 } else {
407 self.analyze_struct_init_field_by_field(
415 anon_struct_type,
416 source_order_expressions,
417 missing_fields,
418 super_type,
419 node,
420 )
421 }
422
423 }
444
445 fn place_anon_struct_fields_that_exist_and_return_missing(
446 &mut self,
447 target_anon_struct_type: &AnonymousStructType,
448 ast_fields: &Vec<swamp_ast::FieldExpression>,
449 ) -> (Vec<(usize, Option<Node>, Expression)>, SeqSet<String>) {
450 let mut missing_fields: SeqSet<String> = target_anon_struct_type
451 .field_name_sorted_fields
452 .keys()
453 .cloned()
454 .collect();
455
456 let mut source_order_expressions = Vec::new();
457
458 for field in ast_fields {
459 let field_name = self.get_text(&field.field_name.0).to_string();
460 let resolved_node = self.to_node(&field.field_name.0);
461
462 if !missing_fields.remove(&field_name) {
464 return if target_anon_struct_type
465 .field_name_sorted_fields
466 .contains_key(&field_name)
467 {
468 self.add_err(
469 ErrorKind::DuplicateFieldInStructInstantiation(field_name),
470 &field.field_name.0,
471 );
472 (vec![], SeqSet::new())
473 } else {
474 self.add_err(ErrorKind::UnknownStructField, &field.field_name.0);
475 (vec![], SeqSet::new())
476 };
477 }
478
479 let looked_up_field = target_anon_struct_type
480 .field_name_sorted_fields
481 .get(&field_name)
482 .expect("field existence checked above");
483
484 self.shared.state.refs.add(looked_up_field.symbol_id.into(), resolved_node.clone());
485 self.shared.definition_table.refs.add(looked_up_field.symbol_id.into(), resolved_node.clone());
486
487 let field_index_in_definition = target_anon_struct_type
488 .field_name_sorted_fields
489 .get_index(&field_name)
490 .expect("field_name is checked earlier");
491
492 let field_type_context = TypeContext::new_argument(
493 &looked_up_field.field_type,
494 looked_up_field
495 .field_type
496 .collection_view_that_needs_explicit_storage(),
497 );
498 let resolved_expression =
499 self.analyze_expression(&field.expression, &field_type_context);
500
501 source_order_expressions.push((
502 field_index_in_definition,
503 Some(resolved_node),
504 resolved_expression,
505 ));
506 }
507
508 (source_order_expressions, missing_fields)
509 }
510
511 pub(crate) fn analyze_anon_struct_instantiation(
512 &mut self,
513 node: &swamp_ast::Node,
514 struct_to_instantiate: &AnonymousStructType,
515 ast_fields: &Vec<swamp_ast::FieldExpression>,
516 allow_rest: bool,
517 ) -> Vec<(usize, Option<Node>, Expression)> {
518 let (source_order_expressions, missing_fields) = self
519 .place_anon_struct_fields_that_exist_and_return_missing(
520 struct_to_instantiate,
521 ast_fields,
522 );
523
524 let mut mapped: Vec<(usize, Option<Node>, Expression)> = source_order_expressions;
525
526 if allow_rest {
527 for missing_field_name in missing_fields {
529 let field = struct_to_instantiate
530 .field_name_sorted_fields
531 .get(&missing_field_name)
532 .expect("field must exist in struct definition");
533
534 let field_index = struct_to_instantiate
535 .field_name_sorted_fields
536 .get_index(&missing_field_name)
537 .expect("field must exist in struct definition");
538
539 if let Some(default_expression) =
541 self.create_default_value_for_type(node, &field.field_type)
542 {
543 mapped.push((field_index, None, default_expression));
544 }
545 }
547 } else if !missing_fields.is_empty() {
548 self.add_err(
549 ErrorKind::MissingFieldInStructInstantiation(
550 missing_fields.to_vec(),
551 struct_to_instantiate.clone(),
552 ),
553 node,
554 );
555 return vec![];
556 }
557
558 mapped
559 }
560}