swamp_analyzer/
structure.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use 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_types::prelude::*;
16
17impl Analyzer<'_> {
18    fn analyze_struct_init_calling_default(
19        &mut self,
20        function: &FunctionRef,
21        super_type: &TypeRef,
22        anon_struct_type: &AnonymousStructType,
23        mut source_order_expressions: Vec<(usize, Option<Node>, Expression)>,
24        node: &swamp_ast::Node,
25    ) -> Expression {
26        // This function is called when the struct type has a default() function.
27        // Algorithm:
28        // 1. Call SomeStruct::default() to get a complete default struct
29        // 2. Create a struct literal where we override only the provided fields
30        // 3. For missing fields, extract them from the default struct
31
32        // Find which fields are provided
33        let mut provided_field_indices = HashSet::new();
34        for (field_index, _, _) in &source_order_expressions {
35            provided_field_indices.insert(*field_index);
36        }
37
38        // Create a call to the struct's default() method
39        let default_call = self.create_default_static_call(node, super_type);
40        let default_struct_expr = self.create_expr(default_call, super_type.clone(), node);
41
42        // For missing fields, create field access expressions from the default struct
43        for (field_index, (_field_name, field_info)) in
44            anon_struct_type.field_name_sorted_fields.iter().enumerate()
45        {
46            if !provided_field_indices.contains(&field_index) {
47                // Create field access: default_struct.field_name
48                let start_of_chain = StartOfChain {
49                    kind: StartOfChainKind::Expression(Box::new(default_struct_expr.clone())),
50                    node: self.to_node(node),
51                };
52                let postfixes = vec![Postfix {
53                    kind: PostfixKind::StructField(super_type.clone(), field_index),
54                    ty: field_info.field_type.clone(),
55                    node: self.to_node(node),
56                }];
57
58                let field_access_expr = self.create_expr(
59                    ExpressionKind::PostfixChain(start_of_chain, postfixes),
60                    field_info.field_type.clone(),
61                    node,
62                );
63
64                source_order_expressions.push((
65                    field_index,
66                    field_info.identifier.clone(),
67                    field_access_expr,
68                ));
69            }
70        }
71
72        // Create a struct literal with all fields (both provided and from struct default)
73        self.create_expr(
74            ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
75                struct_like_type: Self::get_struct_like_type(super_type),
76                source_order_expressions,
77            }),
78            super_type.clone(),
79            node,
80        )
81    }
82
83    fn get_struct_like_type(ty: &TypeRef) -> TypeRef {
84        ty.clone()
85    }
86
87    fn analyze_struct_init_field_by_field(
88        &mut self,
89        borrowed_anon_type: &AnonymousStructType,
90        mut source_order_expressions: Vec<(usize, Option<Node>, Expression)>,
91        missing_fields: SeqSet<String>,
92        result_type: &TypeRef,
93        node: &swamp_ast::Node,
94    ) -> Expression {
95        {
96            for missing_field_name in missing_fields {
97                let field = borrowed_anon_type
98                    .field_name_sorted_fields
99                    .get(&missing_field_name)
100                    .expect("verified");
101                let field_index = borrowed_anon_type
102                    .field_name_sorted_fields
103                    .get_index(&missing_field_name)
104                    .expect("verified");
105
106                // Try to create a default value for this field type
107                if let Some(expression) =
108                    self.create_default_value_for_type(node, &field.field_type)
109                {
110                    source_order_expressions.push((
111                        field_index,
112                        field.identifier.clone(),
113                        expression,
114                    ));
115                }
116                // If no default is available, skip this field - it will remain uninitialized
117            }
118        }
119
120        self.create_expr(
121            ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
122                struct_like_type: Self::get_struct_like_type(result_type),
123                source_order_expressions: source_order_expressions.clone(),
124            }),
125            result_type.clone(),
126            node,
127        )
128    }
129
130    pub fn deduce_the_anon_struct_type(
131        &mut self,
132        ast_fields: &Vec<swamp_ast::FieldExpression>,
133        context: &TypeContext,
134    ) -> AnonymousStructType {
135        let mut map_for_creating_type = SeqMap::new();
136
137        for field in ast_fields {
138            let field_name = self.get_text(&field.field_name.0).to_string();
139            let resolved_node = self.to_node(&field.field_name.0);
140
141            let field_type_context = TypeContext::new_anything_argument(true);
142            let resolved_expression =
143                self.analyze_expression(&field.expression, &field_type_context);
144
145            let expression_type = resolved_expression.ty.clone();
146
147            let field = StructTypeField {
148                identifier: Some(resolved_node),
149                field_type: expression_type,
150            };
151
152            map_for_creating_type
153                .insert(field_name.clone(), field)
154                .expect("insert");
155        }
156
157        // For a pure anonymous struct type, the types of the sorted
158        // fields by field name is the actual type
159        AnonymousStructType::new_and_sort_fields(&map_for_creating_type)
160    }
161
162    /// # Errors
163    ///
164    /// # Panics
165    ///
166    pub fn analyze_anonymous_struct_literal(
167        &mut self,
168        node: &swamp_ast::Node,
169        ast_fields: &Vec<swamp_ast::FieldExpression>,
170        rest_was_specified: bool,
171        context: &TypeContext,
172    ) -> Expression {
173        // First check what we should compare the anonymous struct literal to. Either it is "pure" and then we
174        // compare it against itself or otherwise a type that the context require (a named or an anonymous struct type).
175        let (super_type, anon_struct_type) = if let Some(expected_type) = context.expected_type {
176            match &*expected_type.kind {
177                TypeKind::NamedStruct(named_struct_type) => {
178                    //maybe_named_struct = Some(named_struct.clone());
179                    if let TypeKind::AnonymousStruct(anon_struct) =
180                        &*named_struct_type.anon_struct_type.kind
181                    {
182                        (expected_type, anon_struct)
183                    } else {
184                        return self
185                            .create_err(ErrorKind::CouldNotCoerceTo(expected_type.clone()), node);
186                    }
187                }
188                TypeKind::AnonymousStruct(anonymous_struct_type) => {
189                    (expected_type, anonymous_struct_type)
190                }
191                _ => {
192                    return self
193                        .create_err(ErrorKind::CouldNotCoerceTo(expected_type.clone()), node);
194                }
195            }
196        } else {
197            let deduced_anon_struct_type = self.deduce_the_anon_struct_type(ast_fields, context);
198            let anon_struct_type_ref = self
199                .shared
200                .state
201                .types
202                .anonymous_struct(deduced_anon_struct_type.clone());
203
204            // Generate default functions for the new anonymous struct type
205            self.add_default_functions(&anon_struct_type_ref, node);
206
207            // Move the anon_struct_type_ref to avoid lifetime issues
208            return self.analyze_struct_init(
209                node,
210                &anon_struct_type_ref,
211                &deduced_anon_struct_type,
212                ast_fields,
213                rest_was_specified,
214            );
215        };
216
217        // This path is for the first branch (when we have a specific expected type)
218        self.analyze_struct_init(
219            node,
220            super_type,
221            anon_struct_type,
222            ast_fields,
223            rest_was_specified,
224        )
225    }
226
227    pub(crate) fn analyze_named_struct_literal(
228        &mut self,
229        qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
230        ast_fields: &Vec<swamp_ast::FieldExpression>,
231        rest_was_specified: bool,
232    ) -> Expression {
233        let named_struct_type = self.get_struct_type(qualified_type_identifier);
234
235        let super_type = self
236            .shared
237            .state
238            .types
239            .named_struct(named_struct_type.clone());
240
241        if let TypeKind::AnonymousStruct(anon_struct) = &*named_struct_type.anon_struct_type.kind {
242            self.analyze_struct_init(
243                &qualified_type_identifier.name.0,
244                &super_type,
245                anon_struct,
246                ast_fields,
247                rest_was_specified,
248            )
249        } else {
250            self.create_err(
251                ErrorKind::UnknownStructTypeReference,
252                &qualified_type_identifier.name.0,
253            )
254        }
255    }
256
257    fn analyze_struct_init(
258        &mut self,
259        node: &swamp_ast::Node,
260        super_type: &TypeRef,
261        anon_struct_type: &AnonymousStructType,
262        ast_fields: &Vec<swamp_ast::FieldExpression>,
263        rest_was_specified: bool,
264    ) -> Expression {
265        let (source_order_expressions, missing_fields) = self
266            .place_anon_struct_fields_that_exist_and_return_missing(anon_struct_type, ast_fields);
267
268        if missing_fields.is_empty() {
269            // No missing fields, we are done!
270            self.create_expr(
271                ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
272                    struct_like_type: Self::get_struct_like_type(super_type),
273                    source_order_expressions,
274                }),
275                super_type.clone(),
276                node,
277            )
278        } else {
279            // Missing fields detected!
280            if rest_was_specified {
281                self.make_solution_for_missing_fields(
282                    node,
283                    super_type,
284                    anon_struct_type,
285                    source_order_expressions,
286                    missing_fields,
287                )
288            } else {
289                self.create_err(
290                    ErrorKind::MissingFieldInStructInstantiation(
291                        missing_fields.to_vec(),
292                        anon_struct_type.clone(),
293                    ),
294                    node,
295                )
296            }
297        }
298    }
299
300    /*
301    pub fn analyze_struct_fields_against_anon_struct_type(
302        &mut self,
303        node: &swamp_ast::Node,
304        ast_fields: &Vec<swamp_ast::FieldExpression>,
305        rest_was_specified: bool,
306        context: &TypeContext,
307    ) -> Expression {
308        let mut maybe_named_struct: Option<NamedStructType> = None;
309
310
311
312        let mapped = self.analyze_anon_struct_instantiation(
313            node,
314            &struct_to_instantiate,
315            ast_fields,
316            rest_was_specified,
317        )?;
318
319        let (kind, ty) = if let Some(named_struct) = maybe_named_struct {
320            (
321                ExpressionKind::StructInstantiation(StructInstantiation {
322                    source_order_expressions: mapped,
323                    struct_type_ref: named_struct.clone(),
324                }),
325                TypeKind::NamedStruct(named_struct),
326            )
327        } else {
328            (
329                ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
330                    source_order_expressions: mapped,
331                    anonymous_struct_type: struct_to_instantiate.clone(),
332                }),
333                TypeKind::AnonymousStruct(struct_to_instantiate),
334            )
335        };
336
337        Ok(self.create_expr(kind, ty, node))
338    }
339
340     */
341
342    fn make_solution_for_missing_fields(
343        &mut self,
344        node: &swamp_ast::Node,
345        super_type: &TypeRef,
346        anon_struct_type: &AnonymousStructType,
347        source_order_expressions: Vec<(usize, Option<Node>, Expression)>,
348        missing_fields: SeqSet<String>,
349    ) -> Expression {
350        // First check if the super type has a default function (trait)
351        let maybe_default = {
352            self.shared
353                .state
354                .associated_impls
355                .get_member_function(super_type, "default")
356                .cloned()
357        };
358
359        // if it has a `default` function, call that to get a starting value
360
361        if let Some(function) = maybe_default {
362            self.analyze_struct_init_calling_default(
363                &function,
364                super_type,
365                anon_struct_type,
366                source_order_expressions,
367                node,
368            )
369        } else {
370            /*
371            let mapped: Vec<(usize, Expression)> = &source_order_expressions
372                .into_iter()
373                .map(|(a, _b, c)| (a, c))
374                .collect::<Vec<_>>();
375
376             */
377            self.analyze_struct_init_field_by_field(
378                anon_struct_type,
379                source_order_expressions,
380                missing_fields,
381                super_type,
382                node,
383            )
384        }
385
386        /*
387        else if missing_fields.is_empty() {
388
389            let ty = TypeKind::NamedStruct(struct_to_instantiate.clone());
390            let node = qualified_type_identifier.name.0.clone();
391            let mapped: Vec<(usize, Expression)> = source_order_expressions
392                .into_iter()
393                .map(|(a, _b, c)| (a, c))
394                .collect::<Vec<_>>();
395            Ok(self.create_expr(
396                ExpressionKind::StructInstantiation(StructInstantiation {
397                    source_order_expressions: mapped,
398                    struct_type_ref: struct_to_instantiate,
399                }),
400                ty,
401                &node,
402            ))
403        }
404
405         */
406    }
407
408    fn place_anon_struct_fields_that_exist_and_return_missing(
409        &mut self,
410        target_anon_struct_type: &AnonymousStructType,
411        ast_fields: &Vec<swamp_ast::FieldExpression>,
412    ) -> (Vec<(usize, Option<Node>, Expression)>, SeqSet<String>) {
413        let mut missing_fields: SeqSet<String> = target_anon_struct_type
414            .field_name_sorted_fields
415            .keys()
416            .cloned()
417            .collect();
418
419        let mut source_order_expressions = Vec::new();
420
421        for field in ast_fields {
422            let field_name = self.get_text(&field.field_name.0).to_string();
423            let resolved_node = self.to_node(&field.field_name.0);
424
425            // If we can't remove it from missing_fields, it's either a duplicate or unknown field
426            if !missing_fields.remove(&field_name) {
427                return if target_anon_struct_type
428                    .field_name_sorted_fields
429                    .contains_key(&field_name)
430                {
431                    self.add_err(
432                        ErrorKind::DuplicateFieldInStructInstantiation(field_name),
433                        &field.field_name.0,
434                    );
435                    (vec![], SeqSet::new())
436                } else {
437                    self.add_err(ErrorKind::UnknownStructField, &field.field_name.0);
438                    (vec![], SeqSet::new())
439                };
440            }
441
442            let looked_up_field = target_anon_struct_type
443                .field_name_sorted_fields
444                .get(&field_name)
445                .expect("field existence checked above");
446
447            let field_index_in_definition = target_anon_struct_type
448                .field_name_sorted_fields
449                .get_index(&field_name)
450                .expect("field_name is checked earlier");
451
452            let field_type_context = TypeContext::new_argument(
453                &looked_up_field.field_type,
454                looked_up_field
455                    .field_type
456                    .collection_view_that_needs_explicit_storage(),
457            );
458            let resolved_expression =
459                self.analyze_expression(&field.expression, &field_type_context);
460
461            source_order_expressions.push((
462                field_index_in_definition,
463                Some(resolved_node),
464                resolved_expression,
465            ));
466        }
467
468        (source_order_expressions, missing_fields)
469    }
470
471    pub(crate) fn analyze_anon_struct_instantiation(
472        &mut self,
473        node: &swamp_ast::Node,
474        struct_to_instantiate: &AnonymousStructType,
475        ast_fields: &Vec<swamp_ast::FieldExpression>,
476        allow_rest: bool,
477    ) -> Vec<(usize, Option<Node>, Expression)> {
478        let (source_order_expressions, missing_fields) = self
479            .place_anon_struct_fields_that_exist_and_return_missing(
480                struct_to_instantiate,
481                ast_fields,
482            );
483
484        let mut mapped: Vec<(usize, Option<Node>, Expression)> = source_order_expressions;
485
486        if allow_rest {
487            // Call `default()` for the missing fields
488            for missing_field_name in missing_fields {
489                let field = struct_to_instantiate
490                    .field_name_sorted_fields
491                    .get(&missing_field_name)
492                    .expect("field must exist in struct definition");
493
494                let field_index = struct_to_instantiate
495                    .field_name_sorted_fields
496                    .get_index(&missing_field_name)
497                    .expect("field must exist in struct definition");
498
499                // Try to create the default value for the field
500                if let Some(default_expression) =
501                    self.create_default_value_for_type(node, &field.field_type)
502                {
503                    mapped.push((field_index, None, default_expression));
504                }
505                // If no default is available, skip this field
506            }
507        } else if !missing_fields.is_empty() {
508            self.add_err(
509                ErrorKind::MissingFieldInStructInstantiation(
510                    missing_fields.to_vec(),
511                    struct_to_instantiate.clone(),
512                ),
513                node,
514            );
515            return vec![];
516        }
517
518        mapped
519    }
520}