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