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