1use crate::err::{Error, ErrorKind};
6use crate::{Analyzer, TypeContext};
7use swamp_script_node::Node;
8use swamp_script_semantic::ExpressionKind;
9use swamp_script_semantic::{
10 ArgumentExpressionOrLocation, EnumLiteralData, Expression, Fp, Literal,
11};
12use swamp_script_types::prelude::*;
13use tracing::error;
14
15impl Analyzer<'_> {
16 #[allow(clippy::too_many_lines)]
19 pub fn analyze_complex_literal_to_expression(
20 &mut self,
21 ast_node: &swamp_script_ast::Node,
22 ast_literal_kind: &swamp_script_ast::LiteralKind,
23 context: &TypeContext,
24 ) -> Result<Expression, Error> {
25 let expression = match &ast_literal_kind {
26 swamp_script_ast::LiteralKind::Slice(items) => {
27 let (encountered_element_type, resolved_items) =
28 self.analyze_slice_type_helper(ast_node, items)?;
29
30 let slice_type = Type::Slice(Box::new(encountered_element_type.clone()));
31
32 let found_expected_type = if let Some(inner_type) = context.expected_type {
33 inner_type.clone()
34 } else {
35 let vec_blueprint = self
36 .shared
37 .core_symbol_table
38 .get_blueprint("Vec")
39 .unwrap()
40 .clone();
41 self.shared
42 .state
43 .instantiator
44 .instantiate_blueprint_and_members(
45 &vec_blueprint,
46 &[encountered_element_type.clone()],
47 )?
48 };
49
50 if let Some(found) = self
51 .shared
52 .state
53 .instantiator
54 .associated_impls
55 .get_internal_member_function(&found_expected_type, "new_from_slice")
56 {
57 let required_type = &found.signature.parameters[0].resolved_type;
58 if resolved_items.is_empty() || slice_type.compatible_with(required_type) {
59 let slice_literal =
60 Literal::Slice(slice_type.clone(), resolved_items.clone());
61
62 let expr = self.create_expr(
63 ExpressionKind::Literal(slice_literal),
64 slice_type.clone(),
65 ast_node,
66 );
67 let return_type = *found.signature.return_type.clone();
68 let arg = ArgumentExpressionOrLocation::Expression(expr);
69 let call_kind = self.create_static_call(
70 "new_from_slice",
71 &[arg],
72 ast_node,
73 &found_expected_type.clone(),
74 )?;
75
76 self.create_expr(call_kind, return_type, ast_node)
77 } else {
78 error!(
79 ?slice_type,
80 ?required_type,
81 "incompatible types new_from_slice"
82 );
83 return Err(self.create_err(
84 ErrorKind::IncompatibleTypes {
85 expected: required_type.clone(),
86 found: slice_type,
87 },
88 ast_node,
89 ));
90 }
91 } else {
92 return Err(self.create_err(
93 ErrorKind::MissingMemberFunction("new_from_slice".to_string()),
94 ast_node,
95 ));
96 }
97 }
98
99 swamp_script_ast::LiteralKind::SlicePair(entries) => {
100 let (resolved_items, encountered_key_type, encountered_value_type) =
101 self.analyze_slice_pair_literal(ast_node, entries)?;
102
103 let slice_pair_type = Type::SlicePair(
104 Box::new(encountered_key_type.clone()),
105 Box::new(encountered_value_type.clone()),
106 );
107
108 let found_expected_type = if let Some(inner_type) = context.expected_type {
109 inner_type.clone()
110 } else {
111 let map_blueprint = self
112 .shared
113 .core_symbol_table
114 .get_blueprint("Map")
115 .unwrap()
116 .clone();
117 self.shared
118 .state
119 .instantiator
120 .instantiate_blueprint_and_members(
121 &map_blueprint,
122 &[encountered_key_type.clone(), encountered_value_type.clone()],
123 )?
124 };
125
126 if let Some(found) = self
127 .shared
128 .state
129 .instantiator
130 .associated_impls
131 .get_internal_member_function(&found_expected_type, "new_from_slice_pair")
132 {
133 let required_type = &found.signature.parameters[0].resolved_type;
134 if resolved_items.is_empty() || slice_pair_type.compatible_with(required_type) {
135 let slice_literal =
136 Literal::SlicePair(slice_pair_type.clone(), resolved_items.clone());
137
138 let expr = self.create_expr(
139 ExpressionKind::Literal(slice_literal),
140 slice_pair_type.clone(),
141 ast_node,
142 );
143 let return_type = *found.signature.return_type.clone();
144 let arg = ArgumentExpressionOrLocation::Expression(expr);
145 let call_kind = self.create_static_call(
146 "new_from_slice_pair",
147 &[arg],
148 ast_node,
149 &found_expected_type.clone(),
150 )?;
151
152 self.create_expr(call_kind, return_type, ast_node)
153 } else {
154 return Err(self.create_err(
155 ErrorKind::IncompatibleTypes {
156 expected: required_type.clone(),
157 found: slice_pair_type,
158 },
159 ast_node,
160 ));
161 }
162 } else {
163 return Err(self.create_err(
164 ErrorKind::MissingMemberFunction("new_from_slice_pair".to_string()),
165 ast_node,
166 ));
167 }
168 }
169
170 _ => {
171 let (lit_kind, literal_type) =
172 self.analyze_literal(ast_node, ast_literal_kind, context)?;
173 self.create_expr(ExpressionKind::Literal(lit_kind), literal_type, ast_node)
174 }
175 };
176
177 Ok(expression)
178 }
179
180 #[allow(clippy::too_many_lines)]
181 pub(crate) fn analyze_literal(
182 &mut self,
183 ast_node: &swamp_script_ast::Node,
184 ast_literal_kind: &swamp_script_ast::LiteralKind,
185 context: &TypeContext,
186 ) -> Result<(Literal, Type), Error> {
187 let node_text = self.get_text(ast_node);
188 let resolved_literal = match &ast_literal_kind {
189 swamp_script_ast::LiteralKind::Int => (
190 Literal::IntLiteral(Self::str_to_int(node_text).map_err(|int_conversion_err| {
191 self.create_err(ErrorKind::IntConversionError(int_conversion_err), ast_node)
192 })?),
193 Type::Int,
194 ),
195 swamp_script_ast::LiteralKind::Float => {
196 let float = Self::str_to_float(node_text).map_err(|float_conversion_err| {
197 self.create_err(
198 ErrorKind::FloatConversionError(float_conversion_err),
199 ast_node,
200 )
201 })?;
202 (Literal::FloatLiteral(Fp::from(float)), Type::Float)
203 }
204 swamp_script_ast::LiteralKind::String(processed_string) => (
205 Literal::StringLiteral(processed_string.to_string()),
206 Type::String,
207 ),
208 swamp_script_ast::LiteralKind::Bool => {
209 let bool_val = if node_text == "false" {
210 false
211 } else if node_text == "true" {
212 true
213 } else {
214 return Err(self.create_err(ErrorKind::BoolConversionError, ast_node));
215 };
216 (Literal::BoolLiteral(bool_val), Type::Bool)
217 }
218 swamp_script_ast::LiteralKind::EnumVariant(enum_literal) => {
219 let (enum_name, variant_name) = match enum_literal {
220 swamp_script_ast::EnumVariantLiteral::Simple(enum_name, variant_name) => {
221 (enum_name, variant_name)
222 }
223 swamp_script_ast::EnumVariantLiteral::Tuple(enum_name, variant_name, _) => {
224 (enum_name, variant_name)
225 }
226 swamp_script_ast::EnumVariantLiteral::Struct(enum_name, variant_name, _, _) => {
227 (enum_name, variant_name)
228 }
229 };
230
231 let (symbol_table, name) = self.get_symbol_table_and_name(enum_name)?;
232 if let Some(enum_type_ref) = symbol_table.get_enum(&name) {
233 let enum_type_clone = enum_type_ref.clone();
234 let enum_type = Type::Enum(enum_type_ref.clone());
235
236 let variant_ref = self.analyze_enum_variant_ref(enum_name, variant_name)?;
238
239 let resolved_data = match enum_literal {
240 swamp_script_ast::EnumVariantLiteral::Simple(_, _) => {
241 EnumLiteralData::Nothing
242 }
243 swamp_script_ast::EnumVariantLiteral::Tuple(
244 _node,
245 _variant,
246 ast_expressions,
247 ) => {
248 let EnumVariantType::Tuple(tuple_data) = &variant_ref else {
249 return Err(self.create_err(
250 ErrorKind::WrongEnumVariantContainer(variant_ref),
251 &ast_node,
252 ));
253 };
254
255 let resolved = self.analyze_tuple_type(
256 &enum_literal.node(),
257 &tuple_data.fields_in_order,
258 ast_expressions,
259 )?;
260 EnumLiteralData::Tuple(resolved)
261 }
262 swamp_script_ast::EnumVariantLiteral::Struct(
263 _qualified_type_identifier,
264 variant,
265 anonym_struct_field_and_expressions,
266 detected_rest,
267 ) => {
268 if let EnumVariantType::Struct(ref resolved_variant_struct_ref) =
269 variant_ref
270 {
271 if anonym_struct_field_and_expressions.len()
272 != resolved_variant_struct_ref
273 .anon_struct
274 .field_name_sorted_fields
275 .len()
276 {
277 return Err(self.create_err(
278 ErrorKind::WrongNumberOfArguments(
279 anonym_struct_field_and_expressions.len(),
280 resolved_variant_struct_ref
281 .anon_struct
282 .field_name_sorted_fields
283 .len(),
284 ),
285 &variant.0,
286 ));
287 }
288
289 let resolved = self.analyze_anon_struct_instantiation(
290 &variant.0.clone(),
291 &resolved_variant_struct_ref.anon_struct,
292 anonym_struct_field_and_expressions,
293 *detected_rest,
294 )?;
295
296 EnumLiteralData::Struct(resolved)
297 } else {
298 return Err(self.create_err(
299 ErrorKind::WrongEnumVariantContainer(variant_ref.clone()),
300 &variant.0,
301 ));
302 }
303 }
304 };
305
306 return Ok((
307 Literal::EnumVariantLiteral(enum_type_clone, variant_ref, resolved_data),
308 enum_type,
309 ));
310 }
311 return Err(self.create_err(ErrorKind::UnknownEnumType, ast_node));
312 }
313
314 swamp_script_ast::LiteralKind::Tuple(expressions) => {
315 let (tuple_type_ref, resolved_items) = self.analyze_tuple_literal(expressions)?;
316 (
317 Literal::TupleLiteral(tuple_type_ref.clone(), resolved_items),
318 Type::Tuple(tuple_type_ref),
319 )
320 }
321 swamp_script_ast::LiteralKind::None => {
322 if let Some(found_expected_type) = context.expected_type {
323 if let Type::Optional(_some_type) = found_expected_type {
324 return Ok((Literal::NoneLiteral, found_expected_type.clone()));
325 }
326 }
327 return Err(self.create_err(ErrorKind::NoneNeedsExpectedTypeHint, &ast_node));
328 }
329 &&swamp_script_ast::LiteralKind::Slice(_)
330 | &swamp_script_ast::LiteralKind::SlicePair(_) => todo!(),
331 };
332
333 Ok(resolved_literal)
334 }
335
336 fn analyze_tuple_literal(
337 &mut self,
338 items: &[swamp_script_ast::Expression],
339 ) -> Result<(Vec<Type>, Vec<Expression>), Error> {
340 let expressions = self.analyze_argument_expressions(None, items)?;
341 let mut tuple_types = Vec::new();
342 for expr in &expressions {
343 let item_type = expr.ty.clone();
344 tuple_types.push(item_type);
345 }
346
347 Ok((tuple_types, expressions))
348 }
349
350 fn analyze_tuple_type(
351 &mut self,
352 node: &swamp_script_ast::Node,
353 expected_types: &Vec<Type>,
354 ast_expressions: &Vec<swamp_script_ast::Expression>,
355 ) -> Result<Vec<Expression>, Error> {
356 if ast_expressions.len() != expected_types.len() {
357 return Err(self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node));
358 }
359
360 let mut expressions = Vec::new();
361 for (expected_type, expr) in expected_types.iter().zip(ast_expressions) {
362 let context = TypeContext::new_argument(expected_type);
363 let resolved_expr = self.analyze_expression(expr, &context)?;
364 expressions.push(resolved_expr);
365 }
366
367 Ok(expressions)
368 }
369
370 fn analyze_slice_pair_literal(
371 &mut self,
372 node: &swamp_script_ast::Node,
373 entries: &[(swamp_script_ast::Expression, swamp_script_ast::Expression)],
374 ) -> Result<(Vec<(Expression, Expression)>, Type, Type), Error> {
375 if entries.is_empty() {
376 return Ok((vec![], Type::Unit, Type::Unit));
377 }
378
379 let (first_key, first_value) = &entries[0];
381 let anything_context = TypeContext::new_anything_argument();
382 let resolved_first_key = self.analyze_expression(first_key, &anything_context)?;
383 let resolved_first_value = self.analyze_expression(first_value, &anything_context)?;
384 let key_type = resolved_first_key.ty.clone();
385 let value_type = resolved_first_value.ty.clone();
386
387 let key_context = TypeContext::new_argument(&key_type);
388 let value_context = TypeContext::new_argument(&value_type);
389
390 let mut resolved_entries = Vec::new();
392 resolved_entries.push((resolved_first_key, resolved_first_value));
393
394 for (key, value) in entries.iter().skip(1) {
395 let resolved_key = self.analyze_expression(key, &key_context)?;
396 let resolved_value = self.analyze_expression(value, &value_context)?;
397
398 if !resolved_key.ty.compatible_with(&key_type) {
399 return Err(self.create_err(
400 ErrorKind::MapKeyTypeMismatch {
401 expected: key_type,
402 found: resolved_key.ty,
403 },
404 node,
405 ));
406 }
407
408 if !resolved_value.ty.compatible_with(&value_type) {
409 return Err(self.create_err(
410 ErrorKind::MapValueTypeMismatch {
411 expected: value_type,
412 found: resolved_value.ty,
413 },
414 node,
415 ));
416 }
417
418 resolved_entries.push((resolved_key, resolved_value));
419 }
420
421 Ok((resolved_entries, key_type, value_type))
422 }
423
424 #[must_use]
425 pub fn create_err(&self, kind: ErrorKind, ast_node: &swamp_script_ast::Node) -> Error {
426 error!(?kind, "error created");
427 Error {
428 node: self.to_node(ast_node),
429 kind,
430 }
431 }
432
433 #[must_use]
434 pub fn create_err_resolved(&self, kind: ErrorKind, resolved_node: &Node) -> Error {
435 Error {
436 node: resolved_node.clone(),
437 kind,
438 }
439 }
440}