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            // Move the anon_struct_type_ref to avoid lifetime issues
205            return self.analyze_struct_init(
206                node,
207                &anon_struct_type_ref,
208                &deduced_anon_struct_type,
209                ast_fields,
210                rest_was_specified,
211            );
212        };
213
214        // This path is for the first branch (when we have a specific expected type)
215        self.analyze_struct_init(
216            node,
217            super_type,
218            anon_struct_type,
219            ast_fields,
220            rest_was_specified,
221        )
222    }
223
224    pub(crate) fn analyze_named_struct_literal(
225        &mut self,
226        qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
227        ast_fields: &Vec<swamp_ast::FieldExpression>,
228        rest_was_specified: bool,
229    ) -> Expression {
230        let named_struct_type = self.get_struct_type(qualified_type_identifier);
231
232        let super_type = self
233            .shared
234            .state
235            .types
236            .named_struct(named_struct_type.clone());
237
238        if let TypeKind::AnonymousStruct(anon_struct) = &*named_struct_type.anon_struct_type.kind {
239            self.analyze_struct_init(
240                &qualified_type_identifier.name.0,
241                &super_type,
242                anon_struct,
243                ast_fields,
244                rest_was_specified,
245            )
246        } else {
247            self.create_err(
248                ErrorKind::UnknownStructTypeReference,
249                &qualified_type_identifier.name.0,
250            )
251        }
252    }
253
254    fn analyze_struct_init(
255        &mut self,
256        node: &swamp_ast::Node,
257        super_type: &TypeRef,
258        anon_struct_type: &AnonymousStructType,
259        ast_fields: &Vec<swamp_ast::FieldExpression>,
260        rest_was_specified: bool,
261    ) -> Expression {
262        let (source_order_expressions, missing_fields) = self
263            .place_anon_struct_fields_that_exist_and_return_missing(anon_struct_type, ast_fields);
264
265        if missing_fields.is_empty() {
266            // No missing fields, we are done!
267            self.create_expr(
268                ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
269                    struct_like_type: Self::get_struct_like_type(super_type),
270                    source_order_expressions,
271                }),
272                super_type.clone(),
273                node,
274            )
275        } else {
276            // Missing fields detected!
277            if rest_was_specified {
278                self.make_solution_for_missing_fields(
279                    node,
280                    super_type,
281                    anon_struct_type,
282                    source_order_expressions,
283                    missing_fields,
284                )
285            } else {
286                self.create_err(
287                    ErrorKind::MissingFieldInStructInstantiation(
288                        missing_fields.to_vec(),
289                        anon_struct_type.clone(),
290                    ),
291                    node,
292                )
293            }
294        }
295    }
296
297    /*
298    pub fn analyze_struct_fields_against_anon_struct_type(
299        &mut self,
300        node: &swamp_ast::Node,
301        ast_fields: &Vec<swamp_ast::FieldExpression>,
302        rest_was_specified: bool,
303        context: &TypeContext,
304    ) -> Expression {
305        let mut maybe_named_struct: Option<NamedStructType> = None;
306
307
308
309        let mapped = self.analyze_anon_struct_instantiation(
310            node,
311            &struct_to_instantiate,
312            ast_fields,
313            rest_was_specified,
314        )?;
315
316        let (kind, ty) = if let Some(named_struct) = maybe_named_struct {
317            (
318                ExpressionKind::StructInstantiation(StructInstantiation {
319                    source_order_expressions: mapped,
320                    struct_type_ref: named_struct.clone(),
321                }),
322                TypeKind::NamedStruct(named_struct),
323            )
324        } else {
325            (
326                ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
327                    source_order_expressions: mapped,
328                    anonymous_struct_type: struct_to_instantiate.clone(),
329                }),
330                TypeKind::AnonymousStruct(struct_to_instantiate),
331            )
332        };
333
334        Ok(self.create_expr(kind, ty, node))
335    }
336
337     */
338
339    fn make_solution_for_missing_fields(
340        &mut self,
341        node: &swamp_ast::Node,
342        super_type: &TypeRef,
343        anon_struct_type: &AnonymousStructType,
344        source_order_expressions: Vec<(usize, Option<Node>, Expression)>,
345        missing_fields: SeqSet<String>,
346    ) -> Expression {
347        // First check if the super type has a default function (trait)
348        let maybe_default = {
349            self.shared
350                .state
351                .associated_impls
352                .get_member_function(super_type, "default")
353                .cloned()
354        };
355
356        // if it has a `default` function, call that to get a starting value
357
358        if let Some(function) = maybe_default {
359            self.analyze_struct_init_calling_default(
360                &function,
361                super_type,
362                anon_struct_type,
363                source_order_expressions,
364                node,
365            )
366        } else {
367            /*
368            let mapped: Vec<(usize, Expression)> = &source_order_expressions
369                .into_iter()
370                .map(|(a, _b, c)| (a, c))
371                .collect::<Vec<_>>();
372
373             */
374            self.analyze_struct_init_field_by_field(
375                anon_struct_type,
376                source_order_expressions,
377                missing_fields,
378                super_type,
379                node,
380            )
381        }
382
383        /*
384        else if missing_fields.is_empty() {
385
386            let ty = TypeKind::NamedStruct(struct_to_instantiate.clone());
387            let node = qualified_type_identifier.name.0.clone();
388            let mapped: Vec<(usize, Expression)> = source_order_expressions
389                .into_iter()
390                .map(|(a, _b, c)| (a, c))
391                .collect::<Vec<_>>();
392            Ok(self.create_expr(
393                ExpressionKind::StructInstantiation(StructInstantiation {
394                    source_order_expressions: mapped,
395                    struct_type_ref: struct_to_instantiate,
396                }),
397                ty,
398                &node,
399            ))
400        }
401
402         */
403    }
404
405    fn place_anon_struct_fields_that_exist_and_return_missing(
406        &mut self,
407        target_anon_struct_type: &AnonymousStructType,
408        ast_fields: &Vec<swamp_ast::FieldExpression>,
409    ) -> (Vec<(usize, Option<Node>, Expression)>, SeqSet<String>) {
410        let mut missing_fields: SeqSet<String> = target_anon_struct_type
411            .field_name_sorted_fields
412            .keys()
413            .cloned()
414            .collect();
415
416        let mut source_order_expressions = Vec::new();
417
418        for field in ast_fields {
419            let field_name = self.get_text(&field.field_name.0).to_string();
420            let resolved_node = self.to_node(&field.field_name.0);
421
422            // If we can't remove it from missing_fields, it's either a duplicate or unknown field
423            if !missing_fields.remove(&field_name) {
424                return if target_anon_struct_type
425                    .field_name_sorted_fields
426                    .contains_key(&field_name)
427                {
428                    self.add_err(
429                        ErrorKind::DuplicateFieldInStructInstantiation(field_name),
430                        &field.field_name.0,
431                    );
432                    (vec![], SeqSet::new())
433                } else {
434                    self.add_err(ErrorKind::UnknownStructField, &field.field_name.0);
435                    (vec![], SeqSet::new())
436                };
437            }
438
439            let looked_up_field = target_anon_struct_type
440                .field_name_sorted_fields
441                .get(&field_name)
442                .expect("field existence checked above");
443
444            let field_index_in_definition = target_anon_struct_type
445                .field_name_sorted_fields
446                .get_index(&field_name)
447                .expect("field_name is checked earlier");
448
449            let field_type_context = TypeContext::new_argument(
450                &looked_up_field.field_type,
451                looked_up_field
452                    .field_type
453                    .collection_view_that_needs_explicit_storage(),
454            );
455            let resolved_expression =
456                self.analyze_expression(&field.expression, &field_type_context);
457
458            source_order_expressions.push((
459                field_index_in_definition,
460                Some(resolved_node),
461                resolved_expression,
462            ));
463        }
464
465        (source_order_expressions, missing_fields)
466    }
467
468    pub(crate) fn analyze_anon_struct_instantiation(
469        &mut self,
470        node: &swamp_ast::Node,
471        struct_to_instantiate: &AnonymousStructType,
472        ast_fields: &Vec<swamp_ast::FieldExpression>,
473        allow_rest: bool,
474    ) -> Vec<(usize, Option<Node>, Expression)> {
475        let (source_order_expressions, missing_fields) = self
476            .place_anon_struct_fields_that_exist_and_return_missing(
477                struct_to_instantiate,
478                ast_fields,
479            );
480
481        let mut mapped: Vec<(usize, Option<Node>, Expression)> = source_order_expressions;
482
483        if allow_rest {
484            // Call `default()` for the missing fields
485            for missing_field_name in missing_fields {
486                let field = struct_to_instantiate
487                    .field_name_sorted_fields
488                    .get(&missing_field_name)
489                    .expect("field must exist in struct definition");
490
491                let field_index = struct_to_instantiate
492                    .field_name_sorted_fields
493                    .get_index(&missing_field_name)
494                    .expect("field must exist in struct definition");
495
496                // Try to create the default value for the field
497                if let Some(default_expression) =
498                    self.create_default_value_for_type(node, &field.field_type)
499                {
500                    mapped.push((field_index, None, default_expression));
501                }
502                // If no default is available, skip this field
503            }
504        } else if !missing_fields.is_empty() {
505            self.add_err(
506                ErrorKind::MissingFieldInStructInstantiation(
507                    missing_fields.to_vec(),
508                    struct_to_instantiate.clone(),
509                ),
510                node,
511            );
512            return vec![];
513        }
514
515        mapped
516    }
517}