swamp_analyzer/
lib.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 */
5pub mod access;
6pub mod call;
7pub mod constant;
8pub mod def;
9pub mod err;
10pub mod literal;
11pub mod operator;
12pub mod pattern;
13pub mod prelude;
14mod structure;
15pub mod types;
16pub mod variable;
17
18use crate::err::{Error, ErrorKind};
19use seq_map::SeqMap;
20use source_map_cache::SourceMap;
21use source_map_node::{FileId, Node, Span};
22use std::mem::take;
23use std::num::{ParseFloatError, ParseIntError};
24use std::ops::Deref;
25use swamp_modules::prelude::*;
26use swamp_modules::symtbl::{SymbolTableRef, TypeGeneratorKind};
27use swamp_semantic::instantiator::TypeVariableScope;
28use swamp_semantic::prelude::*;
29use swamp_semantic::type_var_stack::SemanticContext;
30use swamp_semantic::{
31    ArgumentExpressionOrLocation, BlockScope, BlockScopeMode, FunctionScopeState,
32    InternalMainExpression, LocationAccess, LocationAccessKind, MutOrImmutableExpression,
33    NormalPattern, Postfix, PostfixKind, SingleLocationExpression, SingleLocationExpressionKind,
34    SingleMutLocationExpression, TypeWithMut, WhenBinding,
35};
36use swamp_types::all_types_are_concrete_or_unit;
37use swamp_types::prelude::*;
38use tracing::info;
39
40#[derive(Copy, Clone, Eq, PartialEq, Debug)]
41pub enum LocationSide {
42    Lhs,
43    Rhs,
44}
45
46#[derive(Debug)]
47pub struct Program {
48    pub state: ProgramState,
49    pub modules: Modules,
50    pub default_symbol_table: SymbolTable,
51}
52
53impl Default for Program {
54    fn default() -> Self {
55        Self::new(ProgramState::new(), Modules::new(), SymbolTable::new(&[]))
56    }
57}
58
59impl Program {
60    #[must_use]
61    pub const fn new(
62        state: ProgramState,
63        modules: Modules,
64        default_symbol_table: SymbolTable,
65    ) -> Self {
66        Self {
67            state,
68            modules,
69            default_symbol_table,
70        }
71    }
72}
73
74#[must_use]
75pub const fn convert_span(without: &swamp_ast::SpanWithoutFileId, file_id: FileId) -> Span {
76    Span {
77        file_id,
78        offset: without.offset,
79        length: without.length,
80    }
81}
82
83/// Type checking context
84#[derive(Debug, Clone)]
85pub struct TypeContext<'a> {
86    /// Expected type for the current expression
87    pub expected_type: Option<&'a Type>,
88}
89
90impl<'a> TypeContext<'a> {
91    #[must_use]
92    pub const fn new(expected_type: Option<&'a Type>) -> Self {
93        Self { expected_type }
94    }
95
96    #[must_use]
97    pub const fn new_argument(required_type: &'a Type) -> Self {
98        Self {
99            expected_type: Some(required_type),
100        }
101    }
102
103    #[must_use]
104    pub const fn new_unsure_argument(expected_type: Option<&'a Type>) -> Self {
105        Self { expected_type }
106    }
107
108    #[must_use]
109    pub const fn new_anything_argument() -> Self {
110        Self {
111            expected_type: None,
112        }
113    }
114
115    #[must_use]
116    pub const fn new_function(required_type: &'a Type) -> Self {
117        Self {
118            expected_type: Some(required_type),
119        }
120    }
121
122    #[must_use]
123    pub const fn with_expected_type(&self, expected_type: Option<&'a Type>) -> Self {
124        Self { expected_type }
125    }
126
127    pub(crate) const fn we_know_expected_type(&self, found_type: &'a Type) -> Self {
128        self.with_expected_type(Some(found_type))
129    }
130}
131
132pub struct SharedState<'a> {
133    pub state: &'a mut ProgramState,
134    pub lookup_table: SymbolTable,
135    pub definition_table: SymbolTable,
136    pub modules: &'a Modules,
137    pub source_map: &'a SourceMap,
138    pub file_id: FileId,
139    pub core_symbol_table: SymbolTableRef,
140    pub type_variables: SemanticContext,
141}
142
143impl<'a> SharedState<'a> {
144    #[must_use]
145    pub fn get_symbol_table(&'a self, path: &[String]) -> Option<&'a SymbolTable> {
146        if path.is_empty() {
147            return Some(&self.lookup_table);
148        }
149        self.get_module(path).map(|module| &module.symbol_table)
150    }
151
152    #[must_use]
153    pub fn get_module(&'a self, path: &[String]) -> Option<&'a ModuleRef> {
154        let resolved_path = {
155            self.lookup_table.get_package_version(&path[0]).map_or_else(
156                || path.to_vec(),
157                |found_version| {
158                    let mut new_path = path.to_vec();
159                    let complete_name = format!("{}-{found_version}", path[0]);
160                    new_path[0] = complete_name;
161                    new_path
162                    //path.to_vec()
163                },
164            )
165        };
166
167        if path.len() == 1 {
168            if let Some(module_ref) = self.lookup_table.get_module_link(&path[0]) {
169                return Some(module_ref);
170            }
171        }
172
173        if let Some(x) = self.modules.get(&resolved_path) {
174            return Some(x);
175        }
176
177        None
178    }
179}
180
181pub struct Analyzer<'a> {
182    pub shared: SharedState<'a>,
183    scope: FunctionScopeState,
184    function_variables: Vec<VariableRef>,
185    global: FunctionScopeState,
186    module_path: Vec<String>,
187}
188
189impl Analyzer<'_> {
190    #[must_use]
191    pub const fn scopes(&self) -> &FunctionScopeState {
192        &self.scope
193    }
194}
195
196impl<'a> Analyzer<'a> {
197    pub fn new(
198        state: &'a mut ProgramState,
199        modules: &'a Modules,
200        core_symbol_table: SymbolTableRef,
201        source_map: &'a SourceMap,
202        module_path: &[String],
203        file_id: FileId,
204    ) -> Self {
205        let shared = SharedState {
206            state,
207            lookup_table: SymbolTable::new(&[]),
208            definition_table: SymbolTable::new(module_path),
209            modules,
210            core_symbol_table,
211            source_map,
212            file_id,
213            type_variables: SemanticContext::default(),
214        };
215        Self {
216            scope: FunctionScopeState::new(),
217            global: FunctionScopeState::new(),
218            shared,
219            module_path: module_path.to_vec(),
220            function_variables: Vec::new(),
221        }
222    }
223
224    fn start_function(&mut self) {
225        self.global.block_scope_stack = take(&mut self.scope.block_scope_stack);
226        self.scope = FunctionScopeState::new();
227        self.function_variables.clear();
228    }
229
230    fn stop_function(&mut self) {
231        self.scope.block_scope_stack = take(&mut self.global.block_scope_stack);
232        self.function_variables.clear();
233    }
234
235    fn analyze_if_expression(
236        &mut self,
237        condition: &swamp_ast::Expression,
238        true_expression: &swamp_ast::Expression,
239        maybe_false_expression: Option<&swamp_ast::Expression>,
240        context: &TypeContext,
241    ) -> Result<Expression, Error> {
242        let resolved_condition = self.analyze_bool_argument_expression(condition)?;
243
244        let branch_context = context;
245
246        let true_expr = self.analyze_expression(true_expression, branch_context)?;
247        let resolved_true = Box::new(true_expr);
248
249        let mut detected = context.expected_type.cloned();
250        if detected.is_none() && !matches!(resolved_true.ty, Type::Never) {
251            detected = Some(resolved_true.ty.clone());
252        }
253
254        // Analyze the false branch if it exists
255        let else_statements = if let Some(false_expression) = maybe_false_expression {
256            let else_context = branch_context.with_expected_type(detected.as_ref());
257            let else_expr = self.analyze_expression(false_expression, &else_context)?;
258            if detected.is_none() && !matches!(else_expr.ty, Type::Never) {
259                detected = Some(else_expr.ty.clone());
260            }
261
262            Some(Box::new(else_expr))
263        } else {
264            None
265        };
266
267        Ok(self.create_expr(
268            ExpressionKind::If(resolved_condition, resolved_true, else_statements),
269            detected.unwrap(),
270            &condition.node,
271        ))
272    }
273
274    fn get_text(&self, ast_node: &swamp_ast::Node) -> &str {
275        let span = Span {
276            file_id: self.shared.file_id,
277            offset: ast_node.span.offset,
278            length: ast_node.span.length,
279        };
280        self.shared.source_map.get_span_source(
281            self.shared.file_id,
282            span.offset as usize,
283            span.length as usize,
284        )
285    }
286
287    fn get_text_resolved(&self, resolved_node: &Node) -> &str {
288        let span = Span {
289            file_id: self.shared.file_id,
290            offset: resolved_node.span.offset,
291            length: resolved_node.span.length,
292        };
293        self.shared.source_map.get_span_source(
294            self.shared.file_id,
295            span.offset as usize,
296            span.length as usize,
297        )
298    }
299
300    fn get_path(&self, ident: &swamp_ast::QualifiedTypeIdentifier) -> (Vec<String>, String) {
301        let path = ident
302            .module_path
303            .as_ref()
304            .map_or_else(Vec::new, |found_path| {
305                let mut v = Vec::new();
306                for p in &found_path.0 {
307                    v.push(self.get_text(p).to_string());
308                }
309                v
310            });
311        (path, self.get_text(&ident.name.0).to_string())
312    }
313
314    fn analyze_return_type(&mut self, function: &swamp_ast::Function) -> Result<Type, Error> {
315        let ast_return_type = match function {
316            swamp_ast::Function::Internal(x) => &x.declaration.return_type,
317            swamp_ast::Function::External(x) => &x.return_type,
318        };
319
320        let resolved_return_type = match ast_return_type {
321            None => Type::Unit,
322            Some(x) => self.analyze_type(x)?,
323        };
324
325        Ok(resolved_return_type)
326    }
327
328    fn analyze_function_body_expression(
329        &mut self,
330        expression: &swamp_ast::Expression,
331        return_type: &Type,
332    ) -> Result<Expression, Error> {
333        let context = TypeContext::new_function(return_type);
334        let resolved_statement = self.analyze_expression(expression, &context)?;
335
336        Ok(resolved_statement)
337    }
338
339    fn analyze_maybe_type(&mut self, maybe_type: Option<&swamp_ast::Type>) -> Result<Type, Error> {
340        let found_type = match maybe_type {
341            None => Type::Unit,
342            Some(ast_type) => self.analyze_type(ast_type)?,
343        };
344        Ok(found_type)
345    }
346
347    fn analyze_for_pattern(
348        &mut self,
349        pattern: &swamp_ast::ForPattern,
350        key_type: Option<&Type>,
351        value_type: &Type,
352    ) -> Result<ForPattern, Error> {
353        match pattern {
354            swamp_ast::ForPattern::Single(var) => {
355                let variable_ref = self.create_local_variable(
356                    &var.identifier,
357                    Option::from(&var.is_mut),
358                    value_type,
359                )?;
360                Ok(ForPattern::Single(variable_ref))
361            }
362            swamp_ast::ForPattern::Pair(first, second) => {
363                let found_key = key_type.unwrap();
364                let first_var_ref = self.create_local_variable(
365                    &first.identifier,
366                    Option::from(&first.is_mut),
367                    found_key,
368                )?;
369                let second_var_ref = self.create_local_variable(
370                    &second.identifier,
371                    Option::from(&second.is_mut),
372                    value_type,
373                )?;
374                Ok(ForPattern::Pair(first_var_ref, second_var_ref))
375            }
376        }
377    }
378
379    fn analyze_parameters(
380        &mut self,
381        parameters: &Vec<swamp_ast::Parameter>,
382    ) -> Result<Vec<TypeForParameter>, Error> {
383        let mut resolved_parameters = Vec::new();
384        for parameter in parameters {
385            let param_type = self.analyze_type(&parameter.param_type)?;
386            resolved_parameters.push(TypeForParameter {
387                name: self.get_text(&parameter.variable.name).to_string(),
388                resolved_type: param_type,
389                is_mutable: parameter.variable.is_mutable.is_some(),
390                node: Some(ParameterNode {
391                    is_mutable: self.to_node_option(Option::from(&parameter.variable.is_mutable)),
392                    name: self.to_node(&parameter.variable.name),
393                }),
394            });
395        }
396        Ok(resolved_parameters)
397    }
398
399    /// # Errors
400    ///
401    pub fn analyze_start_chain_expression_get_mutability(
402        &mut self,
403        ast_expression: &swamp_ast::Expression,
404        expected_type: Option<&Type>,
405    ) -> Result<(Expression, bool), Error> {
406        let any_parameter_context = TypeContext::new_unsure_argument(expected_type);
407        let resolved = self.analyze_expression(ast_expression, &any_parameter_context)?;
408        let mutability = match resolved.kind {
409            ExpressionKind::VariableAccess(ref resolved_variable) => resolved_variable.is_mutable(),
410            _ => false,
411        };
412
413        Ok((resolved, mutability))
414    }
415
416    pub fn debug_expression(&self, expr: &swamp_ast::Expression) {
417        let (line, _col) = self
418            .shared
419            .source_map
420            .get_span_location_utf8(self.shared.file_id, expr.node.span.offset as usize);
421        let _source_line = self
422            .shared
423            .source_map
424            .get_source_line(self.shared.file_id, line);
425    }
426
427    /// # Errors
428    ///
429    pub fn analyze_main_expression(
430        &mut self,
431        ast_expression: &swamp_ast::Expression,
432    ) -> Result<InternalMainExpression, Error> {
433        self.start_function();
434
435        let context = TypeContext::new_anything_argument();
436        let analyzed_expr = self.analyze_expression(ast_expression, &context)?;
437        let main_expr = InternalMainExpression {
438            expression: analyzed_expr,
439            function_scope_state: self.function_variables.clone(),
440            program_unique_id: self.shared.state.allocate_internal_function_id(),
441        };
442
443        self.stop_function();
444
445        Ok(main_expr)
446    }
447
448    /// # Errors
449    ///
450    #[allow(clippy::too_many_lines)]
451    pub fn analyze_expression(
452        &mut self,
453        ast_expression: &swamp_ast::Expression,
454        context: &TypeContext,
455    ) -> Result<Expression, Error> {
456        let expr = self.analyze_expression_internal(ast_expression, context)?;
457
458        let encountered_type = expr.ty.clone();
459
460        if let Some(found_expected_type) = context.expected_type {
461            if found_expected_type.compatible_with(&encountered_type) {
462                return Ok(expr);
463            }
464
465            let result = self.types_did_not_match_try_late_coerce_expression(
466                expr,
467                found_expected_type,
468                &encountered_type,
469                &ast_expression.node,
470            )?;
471
472            return Ok(result);
473        }
474
475        Ok(expr)
476    }
477
478    /// # Errors
479    ///
480    #[allow(clippy::too_many_lines)]
481    pub fn analyze_expression_internal(
482        &mut self,
483        ast_expression: &swamp_ast::Expression,
484        context: &TypeContext,
485    ) -> Result<Expression, Error> {
486        let expression = match &ast_expression.kind {
487            // Lookups
488            swamp_ast::ExpressionKind::PostfixChain(postfix_chain) => {
489                self.analyze_postfix_chain(postfix_chain)?
490            }
491
492            swamp_ast::ExpressionKind::VariableDefinition(
493                variable,
494                maybe_annotation,
495                source_expression,
496            ) => self.analyze_create_variable(
497                variable,
498                Option::from(maybe_annotation),
499                source_expression,
500            )?,
501
502            swamp_ast::ExpressionKind::VariableAssignment(variable, source_expression) => {
503                self.analyze_variable_assignment(variable, source_expression)?
504            }
505
506            swamp_ast::ExpressionKind::DestructuringAssignment(variables, expression) => {
507                self.analyze_destructuring(&ast_expression.node, variables, expression)?
508            }
509
510            swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
511                self.analyze_identifier(qualified_identifier)?
512            }
513
514            swamp_ast::ExpressionKind::VariableReference(variable) => {
515                self.analyze_variable_reference(&variable.name)?
516            }
517
518            swamp_ast::ExpressionKind::StaticMemberFunctionReference(
519                type_identifier,
520                member_name,
521            ) => self.analyze_static_member_access(type_identifier, member_name)?,
522
523            swamp_ast::ExpressionKind::ConstantReference(constant_identifier) => {
524                self.analyze_constant_access(constant_identifier)?
525            }
526
527            swamp_ast::ExpressionKind::Assignment(location, source) => {
528                self.analyze_assignment(location, source)?
529            }
530
531            swamp_ast::ExpressionKind::CompoundAssignment(target, op, source) => {
532                self.analyze_assignment_compound(target, op, source)?
533            }
534
535            // Operator
536            swamp_ast::ExpressionKind::BinaryOp(resolved_a, operator, resolved_b) => {
537                let (resolved_op, result_type) =
538                    self.analyze_binary_op(resolved_a, operator, resolved_b)?;
539
540                self.create_expr(
541                    ExpressionKind::BinaryOp(resolved_op),
542                    result_type,
543                    &ast_expression.node,
544                )
545            }
546
547            swamp_ast::ExpressionKind::UnaryOp(operator, expression) => {
548                let (resolved_op, result_type) = self.analyze_unary_op(operator, expression)?;
549                self.create_expr(
550                    ExpressionKind::UnaryOp(resolved_op),
551                    result_type,
552                    &ast_expression.node,
553                )
554            }
555
556            swamp_ast::ExpressionKind::Block(expressions) => {
557                let (block, resulting_type) =
558                    self.analyze_block(&ast_expression.node, context, expressions)?;
559                self.create_expr(
560                    ExpressionKind::Block(block),
561                    resulting_type,
562                    &ast_expression.node,
563                )
564            }
565
566            swamp_ast::ExpressionKind::With(variable_bindings, expression) => {
567                self.analyze_with_expr(context, variable_bindings, expression)?
568            }
569
570            swamp_ast::ExpressionKind::When(variable_bindings, true_expr, else_expr) => {
571                self.analyze_when_expr(context, variable_bindings, true_expr, else_expr.as_deref())?
572            }
573
574            swamp_ast::ExpressionKind::InterpolatedString(string_parts) => {
575                let kind = ExpressionKind::InterpolatedString(
576                    self.analyze_interpolated_string(string_parts)?,
577                );
578
579                self.create_expr(kind, Type::String, &ast_expression.node)
580            }
581
582            // Creation
583            swamp_ast::ExpressionKind::NamedStructLiteral(struct_identifier, fields, has_rest) => {
584                self.analyze_struct_instantiation(struct_identifier, fields, *has_rest)?
585            }
586
587            swamp_ast::ExpressionKind::AnonymousStructLiteral(fields, rest_was_specified) => self
588                .analyze_anonymous_struct_literal(
589                &ast_expression.node,
590                fields,
591                *rest_was_specified,
592                context,
593            )?,
594
595            swamp_ast::ExpressionKind::Range(min_value, max_value, range_mode) => {
596                self.analyze_range(min_value, max_value, range_mode, &ast_expression.node)?
597            }
598
599            swamp_ast::ExpressionKind::Literal(literal) => {
600                self.analyze_complex_literal_to_expression(&ast_expression.node, literal, context)?
601            }
602
603            swamp_ast::ExpressionKind::ForLoop(
604                pattern,
605                iterable_expression,
606                guard_expr,
607                statements,
608            ) => {
609                let _analyzed_guard = if let Some(found_guard) = guard_expr {
610                    // TODO: Remove guard in for loops
611                    Some(self.analyze_bool_argument_expression(found_guard)?)
612                } else {
613                    None
614                };
615
616                let resolved_iterator =
617                    self.analyze_iterable(pattern.any_mut(), &iterable_expression.expression)?;
618
619                self.push_block_scope("for_loop");
620                let pattern = self.analyze_for_pattern(
621                    pattern,
622                    resolved_iterator.key_type.as_ref(),
623                    &resolved_iterator.value_type,
624                )?;
625                let resolved_statements = self.analyze_expression(statements, context)?;
626                self.pop_block_scope("for_loop");
627                let resolved_type = resolved_statements.ty.clone();
628                self.create_expr(
629                    ExpressionKind::ForLoop(
630                        pattern,
631                        resolved_iterator,
632                        Box::from(resolved_statements),
633                    ),
634                    resolved_type,
635                    &ast_expression.node,
636                )
637            }
638
639            swamp_ast::ExpressionKind::WhileLoop(expression, statements) => {
640                let condition = self.analyze_bool_argument_expression(expression)?;
641                //self.push_block_scope("while_loop");
642                let resolved_statements = self.analyze_expression(statements, context)?;
643                let resolved_type = resolved_statements.ty.clone();
644                //self.pop_block_scope("while_loop");
645
646                self.create_expr(
647                    ExpressionKind::WhileLoop(condition, Box::from(resolved_statements)),
648                    resolved_type,
649                    &ast_expression.node,
650                )
651            }
652
653            swamp_ast::ExpressionKind::If(expression, true_expression, maybe_false_expression) => {
654                self.analyze_if_expression(
655                    expression,
656                    true_expression,
657                    maybe_false_expression.as_deref(),
658                    context,
659                )?
660            }
661
662            swamp_ast::ExpressionKind::Match(expression, arms) => {
663                let (match_expr, return_type) = self.analyze_match(expression, context, arms)?;
664                self.create_expr(
665                    ExpressionKind::Match(match_expr),
666                    return_type,
667                    &ast_expression.node,
668                )
669            }
670            swamp_ast::ExpressionKind::Guard(guard_expressions) => {
671                self.analyze_guard(&ast_expression.node, context, guard_expressions)?
672            }
673
674            swamp_ast::ExpressionKind::Lambda(variables, expression) => {
675                self.analyze_lambda(&ast_expression.node, variables, expression, context)?
676            }
677        };
678
679        //info!(ty=%expression.ty, kind=?expression.kind,  "resolved expression");
680
681        Ok(expression)
682    }
683
684    fn get_struct_type(
685        &mut self,
686        qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
687    ) -> Result<NamedStructType, Error> {
688        let maybe_struct_type = self.analyze_named_type(qualified_type_identifier)?;
689        match maybe_struct_type {
690            Type::NamedStruct(struct_type) => Ok(struct_type),
691            _ => Err(self.create_err(
692                // For other Type variants that are not Struct
693                ErrorKind::UnknownStructTypeReference,
694                &qualified_type_identifier.name.0,
695            )),
696        }
697    }
698
699    pub(crate) fn analyze_named_type(
700        &mut self,
701        type_name_to_find: &swamp_ast::QualifiedTypeIdentifier,
702    ) -> Result<Type, Error> {
703        let (path, name) = self.get_path(type_name_to_find);
704
705        if path.is_empty() {
706            // Check if it is a type variable first!
707            if let Some(found_type) = self.shared.type_variables.resolve_type_variable(&name) {
708                return Ok(found_type);
709            }
710        }
711
712        let symbol = {
713            let maybe_symbol_table = self.shared.get_symbol_table(&path);
714            let symbol_table = maybe_symbol_table.ok_or_else(|| {
715                self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
716            })?;
717            symbol_table
718                .get_symbol(&name)
719                .ok_or_else(|| {
720                    self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
721                })?
722                .clone()
723        };
724
725        let mut analyzed_type_parameters = Vec::new();
726
727        for analyzed_type in &type_name_to_find.generic_params {
728            let ty = self.analyze_type(analyzed_type)?;
729
730            analyzed_type_parameters.push(ty);
731        }
732
733        let result_type = if analyzed_type_parameters.is_empty() {
734            match &symbol {
735                Symbol::Type(base_type) => base_type.clone(),
736                Symbol::Alias(alias_type) => alias_type.referenced_type.clone(),
737                _ => {
738                    return Err(
739                        self.create_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0)
740                    );
741                }
742            }
743        } else {
744            self.analyze_generic_type(
745                &symbol,
746                &analyzed_type_parameters,
747                &type_name_to_find.name.0,
748            )?
749        };
750
751        Ok(result_type)
752    }
753
754    fn create_default_value_for_type(
755        &mut self,
756        node: &swamp_ast::Node,
757        field_type: &Type,
758    ) -> Result<Expression, Error> {
759        let kind = match field_type {
760            Type::Bool => ExpressionKind::Literal(Literal::BoolLiteral(false)),
761            Type::Int => ExpressionKind::Literal(Literal::IntLiteral(0)),
762            Type::Float => ExpressionKind::Literal(Literal::FloatLiteral(Fp::zero())),
763            Type::String => ExpressionKind::Literal(Literal::StringLiteral(String::new())),
764            Type::Tuple(tuple_type_ref) => {
765                let mut expressions = Vec::new();
766                for resolved_type in tuple_type_ref {
767                    let expr = self.create_default_value_for_type(node, resolved_type)?;
768                    expressions.push(expr);
769                }
770                ExpressionKind::Literal(Literal::TupleLiteral(tuple_type_ref.clone(), expressions))
771            }
772            Type::Optional(_optional_type) => ExpressionKind::Literal(Literal::NoneLiteral),
773
774            Type::NamedStruct(struct_ref) => {
775                self.create_default_static_call(node, &Type::NamedStruct(struct_ref.clone()))?
776            }
777            _ => {
778                return Err(
779                    self.create_err(ErrorKind::NoDefaultImplemented(field_type.clone()), node)
780                );
781            }
782        };
783
784        let expr = self.create_expr(kind, field_type.clone(), node);
785        Ok(expr)
786    }
787
788    fn create_static_call(
789        &mut self,
790        function_name: &str,
791        arguments: &[ArgumentExpressionOrLocation],
792        node: &swamp_ast::Node,
793        ty: &Type,
794    ) -> Result<ExpressionKind, Error> {
795        self.lookup_associated_function(ty, function_name)
796            .map_or_else(
797                || {
798                    Err(self.create_err(
799                        ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
800                        node,
801                    ))
802                },
803                |function| {
804                    let kind = match &*function {
805                        Function::Internal(internal_function) => {
806                            ExpressionKind::InternalFunctionAccess(internal_function.clone())
807                        }
808                        Function::External(external_function) => {
809                            ExpressionKind::ExternalFunctionAccess(external_function.clone())
810                        }
811                    };
812
813                    let base_expr =
814                        self.create_expr(kind, Type::Function(function.signature().clone()), node);
815
816                    let empty_call_postfix = Postfix {
817                        node: self.to_node(node),
818                        ty: *function.signature().return_type.clone(),
819                        kind: PostfixKind::FunctionCall(arguments.to_vec()),
820                    };
821
822                    let kind =
823                        ExpressionKind::PostfixChain(Box::new(base_expr), vec![empty_call_postfix]);
824
825                    Ok(kind)
826                },
827            )
828    }
829
830    fn create_default_static_call(
831        &mut self,
832        node: &swamp_ast::Node,
833        ty: &Type,
834    ) -> Result<ExpressionKind, Error> {
835        self.create_static_call("default", &[], node, ty)
836    }
837
838    fn add_postfix(
839        &mut self,
840        vec: &mut Vec<Postfix>,
841        kind: PostfixKind,
842        ty: Type,
843        node: &swamp_ast::Node,
844    ) {
845        let resolved_node = self.to_node(node);
846        let postfix = Postfix {
847            node: resolved_node,
848            ty,
849            kind,
850        };
851
852        vec.push(postfix);
853    }
854
855    /// # Panics
856    ///
857    /// # Errors
858    ///
859    pub fn analyze_struct_field(
860        &mut self,
861        field_name: &swamp_ast::Node,
862        tv: &Type,
863    ) -> Result<(AnonymousStructType, usize, Type), Error> {
864        let field_name_str = self.get_text(field_name).to_string();
865
866        let anon_struct_ref = match &tv {
867            Type::NamedStruct(struct_type) => struct_type.anon_struct_type.clone(),
868            Type::AnonymousStruct(anon_struct) => anon_struct.clone(),
869            _ => return Err(self.create_err(ErrorKind::UnknownStructField, field_name)),
870        };
871
872        if let Some(found_field) = anon_struct_ref
873            .field_name_sorted_fields
874            .get(&field_name_str)
875        {
876            let index = anon_struct_ref
877                .field_name_sorted_fields
878                .get_index(&field_name_str)
879                .expect("checked earlier");
880
881            return Ok((
882                anon_struct_ref.clone(),
883                index,
884                found_field.field_type.clone(),
885            ));
886        }
887
888        Err(self.create_err(ErrorKind::UnknownStructField, field_name))
889    }
890
891    #[allow(clippy::too_many_lines)]
892    fn analyze_postfix_chain(
893        &mut self,
894        chain: &swamp_ast::PostfixChain,
895    ) -> Result<Expression, Error> {
896        let (start, is_mutable) =
897            self.analyze_start_chain_expression_get_mutability(&chain.base, None)?;
898
899        if let ExpressionKind::IntrinsicFunctionAccess(some_access) = &start.kind {
900            assert_eq!(chain.postfixes.len(), 1);
901            let call_postifx = &chain.postfixes[0];
902            if let swamp_ast::Postfix::FunctionCall(_member, _generic_arguments, arguments) =
903                &call_postifx
904            {
905                let resolved_arguments = self.analyze_and_verify_parameters(
906                    &start.node,
907                    &some_access.signature.parameters,
908                    arguments,
909                )?;
910
911                return Ok(self.create_expr(
912                    ExpressionKind::IntrinsicCallEx(
913                        some_access.intrinsic.clone(),
914                        resolved_arguments,
915                    ),
916                    *some_access.signature.return_type.clone(),
917                    &chain.base.node,
918                ));
919            }
920            panic!("not sure here");
921        }
922
923        let mut tv = TypeWithMut {
924            resolved_type: start.ty.clone(),
925            is_mutable,
926        };
927
928        let mut uncertain = false;
929
930        let mut suffixes = Vec::new();
931
932        for item in &chain.postfixes {
933            match item {
934                swamp_ast::Postfix::FieldAccess(field_name) => {
935                    let (struct_type_ref, index, return_type) =
936                        self.analyze_struct_field(&field_name.clone(), &tv.resolved_type)?;
937                    self.add_postfix(
938                        &mut suffixes,
939                        PostfixKind::StructField(struct_type_ref.clone(), index),
940                        return_type.clone(),
941                        field_name,
942                    );
943
944                    tv.resolved_type = return_type.clone();
945                    // keep previous `is_mutable`
946                }
947                swamp_ast::Postfix::MemberCall(member_name, generic_arguments, ast_arguments) => {
948                    let member_name_str = self.get_text(member_name).to_string();
949
950                    if let Some(_found_member) = self
951                        .shared
952                        .state
953                        .instantiator
954                        .associated_impls
955                        .get_member_function(&tv.resolved_type, &member_name_str)
956                    {
957                        let return_type = self.analyze_postfix_member_call(
958                            &tv.resolved_type,
959                            tv.is_mutable,
960                            member_name,
961                            generic_arguments.clone(),
962                            ast_arguments,
963                            &mut suffixes,
964                        )?;
965
966                        //self.add_postfix(&mut suffixes, kind, return_type.clone(), member_name);
967                        tv.resolved_type = return_type.clone();
968                        tv.is_mutable = false;
969                    } else {
970                        return Err(self.create_err(ErrorKind::UnknownMemberFunction, member_name));
971                    }
972                }
973                swamp_ast::Postfix::FunctionCall(node, _generic_arguments, arguments) => {
974                    if let Type::Function(signature) = &tv.resolved_type {
975                        let resolved_node = self.to_node(node);
976                        let resolved_arguments = self.analyze_and_verify_parameters(
977                            &resolved_node,
978                            &signature.parameters,
979                            arguments,
980                        )?;
981
982                        let call_kind = PostfixKind::FunctionCall(resolved_arguments);
983
984                        self.add_postfix(
985                            &mut suffixes,
986                            call_kind,
987                            *signature.return_type.clone(),
988                            node,
989                        );
990
991                        tv.resolved_type = *signature.return_type.clone();
992                        tv.is_mutable = false;
993                    } else {
994                        panic!("{}", &format!("what is this type {:?} ", tv.resolved_type))
995                    }
996                }
997
998                swamp_ast::Postfix::Subscript(index_expr) => {
999                    let _collection_type = tv.resolved_type.clone();
1000
1001                    let temp_lookup_context = TypeContext::new_anything_argument();
1002                    let temp_analyzed_expr =
1003                        self.analyze_expression(index_expr, &temp_lookup_context)?;
1004
1005                    let mut subscript_function_name = "subscript";
1006
1007                    if let Type::NamedStruct(named_struct) = temp_analyzed_expr.ty {
1008                        if named_struct.assigned_name == "Range"
1009                            && named_struct.module_path == vec!["core-0.0.0".to_string()]
1010                        {
1011                            subscript_function_name = "subscript_range";
1012                        }
1013                    };
1014
1015                    if let Some(found) = self
1016                        .shared
1017                        .state
1018                        .instantiator
1019                        .associated_impls
1020                        .get_member_function(&tv.resolved_type, subscript_function_name)
1021                        .cloned()
1022                    {
1023                        let cloned = found.clone();
1024                        let required_type = &found.signature().parameters[1].resolved_type;
1025                        let subscript_lookup_context = TypeContext::new_argument(&required_type);
1026                        let analyzed_expr =
1027                            self.analyze_expression(index_expr, &subscript_lookup_context)?;
1028
1029                        let return_type = *found.signature().return_type.clone();
1030
1031                        let argument = ArgumentExpressionOrLocation::Expression(analyzed_expr);
1032                        self.add_postfix(
1033                            &mut suffixes,
1034                            PostfixKind::MemberCall(cloned, vec![argument]),
1035                            return_type.clone(),
1036                            &index_expr.node,
1037                        );
1038                        tv.resolved_type = return_type.clone();
1039                    } else {
1040                        return Err(
1041                            self.create_err(ErrorKind::MissingSubscriptMember, &index_expr.node)
1042                        );
1043                    }
1044                }
1045
1046                swamp_ast::Postfix::NoneCoalescingOperator(default_expr) => {
1047                    let unwrapped_type = if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1048                        unwrapped_type
1049                    } else if uncertain {
1050                        &tv.resolved_type
1051                    } else {
1052                        return Err(
1053                            self.create_err(ErrorKind::CanNotNoneCoalesce, &default_expr.node)
1054                        );
1055                    };
1056
1057                    let unwrapped_type_context = TypeContext::new_argument(unwrapped_type);
1058                    let resolved_default_expr =
1059                        self.analyze_expression(default_expr, &unwrapped_type_context)?;
1060                    self.add_postfix(
1061                        &mut suffixes,
1062                        PostfixKind::NoneCoalescingOperator(resolved_default_expr),
1063                        unwrapped_type.clone(),
1064                        &default_expr.node,
1065                    );
1066                    tv.resolved_type = unwrapped_type.clone();
1067                    uncertain = false; // the chain is safe, because this will always solve None
1068                }
1069
1070                swamp_ast::Postfix::OptionalChainingOperator(option_node) => {
1071                    if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1072                        uncertain = true;
1073                        self.add_postfix(
1074                            &mut suffixes,
1075                            PostfixKind::OptionalChainingOperator,
1076                            *unwrapped_type.clone(),
1077                            option_node,
1078                        );
1079                        tv.resolved_type = *unwrapped_type.clone();
1080                    } else {
1081                        return Err(self.create_err(ErrorKind::ExpectedOptional, option_node));
1082                    }
1083                }
1084            }
1085        }
1086
1087        if uncertain {
1088            if let Type::Optional(_) = tv.resolved_type {
1089            } else {
1090                tv.resolved_type = Type::Optional(Box::from(tv.resolved_type.clone()));
1091            }
1092        }
1093
1094        Ok(self.create_expr(
1095            ExpressionKind::PostfixChain(Box::new(start), suffixes),
1096            tv.resolved_type,
1097            &chain.base.node,
1098        ))
1099    }
1100
1101    fn analyze_bool_argument_expression(
1102        &mut self,
1103        expression: &swamp_ast::Expression,
1104    ) -> Result<BooleanExpression, Error> {
1105        let bool_context = TypeContext::new_argument(&Type::Bool);
1106        let resolved_expression = self.analyze_expression(expression, &bool_context)?;
1107        let expr_type = resolved_expression.ty.clone();
1108
1109        let bool_expression = match expr_type {
1110            Type::Bool => resolved_expression,
1111            Type::Optional(_) => self.create_expr(
1112                ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1113                Type::Bool,
1114                &expression.node,
1115            ),
1116            _ => {
1117                return Err(self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node));
1118            }
1119        };
1120
1121        Ok(BooleanExpression {
1122            expression: Box::from(bool_expression),
1123        })
1124    }
1125
1126    fn analyze_iterable(
1127        &mut self,
1128        force_mut: Option<swamp_ast::Node>,
1129        expression: &swamp_ast::MutableOrImmutableExpression,
1130    ) -> Result<Iterable, Error> {
1131        let any_context = TypeContext::new_anything_argument();
1132        let resolved_expression: MutOrImmutableExpression = if force_mut.is_some() {
1133            let resolved_node = self.to_node(&force_mut.unwrap());
1134            MutOrImmutableExpression {
1135                expression_or_location: ArgumentExpressionOrLocation::Location(
1136                    self.analyze_to_location(
1137                        &expression.expression,
1138                        &any_context,
1139                        LocationSide::Rhs,
1140                    )?,
1141                ),
1142                is_mutable: Some(resolved_node),
1143            }
1144        } else {
1145            self.analyze_mut_or_immutable_expression(expression, &any_context, LocationSide::Rhs)?
1146        };
1147
1148        let resolved_type = &resolved_expression.ty().clone();
1149        let (key_type, value_type): (Option<Type>, Type) = match resolved_type {
1150            Type::String => (Some(Type::Int), Type::String),
1151
1152            _ => {
1153                if let Some(found_iter_fn) = self
1154                    .shared
1155                    .state
1156                    .instantiator
1157                    .associated_impls
1158                    .get_internal_member_function(resolved_type, "iter")
1159                {
1160                    let ret_type = found_iter_fn.signature.signature.return_type.clone();
1161                    match *ret_type {
1162                        Type::Tuple(tuple_items) => {
1163                            (Some(tuple_items[0].clone()), tuple_items[1].clone())
1164                        }
1165                        _ => {
1166                            return Err(self.create_err(
1167                                ErrorKind::NotAnIterator,
1168                                &expression.expression.node,
1169                            ));
1170                        }
1171                    }
1172                } else {
1173                    return Err(
1174                        self.create_err(ErrorKind::NotAnIterator, &expression.expression.node)
1175                    );
1176                }
1177            }
1178        };
1179
1180        Ok(Iterable {
1181            key_type,
1182            value_type,
1183            resolved_expression: Box::new(resolved_expression),
1184        })
1185    }
1186
1187    fn analyze_argument_expressions(
1188        &mut self,
1189        expected_type: Option<&Type>,
1190        ast_expressions: &[swamp_ast::Expression],
1191    ) -> Result<Vec<Expression>, Error> {
1192        let mut resolved_expressions = Vec::new();
1193        let argument_expressions_context = TypeContext::new_unsure_argument(expected_type);
1194        for expression in ast_expressions {
1195            resolved_expressions
1196                .push(self.analyze_expression(expression, &argument_expressions_context)?);
1197        }
1198        Ok(resolved_expressions)
1199    }
1200
1201    fn analyze_block(
1202        &mut self,
1203        _node: &swamp_ast::Node,
1204        context: &TypeContext,
1205        ast_expressions: &[swamp_ast::Expression],
1206    ) -> Result<(Vec<Expression>, Type), Error> {
1207        if ast_expressions.is_empty() {
1208            return Ok((vec![], Type::Unit));
1209        }
1210
1211        self.push_block_scope("block");
1212
1213        let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1214
1215        for expression in &ast_expressions[..ast_expressions.len() - 1] {
1216            let stmt_context = context.with_expected_type(Some(&Type::Unit));
1217            let expr = self.analyze_expression(expression, &stmt_context)?;
1218
1219            if matches!(expr.ty, Type::Never) {
1220                resolved_expressions.push(expr);
1221                return Ok((resolved_expressions, Type::Never));
1222            }
1223
1224            resolved_expressions.push(expr);
1225        }
1226
1227        // Process the last expression - it determines the block's type
1228        let last_expr =
1229            self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context)?;
1230        let last_type = last_expr.ty.clone();
1231        resolved_expressions.push(last_expr);
1232
1233        self.pop_block_scope("block");
1234
1235        Ok((resolved_expressions, last_type))
1236    }
1237
1238    fn analyze_interpolated_string(
1239        &mut self,
1240        string_parts: &[swamp_ast::StringPart],
1241    ) -> Result<Vec<StringPart>, Error> {
1242        let mut resolved_parts = Vec::new();
1243        for part in string_parts {
1244            let resolved_string_part = match part {
1245                swamp_ast::StringPart::Literal(string_node, processed_string) => {
1246                    StringPart::Literal(self.to_node(string_node), processed_string.to_string())
1247                }
1248                swamp_ast::StringPart::Interpolation(expression, format_specifier) => {
1249                    let any_context = TypeContext::new_anything_argument();
1250                    let expr = self.analyze_expression(expression, &any_context)?;
1251                    let resolved_format_specifier =
1252                        self.analyze_format_specifier(Option::from(format_specifier));
1253                    StringPart::Interpolation(expr, resolved_format_specifier)
1254                }
1255            };
1256
1257            resolved_parts.push(resolved_string_part);
1258        }
1259
1260        Ok(resolved_parts)
1261    }
1262
1263    pub(crate) fn analyze_identifier(
1264        &self,
1265        qualified_func_name: &swamp_ast::QualifiedIdentifier,
1266    ) -> Result<Expression, Error> {
1267        // Must check variable first, since that is more intuitive for the user.
1268        // local variables before other functions
1269        if qualified_func_name.module_path.is_none()
1270            && qualified_func_name.generic_params.is_empty()
1271        {
1272            if let Some(found_variable) = self.try_find_variable(&qualified_func_name.name) {
1273                return Ok(self.create_expr(
1274                    ExpressionKind::VariableAccess(found_variable.clone()),
1275                    found_variable.resolved_type.clone(),
1276                    &qualified_func_name.name,
1277                ));
1278            }
1279        }
1280
1281        let path = self.get_module_path(qualified_func_name.module_path.as_ref());
1282        let function_name = self.get_text(&qualified_func_name.name);
1283
1284        if let Some(found_table) = self.shared.get_symbol_table(&path) {
1285            if let Some(found_func) = found_table.get_function(function_name) {
1286                let (kind, signature) = match found_func {
1287                    FuncDef::Internal(internal_fn) => (
1288                        ExpressionKind::InternalFunctionAccess(internal_fn.clone()),
1289                        &internal_fn.signature.signature,
1290                    ),
1291                    FuncDef::External(external_fn) => (
1292                        ExpressionKind::ExternalFunctionAccess(external_fn.clone()),
1293                        &external_fn.signature,
1294                    ),
1295                    // Can not have a reference to an intrinsic function
1296                    FuncDef::Intrinsic(intrinsic_fn) => (
1297                        ExpressionKind::IntrinsicFunctionAccess(intrinsic_fn.clone()),
1298                        &intrinsic_fn.signature,
1299                    ),
1300                };
1301
1302                return Ok(self.create_expr(
1303                    kind,
1304                    Type::Function(signature.clone()),
1305                    &qualified_func_name.name,
1306                ));
1307            }
1308        }
1309        Err(self.create_err(
1310            ErrorKind::UnknownIdentifier(function_name.to_string()),
1311            &qualified_func_name.name,
1312        ))
1313    }
1314
1315    // The ast assumes it is something similar to a variable, but it can be a function reference as well.
1316    fn analyze_variable_reference(&self, var_node: &swamp_ast::Node) -> Result<Expression, Error> {
1317        if let Some(found_variable) = self.try_find_variable(var_node) {
1318            return Ok(self.create_expr(
1319                ExpressionKind::VariableAccess(found_variable.clone()),
1320                found_variable.resolved_type.clone(),
1321                var_node,
1322            ));
1323        }
1324        let text = self.get_text(var_node);
1325        Err(self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node))
1326    }
1327
1328    fn analyze_slice_type_helper(
1329        &mut self,
1330        _node: &swamp_ast::Node,
1331        items: &[swamp_ast::Expression],
1332    ) -> Result<(Type, Vec<Expression>), Error> {
1333        let expressions = self.analyze_argument_expressions(None, items)?;
1334        let element_type = if expressions.is_empty() {
1335            Type::Unit
1336        } else {
1337            expressions[0].ty.clone()
1338        };
1339
1340        Ok((element_type, expressions))
1341    }
1342
1343    fn push_block_scope(&mut self, _debug_str: &str) {
1344        self.scope.block_scope_stack.push(BlockScope {
1345            mode: BlockScopeMode::Open,
1346            variables: SeqMap::default(),
1347        });
1348    }
1349
1350    fn pop_block_scope(&mut self, _debug_str: &str) {
1351        self.scope.block_scope_stack.pop();
1352    }
1353
1354    fn push_closed_block_scope(&mut self) {
1355        self.scope.block_scope_stack.push(BlockScope {
1356            mode: BlockScopeMode::Closed,
1357            variables: SeqMap::default(),
1358        });
1359    }
1360
1361    fn pop_closed_block_scope(&mut self) {
1362        self.scope.block_scope_stack.pop();
1363    }
1364
1365    fn analyze_enum_variant_ref(
1366        &self,
1367        qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
1368        variant_name: &swamp_ast::LocalTypeIdentifier,
1369    ) -> Result<EnumVariantType, Error> {
1370        let variant_name_string = self.get_text(&variant_name.0).to_string();
1371        self.get_enum_variant_type(qualified_type_identifier, &variant_name_string)
1372    }
1373
1374    fn analyze_match(
1375        &mut self,
1376        scrutinee: &swamp_ast::MutableOrImmutableExpression,
1377        default_context: &TypeContext,
1378        arms: &Vec<swamp_ast::MatchArm>,
1379    ) -> Result<(Match, Type), Error> {
1380        let mut known_type = default_context.expected_type.cloned();
1381        let own_context = default_context.clone();
1382        // Analyze the scrutinee with no specific expected type
1383        let scrutinee_context = TypeContext::new_anything_argument();
1384        let resolved_scrutinee = self.analyze_mut_or_immutable_expression(
1385            scrutinee,
1386            &scrutinee_context,
1387            LocationSide::Rhs,
1388        )?;
1389        let scrutinee_type = resolved_scrutinee.ty().clone();
1390
1391        // Ensure we have at least one arm
1392        if arms.is_empty() {
1393            return Err(self.create_err(ErrorKind::EmptyMatch, &scrutinee.expression.node));
1394        }
1395
1396        let mut resolved_arms = Vec::with_capacity(arms.len());
1397
1398        for arm in arms {
1399            let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
1400                arm,
1401                &resolved_scrutinee,
1402                &own_context.with_expected_type(known_type.as_ref()),
1403                &scrutinee_type,
1404            )?;
1405
1406            if known_type.is_none() && !matches!(resolved_arm.expression.ty, Type::Never) {
1407                known_type = Some(resolved_arm.expression.ty.clone());
1408            }
1409            resolved_arms.push(resolved_arm);
1410        }
1411
1412        known_type.map_or_else(
1413            || {
1414                Err(self.create_err(
1415                    ErrorKind::MatchArmsMustHaveTypes,
1416                    &scrutinee.expression.node,
1417                ))
1418            },
1419            |encountered_type| {
1420                if matches!(encountered_type, Type::Never) {
1421                    Err(self.create_err(
1422                        ErrorKind::IncompatibleTypes {
1423                            expected: Type::Never,
1424                            found: encountered_type,
1425                        },
1426                        &scrutinee.expression.node,
1427                    ))
1428                } else {
1429                    Ok((
1430                        Match {
1431                            expression: Box::new(resolved_scrutinee),
1432                            arms: resolved_arms,
1433                        },
1434                        encountered_type,
1435                    ))
1436                }
1437            },
1438        )
1439    }
1440
1441    fn analyze_arm(
1442        &mut self,
1443        arm: &swamp_ast::MatchArm,
1444        _expression: &MutOrImmutableExpression,
1445        type_context: &TypeContext,
1446        expected_condition_type: &Type,
1447    ) -> Result<(MatchArm, bool), Error> {
1448        let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
1449            self.analyze_pattern(&arm.pattern, expected_condition_type)?;
1450
1451        let resolved_expression = self.analyze_expression(&arm.expression, type_context)?;
1452        if scope_was_pushed {
1453            self.pop_block_scope("analyze_arm");
1454        }
1455
1456        let resolved_type = resolved_expression.ty.clone();
1457
1458        Ok((
1459            MatchArm {
1460                pattern: resolved_pattern,
1461                expression: Box::from(resolved_expression),
1462                expression_type: resolved_type,
1463            },
1464            anyone_wants_mutable,
1465        ))
1466    }
1467
1468    fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
1469        let text = text.replace('_', "");
1470        text.strip_prefix("0x").map_or_else(
1471            || {
1472                text.strip_prefix("-0x").map_or_else(
1473                    || text.parse::<i32>(),
1474                    |rest| i32::from_str_radix(rest, 16).map(|x| -x),
1475                )
1476            },
1477            |rest| i32::from_str_radix(rest, 16),
1478        )
1479    }
1480
1481    fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
1482        text.parse::<f32>()
1483    }
1484
1485    fn analyze_pattern_literal(
1486        &mut self,
1487        node: &swamp_ast::Node,
1488        ast_literal: &swamp_ast::LiteralKind,
1489        expected_condition_type: &Type,
1490    ) -> Result<NormalPattern, Error> {
1491        let required_condition_type_context = TypeContext::new_argument(expected_condition_type);
1492        let (literal, ty) =
1493            self.analyze_literal(node, ast_literal, &required_condition_type_context)?;
1494
1495        if !ty.compatible_with(expected_condition_type) {
1496            return Err(self.create_err(
1497                ErrorKind::IncompatibleTypes {
1498                    expected: expected_condition_type.clone(),
1499                    found: ty,
1500                },
1501                node,
1502            ));
1503        }
1504
1505        Ok(NormalPattern::Literal(literal))
1506    }
1507
1508    const fn to_node(&self, node: &swamp_ast::Node) -> Node {
1509        Node {
1510            span: Span {
1511                file_id: self.shared.file_id,
1512                offset: node.span.offset,
1513                length: node.span.length,
1514            },
1515        }
1516    }
1517
1518    fn get_module_path(&self, module_path: Option<&swamp_ast::ModulePath>) -> Vec<String> {
1519        module_path.as_ref().map_or_else(Vec::new, |found| {
1520            let mut strings = Vec::new();
1521            for path_item in &found.0 {
1522                strings.push(self.get_text(path_item).to_string());
1523            }
1524            strings
1525        })
1526    }
1527
1528    fn get_enum_variant_type(
1529        &self,
1530        qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
1531        variant_name: &str,
1532    ) -> Result<EnumVariantType, Error> {
1533        let (symbol_table, enum_name) =
1534            self.get_symbol_table_and_name(qualified_type_identifier)?;
1535        symbol_table
1536            .get_enum_variant_type(&enum_name, variant_name)
1537            .ok_or_else(|| {
1538                self.create_err(
1539                    ErrorKind::UnknownEnumVariantType,
1540                    &qualified_type_identifier.name.0,
1541                )
1542            })
1543    }
1544
1545    pub(crate) fn get_symbol_table_and_name(
1546        &self,
1547        type_identifier: &swamp_ast::QualifiedTypeIdentifier,
1548    ) -> Result<(&SymbolTable, String), Error> {
1549        let path = self.get_module_path(type_identifier.module_path.as_ref());
1550        let name = self.get_text(&type_identifier.name.0).to_string();
1551
1552        let maybe_symbol_table = self.shared.get_symbol_table(&path);
1553        maybe_symbol_table.map_or_else(
1554            || Err(self.create_err(ErrorKind::UnknownModule, &type_identifier.name.0)),
1555            |symbol_table| Ok((symbol_table, name)),
1556        )
1557    }
1558
1559    const fn analyze_compound_operator(
1560        &self,
1561        ast_operator: &swamp_ast::CompoundOperator,
1562    ) -> CompoundOperator {
1563        let resolved_node = self.to_node(&ast_operator.node);
1564        let resolved_kind = match ast_operator.kind {
1565            swamp_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
1566            swamp_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
1567            swamp_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
1568            swamp_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
1569            swamp_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
1570        };
1571
1572        CompoundOperator {
1573            node: resolved_node,
1574            kind: resolved_kind,
1575        }
1576    }
1577
1578    const fn to_node_option(&self, maybe_node: Option<&swamp_ast::Node>) -> Option<Node> {
1579        match maybe_node {
1580            None => None,
1581            Some(node) => Some(self.to_node(node)),
1582        }
1583    }
1584
1585    const fn analyze_format_specifier(
1586        &self,
1587        ast_format_specifier: Option<&swamp_ast::FormatSpecifier>,
1588    ) -> Option<FormatSpecifier> {
1589        let f = match ast_format_specifier {
1590            None => return None,
1591            Some(ast_format) => match ast_format {
1592                swamp_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
1593                    node: self.to_node(node),
1594                    kind: FormatSpecifierKind::LowerHex,
1595                },
1596                swamp_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
1597                    node: self.to_node(node),
1598                    kind: FormatSpecifierKind::UpperHex,
1599                },
1600                swamp_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
1601                    node: self.to_node(node),
1602                    kind: FormatSpecifierKind::Binary,
1603                },
1604                swamp_ast::FormatSpecifier::Float(node) => FormatSpecifier {
1605                    node: self.to_node(node),
1606                    kind: FormatSpecifierKind::Float,
1607                },
1608                swamp_ast::FormatSpecifier::Precision(value, node, x) => {
1609                    let (precision_type, precision_node) = match x {
1610                        swamp_ast::PrecisionType::Float(node) => {
1611                            (PrecisionType::Float, self.to_node(node))
1612                        }
1613                        swamp_ast::PrecisionType::String(node) => {
1614                            (PrecisionType::String, self.to_node(node))
1615                        }
1616                    };
1617                    FormatSpecifier {
1618                        node: self.to_node(node),
1619                        kind: FormatSpecifierKind::Precision(
1620                            *value,
1621                            precision_node,
1622                            precision_type,
1623                        ),
1624                    }
1625                }
1626            },
1627        };
1628
1629        Some(f)
1630    }
1631
1632    fn analyze_with_expr(
1633        &mut self,
1634        context: &TypeContext,
1635        variables: &[swamp_ast::VariableBinding],
1636        expression: &swamp_ast::Expression,
1637    ) -> Result<Expression, Error> {
1638        let mut variable_expressions = Vec::new();
1639
1640        for variable in variables {
1641            let any_context = TypeContext::new_anything_argument();
1642            let var = self.analyze_mut_or_immutable_expression(
1643                &variable.expression,
1644                &any_context,
1645                LocationSide::Rhs,
1646            )?;
1647
1648            variable_expressions.push(var);
1649        }
1650
1651        self.push_closed_block_scope();
1652        let mut expressions = Vec::new();
1653        for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
1654            let initialize_variable_expression = self.create_variable_binding_for_with(
1655                &variable_binding.variable,
1656                resolved_expression,
1657            )?;
1658            expressions.push(initialize_variable_expression);
1659        }
1660
1661        let resolved_expression = self.analyze_expression(expression, context)?;
1662        let block_type = resolved_expression.ty.clone();
1663        expressions.push(resolved_expression);
1664
1665        let block_expression_kind = ExpressionKind::Block(expressions);
1666        self.pop_closed_block_scope();
1667
1668        let block_expr = self.create_expr(block_expression_kind, block_type, &expression.node);
1669        Ok(block_expr)
1670    }
1671
1672    fn analyze_when_expr(
1673        &mut self,
1674        context: &TypeContext,
1675        variables: &[swamp_ast::WhenBinding],
1676        true_expr: &swamp_ast::Expression,
1677        else_expr: Option<&swamp_ast::Expression>,
1678    ) -> Result<Expression, Error> {
1679        // Since we are making new variable bindings, we have to push a scope for them
1680        self.push_block_scope("when");
1681        let mut bindings = Vec::new();
1682        for variable_binding in variables {
1683            let mut_expr = if let Some(found_expr) = &variable_binding.expression {
1684                let any_context = TypeContext::new_anything_argument();
1685                self.analyze_mut_or_immutable_expression(
1686                    found_expr,
1687                    &any_context,
1688                    LocationSide::Rhs,
1689                )?
1690            } else {
1691                let same_var = self.find_variable(&variable_binding.variable)?;
1692
1693                let is_mutable = same_var.mutable_node.clone();
1694                let argument_expression = if same_var.is_mutable() {
1695                    let loc = SingleLocationExpression {
1696                        kind: SingleLocationExpressionKind::MutVariableRef,
1697                        node: self.to_node(&variable_binding.variable.name),
1698                        ty: Type::MutableReference(Box::from(same_var.resolved_type.clone())),
1699                        starting_variable: same_var,
1700                        access_chain: vec![],
1701                    };
1702                    ArgumentExpressionOrLocation::Location(loc)
1703                } else {
1704                    let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
1705                    let generated_expression = self.create_expr(
1706                        generated_expr_kind,
1707                        same_var.resolved_type.clone(),
1708                        &variable_binding.variable.name,
1709                    );
1710                    ArgumentExpressionOrLocation::Expression(generated_expression)
1711                };
1712
1713                MutOrImmutableExpression {
1714                    expression_or_location: argument_expression,
1715                    is_mutable,
1716                }
1717            };
1718
1719            let ty = mut_expr.ty();
1720
1721            if let Type::Optional(found_ty) = ty {
1722                let variable_ref = self.create_variable(&variable_binding.variable, found_ty)?;
1723
1724                let binding = WhenBinding {
1725                    variable: variable_ref,
1726                    expr: mut_expr,
1727                };
1728                bindings.push(binding);
1729            } else {
1730                return Err(self.create_err(ErrorKind::ExpectedOptional, &true_expr.node));
1731            }
1732        }
1733
1734        let resolved_true = self.analyze_expression(true_expr, context)?;
1735        let block_type = resolved_true.ty.clone();
1736
1737        self.pop_block_scope("when");
1738
1739        let maybe_resolved_else = if let Some(found_else) = else_expr {
1740            let block_type_for_true_context = context.we_know_expected_type(&block_type);
1741            Some(Box::new(self.analyze_expression(
1742                found_else,
1743                &block_type_for_true_context,
1744            )?))
1745        } else {
1746            None
1747        };
1748
1749        let when_kind =
1750            ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
1751
1752        let block_expr = self.create_expr(when_kind, block_type, &true_expr.node);
1753        Ok(block_expr)
1754    }
1755
1756    fn analyze_guard(
1757        &mut self,
1758        node: &swamp_ast::Node,
1759        context: &TypeContext,
1760        guard_expressions: &Vec<swamp_ast::GuardExpr>,
1761    ) -> Result<Expression, Error> {
1762        let mut guards = Vec::new();
1763        let mut found_wildcard = None;
1764        let mut detected_type = context.expected_type.cloned();
1765
1766        for guard in guard_expressions {
1767            let resolved_condition = match &guard.clause {
1768                swamp_ast::GuardClause::Wildcard(x) => {
1769                    if found_wildcard.is_some() {
1770                        return Err(
1771                            self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node)
1772                        );
1773                    }
1774                    found_wildcard = Some(x);
1775                    None
1776                }
1777                swamp_ast::GuardClause::Expression(clause_expr) => {
1778                    if found_wildcard.is_some() {
1779                        return Err(self.create_err(ErrorKind::WildcardMustBeLastInGuard, node));
1780                    }
1781                    Some(self.analyze_bool_argument_expression(clause_expr)?)
1782                }
1783            };
1784
1785            let resolved_result = self.analyze_expression(
1786                &guard.result,
1787                &context.with_expected_type(detected_type.as_ref()),
1788            )?;
1789            let ty = resolved_result.ty.clone();
1790            if detected_type.is_none() && !matches!(ty, Type::Never) {
1791                detected_type = Some(ty.clone());
1792            }
1793
1794            guards.push(Guard {
1795                condition: resolved_condition,
1796                result: resolved_result,
1797            });
1798        }
1799
1800        if found_wildcard.is_none() {
1801            return Err(self.create_err(ErrorKind::GuardMustHaveWildcard, node));
1802        }
1803
1804        let kind = ExpressionKind::Guard(guards);
1805
1806        detected_type.map_or_else(
1807            || Err(self.create_err(ErrorKind::GuardHasNoType, node)),
1808            |found_expecting_type| {
1809                let expr = self.create_expr(kind, found_expecting_type, node);
1810                Ok(expr)
1811            },
1812        )
1813    }
1814
1815    fn analyze_lambda(
1816        &mut self,
1817        node: &swamp_ast::Node,
1818        variables: &[swamp_ast::Variable],
1819        ast_expr: &swamp_ast::Expression,
1820        context: &TypeContext,
1821    ) -> Result<Expression, Error> {
1822        let Type::Function(signature) = &context.expected_type.unwrap() else {
1823            return Err(self.create_err(ErrorKind::ExpectedLambda, node));
1824        };
1825
1826        let return_block_type = TypeContext::new_argument(&signature.return_type);
1827
1828        self.push_block_scope("lambda");
1829
1830        let arity_required = signature.parameters.len();
1831        let variable_types_to_create = if variables.len() == arity_required {
1832            &signature.parameters
1833        } else if variables.len() + 1 == arity_required {
1834            &signature.parameters[1..].to_vec()
1835        } else {
1836            return Err(self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node));
1837        };
1838
1839        let mut resolved_variables = Vec::new();
1840        for (variable, variable_type) in variables.iter().zip(variable_types_to_create) {
1841            let variable_ref = self.create_local_variable(
1842                &variable.name,
1843                Some(node),
1844                &variable_type.resolved_type,
1845            )?;
1846            resolved_variables.push(variable_ref);
1847        }
1848
1849        let analyzed_expression = self.analyze_expression(ast_expr, &return_block_type)?;
1850
1851        self.pop_block_scope("lambda");
1852
1853        Ok(self.create_expr(
1854            ExpressionKind::Lambda(resolved_variables, Box::new(analyzed_expression)),
1855            Type::Function(signature.clone()),
1856            node,
1857        ))
1858    }
1859
1860    /// # Errors
1861    ///
1862    pub fn analyze_variable_assignment(
1863        &mut self,
1864        variable: &swamp_ast::Variable,
1865        source_expression: &swamp_ast::MutableOrImmutableExpression,
1866    ) -> Result<Expression, Error> {
1867        let maybe_found_variable = self.try_find_variable(&variable.name);
1868
1869        let required_type = maybe_found_variable
1870            .as_ref()
1871            .map(|found_variable| found_variable.resolved_type.clone());
1872
1873        let context = TypeContext::new_unsure_argument(required_type.as_ref());
1874
1875        let source_expr = self.analyze_mut_or_immutable_expression(
1876            source_expression,
1877            &context,
1878            LocationSide::Rhs,
1879        )?;
1880        let ty = source_expr.ty().clone();
1881        if !ty.is_concrete() {
1882            return Err(self.create_err(ErrorKind::VariableTypeMustBeConcrete, &variable.name));
1883        }
1884
1885        let kind: ExpressionKind = if let Some(found_var) = maybe_found_variable {
1886            if !found_var.is_mutable() {
1887                return Err(self.create_err(ErrorKind::VariableIsNotMutable, &variable.name));
1888            }
1889            if !found_var.resolved_type.assignable_type(&ty) {
1890                return Err(self.create_err(
1891                    ErrorKind::IncompatibleTypes {
1892                        expected: ty,
1893                        found: found_var.resolved_type.clone(),
1894                    },
1895                    &variable.name,
1896                ));
1897            }
1898            ExpressionKind::VariableReassignment(found_var, Box::from(source_expr))
1899        } else {
1900            let new_var = self.create_variable(variable, &ty)?;
1901            ExpressionKind::VariableDefinition(new_var, Box::from(source_expr))
1902        };
1903
1904        Ok(self.create_expr(kind, Type::Unit, &variable.name))
1905    }
1906
1907    fn analyze_create_variable(
1908        &mut self,
1909        var: &swamp_ast::Variable,
1910        annotation_type: Option<&swamp_ast::Type>,
1911        source_expression: &swamp_ast::MutableOrImmutableExpression,
1912    ) -> Result<Expression, Error> {
1913        let ty = if let Some(found_ast_type) = annotation_type {
1914            Some(self.analyze_type(found_ast_type)?)
1915        } else {
1916            None
1917        };
1918
1919        let unsure_arg_context = TypeContext::new_unsure_argument(ty.as_ref());
1920
1921        let resolved_source = self.analyze_mut_or_immutable_expression(
1922            source_expression,
1923            &unsure_arg_context,
1924            LocationSide::Rhs,
1925        )?;
1926
1927        let var_ref = self.create_local_variable(
1928            &var.name,
1929            Option::from(&var.is_mutable),
1930            resolved_source.ty(),
1931        )?;
1932
1933        let resolved_type = resolved_source.ty().clone();
1934        assert_ne!(resolved_type, Type::Unit);
1935        let kind = ExpressionKind::VariableDefinition(var_ref, Box::from(resolved_source));
1936
1937        let resolved_expr = self.create_expr(kind, Type::Unit, &var.name);
1938
1939        Ok(resolved_expr)
1940    }
1941
1942    fn add_location_item(
1943        &mut self,
1944        vec: &mut Vec<LocationAccess>,
1945        kind: LocationAccessKind,
1946        ty: Type,
1947        ast_node: &swamp_ast::Node,
1948    ) {
1949        let resolved_node = self.to_node(ast_node);
1950        let postfix = LocationAccess {
1951            node: resolved_node,
1952            ty,
1953            kind,
1954        };
1955
1956        vec.push(postfix);
1957    }
1958
1959    fn extract_single_intrinsic_call(body: &Expression) -> Option<IntrinsicFunction> {
1960        match &body.kind {
1961            ExpressionKind::Block(expressions) => {
1962                let first_kind = &expressions[0].kind;
1963                if let ExpressionKind::IntrinsicCallEx(intrinsic_fn, _args) = first_kind {
1964                    return Some(intrinsic_fn.clone());
1965                }
1966            }
1967            _ => {}
1968        }
1969        None
1970    }
1971
1972    #[allow(clippy::too_many_lines)]
1973    fn analyze_chain_to_location(
1974        &mut self,
1975        chain: &swamp_ast::PostfixChain,
1976        context: &TypeContext,
1977        location_side: LocationSide,
1978    ) -> Result<SingleLocationExpression, Error> {
1979        let mut items = Vec::new();
1980
1981        let nothing_context = TypeContext::new(None);
1982
1983        let base_expr = self.analyze_expression(&chain.base, &nothing_context)?;
1984        let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
1985            return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node));
1986        };
1987
1988        if !start_variable.is_mutable() {
1989            return Err(self.create_err(ErrorKind::VariableIsNotMutable, &chain.base.node));
1990        }
1991
1992        let mut ty = start_variable.resolved_type.clone();
1993        for (i, item) in chain.postfixes.iter().enumerate() {
1994            match &item {
1995                swamp_ast::Postfix::FieldAccess(field_name_node) => {
1996                    //let field_name_resolved = self.to_node(field_name_node)
1997                    let (struct_type_ref, index, return_type) =
1998                        self.analyze_struct_field(field_name_node, &ty)?;
1999                    self.add_location_item(
2000                        &mut items,
2001                        LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
2002                        return_type.clone(),
2003                        field_name_node,
2004                    );
2005
2006                    ty = return_type.clone();
2007                }
2008                swamp_ast::Postfix::Subscript(key_expression) => {
2009                    let is_last_in_chain = i == chain.postfixes.len() - 1;
2010                    let create_if_not_exists =
2011                        is_last_in_chain && location_side == LocationSide::Lhs;
2012
2013                    let subscript_member_function_name = if create_if_not_exists {
2014                        "subscript_mut_create_if_needed"
2015                    } else {
2016                        "subscript_mut"
2017                    };
2018
2019                    if let Some(found) = self
2020                        .shared
2021                        .state
2022                        .instantiator
2023                        .associated_impls
2024                        .get_internal_member_function(&ty, subscript_member_function_name)
2025                        .cloned()
2026                    {
2027                        let intrinsic_to_call =
2028                            Self::extract_single_intrinsic_call(&found.body).expect("must exist");
2029
2030                        let create_if_not_exists_bool_expr = self.create_expr(
2031                            ExpressionKind::Literal(Literal::BoolLiteral(create_if_not_exists)),
2032                            Type::Bool,
2033                            &chain.base.node,
2034                        );
2035
2036                        let required_type = &found.signature.signature.parameters[1].resolved_type;
2037                        let subscript_lookup_context = TypeContext::new_argument(required_type);
2038                        let analyzed_key_expression =
2039                            self.analyze_expression(key_expression, &subscript_lookup_context)?;
2040                        let return_type = *found.signature.signature.return_type.clone();
2041                        ty = return_type.clone();
2042                        //let argument = ArgumentExpressionOrLocation::Expression(analyzed_expr);
2043                        self.add_location_item(
2044                            &mut items,
2045                            LocationAccessKind::IntrinsicCallMut(
2046                                intrinsic_to_call,
2047                                vec![analyzed_key_expression, create_if_not_exists_bool_expr],
2048                            ),
2049                            return_type,
2050                            &key_expression.node,
2051                        );
2052                    } else {
2053                        return Err(self
2054                            .create_err(ErrorKind::MissingSubscriptMember, &key_expression.node));
2055                    }
2056                }
2057
2058                swamp_ast::Postfix::MemberCall(node, _generic_arguments, _regular_args) => {
2059                    return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2060                }
2061
2062                swamp_ast::Postfix::FunctionCall(node, _generic_arguments, _regular_args) => {
2063                    return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2064                }
2065                swamp_ast::Postfix::OptionalChainingOperator(node) => {
2066                    return Err(self.create_err(ErrorKind::UnwrapCanNotBePartOfChain, node));
2067                }
2068                swamp_ast::Postfix::NoneCoalescingOperator(expr) => {
2069                    return Err(
2070                        self.create_err(ErrorKind::NoneCoalesceCanNotBePartOfChain, &expr.node)
2071                    );
2072                }
2073            }
2074        }
2075
2076        if let Some(found_expected_type) = context.expected_type {
2077            if !ty.compatible_with(found_expected_type) {
2078                return Err(self.create_err(
2079                    ErrorKind::IncompatibleTypes {
2080                        expected: found_expected_type.clone(),
2081                        found: ty,
2082                    },
2083                    &chain.base.node,
2084                ));
2085            }
2086        }
2087
2088        let location = SingleLocationExpression {
2089            kind: SingleLocationExpressionKind::MutVariableRef,
2090            node: self.to_node(&chain.base.node),
2091            ty,
2092            starting_variable: start_variable,
2093            access_chain: items,
2094        };
2095        Ok(location)
2096    }
2097
2098    fn analyze_to_location(
2099        &mut self,
2100        expr: &swamp_ast::Expression,
2101        context: &TypeContext,
2102        location_type: LocationSide,
2103    ) -> Result<SingleLocationExpression, Error> {
2104        match &expr.kind {
2105            swamp_ast::ExpressionKind::PostfixChain(chain) => {
2106                self.analyze_chain_to_location(chain, context, location_type)
2107            }
2108            swamp_ast::ExpressionKind::VariableReference(variable) => {
2109                let var = self.find_variable(variable)?;
2110                if var.is_mutable() {
2111                    Ok(SingleLocationExpression {
2112                        kind: SingleLocationExpressionKind::MutVariableRef,
2113                        node: self.to_node(&variable.name),
2114                        ty: Type::MutableReference(Box::from(var.resolved_type.clone())),
2115                        starting_variable: var,
2116                        access_chain: vec![],
2117                    })
2118                } else {
2119                    Err(self.create_err(ErrorKind::VariableIsNotMutable, &expr.node))
2120                }
2121            }
2122            swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
2123                let generated_var = swamp_ast::Variable {
2124                    name: qualified_identifier.name.clone(),
2125                    is_mutable: None,
2126                };
2127                let var = self.find_variable(&generated_var)?;
2128                if var.is_mutable() {
2129                    Ok(SingleLocationExpression {
2130                        kind: SingleLocationExpressionKind::MutVariableRef,
2131                        node: self.to_node(&generated_var.name),
2132                        ty: Type::MutableReference(Box::from(var.resolved_type.clone())),
2133                        starting_variable: var,
2134                        access_chain: vec![],
2135                    })
2136                } else {
2137                    Err(self.create_err(ErrorKind::VariableIsNotMutable, &expr.node))
2138                }
2139            }
2140            _ => Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &expr.node)),
2141        }
2142    }
2143
2144    fn analyze_assignment_compound(
2145        &mut self,
2146        target_expression: &swamp_ast::Expression,
2147        ast_op: &swamp_ast::CompoundOperator,
2148        ast_source_expression: &swamp_ast::Expression,
2149    ) -> Result<Expression, Error> {
2150        let resolved_op = self.analyze_compound_operator(ast_op);
2151        let any_argument_context = TypeContext::new_anything_argument();
2152        let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context)?;
2153        let source_expr_type_context = TypeContext::new_argument(&source_expr.ty);
2154
2155        let resolved_location = SingleMutLocationExpression(self.analyze_to_location(
2156            target_expression,
2157            &source_expr_type_context,
2158            LocationSide::Rhs,
2159        )?);
2160
2161        let kind = ExpressionKind::CompoundAssignment(
2162            resolved_location,
2163            resolved_op.kind,
2164            Box::from(source_expr),
2165        );
2166
2167        let expr = self.create_expr(kind, Type::Unit, &target_expression.node);
2168
2169        Ok(expr)
2170    }
2171
2172    fn analyze_assignment(
2173        &mut self,
2174        target_location: &swamp_ast::Expression,
2175        ast_source_expression: &swamp_ast::Expression,
2176    ) -> Result<Expression, Error> {
2177        let any_argument_context = TypeContext::new_anything_argument();
2178        let resolved_location =
2179            self.analyze_to_location(target_location, &any_argument_context, LocationSide::Lhs)?;
2180
2181        let ty = resolved_location.ty.clone();
2182        assert!(ty.is_concrete());
2183
2184        let lhs_argument_context = TypeContext::new_argument(&ty);
2185        let source_expr = self.analyze_expression(ast_source_expression, &lhs_argument_context)?;
2186
2187        let mut_location = SingleMutLocationExpression(resolved_location);
2188
2189        let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
2190
2191        let expr = self.create_expr(kind, Type::Unit, &target_location.node); // Assignments are always of type Unit
2192
2193        Ok(expr)
2194    }
2195
2196    #[must_use]
2197    pub const fn create_expr(
2198        &self,
2199        kind: ExpressionKind,
2200        ty: Type,
2201        ast_node: &swamp_ast::Node,
2202    ) -> Expression {
2203        //info!(%ty, ?kind, "create_expr()");
2204        Expression {
2205            kind,
2206            ty,
2207            node: self.to_node(ast_node),
2208        }
2209    }
2210
2211    #[must_use]
2212    pub fn create_expr_resolved(
2213        &self,
2214        kind: ExpressionKind,
2215        ty: Type,
2216        ast_node: &Node,
2217    ) -> Expression {
2218        Expression {
2219            kind,
2220            ty,
2221            node: ast_node.clone(),
2222        }
2223    }
2224
2225    fn analyze_destructuring(
2226        &mut self,
2227        node: &swamp_ast::Node,
2228        target_ast_variables: &[swamp_ast::Variable],
2229        tuple_expression: &swamp_ast::Expression,
2230    ) -> Result<Expression, Error> {
2231        let any_context = TypeContext::new_anything_argument();
2232        let tuple_resolved = self.analyze_expression(tuple_expression, &any_context)?;
2233        let tuple_expr_type = &tuple_resolved.ty;
2234
2235        let mut variable_refs = Vec::new();
2236        if let Type::Tuple(tuple) = tuple_expr_type.clone() {
2237            if target_ast_variables.len() > tuple.len() {
2238                return Err(self.create_err(ErrorKind::TooManyDestructureVariables, node));
2239            }
2240            for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
2241                let variable_ref = self.create_local_variable(
2242                    &ast_variable.name,
2243                    ast_variable.is_mutable.as_ref(),
2244                    &tuple_type,
2245                )?;
2246                variable_refs.push(variable_ref);
2247            }
2248            let expr_kind =
2249                ExpressionKind::TupleDestructuring(variable_refs, tuple, Box::from(tuple_resolved));
2250
2251            Ok(self.create_expr(expr_kind, Type::Unit, node))
2252        } else {
2253            Err(self.create_err(ErrorKind::CanNotDestructure, node))
2254        }
2255    }
2256
2257    fn analyze_postfix_member_call(
2258        &mut self,
2259        type_that_member_is_on: &Type,
2260        is_mutable: bool,
2261        member_name: &swamp_ast::Node,
2262        ast_maybe_generic_arguments: Option<Vec<swamp_ast::Type>>,
2263        arguments: &[swamp_ast::MutableOrImmutableExpression],
2264        suffixes: &mut Vec<Postfix>,
2265    ) -> Result<Type, Error> {
2266        let field_name_str = self.get_text(member_name).to_string();
2267
2268        let resolved_node = self.to_node(member_name);
2269
2270        let generic_arguments = if let Some(ast_generic_arguments) = ast_maybe_generic_arguments {
2271            let mut resolved_types = Vec::new();
2272            for ast_type in ast_generic_arguments {
2273                resolved_types.push(self.analyze_type(&ast_type)?);
2274            }
2275            resolved_types
2276        } else {
2277            vec![]
2278        };
2279
2280        let maybe_function = self
2281            .shared
2282            .state
2283            .instantiator
2284            .associated_impls
2285            .get_member_function(type_that_member_is_on, &field_name_str)
2286            .cloned();
2287
2288        let Some(found_function) = maybe_function else {
2289            return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, member_name));
2290        };
2291
2292        let (maybe_generic, alternative_signature) = found_function.signatures();
2293
2294        let signature = if let Some(found_generic) = maybe_generic {
2295            let mut seq_map = SeqMap::new();
2296            if generic_arguments.len() != found_generic.generic_type_variables.len() {
2297                return Err(self
2298                    .create_err_resolved(ErrorKind::WrongNumberOfArguments(0, 0), &resolved_node));
2299            }
2300            for (variable, generic_argument_type) in found_generic
2301                .generic_type_variables
2302                .iter()
2303                .zip(generic_arguments)
2304            {
2305                info!(?variable, ?generic_argument_type, "SETTING VAR");
2306                seq_map
2307                    .insert(variable.0.to_string(), generic_argument_type.clone())
2308                    .unwrap();
2309            }
2310            let scope = TypeVariableScope::new(seq_map);
2311            let instantiated_signature = self
2312                .shared
2313                .state
2314                .instantiator
2315                .instantiate_generic_signature(type_that_member_is_on, found_generic, &scope)?
2316                .clone();
2317
2318            &instantiated_signature.clone()
2319        } else {
2320            alternative_signature
2321        };
2322
2323        let self_type = &signature.parameters[0];
2324        if !self_type
2325            .resolved_type
2326            .compatible_with(type_that_member_is_on)
2327            || self_type.is_mutable && !is_mutable
2328        {
2329            return Err(self.create_err_resolved(ErrorKind::SelfNotCorrectType, &resolved_node));
2330        }
2331
2332        let resolved_arguments = self.analyze_and_verify_parameters(
2333            &resolved_node,
2334            &signature.parameters[1..],
2335            arguments,
2336        )?;
2337
2338        let kind = PostfixKind::MemberCall(found_function.clone(), resolved_arguments);
2339
2340        let postfix = Postfix {
2341            node: resolved_node.clone(),
2342            ty: *signature.return_type.clone(),
2343            kind,
2344        };
2345
2346        let last_type = postfix.ty.clone();
2347        suffixes.push(postfix);
2348
2349        Ok(last_type)
2350    }
2351
2352    fn types_did_not_match_try_late_coerce_expression(
2353        &self,
2354        expr: Expression,
2355        expected_type: &Type,
2356        encountered_type: &Type,
2357        node: &swamp_ast::Node,
2358    ) -> Result<Expression, Error> {
2359        if let Type::Optional(expected_inner_type) = expected_type {
2360            // If an optional is expected, we can wrap it if this type has the exact same
2361            // inner type
2362            assert!(
2363                expected_inner_type
2364                    .inner_optional_mut_or_immutable()
2365                    .is_none()
2366            );
2367
2368            // First make sure it is not already an optional type. we can not wrap an option with an option
2369            if encountered_type.inner_optional_mut_or_immutable().is_none() {
2370                // good it isn't, lets see if they share inner types
2371                if expected_inner_type.compatible_ignore_mutability_of(encountered_type) {
2372                    // they share inner types as well, lets wrap it up
2373                    let wrapped = self.create_expr(
2374                        ExpressionKind::Option(Option::from(Box::new(expr))),
2375                        expected_type.clone(),
2376                        node,
2377                    );
2378                    return Ok(wrapped);
2379                }
2380            }
2381        } else if matches!(expected_type, &Type::Bool) {
2382            // if it has a mut or immutable optional, then it works well to wrap it
2383            if encountered_type.inner_optional_mut_or_immutable().is_some() {
2384                let wrapped = self.create_expr(
2385                    ExpressionKind::CoerceOptionToBool(Box::from(expr)),
2386                    Type::Bool,
2387                    node,
2388                );
2389                return Ok(wrapped);
2390            }
2391        }
2392
2393        Err(self.create_err(
2394            ErrorKind::IncompatibleTypes {
2395                expected: expected_type.clone(),
2396                found: encountered_type.clone(),
2397            },
2398            node,
2399        ))
2400    }
2401
2402    #[allow(clippy::too_many_lines)]
2403    fn analyze_generic_type(
2404        &mut self,
2405        symbol: &Symbol,
2406        analyzed_type_parameters: &[Type],
2407        node: &swamp_ast::Node,
2408    ) -> Result<Type, Error> {
2409        let ty = match symbol {
2410            //            Symbol::Type(base_type) => base_type.clone(),
2411            //          Symbol::Alias(alias_type) => alias_type.referenced_type.clone(),
2412            Symbol::Blueprint(blueprint) => {
2413                if all_types_are_concrete_or_unit(analyzed_type_parameters) {
2414                    self.shared
2415                        .state
2416                        .instantiator
2417                        .instantiate_blueprint_and_members(blueprint, analyzed_type_parameters)?
2418                } else {
2419                    Type::Generic(blueprint.clone(), analyzed_type_parameters.to_vec())
2420                }
2421            }
2422            Symbol::TypeGenerator(type_gen) => match type_gen.kind {
2423                TypeGeneratorKind::Slice => {
2424                    //assert!(analyzed_type_parameters[0].is_concrete());
2425                    Type::Slice(Box::new(analyzed_type_parameters[0].clone()))
2426                }
2427                TypeGeneratorKind::SlicePair => {
2428                    //assert!(analyzed_type_parameters[0].is_concrete());
2429                    //assert!(analyzed_type_parameters[1].is_concrete());
2430                    Type::SlicePair(
2431                        Box::new(analyzed_type_parameters[0].clone()),
2432                        Box::new(analyzed_type_parameters[1].clone()),
2433                    )
2434                }
2435            },
2436            _ => return Err(self.create_err(ErrorKind::UnknownSymbol, node)),
2437        };
2438
2439        Ok(ty)
2440    }
2441}