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