swamp_analyzer/
literal.rs

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