swamp_script_analyzer/
structure.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/script
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use crate::err::{Error, ErrorKind};
6use crate::{Analyzer, TypeContext};
7use seq_map::SeqMap;
8use seq_set::SeqSet;
9use swamp_script_semantic::{
10    AnonymousStructLiteral, AnonymousStructType, ArgumentExpressionOrLocation, Expression,
11    ExpressionKind, FunctionRef, LocationAccess, LocationAccessKind, MutOrImmutableExpression,
12    Node, SingleLocationExpression, SingleLocationExpressionKind, SingleMutLocationExpression,
13    StructInstantiation, StructTypeField, StructTypeRef, Type,
14};
15
16impl Analyzer<'_> {
17    fn analyze_struct_init_calling_default(
18        &mut self,
19        function: &FunctionRef,
20        struct_to_instantiate: StructTypeRef,
21        source_order_expressions: Vec<(usize, Node, Expression)>,
22        node: &swamp_script_ast::Node,
23    ) -> Result<Expression, Error> {
24        let mut expressions = Vec::new();
25
26        self.push_block_scope("struct_instantiation");
27
28        let temp_var = self.create_local_variable_generated(
29            "__generated",
30            true,
31            &Type::NamedStruct(struct_to_instantiate.clone()),
32        )?;
33
34        // temp_var = StructType::default()
35        let return_type = *function.signature().return_type.clone();
36
37        let default_call_kind = self
38            .create_default_static_call(node, &Type::NamedStruct(struct_to_instantiate.clone()))?;
39
40        let static_call = self.create_expr(default_call_kind, return_type, node);
41
42        let expr = self.create_expr(
43            ExpressionKind::VariableDefinition(
44                temp_var.clone(),
45                Box::new(MutOrImmutableExpression {
46                    expression_or_location: ArgumentExpressionOrLocation::Expression(static_call),
47                    is_mutable: None,
48                }),
49            ),
50            Type::Unit,
51            node,
52        );
53        expressions.push(expr);
54
55        // overwrite fields in temp_var with assignments
56        for (field_target_index, resolved_field_name_node, field_source_expression) in
57            source_order_expressions
58        {
59            let node = field_source_expression.node.clone();
60
61            let field_expression_type = field_source_expression.ty.clone();
62
63            let kind = LocationAccessKind::FieldIndex(
64                struct_to_instantiate.borrow().anon_struct_type.clone(),
65                field_target_index,
66            );
67
68            let single_chain = vec![LocationAccess {
69                node: resolved_field_name_node,
70                ty: field_expression_type.clone(),
71                kind,
72            }];
73
74            let created_location = SingleLocationExpression {
75                kind: SingleLocationExpressionKind::MutStructFieldRef(
76                    struct_to_instantiate.clone(),
77                    field_target_index,
78                ),
79                node: node.clone(),
80                ty: field_expression_type,
81                starting_variable: temp_var.clone(),
82                access_chain: single_chain,
83            };
84
85            let created_mut_location = SingleMutLocationExpression(created_location);
86
87            let overwrite_expression = self.create_expr_resolved(
88                ExpressionKind::Assignment(
89                    Box::from(created_mut_location),
90                    Box::new(field_source_expression),
91                ),
92                Type::Unit,
93                &node,
94            );
95
96            expressions.push(overwrite_expression);
97        }
98
99        let ty = temp_var.resolved_type.clone();
100        let access_variable =
101            self.create_expr(ExpressionKind::VariableAccess(temp_var), ty.clone(), &node);
102
103        expressions.push(access_variable); // make sure the block returns the overwritten temp_var
104
105        self.pop_block_scope("struct instantiation");
106
107        let block = self.create_expr(ExpressionKind::Block(expressions), ty, &node);
108        Ok(block)
109    }
110
111    fn analyze_struct_init_field_by_field(
112        &mut self,
113        struct_to_instantiate: StructTypeRef,
114        mut source_order_expressions: Vec<(usize, Expression)>,
115        missing_fields: SeqSet<String>,
116        node: &swamp_script_ast::Node,
117    ) -> Result<Expression, Error> {
118        {
119            let borrowed_anon_type = &struct_to_instantiate.borrow().anon_struct_type;
120
121            for missing_field_name in missing_fields {
122                let field = borrowed_anon_type
123                    .field_name_sorted_fields
124                    .get(&missing_field_name)
125                    .expect("should have been verified by helper function");
126                let field_index = borrowed_anon_type
127                    .field_name_sorted_fields
128                    .get_index(&missing_field_name)
129                    .expect("should have been verified earlier");
130
131                let expression = self.create_default_value_for_type(&node, &field.field_type)?; // expression is usually a literal
132
133                source_order_expressions.push((field_index, expression));
134            }
135        }
136
137        let ty = Type::NamedStruct(struct_to_instantiate.clone());
138
139        Ok(self.create_expr(
140            ExpressionKind::StructInstantiation(StructInstantiation {
141                source_order_expressions,
142                struct_type_ref: struct_to_instantiate,
143            }),
144            ty,
145            &node,
146        ))
147    }
148
149    /// # Errors
150    ///
151    /// # Panics
152    ///
153    pub fn analyze_anonymous_struct_literal(
154        &mut self,
155        node: &swamp_script_ast::Node,
156        ast_fields: &Vec<swamp_script_ast::FieldExpression>,
157        rest_was_specified: bool,
158        context: &TypeContext,
159    ) -> Result<Expression, Error> {
160        let mut maybe_named_struct: Option<StructTypeRef> = None;
161
162        let struct_to_instantiate = if let Some(expected_type) = context.expected_type {
163            match expected_type {
164                Type::NamedStruct(named_struct) => {
165                    maybe_named_struct = Some(named_struct.clone());
166                    named_struct.borrow().anon_struct_type.clone()
167                }
168                Type::AnonymousStruct(anonymous_struct) => anonymous_struct.clone(),
169                _ => {
170                    return Err(
171                        self.create_err(ErrorKind::CouldNotCoerceTo(expected_type.clone()), node)
172                    );
173                }
174            }
175        } else {
176            //let mut field_name_and_expression = SeqMap::new();
177            let mut map_for_creating_type = SeqMap::new();
178
179            for field in ast_fields {
180                let field_name = self.get_text(&field.field_name.0).to_string();
181                let resolved_node = self.to_node(&field.field_name.0);
182
183                let field_type_context = TypeContext::new_anything_argument();
184                let resolved_expression =
185                    self.analyze_expression(&field.expression, &field_type_context)?;
186
187                let expression_type = resolved_expression.ty.clone();
188                //field_name_and_expression.insert(field_name.clone(), resolved_expression);
189                let field = StructTypeField {
190                    identifier: Some(resolved_node),
191                    field_type: expression_type,
192                };
193
194                map_for_creating_type
195                    .insert(field_name.clone(), field)
196                    .expect("TODO: panic message");
197            }
198
199            AnonymousStructType::new_and_sort_fields(map_for_creating_type)
200        };
201
202        let mapped = self.analyze_anon_struct_instantiation(
203            node,
204            &struct_to_instantiate,
205            ast_fields,
206            rest_was_specified,
207        )?;
208
209        let (kind, ty) = if let Some(named_struct) = maybe_named_struct {
210            (
211                ExpressionKind::StructInstantiation(StructInstantiation {
212                    source_order_expressions: mapped,
213                    struct_type_ref: named_struct.clone(),
214                }),
215                Type::NamedStruct(named_struct),
216            )
217        } else {
218            (
219                ExpressionKind::AnonymousStructLiteral(AnonymousStructLiteral {
220                    source_order_expressions: mapped,
221                    anonymous_struct_type: struct_to_instantiate.clone(),
222                }),
223                Type::AnonymousStruct(struct_to_instantiate),
224            )
225        };
226
227        Ok(self.create_expr(kind, ty, &node))
228    }
229
230    pub(crate) fn analyze_struct_instantiation(
231        &mut self,
232        qualified_type_identifier: &swamp_script_ast::QualifiedTypeIdentifier,
233        ast_fields: &Vec<swamp_script_ast::FieldExpression>,
234        has_rest: bool,
235    ) -> Result<Expression, Error> {
236        let struct_to_instantiate = self.get_struct_type(qualified_type_identifier)?;
237
238        let (source_order_expressions, missing_fields) = self
239            .analyze_anon_struct_instantiation_helper(
240                &struct_to_instantiate.borrow().anon_struct_type,
241                ast_fields,
242            )?;
243
244        if has_rest {
245            let maybe_default = {
246                self.shared
247                    .state
248                    .associated_impls
249                    .get_member_function(
250                        &Type::NamedStruct(struct_to_instantiate.clone()),
251                        "default",
252                    )
253                    .cloned()
254            };
255
256            if let Some(function) = maybe_default {
257                self.analyze_struct_init_calling_default(
258                    &function,
259                    struct_to_instantiate,
260                    source_order_expressions,
261                    &qualified_type_identifier.name.0,
262                )
263            } else {
264                let mapped: Vec<(usize, Expression)> = source_order_expressions
265                    .into_iter()
266                    .map(|(a, _b, c)| (a, c))
267                    .collect::<Vec<_>>();
268                self.analyze_struct_init_field_by_field(
269                    struct_to_instantiate,
270                    mapped,
271                    missing_fields,
272                    &qualified_type_identifier.name.0,
273                )
274            }
275        } else if missing_fields.is_empty() {
276            let ty = Type::NamedStruct(struct_to_instantiate.clone());
277            let node = qualified_type_identifier.name.0.clone();
278            let mapped: Vec<(usize, Expression)> = source_order_expressions
279                .into_iter()
280                .map(|(a, _b, c)| (a, c))
281                .collect::<Vec<_>>();
282            Ok(self.create_expr(
283                ExpressionKind::StructInstantiation(StructInstantiation {
284                    source_order_expressions: mapped,
285                    struct_type_ref: struct_to_instantiate,
286                }),
287                ty,
288                &node,
289            ))
290        } else {
291            let node = qualified_type_identifier.name.0.clone();
292            Err(self.create_err(
293                ErrorKind::MissingFieldInStructInstantiation(
294                    missing_fields.to_vec(),
295                    struct_to_instantiate.borrow().anon_struct_type.clone(),
296                ),
297                &node,
298            ))
299        }
300    }
301
302    fn analyze_anon_struct_instantiation_helper(
303        &mut self,
304        struct_to_instantiate: &AnonymousStructType,
305        ast_fields: &Vec<swamp_script_ast::FieldExpression>,
306    ) -> Result<(Vec<(usize, Node, Expression)>, SeqSet<String>), Error> {
307        let mut missing_fields: SeqSet<String> = struct_to_instantiate
308            .field_name_sorted_fields
309            .keys()
310            .cloned()
311            .collect();
312
313        let mut source_order_expressions = Vec::new();
314
315        for field in ast_fields {
316            let field_name = self.get_text(&field.field_name.0).to_string();
317            let resolved_node = self.to_node(&field.field_name.0);
318
319            // If we can't remove it from missing_fields, it's either a duplicate or unknown field
320            if !missing_fields.remove(&field_name) {
321                return if struct_to_instantiate
322                    .field_name_sorted_fields
323                    .contains_key(&field_name)
324                {
325                    Err(self.create_err(
326                        ErrorKind::DuplicateFieldInStructInstantiation(field_name),
327                        &field.field_name.0,
328                    ))
329                } else {
330                    Err(self.create_err(ErrorKind::UnknownStructField, &field.field_name.0))
331                };
332            }
333
334            let looked_up_field = struct_to_instantiate
335                .field_name_sorted_fields
336                .get(&field_name)
337                .expect("field existence checked above");
338
339            let field_index_in_definition = struct_to_instantiate
340                .field_name_sorted_fields
341                .get_index(&field_name)
342                .expect("field_name is checked earlier");
343
344            let field_type_context = TypeContext::new_argument(&looked_up_field.field_type);
345            let resolved_expression =
346                self.analyze_expression(&field.expression, &field_type_context)?;
347
348            source_order_expressions.push((
349                field_index_in_definition,
350                resolved_node,
351                resolved_expression,
352            ));
353        }
354
355        Ok((source_order_expressions, missing_fields))
356    }
357
358    pub(crate) fn analyze_anon_struct_instantiation(
359        &mut self,
360        node: &swamp_script_ast::Node,
361        struct_to_instantiate: &AnonymousStructType,
362        ast_fields: &Vec<swamp_script_ast::FieldExpression>,
363        allow_rest: bool,
364    ) -> Result<Vec<(usize, Expression)>, Error> {
365        let (source_order_expressions, missing_fields) =
366            self.analyze_anon_struct_instantiation_helper(struct_to_instantiate, ast_fields)?;
367
368        let mut mapped: Vec<(usize, Expression)> = source_order_expressions
369            .into_iter()
370            .map(|(a, _b, c)| (a, c))
371            .collect::<Vec<_>>();
372
373        if allow_rest {
374            // Call `default()` for the missing fields
375            for missing_field_name in missing_fields {
376                let field = struct_to_instantiate
377                    .field_name_sorted_fields
378                    .get(&missing_field_name)
379                    .expect("field must exist in struct definition");
380
381                let field_index = struct_to_instantiate
382                    .field_name_sorted_fields
383                    .get_index(&missing_field_name)
384                    .expect("field must exist in struct definition");
385
386                // Here you would create the default value for the field
387                let default_expression =
388                    self.create_default_value_for_type(node, &field.field_type)?;
389
390                mapped.push((field_index, default_expression));
391            }
392        } else if !missing_fields.is_empty() {
393            return Err(self.create_err(
394                ErrorKind::MissingFieldInStructInstantiation(
395                    missing_fields.to_vec(),
396                    struct_to_instantiate.clone(),
397                ),
398                node,
399            ));
400        }
401
402        Ok(mapped)
403    }
404}