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