1use 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 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 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); 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)?; 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 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 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 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 !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 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 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}