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