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