swamp_script_analyzer/
literal.rs

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