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