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::{Analyzer, TypeContext};
6use source_map_node::Node;
7use swamp_ast::FieldExpression;
8use swamp_semantic::err::ErrorKind;
9use swamp_semantic::prelude::Error;
10use swamp_semantic::{EnumLiteralExpressions, ExpressionKind};
11use swamp_semantic::{Expression, Fp};
12use swamp_types::prelude::*;
13use tracing::{error, warn};
14
15impl Analyzer<'_> {
16    pub fn analyze_enum_variant_struct_literal(
17        &mut self,
18        variant_ref: &EnumVariantType,
19        found_enum_type: &TypeRef,
20        /*anon_payload: AnonymousStructType, */
21        anonym_struct_field_and_expressions: &[FieldExpression],
22        detected_rest: bool,
23        node: &swamp_ast::Node,
24    ) -> Expression {
25        if let TypeKind::AnonymousStruct(anon_payload) = &*variant_ref.payload_type.kind {
26            if anonym_struct_field_and_expressions.len()
27                != anon_payload.field_name_sorted_fields.len()
28            {
29                return self.create_err(
30                    ErrorKind::WrongNumberOfArguments(
31                        anonym_struct_field_and_expressions.len(),
32                        anon_payload.field_name_sorted_fields.len(),
33                    ),
34                    node,
35                );
36            }
37
38            let resolved_fields = self.analyze_anon_struct_instantiation(
39                node,
40                anon_payload,
41                &anonym_struct_field_and_expressions.to_vec(),
42                detected_rest,
43            );
44
45            let data = EnumLiteralExpressions::Struct(resolved_fields);
46
47            self.create_expr(
48                ExpressionKind::EnumVariantLiteral(variant_ref.clone(), data),
49                found_enum_type.clone(),
50                node,
51            )
52        } else {
53            panic!("strange")
54        }
55    }
56
57    /// # Errors
58    ///
59    /// # Panics
60    /// if core hasn't added `Vec`
61    #[allow(clippy::too_many_lines)]
62    pub fn analyze_complex_literal_to_expression(
63        &mut self,
64        ast_expression: &swamp_ast::Expression,
65        ast_literal_kind: &swamp_ast::LiteralKind,
66        parent_context: &TypeContext,
67    ) -> Expression {
68        // We intentionally take the inner optional type if it exists
69        // Since we know that the caller will eventually wrap this with an
70        // ExpressionKind::Option()
71        let literal_context = parent_context.expected_type_or_optional_inner();
72
73        let ast_node = &ast_expression.node;
74        let (lit_kind, literal_type) = match &ast_literal_kind {
75            swamp_ast::LiteralKind::InternalInitializerList(items) => {
76                let (collection_type, resolved_items) =
77                    self.analyze_internal_initializer_list(ast_node, items, &literal_context);
78
79                (
80                    ExpressionKind::InitializerList(collection_type.clone(), resolved_items),
81                    collection_type,
82                )
83            }
84
85            swamp_ast::LiteralKind::InternalInitializerPairList(entries) => {
86                let (collection_type, resolved_items) = self
87                    .analyze_internal_initializer_pair_list(ast_node, entries, &literal_context);
88
89                (
90                    ExpressionKind::InitializerPairList(collection_type.clone(), resolved_items),
91                    collection_type,
92                )
93            }
94
95            _ => {
96                return self.analyze_literal(
97                    ast_node,
98                    ast_literal_kind,
99                    parent_context,
100                    &literal_context,
101                );
102            }
103        };
104
105        self.create_expr(lit_kind, literal_type, ast_node)
106    }
107
108    #[allow(clippy::too_many_lines)]
109    pub(crate) fn analyze_literal(
110        &mut self,
111        ast_node: &swamp_ast::Node,
112        ast_literal_kind: &swamp_ast::LiteralKind,
113        parent_context: &TypeContext,
114        context: &TypeContext,
115    ) -> Expression {
116        let node_text = self.get_text(ast_node);
117        let (expression_kind, ty) = match &ast_literal_kind {
118            swamp_ast::LiteralKind::Int => match Self::str_to_int(node_text) {
119                Err(int_err) => {
120                    return self.create_err(ErrorKind::IntConversionError(int_err), ast_node);
121                }
122                Ok(int_value) => (
123                    ExpressionKind::IntLiteral(int_value),
124                    self.shared.state.types.int(),
125                ),
126            },
127            swamp_ast::LiteralKind::Byte => match Self::str_to_byte(node_text) {
128                Err(byte_err) => {
129                    return self.create_err(
130                        ErrorKind::ByteConversionError(format!("{byte_err:?}")),
131                        ast_node,
132                    );
133                }
134                Ok(byte_value) => (
135                    ExpressionKind::ByteLiteral(byte_value),
136                    self.shared.state.types.byte(),
137                ),
138            },
139            swamp_ast::LiteralKind::Float => match Self::str_to_float(node_text) {
140                Err(float_err) => {
141                    return self.create_err(ErrorKind::FloatConversionError(float_err), ast_node);
142                }
143                Ok(float_value) => (
144                    ExpressionKind::FloatLiteral(Fp::from(float_value)),
145                    self.shared.state.types.float(),
146                ),
147            },
148            swamp_ast::LiteralKind::String(processed_string) => (
149                ExpressionKind::StringLiteral(processed_string.to_string()),
150                self.shared.state.types.string(),
151            ),
152            swamp_ast::LiteralKind::Bool => match Self::str_to_bool(node_text) {
153                Err(_bool_err) => return self.create_err(ErrorKind::BoolConversionError, ast_node),
154                Ok(bool_value) => (
155                    ExpressionKind::BoolLiteral(bool_value),
156                    self.shared.state.types.bool(),
157                ),
158            },
159            swamp_ast::LiteralKind::EnumVariant(enum_variant_literal) => {
160                let variant_name_text = self.get_text(&enum_variant_literal.name.0).to_string();
161
162                let found_enum_type = if let Some(enum_type_name_node) =
163                    &enum_variant_literal.qualified_enum_type_name
164                {
165                    let Some((symbol_table, name)) =
166                        self.get_symbol_table_and_name(enum_type_name_node)
167                    else {
168                        self.add_err(ErrorKind::UnknownModule, &enum_type_name_node.name.0);
169                        return self.create_err(ErrorKind::UnknownEnumVariantType, ast_node);
170                    };
171                    let Some(found_enum_type) = symbol_table.get_type(&name) else {
172                        return self.create_err(ErrorKind::UnknownEnumType, ast_node);
173                    };
174                    found_enum_type.clone()
175                } else if let Some(expected_type) = context.expected_type {
176                    if let TypeKind::Enum(_enum_type) = &*expected_type.kind {
177                        expected_type.clone()
178                    } else {
179                        return self.create_err(ErrorKind::EnumTypeWasntExpectedHere, ast_node);
180                    }
181                } else {
182                    return self.create_err(ErrorKind::CanNotInferEnumType, ast_node);
183                };
184
185                let TypeKind::Enum(enum_type) = &*found_enum_type.kind else {
186                    return self.create_err(ErrorKind::UnknownEnumType, ast_node);
187                };
188
189                let variant_name = &variant_name_text;
190                // Handle enum variant literals in patterns
191                let Some(variant_ref) = enum_type.get_variant(variant_name) else {
192                    return self.create_err(
193                        ErrorKind::UnknownEnumVariantType,
194                        &enum_variant_literal.name.0,
195                    );
196                };
197
198                let variant_reference_name_node = self.to_node(&enum_variant_literal.name.0);
199                self.shared.state.refs.add(
200                    variant_ref.common.symbol_id.into(),
201                    variant_reference_name_node.clone(),
202                );
203                self.shared.definition_table.refs.add(
204                    variant_ref.common.symbol_id.into(),
205                    variant_reference_name_node,
206                );
207
208                let resolved_data = match &enum_variant_literal.kind {
209                    swamp_ast::EnumVariantLiteralKind::Simple => EnumLiteralExpressions::Nothing,
210                    swamp_ast::EnumVariantLiteralKind::Tuple(ast_expressions) => {
211                        if let TypeKind::Tuple(tuple_field_types) = &*variant_ref.payload_type.kind
212                        {
213                            // Multi-element tuple variant
214                            if tuple_field_types.len() != ast_expressions.len() {
215                                return self.create_err(
216                                    ErrorKind::WrongNumberOfArguments(
217                                        tuple_field_types.len(),
218                                        ast_expressions.len(),
219                                    ),
220                                    ast_node,
221                                );
222                            }
223
224                            let resolved_expression = tuple_field_types
225                                .iter()
226                                .zip(ast_expressions)
227                                .map(|(expected_type, ast_expression)| {
228                                    let ctx = context.argument(expected_type);
229                                    self.analyze_expression(ast_expression, &ctx)
230                                })
231                                .collect();
232
233                            EnumLiteralExpressions::Tuple(resolved_expression)
234                        } else {
235                            // Single-element variant with direct payload type
236                            if ast_expressions.len() != 1 {
237                                return self.create_err(
238                                    ErrorKind::WrongNumberOfArguments(1, ast_expressions.len()),
239                                    ast_node,
240                                );
241                            }
242
243                            let ctx = context.argument(&variant_ref.payload_type);
244                            let resolved_expression =
245                                self.analyze_expression(&ast_expressions[0], &ctx);
246
247                            EnumLiteralExpressions::Tuple(vec![resolved_expression])
248                        }
249                    }
250                    swamp_ast::EnumVariantLiteralKind::Struct(
251                        anonym_struct_field_and_expressions,
252                        detected_rest,
253                    ) => {
254                        let TypeKind::AnonymousStruct(anon_payload) =
255                            &*variant_ref.payload_type.kind
256                        else {
257                            return self.create_err(
258                                ErrorKind::WrongEnumVariantContainer(variant_ref.clone()),
259                                ast_node,
260                            );
261                        };
262
263                        if anonym_struct_field_and_expressions.len()
264                            != anon_payload.field_name_sorted_fields.len()
265                        {
266                            return self.create_err(
267                                ErrorKind::WrongNumberOfArguments(
268                                    anonym_struct_field_and_expressions.len(),
269                                    anon_payload.field_name_sorted_fields.len(),
270                                ),
271                                &enum_variant_literal.name.0,
272                            );
273                        }
274
275                        let resolved_fields = self.analyze_anon_struct_instantiation(
276                            &enum_variant_literal.name.0,
277                            anon_payload,
278                            anonym_struct_field_and_expressions,
279                            *detected_rest,
280                        );
281
282                        EnumLiteralExpressions::Struct(resolved_fields)
283                    }
284                };
285
286                (
287                    ExpressionKind::EnumVariantLiteral(variant_ref.clone(), resolved_data),
288                    found_enum_type.clone(),
289                )
290            }
291
292            swamp_ast::LiteralKind::Tuple(expressions) => {
293                let (tuple_type_ref, resolved_items) =
294                    self.analyze_tuple_literal(expressions, context);
295
296                let tuple_type = self.shared.state.types.tuple(tuple_type_ref);
297
298                self.ensure_default_functions_for_type(&tuple_type, &expressions[0].node);
299                (ExpressionKind::TupleLiteral(resolved_items), tuple_type)
300            }
301            swamp_ast::LiteralKind::None => {
302                if let Some(found_expected_type) = parent_context.expected_type {
303                    let underlying = found_expected_type;
304                    if let TypeKind::Optional(_some_type) = &*underlying.kind {
305                        (ExpressionKind::NoneLiteral, underlying.clone())
306                    } else {
307                        return self.create_err(ErrorKind::NoneNeedsExpectedTypeHint, ast_node);
308                    }
309                } else {
310                    return self.create_err(ErrorKind::NoneNeedsExpectedTypeHint, ast_node);
311                }
312            }
313            &&swamp_ast::LiteralKind::InternalInitializerList(_)
314            | &swamp_ast::LiteralKind::InternalInitializerPairList(_) => {
315                panic!("initializer lists are not basic literals")
316            }
317        };
318
319        self.create_expr(expression_kind, ty, ast_node)
320    }
321
322    fn analyze_tuple_literal(
323        &mut self,
324        items: &[swamp_ast::Expression],
325        context: &TypeContext,
326    ) -> (Vec<TypeRef>, Vec<Expression>) {
327        let expressions = self.analyze_argument_expressions(None, context, items);
328        let mut tuple_types = Vec::new();
329        for expr in &expressions {
330            let item_type = expr.ty.clone();
331            tuple_types.push(item_type);
332        }
333
334        (tuple_types, expressions)
335    }
336
337    fn analyze_tuple_type(
338        &mut self,
339        node: &swamp_ast::Node,
340        expected_types: &[TypeRef],
341        ast_expressions: &Vec<swamp_ast::Expression>,
342    ) -> Vec<Expression> {
343        if ast_expressions.len() != expected_types.len() {
344            return vec![self.create_err(
345                ErrorKind::WrongNumberOfArguments(expected_types.len(), ast_expressions.len()),
346                node,
347            )];
348        }
349
350        let mut expressions = Vec::new();
351        for (expected_type, expr) in expected_types.iter().zip(ast_expressions) {
352            let context = TypeContext::new_argument(
353                expected_type,
354                expected_type.collection_view_that_needs_explicit_storage(),
355            );
356            let resolved_expr = self.analyze_expression(expr, &context);
357            expressions.push(resolved_expr);
358        }
359
360        expressions
361    }
362
363    pub fn add_err(&mut self, kind: ErrorKind, ast_node: &swamp_ast::Node) {
364        self.add_err_resolved(kind, &self.to_node(ast_node));
365    }
366    pub(crate) fn add_hint(&mut self, kind: ErrorKind, ast_node: &swamp_ast::Node) {
367        self.add_hint_resolved(kind, &self.to_node(ast_node));
368    }
369
370    pub(crate) fn add_hint_resolved(&mut self, kind: ErrorKind, node: &Node) {
371        warn!(?kind, "add error");
372        let err = Error {
373            node: node.clone(),
374            kind,
375        };
376
377        self.shared.state.hints.push(err);
378    }
379
380    pub(crate) fn add_err_resolved(&mut self, kind: ErrorKind, node: &Node) {
381        error!(?kind, "add error");
382        let err = Error {
383            node: node.clone(),
384            kind,
385        };
386        self.shared.state.errors.push(err);
387    }
388
389    #[must_use]
390    pub fn create_err_vec(
391        &mut self,
392        kind: ErrorKind,
393        ast_node: &swamp_ast::Node,
394    ) -> Vec<Expression> {
395        vec![self.create_err(kind, ast_node)]
396    }
397
398    #[must_use]
399    pub fn create_err(&mut self, kind: ErrorKind, ast_node: &swamp_ast::Node) -> Expression {
400        self.add_err(kind.clone(), ast_node);
401
402        Expression {
403            ty: self.types().unit(),
404            node: self.to_node(ast_node),
405            kind: ExpressionKind::Error(kind),
406        }
407    }
408    #[must_use]
409    pub fn create_err_resolved(&mut self, kind: ErrorKind, resolved_node: &Node) -> Expression {
410        self.add_err_resolved(kind.clone(), resolved_node);
411
412        Expression {
413            ty: self.types().unit(),
414            node: resolved_node.clone(),
415            kind: ExpressionKind::Error(kind),
416        }
417    }
418}