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