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_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        // This function is called when the struct type has a default() function.
28        // Algorithm:
29        // 1. Call SomeStruct::default() to get a complete default struct
30        // 2. Create a struct literal where we override only the provided fields
31        // 3. For missing fields, extract them from the default struct
32
33        // Find which fields are provided
34        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        // Create a call to the struct's default() method
40        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 missing fields, create field access expressions from the default struct
44        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                // Create field access: default_struct.field_name
49                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        // Create a struct literal with all fields (both provided and from struct default)
74        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                // Try to create a default value for this field type
108                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                // If no default is available, skip this field - it will remain uninitialized
118            }
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(
150                symbol_id,
151                Symbol {
152                    id: symbol_id.into(),
153                    kind: SymbolKind::AnonStructField,
154                    source_map_node: Default::default(),
155                    name: Default::default(),
156                },
157            );
158
159            let field = StructTypeField {
160                symbol_id,
161                identifier: Some(resolved_node),
162                field_type: expression_type,
163            };
164
165            map_for_creating_type
166                .insert(field_name.clone(), field)
167                .expect("insert");
168        }
169
170        // For a pure anonymous struct type, the types of the sorted
171        // fields by field name is the actual type
172        AnonymousStructType::new_and_sort_fields(&map_for_creating_type)
173    }
174
175    /// # Errors
176    ///
177    /// # Panics
178    ///
179    pub fn analyze_anonymous_struct_literal(
180        &mut self,
181        node: &swamp_ast::Node,
182        ast_fields: &Vec<swamp_ast::FieldExpression>,
183        rest_was_specified: bool,
184        context: &TypeContext,
185    ) -> Expression {
186        // First check what we should compare the anonymous struct literal to. Either it is "pure" and then we
187        // compare it against itself or otherwise a type that the context require (a named or an anonymous struct type).
188        let (super_type, anon_struct_type) = if let Some(expected_type) = context.expected_type {
189            match &*expected_type.kind {
190                TypeKind::NamedStruct(named_struct_type) => {
191                    //maybe_named_struct = Some(named_struct.clone());
192                    if let TypeKind::AnonymousStruct(anon_struct) =
193                        &*named_struct_type.anon_struct_type.kind
194                    {
195                        (expected_type, anon_struct)
196                    } else {
197                        return self
198                            .create_err(ErrorKind::CouldNotCoerceTo(expected_type.clone()), node);
199                    }
200                }
201                TypeKind::AnonymousStruct(anonymous_struct_type) => {
202                    (expected_type, anonymous_struct_type)
203                }
204                _ => {
205                    return self
206                        .create_err(ErrorKind::CouldNotCoerceTo(expected_type.clone()), node);
207                }
208            }
209        } else {
210            let deduced_anon_struct_type = self.deduce_the_anon_struct_type(ast_fields, context);
211            let anon_struct_type_ref = self
212                .shared
213                .state
214                .types
215                .anonymous_struct(deduced_anon_struct_type.clone());
216
217            // Generate default functions for the new anonymous struct type
218            self.add_default_functions(&anon_struct_type_ref, node);
219
220            // Move the anon_struct_type_ref to avoid lifetime issues
221            return self.analyze_struct_init(
222                node,
223                &anon_struct_type_ref,
224                &deduced_anon_struct_type,
225                ast_fields,
226                rest_was_specified,
227            );
228        };
229
230        // This path is for the first branch (when we have a specific expected type)
231        self.analyze_struct_init(
232            node,
233            super_type,
234            anon_struct_type,
235            ast_fields,
236            rest_was_specified,
237        )
238    }
239
240    pub(crate) fn analyze_named_struct_literal(
241        &mut self,
242        qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
243        ast_fields: &Vec<swamp_ast::FieldExpression>,
244        rest_was_specified: bool,
245        context: &TypeContext,
246    ) -> Expression {
247        if qualified_type_identifier.module_path.is_none()
248            && let Some(expected_type) = context.expected_type
249            && let TypeKind::Enum(found_enum_type) = &*expected_type.kind
250        {
251            let named_struct_or_variant = self.get_text(&qualified_type_identifier.name.0);
252            if let Some(found_variant) = found_enum_type.get_variant(named_struct_or_variant)
253                && matches!(
254                    *found_variant.payload_type.kind,
255                    TypeKind::AnonymousStruct(_)
256                )
257            {
258                return self.analyze_enum_variant_struct_literal(
259                    found_variant,
260                    expected_type,
261                    ast_fields,
262                    rest_was_specified,
263                    &qualified_type_identifier.name.0,
264                );
265            }
266        }
267
268        let named_struct_type = self.get_struct_type(qualified_type_identifier);
269        let sem_node = self.to_node(&qualified_type_identifier.name.0);
270
271        self.shared
272            .state
273            .refs
274            .add(named_struct_type.symbol_id.into(), sem_node);
275
276        let super_type = self
277            .shared
278            .state
279            .types
280            .named_struct(named_struct_type.clone());
281
282        if let TypeKind::AnonymousStruct(anon_struct) = &*named_struct_type.anon_struct_type.kind {
283            let anon_expr = self.analyze_struct_init(
284                &qualified_type_identifier.name.0,
285                &super_type,
286                anon_struct,
287                ast_fields,
288                rest_was_specified,
289            );
290            let ty = anon_expr.ty.clone();
291
292            self.create_expr(
293                ExpressionKind::NamedStructLiteral(Box::from(anon_expr)),
294                ty,
295                &qualified_type_identifier.name.0,
296            )
297        } else {
298            self.create_err(
299                ErrorKind::UnknownStructTypeReference,
300                &qualified_type_identifier.name.0,
301            )
302        }
303    }
304
305    fn analyze_struct_init(
306        &mut self,
307        node: &swamp_ast::Node,
308        super_type: &TypeRef,
309        anon_struct_type: &AnonymousStructType,
310        ast_fields: &Vec<swamp_ast::FieldExpression>,
311        rest_was_specified: bool,
312    ) -> Expression {
313        let (source_order_expressions, missing_fields) = self
314            .place_anon_struct_fields_that_exist_and_return_missing(anon_struct_type, ast_fields);
315
316        if missing_fields.is_empty() {
317            // No missing fields, we are done!
318            self.create_expr(
319                ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
320                    struct_like_type: Self::get_struct_like_type(super_type),
321                    source_order_expressions,
322                }),
323                super_type.clone(),
324                node,
325            )
326        } else {
327            // Missing fields detected!
328            if rest_was_specified {
329                self.make_solution_for_missing_fields(
330                    node,
331                    super_type,
332                    anon_struct_type,
333                    source_order_expressions,
334                    missing_fields,
335                )
336            } else {
337                self.create_err(
338                    ErrorKind::MissingFieldInStructInstantiation(
339                        missing_fields.to_vec(),
340                        anon_struct_type.clone(),
341                    ),
342                    node,
343                )
344            }
345        }
346    }
347
348    /*
349    pub fn analyze_struct_fields_against_anon_struct_type(
350        &mut self,
351        node: &swamp_ast::Node,
352        ast_fields: &Vec<swamp_ast::FieldExpression>,
353        rest_was_specified: bool,
354        context: &TypeContext,
355    ) -> Expression {
356        let mut maybe_named_struct: Option<NamedStructType> = None;
357
358
359
360        let mapped = self.analyze_anon_struct_instantiation(
361            node,
362            &struct_to_instantiate,
363            ast_fields,
364            rest_was_specified,
365        )?;
366
367        let (kind, ty) = if let Some(named_struct) = maybe_named_struct {
368            (
369                ExpressionKind::StructInstantiation(StructInstantiation {
370                    source_order_expressions: mapped,
371                    struct_type_ref: named_struct.clone(),
372                }),
373                TypeKind::NamedStruct(named_struct),
374            )
375        } else {
376            (
377                ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
378                    source_order_expressions: mapped,
379                    anonymous_struct_type: struct_to_instantiate.clone(),
380                }),
381                TypeKind::AnonymousStruct(struct_to_instantiate),
382            )
383        };
384
385        Ok(self.create_expr(kind, ty, node))
386    }
387
388     */
389
390    fn make_solution_for_missing_fields(
391        &mut self,
392        node: &swamp_ast::Node,
393        super_type: &TypeRef,
394        anon_struct_type: &AnonymousStructType,
395        source_order_expressions: Vec<(usize, Option<Node>, Expression)>,
396        missing_fields: SeqSet<String>,
397    ) -> Expression {
398        // First check if the super type has a default function (trait)
399        let maybe_default = {
400            self.shared
401                .state
402                .associated_impls
403                .get_member_function(super_type, "default")
404                .cloned()
405        };
406
407        // if it has a `default` function, call that to get a starting value
408
409        if let Some(function) = maybe_default {
410            self.analyze_struct_init_calling_default(
411                &function,
412                super_type,
413                anon_struct_type,
414                source_order_expressions,
415                node,
416            )
417        } else {
418            /*
419            let mapped: Vec<(usize, Expression)> = &source_order_expressions
420                .into_iter()
421                .map(|(a, _b, c)| (a, c))
422                .collect::<Vec<_>>();
423
424             */
425            self.analyze_struct_init_field_by_field(
426                anon_struct_type,
427                source_order_expressions,
428                missing_fields,
429                super_type,
430                node,
431            )
432        }
433
434        /*
435        else if missing_fields.is_empty() {
436
437            let ty = TypeKind::NamedStruct(struct_to_instantiate.clone());
438            let node = qualified_type_identifier.name.0.clone();
439            let mapped: Vec<(usize, Expression)> = source_order_expressions
440                .into_iter()
441                .map(|(a, _b, c)| (a, c))
442                .collect::<Vec<_>>();
443            Ok(self.create_expr(
444                ExpressionKind::StructInstantiation(StructInstantiation {
445                    source_order_expressions: mapped,
446                    struct_type_ref: struct_to_instantiate,
447                }),
448                ty,
449                &node,
450            ))
451        }
452
453         */
454    }
455
456    fn place_anon_struct_fields_that_exist_and_return_missing(
457        &mut self,
458        target_anon_struct_type: &AnonymousStructType,
459        ast_fields: &Vec<swamp_ast::FieldExpression>,
460    ) -> (Vec<(usize, Option<Node>, Expression)>, SeqSet<String>) {
461        let mut missing_fields: SeqSet<String> = target_anon_struct_type
462            .field_name_sorted_fields
463            .keys()
464            .cloned()
465            .collect();
466
467        let mut source_order_expressions = Vec::new();
468
469        for field in ast_fields {
470            let field_name = self.get_text(&field.field_name.0).to_string();
471            let resolved_node = self.to_node(&field.field_name.0);
472
473            // If we can't remove it from missing_fields, it's either a duplicate or unknown field
474            if !missing_fields.remove(&field_name) {
475                return if target_anon_struct_type
476                    .field_name_sorted_fields
477                    .contains_key(&field_name)
478                {
479                    self.add_err(
480                        ErrorKind::DuplicateFieldInStructInstantiation(field_name),
481                        &field.field_name.0,
482                    );
483                    (vec![], SeqSet::new())
484                } else {
485                    self.add_err(ErrorKind::UnknownStructField, &field.field_name.0);
486                    (vec![], SeqSet::new())
487                };
488            }
489
490            let looked_up_field = target_anon_struct_type
491                .field_name_sorted_fields
492                .get(&field_name)
493                .expect("field existence checked above");
494
495            self.shared
496                .state
497                .refs
498                .add(looked_up_field.symbol_id.into(), resolved_node.clone());
499            self.shared
500                .definition_table
501                .refs
502                .add(looked_up_field.symbol_id.into(), resolved_node.clone());
503
504            let field_index_in_definition = target_anon_struct_type
505                .field_name_sorted_fields
506                .get_index(&field_name)
507                .expect("field_name is checked earlier");
508
509            let field_type_context = TypeContext::new_argument(
510                &looked_up_field.field_type,
511                looked_up_field
512                    .field_type
513                    .collection_view_that_needs_explicit_storage(),
514            );
515            let resolved_expression =
516                self.analyze_expression(&field.expression, &field_type_context);
517
518            source_order_expressions.push((
519                field_index_in_definition,
520                Some(resolved_node),
521                resolved_expression,
522            ));
523        }
524
525        (source_order_expressions, missing_fields)
526    }
527
528    pub(crate) fn analyze_anon_struct_instantiation(
529        &mut self,
530        node: &swamp_ast::Node,
531        struct_to_instantiate: &AnonymousStructType,
532        ast_fields: &Vec<swamp_ast::FieldExpression>,
533        allow_rest: bool,
534    ) -> Vec<(usize, Option<Node>, Expression)> {
535        let (source_order_expressions, missing_fields) = self
536            .place_anon_struct_fields_that_exist_and_return_missing(
537                struct_to_instantiate,
538                ast_fields,
539            );
540
541        let mut mapped: Vec<(usize, Option<Node>, Expression)> = source_order_expressions;
542
543        if allow_rest {
544            // Call `default()` for the missing fields
545            for missing_field_name in missing_fields {
546                let field = struct_to_instantiate
547                    .field_name_sorted_fields
548                    .get(&missing_field_name)
549                    .expect("field must exist in struct definition");
550
551                let field_index = struct_to_instantiate
552                    .field_name_sorted_fields
553                    .get_index(&missing_field_name)
554                    .expect("field must exist in struct definition");
555
556                // Try to create the default value for the field
557                if let Some(default_expression) =
558                    self.create_default_value_for_type(node, &field.field_type)
559                {
560                    mapped.push((field_index, None, default_expression));
561                }
562                // If no default is available, skip this field
563            }
564        } else if !missing_fields.is_empty() {
565            self.add_err(
566                ErrorKind::MissingFieldInStructInstantiation(
567                    missing_fields.to_vec(),
568                    struct_to_instantiate.clone(),
569                ),
570                node,
571            );
572            return vec![];
573        }
574
575        mapped
576    }
577}