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;
6mod attributes;
7pub mod call;
8pub mod constant;
9pub mod def;
10pub mod literal;
11pub mod operator;
12pub mod pattern;
13pub mod prelude;
14mod structure;
15mod to_string;
16pub mod types;
17pub mod variable;
18
19use crate::call::MaybeBorrowMutRefExpression;
20use crate::to_string::create_expr_resolved;
21use seq_map::SeqMap;
22use source_map_cache::SourceMap;
23use source_map_node::{FileId, Node, Span};
24use std::mem::take;
25use std::num::{ParseFloatError, ParseIntError};
26use std::rc::Rc;
27use std::str::{FromStr, ParseBoolError};
28use swamp_ast::{GenericParameter, QualifiedTypeIdentifier};
29use swamp_modules::prelude::*;
30use swamp_modules::symtbl::SymbolTableRef;
31use swamp_semantic::prelude::*;
32use swamp_semantic::{
33    ArgumentExpression, BinaryOperatorKind, BlockScope, BlockScopeMode, FunctionScopeState,
34    GridType, InternalMainExpression, LocationAccess, LocationAccessKind, MapType,
35    MutableReferenceKind, NormalPattern, Postfix, PostfixKind, ScopeInfo, SingleLocationExpression,
36    SliceViewType, SparseType, TargetAssignmentLocation, TypeWithMut, VariableType, VecType,
37    WhenBinding,
38};
39use swamp_semantic::{StartOfChain, StartOfChainKind};
40use swamp_types::TypeKind;
41use swamp_types::prelude::*;
42use tracing::error;
43
44#[derive(Copy, Clone, Eq, PartialEq)]
45pub enum AssignmentMode {
46    OwnedValue,
47    CopyBlittable,
48    CopySharedPtr,
49}
50
51#[derive(Copy, Clone, Eq, PartialEq, Debug)]
52pub enum LocationSide {
53    Lhs,
54    Mutable,
55    Rhs,
56}
57
58#[derive(Debug)]
59pub enum StartOfChainBase {
60    FunctionReference(Function),
61    Variable(VariableRef),
62}
63#[derive(Debug)]
64pub struct Program {
65    pub state: ProgramState,
66    pub modules: Modules,
67    pub default_symbol_table: SymbolTable,
68}
69
70impl Default for Program {
71    fn default() -> Self {
72        Self::new(ProgramState::new(), Modules::new(), SymbolTable::new(&[]))
73    }
74}
75
76impl Program {
77    #[must_use]
78    pub const fn new(
79        state: ProgramState,
80        modules: Modules,
81        default_symbol_table: SymbolTable,
82    ) -> Self {
83        Self {
84            state,
85            modules,
86            default_symbol_table,
87        }
88    }
89}
90
91#[must_use]
92pub const fn convert_span(without: &swamp_ast::SpanWithoutFileId, file_id: FileId) -> Span {
93    Span {
94        file_id,
95        offset: without.offset,
96        length: without.length,
97    }
98}
99
100/// `TypeRef` checking context
101#[derive(Debug, Clone)]
102pub struct TypeContext<'a> {
103    /// Expected type for the current expression
104    pub expected_type: Option<&'a TypeRef>,
105    pub has_lvalue_target: bool,
106}
107
108impl<'a> TypeContext<'a> {
109    #[must_use]
110    pub const fn new(expected_type: Option<&'a TypeRef>, has_lvalue_target: bool) -> Self {
111        Self {
112            expected_type,
113            has_lvalue_target,
114        }
115    }
116
117    pub(crate) const fn with_lvalue(&self) -> Self {
118        Self {
119            expected_type: self.expected_type,
120            has_lvalue_target: true,
121        }
122    }
123
124    pub(crate) const fn argument(&self, expected_type: &'a TypeRef) -> Self {
125        Self {
126            expected_type: Some(expected_type),
127            has_lvalue_target: self.has_lvalue_target,
128        }
129    }
130
131    #[must_use]
132    pub const fn new_argument(required_type: &'a TypeRef, has_lvalue_target: bool) -> Self {
133        Self {
134            expected_type: Some(required_type),
135            has_lvalue_target,
136        }
137    }
138
139    #[must_use]
140    pub const fn new_unsure_argument(
141        expected_type: Option<&'a TypeRef>,
142        has_lvalue_target: bool,
143    ) -> Self {
144        Self {
145            expected_type,
146            has_lvalue_target,
147        }
148    }
149
150    #[must_use]
151    pub const fn new_anything_argument(has_lvalue_target: bool) -> Self {
152        Self {
153            expected_type: None,
154            has_lvalue_target,
155        }
156    }
157
158    #[must_use]
159    pub fn new_function(required_type: &'a TypeRef) -> Self {
160        Self {
161            expected_type: Some(required_type),
162            has_lvalue_target: required_type.collection_view_that_needs_explicit_storage(),
163        }
164    }
165
166    #[must_use]
167    pub const fn with_expected_type(
168        &self,
169        expected_type: Option<&'a TypeRef>,
170        has_lvalue_target: bool,
171    ) -> Self {
172        Self {
173            expected_type,
174            has_lvalue_target,
175        }
176    }
177
178    pub(crate) const fn we_know_expected_type(
179        &self,
180        found_type: &'a TypeRef,
181        has_lvalue_target: bool,
182    ) -> Self {
183        self.with_expected_type(Some(found_type), has_lvalue_target)
184    }
185}
186
187pub struct SharedState<'a> {
188    pub state: &'a mut ProgramState,
189    pub lookup_table: SymbolTable,
190    pub definition_table: SymbolTable,
191    pub modules: &'a Modules,
192    pub source_map: &'a SourceMap,
193    pub file_id: FileId,
194    pub core_symbol_table: SymbolTableRef,
195}
196
197impl<'a> SharedState<'a> {
198    #[must_use]
199    pub fn get_symbol_table(&'a self, path: &[String]) -> Option<&'a SymbolTable> {
200        if path.is_empty() {
201            return Some(&self.lookup_table);
202        }
203        self.get_module(path).map(|module| &module.symbol_table)
204    }
205
206    #[must_use]
207    pub fn get_module(&'a self, path: &[String]) -> Option<&'a ModuleRef> {
208        let resolved_path = {
209            self.lookup_table.get_package_version(&path[0]).map_or_else(
210                || path.to_vec(),
211                |found_version| {
212                    let mut new_path = path.to_vec();
213                    let complete_name = format!("{}-{found_version}", path[0]);
214                    new_path[0] = complete_name;
215                    new_path
216                    //path.to_vec()
217                },
218            )
219        };
220
221        if path.len() == 1 {
222            if let Some(module_ref) = self.lookup_table.get_module_link(&path[0]) {
223                return Some(module_ref);
224            }
225        }
226
227        if let Some(x) = self.modules.get(&resolved_path) {
228            return Some(x);
229        }
230
231        None
232    }
233}
234
235pub struct Analyzer<'a> {
236    pub shared: SharedState<'a>,
237    scope: ScopeInfo,
238    global: FunctionScopeState,
239    module_path: Vec<String>,
240}
241
242impl<'a> Analyzer<'a> {
243    pub fn new(
244        state: &'a mut ProgramState,
245        modules: &'a Modules,
246        core_symbol_table: SymbolTableRef,
247        source_map: &'a SourceMap,
248        module_path: &[String],
249        file_id: FileId,
250    ) -> Self {
251        let shared = SharedState {
252            state,
253            lookup_table: SymbolTable::new(&[]),
254            definition_table: SymbolTable::new(module_path),
255            modules,
256            core_symbol_table,
257            source_map,
258            file_id,
259        };
260        Self {
261            scope: ScopeInfo::default(),
262            global: FunctionScopeState::new(),
263            shared,
264            module_path: module_path.to_vec(),
265        }
266    }
267
268    fn start_function(&mut self) {
269        self.global.block_scope_stack = take(&mut self.scope.active_scope.block_scope_stack);
270        self.scope = ScopeInfo::default();
271    }
272
273    fn stop_function(&mut self) {
274        self.scope.active_scope.block_scope_stack = take(&mut self.global.block_scope_stack);
275    }
276
277    fn analyze_if_expression(
278        &mut self,
279        condition: &swamp_ast::Expression,
280        true_expression: &swamp_ast::Expression,
281        maybe_false_expression: Option<&swamp_ast::Expression>,
282        context: &TypeContext,
283    ) -> Expression {
284        let resolved_condition = self.analyze_bool_argument_expression(condition);
285
286        let branch_context = context;
287
288        let true_expr = self.analyze_expression(true_expression, branch_context);
289        let resolved_true = Box::new(true_expr);
290
291        let mut detected = context.expected_type.cloned();
292        if detected.is_none() {
293            detected = Some(resolved_true.ty.clone());
294        }
295
296        // Analyze the false branch if it exists
297        let else_statements = if let Some(false_expression) = maybe_false_expression {
298            let else_context =
299                branch_context.with_expected_type(detected.as_ref(), context.has_lvalue_target);
300            let else_expr = self.analyze_expression(false_expression, &else_context);
301            if detected.is_none() {
302                detected = Some(else_expr.ty.clone());
303            }
304
305            Some(Box::new(else_expr))
306        } else {
307            None
308        };
309
310        self.create_expr(
311            ExpressionKind::If(resolved_condition, resolved_true, else_statements),
312            detected.unwrap(),
313            &condition.node,
314        )
315    }
316
317    fn get_text(&self, ast_node: &swamp_ast::Node) -> &str {
318        let span = Span {
319            file_id: self.shared.file_id,
320            offset: ast_node.span.offset,
321            length: ast_node.span.length,
322        };
323        self.shared.source_map.get_span_source(
324            self.shared.file_id,
325            span.offset as usize,
326            span.length as usize,
327        )
328    }
329
330    fn get_text_resolved(&self, resolved_node: &Node) -> &str {
331        let span = Span {
332            file_id: self.shared.file_id,
333            offset: resolved_node.span.offset,
334            length: resolved_node.span.length,
335        };
336        self.shared.source_map.get_span_source(
337            self.shared.file_id,
338            span.offset as usize,
339            span.length as usize,
340        )
341    }
342
343    fn get_path(&self, ident: &swamp_ast::QualifiedTypeIdentifier) -> (Vec<String>, String) {
344        let path = ident
345            .module_path
346            .as_ref()
347            .map_or_else(Vec::new, |found_path| {
348                let mut v = Vec::new();
349                for p in &found_path.0 {
350                    v.push(self.get_text(p).to_string());
351                }
352                v
353            });
354        (path, self.get_text(&ident.name.0).to_string())
355    }
356
357    fn analyze_return_type(&mut self, function: &swamp_ast::Function) -> TypeRef {
358        let ast_return_type = match function {
359            swamp_ast::Function::Internal(x) => &x.declaration.return_type,
360            swamp_ast::Function::External(_, x) => &x.return_type,
361        };
362
363        match ast_return_type {
364            None => self.shared.state.types.unit(),
365            Some(x) => self.analyze_type(x),
366        }
367    }
368
369    fn analyze_function_body_expression(
370        &mut self,
371        expression: &swamp_ast::Expression,
372        return_type: &TypeRef,
373    ) -> Expression {
374        let context = TypeContext::new_function(return_type);
375
376        self.analyze_expression(expression, &context)
377    }
378
379    fn analyze_maybe_type(&mut self, maybe_type: Option<&swamp_ast::Type>) -> TypeRef {
380        match maybe_type {
381            None => self.shared.state.types.unit(),
382            Some(ast_type) => self.analyze_type(ast_type),
383        }
384    }
385
386    fn analyze_for_pattern(
387        &mut self,
388        pattern: &swamp_ast::ForPattern,
389        key_type: Option<&TypeRef>,
390        value_type: &TypeRef,
391    ) -> ForPattern {
392        match pattern {
393            swamp_ast::ForPattern::Single(var) => {
394                let variable_ref = self.create_local_variable(
395                    &var.identifier,
396                    Option::from(&var.is_mut),
397                    value_type,
398                    false,
399                );
400                ForPattern::Single(variable_ref)
401            }
402            swamp_ast::ForPattern::Pair(first, second) => {
403                let found_key = key_type.unwrap();
404                let first_var_ref = self.create_local_variable(
405                    &first.identifier,
406                    Option::from(&first.is_mut),
407                    found_key,
408                    false,
409                );
410                let second_var_ref = self.create_local_variable(
411                    &second.identifier,
412                    Option::from(&second.is_mut),
413                    value_type,
414                    false,
415                );
416                ForPattern::Pair(first_var_ref, second_var_ref)
417            }
418        }
419    }
420    const MAX_PARAMETER_COUNT: usize = 6; // NOTE: Must be same or lower than the ABI allows (so it doesn't fail in codegen)
421    fn analyze_parameters(
422        &mut self,
423        parameters: &Vec<swamp_ast::Parameter>,
424    ) -> Vec<TypeForParameter> {
425        let mut resolved_parameters = Vec::new();
426        if parameters.len() > Self::MAX_PARAMETER_COUNT {
427            self.add_err(
428                ErrorKind::TooManyParameters {
429                    encountered: parameters.len(),
430                    allowed: Self::MAX_PARAMETER_COUNT,
431                },
432                &parameters[0].variable.name,
433            );
434            return vec![];
435        }
436        for parameter in parameters {
437            let param_type = self.analyze_type(&parameter.param_type);
438            if !param_type.allowed_as_parameter_type() {
439                self.add_err(
440                    ErrorKind::ParameterTypeCanNotBeStorage(param_type),
441                    &parameter.variable.name,
442                );
443                continue;
444            }
445            resolved_parameters.push(TypeForParameter {
446                name: self.get_text(&parameter.variable.name).to_string(),
447                resolved_type: param_type,
448                is_mutable: parameter.variable.is_mutable.is_some(),
449                node: Some(ParameterNode {
450                    is_mutable: self.to_node_option(Option::from(&parameter.variable.is_mutable)),
451                    name: self.to_node(&parameter.variable.name),
452                }),
453            });
454        }
455        resolved_parameters
456    }
457
458    pub(crate) fn analyze_static_member_access(
459        &mut self,
460        named_type: &swamp_ast::QualifiedTypeIdentifier,
461        member_name_node: &swamp_ast::Node,
462    ) -> Option<Function> {
463        if let Some(found_function) = self.special_static_member(named_type, member_name_node) {
464            Some(found_function)
465        } else {
466            let some_type = self.analyze_named_type(named_type);
467
468            let member_name = self.get_text(member_name_node);
469            self.lookup_associated_function(&some_type, member_name)
470        }
471    }
472
473    pub fn analyze_local_function_access(
474        &mut self,
475        qualified_func_name: &swamp_ast::QualifiedIdentifier,
476    ) -> Option<Function> {
477        let path = self.get_module_path(qualified_func_name.module_path.as_ref());
478        let function_name = self.get_text(&qualified_func_name.name);
479
480        if let Some(found_table) = self.shared.get_symbol_table(&path) {
481            if let Some(found_func) = found_table.get_function(function_name) {
482                let (kind, signature) = match found_func {
483                    FuncDef::Internal(internal_fn) => (
484                        Function::Internal(internal_fn.clone()),
485                        &internal_fn.signature,
486                    ),
487                    FuncDef::External(external_fn) => (
488                        Function::External(external_fn.clone()),
489                        &external_fn.signature,
490                    ),
491                    // Can not have a reference to an intrinsic function
492                    FuncDef::Intrinsic(intrinsic_fn) => (
493                        Function::Intrinsic(intrinsic_fn.clone()),
494                        &intrinsic_fn.signature,
495                    ),
496                };
497
498                return Some(kind);
499            }
500        }
501
502        None
503    }
504
505    fn check_if_function_reference(
506        &mut self,
507        ast_expression: &swamp_ast::Expression,
508    ) -> Option<Function> {
509        match &ast_expression.kind {
510            swamp_ast::ExpressionKind::StaticMemberFunctionReference(
511                qualified_type_identifier,
512                node,
513            ) => self.analyze_static_member_access(qualified_type_identifier, node),
514            swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
515                self.analyze_local_function_access(qualified_identifier)
516            }
517            _ => None,
518        }
519    }
520
521    /// # Errors
522    ///
523    pub fn analyze_start_chain_expression_get_mutability(
524        &mut self,
525        ast_expression: &swamp_ast::Expression,
526    ) -> Option<StartOfChainBase> {
527        self.check_if_function_reference(ast_expression)
528            .map_or_else(
529                || {
530                    if let swamp_ast::ExpressionKind::IdentifierReference(
531                        found_qualified_identifier,
532                    ) = &ast_expression.kind
533                    {
534                        self.try_find_variable(&found_qualified_identifier.name)
535                            .map(StartOfChainBase::Variable)
536                    } else {
537                        None
538                    }
539                },
540                |found_func_def| Some(StartOfChainBase::FunctionReference(found_func_def)),
541            )
542    }
543
544    pub fn debug_expression(&self, expr: &swamp_ast::Expression, description: &str) {
545        self.debug_line(expr.node.span.offset as usize, description);
546    }
547
548    pub fn debug_line(&self, offset: usize, description: &str) {
549        let (line, col) = self
550            .shared
551            .source_map
552            .get_span_location_utf8(self.shared.file_id, offset);
553
554        let source_line = self
555            .shared
556            .source_map
557            .get_source_line(self.shared.file_id, line);
558
559        let source_path = self
560            .shared
561            .source_map
562            .fetch_relative_filename(self.shared.file_id);
563        let debug_line = format!("{source_path}:{line}:{col}> {}", source_line.unwrap());
564        //info!(%debug_line, "source");
565
566        //        info!(?line, ?col, "source reference");
567    }
568
569    /// # Errors
570    ///
571    pub fn analyze_main_expression(
572        &mut self,
573        ast_expression: &swamp_ast::Expression,
574    ) -> InternalMainExpression {
575        self.start_function();
576
577        let context = TypeContext::new_anything_argument(true); // function returns are per definition lvalue target for aggregates
578        let analyzed_expr = self.analyze_expression(ast_expression, &context);
579        let main_expr = InternalMainExpression {
580            expression: analyzed_expr,
581            scopes: self.scope.total_scopes.clone(),
582            program_unique_id: self.shared.state.allocate_internal_function_id(),
583        };
584
585        self.stop_function();
586
587        main_expr
588    }
589
590    fn analyze_maybe_ref_expression(
591        &mut self,
592        ast_expr: &swamp_ast::Expression,
593    ) -> MaybeBorrowMutRefExpression {
594        if let swamp_ast::ExpressionKind::UnaryOp(found_unary, ast_inner_expression) =
595            &ast_expr.kind
596        {
597            if let swamp_ast::UnaryOperator::BorrowMutRef(node) = found_unary {
598                //let inner = self.analyze_expression(ast_inner_expression, context)?;
599                let resolved_node = self.to_node(node);
600                return MaybeBorrowMutRefExpression {
601                    ast_expression: *ast_inner_expression.clone(),
602                    has_borrow_mutable_reference: Some(resolved_node),
603                };
604            }
605        }
606
607        MaybeBorrowMutRefExpression {
608            ast_expression: ast_expr.clone(),
609            has_borrow_mutable_reference: None,
610        }
611    }
612
613    /// Check if an expression needs explicit storage and should return an error
614    fn needs_storage_error(
615        &self,
616        expr: &Expression,
617        is_function_call: bool,
618        context: &TypeContext,
619        ast_node: &swamp_ast::Node,
620    ) -> bool {
621        let is_constant = matches!(expr.kind, ExpressionKind::ConstantAccess(_));
622        let is_variable = matches!(expr.kind, ExpressionKind::VariableAccess(_));
623
624        // Return true if we need to create an error
625        !context.has_lvalue_target
626            && expr.ty.collection_view_that_needs_explicit_storage()
627            && is_function_call
628            && !is_constant
629            && !is_variable
630    }
631
632    pub fn analyze_expression(
633        &mut self,
634        ast_expression: &swamp_ast::Expression,
635        context: &TypeContext,
636    ) -> Expression {
637        //info!(?ast_expression, "analyze expression");
638        //self.debug_expression(ast_expression, "analyze");
639        let expr = self.analyze_expression_internal(ast_expression, context);
640
641        if matches!(expr.kind, ExpressionKind::Error(_)) {
642            return expr;
643        }
644
645        let encountered_type = expr.ty.clone();
646
647        //info!(?expr, "analyze expression");
648        let expr = if let Some(found_expected_type) = context.expected_type {
649            let reduced_expected = found_expected_type;
650
651            let reduced_encountered_type = encountered_type;
652            if self
653                .shared
654                .state
655                .types
656                .compatible_with(reduced_expected, &reduced_encountered_type)
657            {
658                expr
659            } else {
660                self.types_did_not_match_try_late_coerce_expression(
661                    expr,
662                    reduced_expected,
663                    &reduced_encountered_type,
664                    &ast_expression.node,
665                )
666            }
667        } else {
668            expr
669            //todo!()
670            // TODO: self.coerce_unrestricted_type(&ast_expression.node, expr)?
671        };
672
673        // Only apply storage rule to function calls that return types needing explicit storage
674        // Exclude literals, constants, and variables which already have storage or are constructed directly
675        let is_function_call = Self::is_aggregate_function_call(ast_expression);
676
677        if self.needs_storage_error(&expr, is_function_call, context, &ast_expression.node) {
678            // We have no way to store it
679            self.create_err(ErrorKind::NeedStorage, &ast_expression.node)
680        } else {
681            expr
682        }
683    }
684
685    /// # Errors
686    ///
687    #[allow(clippy::too_many_lines)]
688    pub fn analyze_expression_internal(
689        &mut self,
690        ast_expression: &swamp_ast::Expression,
691        context: &TypeContext,
692    ) -> Expression {
693        //info!(ty=%expression.ty, kind=?expression.kind,  "resolved expression");
694
695        match &ast_expression.kind {
696            // Lookups
697            swamp_ast::ExpressionKind::PostfixChain(postfix_chain) => {
698                self.analyze_postfix_chain(postfix_chain, context)
699            }
700
701            swamp_ast::ExpressionKind::VariableDefinition(
702                variable,
703                maybe_annotation,
704                source_expression,
705            ) => self.analyze_create_variable(
706                variable,
707                Option::from(maybe_annotation),
708                source_expression,
709            ),
710
711            swamp_ast::ExpressionKind::VariableAssignment(variable, source_expression) => {
712                self.analyze_variable_assignment(variable, source_expression)
713            }
714
715            swamp_ast::ExpressionKind::DestructuringAssignment(variables, expression) => {
716                self.analyze_destructuring(&ast_expression.node, variables, expression)
717            }
718
719            swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
720                self.analyze_identifier(qualified_identifier)
721            }
722
723            swamp_ast::ExpressionKind::VariableReference(variable) => {
724                self.analyze_variable_reference(&variable.name)
725            }
726
727            swamp_ast::ExpressionKind::ContextAccess => {
728                todo!("context access is not done yet")
729            }
730
731            swamp_ast::ExpressionKind::StaticMemberFunctionReference(
732                type_identifier,
733                member_name,
734            ) => {
735                let debug_name = self.get_text(member_name);
736                let type_name = self.get_text(&type_identifier.name.0);
737                panic!("can not have separate member func ref {type_name:?} {debug_name}")
738            }
739
740            swamp_ast::ExpressionKind::ConstantReference(constant_identifier) => {
741                self.analyze_constant_access(constant_identifier)
742            }
743
744            swamp_ast::ExpressionKind::Assignment(location, source) => {
745                self.analyze_assignment(location, source)
746            }
747
748            swamp_ast::ExpressionKind::CompoundAssignment(target, op, source) => {
749                self.analyze_assignment_compound(target, op, source)
750            }
751
752            // Operator
753            swamp_ast::ExpressionKind::BinaryOp(resolved_a, operator, resolved_b) => {
754                let Some((resolved_op, result_type)) =
755                    self.analyze_binary_op(resolved_a, operator, resolved_b)
756                else {
757                    return self.create_err(ErrorKind::OperatorProblem, &operator.node);
758                };
759
760                self.create_expr(
761                    ExpressionKind::BinaryOp(resolved_op),
762                    result_type,
763                    &ast_expression.node,
764                )
765            }
766
767            swamp_ast::ExpressionKind::UnaryOp(operator, expression) => {
768                if let swamp_ast::UnaryOperator::BorrowMutRef(_node) = operator {
769                    let inner_expr =
770                        self.analyze_to_location(expression, context, LocationSide::Rhs);
771                    let ty = inner_expr.ty.clone();
772                    self.create_expr(
773                        ExpressionKind::BorrowMutRef(Box::from(inner_expr)),
774                        ty,
775                        &ast_expression.node,
776                    )
777                } else {
778                    let Some((resolved_op, result_type)) =
779                        self.analyze_unary_op(operator, expression)
780                    else {
781                        return self.create_err(ErrorKind::OperatorProblem, &ast_expression.node);
782                    };
783                    self.create_expr(
784                        ExpressionKind::UnaryOp(resolved_op),
785                        result_type,
786                        &ast_expression.node,
787                    )
788                }
789            }
790
791            swamp_ast::ExpressionKind::Block(expressions) => {
792                let (block, resulting_type) =
793                    self.analyze_block(&ast_expression.node, context, expressions);
794                self.create_expr(
795                    ExpressionKind::Block(block),
796                    resulting_type,
797                    &ast_expression.node,
798                )
799            }
800
801            swamp_ast::ExpressionKind::With(variable_bindings, expression) => {
802                self.analyze_with_expr(context, variable_bindings, expression)
803            }
804
805            swamp_ast::ExpressionKind::When(variable_bindings, true_expr, else_expr) => {
806                self.analyze_when_expr(context, variable_bindings, true_expr, else_expr.as_deref())
807            }
808
809            swamp_ast::ExpressionKind::InterpolatedString(string_parts) => {
810                self.analyze_interpolated_string_lowering(&ast_expression.node, string_parts)
811            }
812
813            // Creation
814            swamp_ast::ExpressionKind::NamedStructLiteral(struct_identifier, fields, has_rest) => {
815                self.analyze_named_struct_literal(struct_identifier, fields, *has_rest)
816            }
817
818            swamp_ast::ExpressionKind::AnonymousStructLiteral(fields, rest_was_specified) => self
819                .analyze_anonymous_struct_literal(
820                    &ast_expression.node,
821                    fields,
822                    *rest_was_specified,
823                    context,
824                ),
825
826            swamp_ast::ExpressionKind::ContextAccess => {
827                todo!("lone dot not implemented yet")
828            }
829
830            swamp_ast::ExpressionKind::Range(min_value, max_value, range_mode) => {
831                self.analyze_range(min_value, max_value, range_mode, &ast_expression.node)
832            }
833
834            swamp_ast::ExpressionKind::ForLoop(pattern, iterable_expression, statements) => {
835                if pattern.is_key_variable_mut() {
836                    return self.create_err(
837                        ErrorKind::KeyVariableNotAllowedToBeMutable,
838                        &ast_expression.node,
839                    );
840                }
841                let resolved_iterator =
842                    self.analyze_iterable(pattern.is_value_mut(), &iterable_expression.expression);
843
844                self.push_block_scope("for_loop");
845                let pattern = self.analyze_for_pattern(
846                    pattern,
847                    resolved_iterator.key_type.as_ref(),
848                    &resolved_iterator.value_type,
849                );
850                let resolved_statements = self.analyze_expression(statements, context);
851                self.pop_block_scope("for_loop");
852                let resolved_type = resolved_statements.ty.clone();
853                self.create_expr(
854                    ExpressionKind::ForLoop(
855                        pattern,
856                        resolved_iterator,
857                        Box::from(resolved_statements),
858                    ),
859                    resolved_type,
860                    &ast_expression.node,
861                )
862            }
863
864            swamp_ast::ExpressionKind::WhileLoop(expression, statements) => {
865                let condition = self.analyze_bool_argument_expression(expression);
866                //self.push_block_scope("while_loop");
867                let resolved_statements = self.analyze_expression(statements, context);
868                let resolved_type = resolved_statements.ty.clone();
869                //self.pop_block_scope("while_loop");
870
871                self.create_expr(
872                    ExpressionKind::WhileLoop(condition, Box::from(resolved_statements)),
873                    resolved_type,
874                    &ast_expression.node,
875                )
876            }
877
878            swamp_ast::ExpressionKind::If(expression, true_expression, maybe_false_expression) => {
879                self.analyze_if_expression(
880                    expression,
881                    true_expression,
882                    maybe_false_expression.as_deref(),
883                    context,
884                )
885            }
886
887            swamp_ast::ExpressionKind::Match(expression, arms) => {
888                let (match_expr, return_type) = self.analyze_match(expression, context, arms);
889                self.create_expr(
890                    ExpressionKind::Match(match_expr),
891                    return_type,
892                    &ast_expression.node,
893                )
894            }
895            swamp_ast::ExpressionKind::Guard(guard_expressions) => {
896                self.analyze_guard(&ast_expression.node, context, guard_expressions)
897            }
898
899            swamp_ast::ExpressionKind::Lambda(variables, expression) => {
900                self.analyze_lambda(&ast_expression.node, variables, expression, context)
901            }
902            swamp_ast::ExpressionKind::Error => {
903                self.create_err(ErrorKind::UnexpectedType, &ast_expression.node)
904            }
905            swamp_ast::ExpressionKind::Literal(literal) => {
906                self.analyze_complex_literal_to_expression(ast_expression, literal, context)
907            } //self.create_err(ErrorKind::UnexpectedType, &ast_expression.node),
908        }
909    }
910
911    fn get_struct_type(
912        &mut self,
913        qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
914    ) -> NamedStructType {
915        let maybe_struct_type = self.analyze_named_type(qualified_type_identifier);
916        if let TypeKind::NamedStruct(struct_type) = &*maybe_struct_type.kind {
917            struct_type.clone()
918        } else {
919            self.add_err(
920                // For other TypeRef variants that are not Struct
921                ErrorKind::UnknownStructTypeReference,
922                &qualified_type_identifier.name.0,
923            );
924
925            NamedStructType {
926                name: Default::default(),
927                module_path: vec![],
928                assigned_name: String::new(),
929                anon_struct_type: self.types().unit(),
930                instantiated_type_parameters: vec![],
931            }
932        }
933    }
934
935    pub(crate) fn analyze_named_type(
936        &mut self,
937        type_name_to_find: &swamp_ast::QualifiedTypeIdentifier,
938    ) -> TypeRef {
939        let (path, name) = self.get_path(type_name_to_find);
940        let mut analyzed_type_parameters = Vec::new();
941
942        if let Some(found) =
943            self.analyze_special_named_type(&path, &name, &type_name_to_find.generic_params)
944        {
945            return found;
946        }
947
948        for analyzed_type in &type_name_to_find.generic_params {
949            let ty = self.analyze_type(analyzed_type.get_type());
950
951            analyzed_type_parameters.push(ty);
952        }
953
954        let symbol = {
955            if let Some(symbol_table) = self.shared.get_symbol_table(&path) {
956                if let Some(x) = symbol_table.get_symbol(&name) {
957                    x
958                } else {
959                    self.add_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0);
960                    return self.types().unit();
961                }
962            } else {
963                self.add_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0);
964                return self.types().unit();
965            }
966        };
967
968        if analyzed_type_parameters.is_empty() {
969            match &symbol {
970                Symbol::Type(base_type) => base_type.clone(),
971                Symbol::Alias(alias_type) => alias_type.ty.clone(),
972                _ => {
973                    self.add_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0);
974                    self.types().unit()
975                }
976            }
977        } else {
978            panic!("unknown type")
979        }
980    }
981
982    fn create_default_value_for_type(
983        &mut self,
984        node: &swamp_ast::Node,
985        field_type: &TypeRef,
986    ) -> Option<Expression> {
987        let kind = match &*field_type.kind {
988            TypeKind::Tuple(tuple_type_ref) => {
989                let mut expressions = Vec::new();
990                for resolved_type in tuple_type_ref {
991                    let expr = self.create_default_value_for_type(node, resolved_type)?;
992                    expressions.push(expr);
993                }
994                ExpressionKind::TupleLiteral(expressions)
995            }
996
997            TypeKind::NamedStruct(_struct_ref) => {
998                // Only call default() if the type actually has a default implementation
999                if self
1000                    .shared
1001                    .state
1002                    .associated_impls
1003                    .get_member_function(field_type, "default")
1004                    .is_some()
1005                {
1006                    self.create_default_static_call(node, field_type)
1007                } else {
1008                    // This type doesn't have a default implementation, skip it
1009                    return None;
1010                }
1011            }
1012
1013            _ => {
1014                // For primitives and other types without default implementations, skip them
1015                return None;
1016            }
1017        };
1018
1019        Some(self.create_expr(kind, field_type.clone(), node))
1020    }
1021
1022    fn create_static_member_call(
1023        &mut self,
1024        function_name: &str,
1025        arguments: &[ArgumentExpression],
1026        node: &swamp_ast::Node,
1027        ty: &TypeRef,
1028    ) -> ExpressionKind {
1029        self.lookup_associated_function(ty, function_name)
1030            .map_or_else(
1031                || {
1032                    self.create_err(
1033                        ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
1034                        node,
1035                    )
1036                    .kind
1037                },
1038                |function| {
1039                    let Function::Internal(internal_function) = &function else {
1040                        panic!("only allowed for internal functions");
1041                    };
1042
1043                    ExpressionKind::InternalCall(internal_function.clone(), arguments.to_vec())
1044                },
1045            )
1046    }
1047
1048    fn create_static_member_intrinsic_call(
1049        &mut self,
1050        function_name: &str,
1051        arguments: &[ArgumentExpression],
1052        node: &swamp_ast::Node,
1053        ty: &TypeRef,
1054    ) -> ExpressionKind {
1055        // Look up the function first to avoid closure borrowing issues
1056        if let Some(function) = self.lookup_associated_function(ty, function_name) {
1057            let Function::Internal(internal_function) = &function else {
1058                panic!("only allowed for internal functions");
1059            };
1060
1061            if let Some((intrinsic_fn, _)) =
1062                Self::extract_single_intrinsic_call(&internal_function.body)
1063            {
1064                ExpressionKind::IntrinsicCallEx(intrinsic_fn, arguments.to_vec())
1065            } else {
1066                self.create_err(
1067                    ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
1068                    node,
1069                )
1070                .kind
1071            }
1072        } else {
1073            self.create_err(
1074                ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
1075                node,
1076            )
1077            .kind
1078        }
1079    }
1080
1081    fn create_default_static_call(
1082        &mut self,
1083        node: &swamp_ast::Node,
1084        ty: &TypeRef,
1085    ) -> ExpressionKind {
1086        self.create_static_member_call("default", &[], node, ty)
1087    }
1088
1089    fn add_postfix(
1090        &mut self,
1091        vec: &mut Vec<Postfix>,
1092        kind: PostfixKind,
1093        ty: TypeRef,
1094        node: &swamp_ast::Node,
1095    ) {
1096        let resolved_node = self.to_node(node);
1097        let postfix = Postfix {
1098            node: resolved_node,
1099            ty,
1100            kind,
1101        };
1102
1103        vec.push(postfix);
1104    }
1105
1106    /// # Panics
1107    ///
1108    /// # Errors
1109    ///
1110    pub fn analyze_struct_field(
1111        &mut self,
1112        field_name: &swamp_ast::Node,
1113        tv: &TypeRef,
1114    ) -> (AnonymousStructType, usize, TypeRef) {
1115        let field_name_str = self.get_text(field_name).to_string();
1116
1117        let anon_struct_ref = match &*tv.kind {
1118            TypeKind::NamedStruct(struct_type) => struct_type.anon_struct_type.clone(),
1119            TypeKind::AnonymousStruct(anon_struct) => {
1120                // Create a TypeRef from the AnonymousStructType
1121                self.shared
1122                    .state
1123                    .types
1124                    .anonymous_struct(anon_struct.clone())
1125            }
1126            TypeKind::Range(range_struct_ref) => {
1127                // Extract NamedStructType from TypeRef, then AnonymousStructType from that
1128                if let TypeKind::NamedStruct(named_struct) = &*range_struct_ref.kind {
1129                    named_struct.anon_struct_type.clone()
1130                } else {
1131                    self.add_err(ErrorKind::UnknownStructField, field_name);
1132                    // Return fallback values
1133                    return (
1134                        AnonymousStructType::new(SeqMap::new()),
1135                        0,
1136                        self.shared.state.types.unit(),
1137                    );
1138                }
1139            }
1140            _ => {
1141                self.add_err(ErrorKind::UnknownStructField, field_name);
1142                // Return fallback values
1143                return (
1144                    AnonymousStructType::new(SeqMap::new()),
1145                    0,
1146                    self.shared.state.types.unit(),
1147                );
1148            }
1149        };
1150
1151        // Extract the AnonymousStructType from the TypeRef
1152        if let TypeKind::AnonymousStruct(anon_struct) = &*anon_struct_ref.kind {
1153            if let Some(found_field) = anon_struct.field_name_sorted_fields.get(&field_name_str) {
1154                let index = anon_struct
1155                    .field_name_sorted_fields
1156                    .get_index(&field_name_str)
1157                    .expect("checked earlier");
1158
1159                return (anon_struct.clone(), index, found_field.field_type.clone());
1160            }
1161        }
1162
1163        self.add_err(ErrorKind::UnknownStructField, field_name);
1164        // Return fallback values
1165        (
1166            AnonymousStructType::new(SeqMap::new()),
1167            0,
1168            self.shared.state.types.unit(),
1169        )
1170    }
1171
1172    pub fn analyze_static_call(
1173        &mut self,
1174        ast_node: &swamp_ast::Node,
1175        maybe_associated_to_type: Option<TypeRef>,
1176        func_def: Function,
1177        maybe_generic_arguments: &Option<Vec<swamp_ast::GenericParameter>>,
1178        arguments: &[swamp_ast::Expression],
1179        context: &TypeContext,
1180    ) -> Expression {
1181        let signature = func_def.signature().clone();
1182
1183        let analyzed_arguments =
1184            self.analyze_and_verify_parameters(ast_node, &signature.parameters, arguments);
1185
1186        let expr_kind = match &func_def {
1187            Function::Internal(internal) => {
1188                ExpressionKind::InternalCall(internal.clone(), analyzed_arguments)
1189            }
1190            Function::External(host) => ExpressionKind::HostCall(host.clone(), analyzed_arguments),
1191            Function::Intrinsic(intrinsic) => {
1192                ExpressionKind::IntrinsicCallEx(intrinsic.intrinsic.clone(), analyzed_arguments)
1193            }
1194        };
1195
1196        let expr = self.create_expr(expr_kind, signature.return_type.clone(), ast_node);
1197
1198        // Check if function returns a type that needs explicit storage and we don't have an lvalue target
1199        if self.needs_storage_error(&expr, true, context, ast_node) {
1200            return self.create_err(ErrorKind::NeedStorage, ast_node);
1201        }
1202
1203        expr
1204    }
1205
1206    #[allow(clippy::too_many_lines)]
1207    fn analyze_postfix_chain(
1208        &mut self,
1209        chain: &swamp_ast::PostfixChain,
1210        context: &TypeContext,
1211    ) -> Expression {
1212        let maybe_start_of_chain_base =
1213            self.analyze_start_chain_expression_get_mutability(&chain.base);
1214
1215        let mut start_index = 0;
1216
1217        let start_of_chain_kind = if let Some(start_of_chain_base) = maybe_start_of_chain_base {
1218            //trace!(?start_of_chain_base, "start of postfix chain");
1219            match start_of_chain_base {
1220                StartOfChainBase::FunctionReference(func_def) => {
1221                    // In this language version, it is not allowed to provide references to functions
1222                    // So it must mean that this is a function call
1223                    if let swamp_ast::Postfix::FunctionCall(
1224                        ast_node,
1225                        maybe_generic_arguments,
1226                        arguments,
1227                    ) = &chain.postfixes[0]
1228                    {
1229                        start_index = 1;
1230                        let call_expr = self.analyze_static_call(
1231                            ast_node,
1232                            None,
1233                            func_def,
1234                            maybe_generic_arguments,
1235                            arguments,
1236                            context,
1237                        );
1238                        if chain.postfixes.len() == 1 {
1239                            return call_expr;
1240                        }
1241                        StartOfChainKind::Expression(Box::from(call_expr))
1242                    } else {
1243                        panic!("must be a normal function call")
1244                    }
1245                }
1246                StartOfChainBase::Variable(var) => StartOfChainKind::Variable(var),
1247            }
1248        } else {
1249            let ctx = TypeContext::new_anything_argument(true); // we will allocate space for the starting point
1250            StartOfChainKind::Expression(Box::from(self.analyze_expression(&chain.base, &ctx)))
1251        };
1252
1253        let start_of_chain_node = self.to_node(&chain.base.node);
1254
1255        let start_of_chain = StartOfChain {
1256            kind: start_of_chain_kind.clone(),
1257            node: start_of_chain_node,
1258        };
1259
1260        let mut tv = TypeWithMut {
1261            resolved_type: start_of_chain_kind.ty(),
1262            is_mutable: start_of_chain_kind.is_mutable(),
1263        };
1264
1265        let mut uncertain = false;
1266
1267        let mut suffixes = Vec::new();
1268
1269        for (index, item) in chain.postfixes[start_index..].iter().enumerate() {
1270            //            trace!(?item, "postfix");
1271            let is_last = index == chain.postfixes[start_index..].len() - 1;
1272
1273            match item {
1274                /*
1275                swamp_ast::Postfix::AdvancedFunctionCall(..) => {
1276                    todo!("AdvancedFunctionCall")
1277                }
1278
1279                 */
1280                swamp_ast::Postfix::FieldAccess(field_name) => {
1281                    let (struct_type_ref, index, return_type) =
1282                        self.analyze_struct_field(&field_name.clone(), &tv.resolved_type);
1283                    let struct_type_type_ref = self
1284                        .shared
1285                        .state
1286                        .types
1287                        .anonymous_struct(struct_type_ref.clone());
1288                    self.add_postfix(
1289                        &mut suffixes,
1290                        PostfixKind::StructField(struct_type_type_ref, index),
1291                        return_type.clone(),
1292                        field_name,
1293                    );
1294
1295                    tv.resolved_type = return_type.clone();
1296                    // keep previous `is_mutable`
1297                }
1298
1299                swamp_ast::Postfix::SubscriptTuple(col_expr, row_expr) => {
1300                    let collection_type = tv.resolved_type.clone();
1301                    match &*collection_type.kind {
1302                        TypeKind::GridStorage(element_type, x, _) => {
1303                            let int_type = self.shared.state.types.int();
1304                            let unsigned_int_x_context =
1305                                TypeContext::new_argument(&int_type, false);
1306                            let unsigned_int_x_expression =
1307                                self.analyze_expression(col_expr, &unsigned_int_x_context);
1308
1309                            let unsigned_int_y_context =
1310                                TypeContext::new_argument(&int_type, false);
1311                            let unsigned_int_y_expression =
1312                                self.analyze_expression(row_expr, &unsigned_int_y_context);
1313
1314                            let vec_type = GridType {
1315                                element: element_type.clone(),
1316                            };
1317
1318                            self.add_postfix(
1319                                &mut suffixes,
1320                                PostfixKind::GridSubscript(
1321                                    vec_type,
1322                                    unsigned_int_x_expression,
1323                                    unsigned_int_y_expression,
1324                                ),
1325                                element_type.clone(),
1326                                &col_expr.node,
1327                            );
1328
1329                            // Keep previous mutable
1330                            tv.resolved_type = element_type.clone();
1331                        }
1332                        _ => panic!("not a subscript tuple"),
1333                    }
1334                }
1335
1336                swamp_ast::Postfix::Subscript(lookup_expr) => {
1337                    let collection_type = tv.resolved_type.clone();
1338                    match &*collection_type.kind {
1339                        TypeKind::FixedCapacityAndLengthArray(element_type_in_slice, _) => {
1340                            let int_type = self.shared.state.types.int();
1341                            let unsigned_int_context = TypeContext::new_argument(&int_type, false);
1342                            let unsigned_int_expression =
1343                                self.analyze_expression(lookup_expr, &unsigned_int_context);
1344
1345                            let slice_type = SliceViewType {
1346                                element: element_type_in_slice.clone(),
1347                            };
1348
1349                            self.add_postfix(
1350                                &mut suffixes,
1351                                PostfixKind::SliceViewSubscript(
1352                                    slice_type,
1353                                    unsigned_int_expression,
1354                                ),
1355                                collection_type.clone(),
1356                                &lookup_expr.node,
1357                            );
1358
1359                            // Keep previous mutable
1360                            tv.resolved_type = element_type_in_slice.clone();
1361                        }
1362                        TypeKind::QueueStorage(element_type, _)
1363                        | TypeKind::StackStorage(element_type, _)
1364                        | TypeKind::StackView(element_type)
1365                        | TypeKind::VecStorage(element_type, _)
1366                        | TypeKind::DynamicLengthVecView(element_type)
1367                        | TypeKind::SliceView(element_type) => {
1368                            let int_type = self.shared.state.types.int();
1369                            let unsigned_int_context = TypeContext::new_argument(&int_type, false);
1370                            let unsigned_int_expression =
1371                                self.analyze_expression(lookup_expr, &unsigned_int_context);
1372
1373                            let vec_type = VecType {
1374                                element: element_type.clone(),
1375                            };
1376
1377                            self.add_postfix(
1378                                &mut suffixes,
1379                                PostfixKind::VecSubscript(vec_type, unsigned_int_expression),
1380                                element_type.clone(),
1381                                &lookup_expr.node,
1382                            );
1383
1384                            // Keep previous mutable
1385                            tv.resolved_type = element_type.clone();
1386                        }
1387                        TypeKind::SparseStorage(element_type, _)
1388                        | TypeKind::SparseView(element_type) => {
1389                            let int_type = self.shared.state.types.int();
1390                            let unsigned_int_context = TypeContext::new_argument(&int_type, false);
1391                            let unsigned_int_expression =
1392                                self.analyze_expression(lookup_expr, &unsigned_int_context);
1393
1394                            let vec_type = SparseType {
1395                                element: element_type.clone(),
1396                            };
1397
1398                            self.add_postfix(
1399                                &mut suffixes,
1400                                PostfixKind::SparseSubscript(vec_type, unsigned_int_expression),
1401                                element_type.clone(),
1402                                &lookup_expr.node,
1403                            );
1404
1405                            // Keep previous mutable
1406                            tv.resolved_type = element_type.clone();
1407                        }
1408                        TypeKind::MapStorage(key_type, value_type, _)
1409                        | TypeKind::DynamicLengthMapView(key_type, value_type) => {
1410                            let key_context = TypeContext::new_argument(key_type, false);
1411                            let key_expression = self.analyze_expression(lookup_expr, &key_context);
1412
1413                            let map_type = MapType {
1414                                key: key_type.clone(),
1415                                value: value_type.clone(),
1416                            };
1417
1418                            self.add_postfix(
1419                                &mut suffixes,
1420                                PostfixKind::MapSubscript(map_type, key_expression),
1421                                value_type.clone(),
1422                                &lookup_expr.node,
1423                            );
1424
1425                            // Keep previous mutable
1426                            tv.resolved_type = value_type.clone();
1427                        }
1428                        _ => {
1429                            eprintln!("xwhat is this: {collection_type:?}");
1430                            return self
1431                                .create_err(ErrorKind::MissingSubscriptMember, &lookup_expr.node);
1432                        }
1433                    }
1434
1435                    /*
1436
1437                    let temp_lookup_context = TypeContext::new_anything_argument();
1438                    let temp_analyzed_expr =
1439                        self.analyze_expression(index_expr, &temp_lookup_context)?;
1440
1441                    let mut subscript_function_name = "subscript";
1442
1443                    if let TypeKind::NamedStruct(named_struct) = temp_analyzed_expr.ty {
1444                        if named_struct.assigned_name == "Range"
1445                            && named_struct.module_path == vec!["core-0.0.0".to_string()]
1446                        {
1447                            subscript_function_name = "subscript_range";
1448                        }
1449                    };
1450
1451                    if let Some(found) = self
1452                        .shared
1453                        .state
1454                        .instantiator
1455                        .associated_impls
1456                        .get_member_function(&tv.resolved_type, subscript_function_name)
1457                        .cloned()
1458                    {
1459                        let cloned = found.clone();
1460                        let required_type = &found.signature().parameters[1].resolved_type;
1461                        let subscript_lookup_context = TypeContext::new_argument(&required_type);
1462                        let analyzed_expr =
1463                            self.analyze_expression(index_expr, &subscript_lookup_context)?;
1464
1465                        let return_type = *found.signature().return_type.clone();
1466
1467                        let argument = MutRefOrImmutableExpression::Expression(analyzed_expr);
1468                        self.add_postfix(
1469                            &mut suffixes,
1470                            PostfixKind::MemberCall(cloned, vec![argument]),
1471                            return_type.clone(),
1472                            &index_expr.node,
1473                        );
1474                        tv.resolved_type = return_type.clone();
1475                    } else {
1476                        return self.create_err(ErrorKind::MissingSubscriptMember, &index_expr.node);
1477                    }
1478
1479                     */
1480                }
1481
1482                swamp_ast::Postfix::MemberCall(member_name, generic_arguments, ast_arguments) => {
1483                    let member_name_str = self.get_text(member_name).to_string();
1484                    let underlying_type = tv.resolved_type;
1485
1486                    let (kind, return_type) = self.analyze_member_call(
1487                        &underlying_type,
1488                        &member_name_str,
1489                        generic_arguments.clone(),
1490                        ast_arguments,
1491                        tv.is_mutable,
1492                        member_name,
1493                    );
1494
1495                    self.add_postfix(&mut suffixes, kind, return_type.clone(), member_name);
1496                    tv.resolved_type = return_type.clone();
1497                    tv.is_mutable = false;
1498                    /*
1499                    if let Some(_found_member) = self
1500                        .shared
1501                        .state
1502                        .instantiator
1503                        .associated_impls
1504                        .get_member_function(&underlying_type, &member_name_str)
1505                    {
1506                        let return_type = self.analyze_postfix_member_call(
1507                            &tv.resolved_type,
1508                            tv.is_mutable,
1509                            member_name,
1510                            generic_arguments.clone(),
1511                            ast_arguments,
1512                            &mut suffixes,
1513                        )?;
1514
1515                        //self.add_postfix(&mut suffixes, kind, return_type.clone(), member_name);
1516                        tv.resolved_type = return_type.clone();
1517                        tv.is_mutable = false;
1518                    } else {
1519                        return self.create_err(
1520                            ErrorKind::UnknownMemberFunction(underlying_type.clone()),
1521                            member_name,
1522                        );
1523                    }
1524
1525                     */
1526                }
1527                swamp_ast::Postfix::FunctionCall(node, _generic_arguments, arguments) => {
1528                    /*
1529                    if let TypeKind::Function(signature) = &*tv.resolved_type.kind {
1530                        let resolved_node = self.to_node(node);
1531                        let resolved_arguments = self.analyze_and_verify_parameters(
1532                            &resolved_node,
1533                            &signature.parameters,
1534                            arguments,
1535                        )?;
1536
1537                        let call_kind = PostfixKind::FunctionCall(resolved_arguments);
1538
1539                        self.add_postfix(
1540                            &mut suffixes,
1541                            call_kind,
1542                            *signature.return_type.clone(),
1543                            node,
1544                        );
1545
1546                        tv.resolved_type = *signature.return_type.clone();
1547                        tv.is_mutable = false;
1548
1549                    } else {
1550                        panic!("{}", &format!("what is this type {:?} ", tv.resolved_type))
1551                    }
1552
1553                     */
1554                    panic!("can only have function call at the start of a postfix chain")
1555                }
1556
1557                swamp_ast::Postfix::NoneCoalescingOperator(default_expr) => {
1558                    let unwrapped_type = if let TypeKind::Optional(unwrapped_type) =
1559                        &*tv.resolved_type.kind
1560                    {
1561                        unwrapped_type
1562                    } else if uncertain {
1563                        &tv.resolved_type
1564                    } else {
1565                        return self.create_err(ErrorKind::CanNotNoneCoalesce, &default_expr.node);
1566                    };
1567
1568                    let unwrapped_type_context = TypeContext::new_argument(unwrapped_type, false);
1569                    let resolved_default_expr =
1570                        self.analyze_expression(default_expr, &unwrapped_type_context);
1571                    self.add_postfix(
1572                        &mut suffixes,
1573                        PostfixKind::NoneCoalescingOperator(resolved_default_expr),
1574                        (*unwrapped_type).clone(),
1575                        &default_expr.node,
1576                    );
1577                    tv.resolved_type = (*unwrapped_type).clone();
1578                    uncertain = false; // the chain is safe, because this will always solve None
1579                }
1580
1581                swamp_ast::Postfix::OptionalChainingOperator(option_node) => {
1582                    if is_last {
1583                        return self.create_err(
1584                            ErrorKind::OptionalChainingOperatorCanNotBePartOfChain,
1585                            option_node,
1586                        );
1587                    }
1588
1589                    if let TypeKind::Optional(unwrapped_type) = &*tv.resolved_type.kind {
1590                        uncertain = true;
1591                        self.add_postfix(
1592                            &mut suffixes,
1593                            PostfixKind::OptionalChainingOperator,
1594                            (*unwrapped_type).clone(),
1595                            option_node,
1596                        );
1597                        tv.resolved_type = (*unwrapped_type).clone();
1598                    } else {
1599                        return self.create_err(ErrorKind::ExpectedOptional, option_node);
1600                    }
1601                }
1602            }
1603        }
1604
1605        if uncertain {
1606            if let TypeKind::Optional(_) = &*tv.resolved_type.kind {
1607            } else {
1608                tv.resolved_type = self.shared.state.types.optional(&tv.resolved_type.clone());
1609            }
1610        }
1611
1612        self.create_expr(
1613            ExpressionKind::PostfixChain(start_of_chain, suffixes),
1614            tv.resolved_type,
1615            &chain.base.node,
1616        )
1617    }
1618
1619    fn analyze_bool_argument_expression(
1620        &mut self,
1621        expression: &swamp_ast::Expression,
1622    ) -> BooleanExpression {
1623        let bool_type = self.shared.state.types.bool();
1624        let bool_context = TypeContext::new_argument(&bool_type, false);
1625        let resolved_expression = self.analyze_expression(expression, &bool_context);
1626        let expr_type = resolved_expression.ty.clone();
1627
1628        let bool_expression = match &*expr_type.kind {
1629            TypeKind::Bool => resolved_expression,
1630            TypeKind::Optional(_) => {
1631                let bool = self.types().bool();
1632                self.create_expr(
1633                    ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1634                    bool,
1635                    &expression.node,
1636                )
1637            }
1638            _ => self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node),
1639        };
1640
1641        BooleanExpression {
1642            expression: Box::from(bool_expression),
1643        }
1644    }
1645
1646    /// Check if an expression is a function call that returns an aggregate type
1647    fn is_aggregate_function_call(expression: &swamp_ast::Expression) -> bool {
1648        match &expression.kind {
1649            swamp_ast::ExpressionKind::PostfixChain(chain) => {
1650                if chain.postfixes.is_empty() {
1651                    return false;
1652                }
1653
1654                for postfix in &chain.postfixes {
1655                    if let swamp_ast::Postfix::FunctionCall(_, _, _) = postfix {
1656                        return true;
1657                    }
1658                }
1659                false
1660            }
1661            _ => false, // Other expressions (variables, literals, etc.) are not function calls
1662        }
1663    }
1664
1665    fn analyze_iterable(
1666        &mut self,
1667        mut_requested_for_value_variable: Option<swamp_ast::Node>,
1668        expression: &swamp_ast::Expression,
1669    ) -> Iterable {
1670        // Only set has_lvalue_target=false for function calls that return aggregates
1671        // Variables/parameters already have storage, so they should have has_lvalue_target=true
1672        let has_lvalue_target = !Self::is_aggregate_function_call(expression);
1673        let any_context = TypeContext::new_anything_argument(has_lvalue_target);
1674
1675        let resolved_expression = self.analyze_expression(expression, &any_context);
1676
1677        let resolved_type = &resolved_expression.ty.clone();
1678        let int_type = Some(self.types().int());
1679        let (key_type, value_type): (Option<TypeRef>, TypeRef) = match &*resolved_type.kind {
1680            TypeKind::String => (int_type, self.types().string()),
1681            TypeKind::SliceView(element_type) => (int_type, element_type.clone()),
1682            TypeKind::VecStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1683            TypeKind::SparseStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1684            TypeKind::StackStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1685            TypeKind::StackView(element_type) => (int_type, element_type.clone()),
1686            TypeKind::QueueStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1687            TypeKind::QueueView(element_type) => (int_type, element_type.clone()),
1688            TypeKind::DynamicLengthVecView(element_type) => (int_type, element_type.clone()),
1689            TypeKind::SparseView(element_type) => (int_type, element_type.clone()),
1690            TypeKind::DynamicLengthMapView(key_type, value_type)
1691            | TypeKind::MapStorage(key_type, value_type, _) => {
1692                (Some(key_type.clone()), value_type.clone())
1693            }
1694            TypeKind::Range(_) => (None, self.types().int()),
1695            _ => {
1696                error!(?resolved_type, "not an iterator");
1697                return Iterable {
1698                    key_type: None,
1699                    value_type: self.shared.state.types.unit(),
1700                    resolved_expression: Box::new(
1701                        self.create_err(ErrorKind::NotAnIterator, &expression.node),
1702                    ),
1703                };
1704            }
1705        };
1706
1707        if mut_requested_for_value_variable.is_some() {
1708            // we check if we can get to a lvalue, otherwise it is not mutable:
1709            let _resulting_location =
1710                self.analyze_to_location(expression, &any_context, LocationSide::Mutable);
1711            // Note: mutable references are now handled through SingleLocationExpression
1712            // The value_type stays the same, mutability is tracked separately
1713        }
1714
1715        Iterable {
1716            key_type,
1717            value_type,
1718            resolved_expression: Box::new(resolved_expression),
1719        }
1720    }
1721
1722    fn analyze_argument_expressions(
1723        &mut self,
1724        expected_type: Option<&TypeRef>,
1725        context: &TypeContext,
1726        ast_expressions: &[swamp_ast::Expression],
1727    ) -> Vec<Expression> {
1728        let mut resolved_expressions = Vec::new();
1729        // Function arguments should not have lvalue targets by default - they need proper storage allocation
1730        let argument_expressions_context = TypeContext::new_unsure_argument(expected_type, false);
1731
1732        for expression in ast_expressions {
1733            resolved_expressions
1734                .push(self.analyze_expression(expression, &argument_expressions_context));
1735        }
1736        resolved_expressions
1737    }
1738
1739    fn analyze_block(
1740        &mut self,
1741        _node: &swamp_ast::Node,
1742        context: &TypeContext,
1743        ast_expressions: &[swamp_ast::Expression],
1744    ) -> (Vec<Expression>, TypeRef) {
1745        if ast_expressions.is_empty() {
1746            return (vec![], self.shared.state.types.unit());
1747        }
1748
1749        self.push_block_scope("block");
1750
1751        let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1752
1753        for expression in &ast_expressions[..ast_expressions.len() - 1] {
1754            let unit_type = self.shared.state.types.unit();
1755            let stmt_context =
1756                context.with_expected_type(Some(&unit_type), context.has_lvalue_target);
1757            let expr = self.analyze_expression(expression, &stmt_context);
1758
1759            resolved_expressions.push(expr);
1760        }
1761
1762        // Process the last expression - it determines the block's type
1763        let last_expr =
1764            self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context);
1765        let last_type = last_expr.ty.clone();
1766        resolved_expressions.push(last_expr);
1767
1768        self.pop_block_scope("block");
1769
1770        (resolved_expressions, last_type)
1771    }
1772
1773    fn analyze_interpolated_string_lowering(
1774        &mut self,
1775        node: &swamp_ast::Node,
1776        string_parts: &[swamp_ast::StringPart],
1777    ) -> Expression {
1778        let mut last_expression: Option<Expression> = None;
1779        for part in string_parts {
1780            let created_expression = match part {
1781                swamp_ast::StringPart::Literal(string_node, processed_string) => {
1782                    let string_literal =
1783                        ExpressionKind::StringLiteral(processed_string.to_string());
1784                    let basic_literal = string_literal;
1785                    let string_type = self.shared.state.types.string();
1786                    self.create_expr(basic_literal, string_type, string_node)
1787                }
1788                swamp_ast::StringPart::Interpolation(expression, format_specifier) => {
1789                    let any_context = TypeContext::new_anything_argument(false); // String interpolation context has no lvalue target for storage
1790
1791                    let expr = self.analyze_expression(expression, &any_context);
1792
1793                    let tk = (*expr.ty.kind).clone();
1794
1795                    let maybe_to_string = self
1796                        .shared
1797                        .state
1798                        .associated_impls
1799                        .get_internal_member_function(&expr.ty, "to_string");
1800
1801                    if matches!(tk, TypeKind::String) {
1802                        expr
1803                    } else {
1804                        let underlying = expr.ty.clone();
1805
1806                        // Check if the expression needs storage validation before proceeding
1807                        if self.needs_storage_error(&expr, true, &any_context, &expression.node) {
1808                            return self.create_err(ErrorKind::NeedStorage, &expression.node);
1809                        }
1810
1811                        let call_expr_kind = if maybe_to_string.is_none() {
1812                            let string_type = self.types().string();
1813
1814                            ExpressionKind::StringLiteral(format!("missing {string_type}"))
1815                            /* TODO:
1816
1817                                       return self.create_err(
1818                                           ErrorKind::MissingToString(string_type),
1819                                           &expression.node,
1820                                       );
1821
1822                            */
1823                        } else {
1824                            let expr_as_param = ArgumentExpression::Expression(expr);
1825                            self.create_static_member_call(
1826                                "to_string",
1827                                &[expr_as_param.clone()],
1828                                &expression.node,
1829                                &underlying,
1830                            )
1831                        };
1832
1833                        /*
1834                        TODO: SUPPORT FORMAT SPEC
1835                        let resolved_format_specifier =
1836                            self.analyze_format_specifier(Option::from(format_specifier));
1837
1838                         */
1839
1840                        let string_type = self.shared.state.types.string();
1841                        self.create_expr(call_expr_kind, string_type, &expression.node)
1842                    }
1843                }
1844            };
1845
1846            let x_last_expr = if let Some(last_expr) = last_expression.clone() {
1847                let op_kind = BinaryOperatorKind::Add;
1848                let node = created_expression.node.clone();
1849                let op = BinaryOperator {
1850                    left: Box::new(last_expr),
1851                    right: Box::new(created_expression),
1852                    kind: op_kind,
1853                    node: node.clone(),
1854                };
1855
1856                let string_type = self.shared.state.types.string();
1857                create_expr_resolved(ExpressionKind::BinaryOp(op), string_type, &node)
1858            } else {
1859                created_expression
1860            };
1861
1862            last_expression = Some(x_last_expr);
1863        }
1864
1865        if last_expression.is_none() {
1866            let string_type = self.shared.state.types.string();
1867            return self.create_expr(
1868                ExpressionKind::StringLiteral("hello".to_string()),
1869                string_type,
1870                node,
1871            );
1872        }
1873
1874        last_expression.unwrap()
1875    }
1876
1877    pub(crate) fn analyze_identifier(
1878        &mut self,
1879        qualified_func_name: &swamp_ast::QualifiedIdentifier,
1880    ) -> Expression {
1881        // Must check variable first, since that is more intuitive for the user.
1882        // local variables before other functions
1883        if qualified_func_name.module_path.is_none()
1884            && qualified_func_name.generic_params.is_empty()
1885        {
1886            if let Some(found_variable) = self.try_find_variable(&qualified_func_name.name) {
1887                return self.create_expr(
1888                    ExpressionKind::VariableAccess(found_variable.clone()),
1889                    found_variable.resolved_type.clone(),
1890                    &qualified_func_name.name,
1891                );
1892            }
1893        }
1894
1895        let text = self.get_text(&qualified_func_name.name);
1896        self.create_err(
1897            ErrorKind::UnknownIdentifier(text.to_string()),
1898            &qualified_func_name.name,
1899        )
1900    }
1901
1902    // The ast assumes it is something similar to a variable, but it can be a function reference as well.
1903    fn analyze_variable_reference(&mut self, var_node: &swamp_ast::Node) -> Expression {
1904        if let Some(found_variable) = self.try_find_variable(var_node) {
1905            return self.create_expr(
1906                ExpressionKind::VariableAccess(found_variable.clone()),
1907                found_variable.resolved_type.clone(),
1908                var_node,
1909            );
1910        }
1911        let text = self.get_text(var_node);
1912        self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node)
1913    }
1914    fn analyze_slice_pair_literal(
1915        &mut self,
1916        node: &swamp_ast::Node,
1917        entries: &[(swamp_ast::Expression, swamp_ast::Expression)],
1918    ) -> (Vec<(Expression, Expression)>, TypeRef, TypeRef) {
1919        if entries.is_empty() {
1920            return (
1921                vec![],
1922                self.shared.state.types.unit(),
1923                self.shared.state.types.unit(),
1924            );
1925        }
1926
1927        // Resolve first entry to determine map types
1928        let (first_key, first_value) = &entries[0];
1929        let anything_context = TypeContext::new_anything_argument(true);
1930        let resolved_first_key = self.analyze_expression(first_key, &anything_context);
1931        let resolved_first_value = self.analyze_expression(first_value, &anything_context);
1932        let key_type = resolved_first_key.ty.clone();
1933        let value_type = resolved_first_value.ty.clone();
1934
1935        let key_context = TypeContext::new_argument(&key_type, true);
1936        let value_context = TypeContext::new_argument(&value_type, true);
1937
1938        // Check all entries match the types
1939        let mut resolved_entries = Vec::new();
1940        resolved_entries.push((resolved_first_key, resolved_first_value));
1941
1942        for (key, value) in entries.iter().skip(1) {
1943            let resolved_key = self.analyze_expression(key, &key_context);
1944            let resolved_value = self.analyze_expression(value, &value_context);
1945
1946            if !self
1947                .shared
1948                .state
1949                .types
1950                .compatible_with(&resolved_key.ty, &key_type)
1951            {
1952                return (
1953                    vec![],
1954                    self.shared.state.types.unit(),
1955                    self.shared.state.types.unit(),
1956                );
1957            }
1958
1959            if !self
1960                .shared
1961                .state
1962                .types
1963                .compatible_with(&resolved_value.ty, &value_type)
1964            {
1965                return (
1966                    vec![],
1967                    self.shared.state.types.unit(),
1968                    self.shared.state.types.unit(),
1969                );
1970            }
1971
1972            resolved_entries.push((resolved_key, resolved_value));
1973        }
1974
1975        (resolved_entries, key_type, value_type)
1976    }
1977
1978    fn analyze_internal_initializer_pair_list(
1979        &mut self,
1980        node: &swamp_ast::Node,
1981        items: &[(swamp_ast::Expression, swamp_ast::Expression)],
1982        context: &TypeContext,
1983    ) -> (TypeRef, Vec<(Expression, Expression)>) {
1984        let (collection_type, key_type, value_type) = if let Some(expected_type) =
1985            context.expected_type
1986        {
1987            match &*expected_type.kind {
1988                TypeKind::MapStorage(key, value, capacity) => {
1989                    if items.len() > *capacity {
1990                        self.add_err(
1991                            ErrorKind::TooManyInitializerListElementsForStorage {
1992                                capacity: *capacity,
1993                            },
1994                            node,
1995                        );
1996                        return (self.types().unit(), vec![]);
1997                    }
1998                    (expected_type.clone(), key.clone(), value.clone())
1999                }
2000                TypeKind::DynamicLengthMapView(key, value) => {
2001                    (expected_type.clone(), key.clone(), value.clone())
2002                }
2003                _ => {
2004                    self.add_err(ErrorKind::ExpectedSlice, node);
2005                    return (self.types().unit(), vec![]);
2006                }
2007            }
2008        } else if items.is_empty() {
2009            self.add_err(ErrorKind::NoInferredTypeForEmptyInitializer, node);
2010            return (self.types().unit(), vec![]);
2011        } else {
2012            // Try to detect, by checking the first
2013            let maybe_key_context = TypeContext::new_anything_argument(true);
2014
2015            let first_key_expression = self.analyze_expression(&items[0].0, &maybe_key_context);
2016
2017            let maybe_value_context = TypeContext::new_anything_argument(true);
2018            let first_value_expression = self.analyze_expression(&items[0].1, &maybe_value_context);
2019
2020            let required_key_type = first_key_expression.ty;
2021            let required_value_type = first_value_expression.ty;
2022
2023            let inferred_type =
2024                self.types()
2025                    .map_storage(&required_key_type, &required_value_type, items.len());
2026
2027            (inferred_type, required_key_type, required_value_type)
2028        };
2029
2030        assert!(!matches!(*key_type.kind, TypeKind::Unit));
2031        assert!(!matches!(*value_type.kind, TypeKind::Unit));
2032
2033        let required_key_context = TypeContext::new_argument(&key_type, true);
2034        let required_value_context = TypeContext::new_argument(&value_type, true);
2035
2036        let mut resolved_items = Vec::new();
2037
2038        for (key_expr, value_expr) in items {
2039            let analyzed_key_expr = self.analyze_expression(key_expr, &required_key_context);
2040            let analyzed_value_expr = self.analyze_expression(value_expr, &required_value_context);
2041            resolved_items.push((analyzed_key_expr, analyzed_value_expr));
2042        }
2043
2044        (collection_type, resolved_items)
2045    }
2046
2047    fn analyze_internal_initializer_list(
2048        &mut self,
2049        node: &swamp_ast::Node,
2050        items: &[swamp_ast::Expression],
2051        context: &TypeContext,
2052    ) -> (TypeRef, Vec<Expression>) {
2053        let (collection_type, element_type) = if let Some(expected_type) = context.expected_type {
2054            match &*expected_type.kind {
2055                TypeKind::GridStorage(element_type, width, height) => {
2056                    let capacity = width * height;
2057                    if items.len() > capacity {
2058                        return (
2059                            self.types().unit(),
2060                            self.create_err_vec(
2061                                ErrorKind::TooManyInitializerListElementsForStorage { capacity },
2062                                node,
2063                            ),
2064                        );
2065                    }
2066                    (expected_type.clone(), element_type.clone())
2067                }
2068                TypeKind::StackStorage(element_type, capacity)
2069                | TypeKind::QueueStorage(element_type, capacity)
2070                | TypeKind::SparseStorage(element_type, capacity)
2071                | TypeKind::VecStorage(element_type, capacity) => {
2072                    if items.len() > *capacity {
2073                        return (
2074                            self.types().unit(),
2075                            self.create_err_vec(
2076                                ErrorKind::TooManyInitializerListElementsForStorage {
2077                                    capacity: *capacity,
2078                                },
2079                                node,
2080                            ),
2081                        );
2082                    }
2083                    (expected_type.clone(), element_type.clone())
2084                }
2085                TypeKind::QueueView(element_type)
2086                | TypeKind::SparseView(element_type)
2087                | TypeKind::StackView(element_type)
2088                | TypeKind::GridView(element_type)
2089                | TypeKind::DynamicLengthVecView(element_type) => {
2090                    (expected_type.clone(), element_type.clone())
2091                }
2092                TypeKind::FixedCapacityAndLengthArray(element_type, _size) => {
2093                    (expected_type.clone(), element_type.clone())
2094                }
2095                TypeKind::SliceView(element_type) => (expected_type.clone(), element_type.clone()),
2096                _ => {
2097                    return (
2098                        self.types().unit(),
2099                        self.create_err_vec(
2100                            ErrorKind::ExpectedInitializerTarget {
2101                                destination_type: expected_type.clone(),
2102                            },
2103                            node,
2104                        ),
2105                    );
2106                }
2107            }
2108        } else if items.is_empty() {
2109            return (
2110                self.types().unit(),
2111                self.create_err_vec(ErrorKind::NoInferredTypeForEmptyInitializer, node),
2112            );
2113        } else {
2114            // Try to detect, by checking the first
2115            let maybe_context = TypeContext::new_anything_argument(true);
2116            let first = self.analyze_expression(&items[0], &maybe_context);
2117            let required_type = first.ty;
2118            let inferred_vec_storage_type = self.types().vec_storage(&required_type, items.len());
2119            // Generate default functions for the inferred vec storage type
2120            let default_node = swamp_ast::Node::default();
2121            self.add_default_functions(&inferred_vec_storage_type, &default_node);
2122            (inferred_vec_storage_type, required_type)
2123        };
2124
2125        let required_context = TypeContext::new_argument(&element_type, true);
2126        let mut resolved_items = Vec::new();
2127        for item in items {
2128            let resolved_expr = self.analyze_expression(item, &required_context);
2129            resolved_items.push(resolved_expr);
2130        }
2131        (collection_type, resolved_items)
2132    }
2133
2134    fn push_block_scope(&mut self, debug_str: &str) {
2135        let register_watermark = self.scope.total_scopes.current_register;
2136
2137        self.scope.active_scope.block_scope_stack.push(BlockScope {
2138            mode: BlockScopeMode::Open,
2139            lookup: Default::default(),
2140            variables: SeqMap::default(),
2141            register_watermark,
2142        });
2143    }
2144
2145    fn push_lambda_scope(&mut self, debug_str: &str) {
2146        // Lambda scopes are virtual and completely transparent to register allocation
2147        // They don't save any watermark and don't affect register allocation
2148        self.scope.active_scope.block_scope_stack.push(BlockScope {
2149            mode: BlockScopeMode::Lambda,
2150            lookup: SeqMap::default(),
2151            variables: SeqMap::default(),
2152            register_watermark: 0, // Not used for lambda scopes
2153        });
2154    }
2155
2156    fn pop_block_scope(&mut self, debug_str: &str) {
2157        self.pop_any_block_scope();
2158    }
2159
2160    fn push_closed_block_scope(&mut self) {
2161        let register_watermark = self.scope.total_scopes.current_register;
2162        self.scope.active_scope.block_scope_stack.push(BlockScope {
2163            mode: BlockScopeMode::Closed,
2164            lookup: Default::default(),
2165            variables: SeqMap::default(),
2166            register_watermark,
2167        });
2168    }
2169
2170    fn pop_closed_block_scope(&mut self) {
2171        //self.scope.active_scope.block_scope_stack.pop();
2172        self.pop_any_block_scope();
2173    }
2174
2175    fn pop_any_block_scope(&mut self) {
2176        let scope = self.scope.active_scope.block_scope_stack.pop().unwrap();
2177
2178        // Record the highest watermark (greatest depth of virtual registers)
2179        self.scope.total_scopes.highest_virtual_register = self.scope.total_scopes.current_register;
2180
2181        // Check if we're inside a lambda scope - if so, don't restore register counter
2182        let is_inside_lambda = self
2183            .scope
2184            .active_scope
2185            .block_scope_stack
2186            .iter()
2187            .any(|s| matches!(s.mode, BlockScopeMode::Lambda));
2188
2189        if matches!(scope.mode, BlockScopeMode::Lambda) {
2190            // lambda scope - completely transparent, no register changes
2191        } else if is_inside_lambda {
2192            // block scope inside lambda - virtual, no register restoration
2193        } else {
2194            // Regular scopes restore their watermark to free up registers
2195            self.scope.total_scopes.current_register = scope.register_watermark;
2196        }
2197    }
2198
2199    fn analyze_match(
2200        &mut self,
2201        scrutinee: &swamp_ast::Expression,
2202        default_context: &TypeContext,
2203        arms: &Vec<swamp_ast::MatchArm>,
2204    ) -> (Match, TypeRef) {
2205        let mut known_type = default_context.expected_type.cloned();
2206        let own_context = default_context.clone();
2207        // Analyze the scrutinee with no specific expected type
2208        let scrutinee_context = TypeContext::new_anything_argument(true); // we just using the pointer, so pretend that it is a target
2209        let resolved_scrutinee = self.analyze_expression(scrutinee, &scrutinee_context);
2210        let scrutinee_type = resolved_scrutinee.ty.clone();
2211
2212        let mut resolved_arms = Vec::with_capacity(arms.len());
2213
2214        // Ensure we have at least one arm
2215        if arms.is_empty() {
2216            let err_match = Match {
2217                expression: Box::new(
2218                    self.create_err(ErrorKind::MatchMustHaveAtLeastOneArm, &scrutinee.node),
2219                ),
2220                arms: resolved_arms,
2221            };
2222            return (err_match, self.types().unit());
2223        }
2224
2225        for arm in arms {
2226            let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
2227                arm,
2228                &resolved_scrutinee,
2229                &own_context.with_expected_type(known_type.as_ref(), false),
2230                &scrutinee_type,
2231            );
2232
2233            if known_type.is_none() {
2234                known_type = Some(resolved_arm.expression.ty.clone());
2235            }
2236            resolved_arms.push(resolved_arm);
2237        }
2238
2239        if let Some(encountered_type) = known_type {
2240            (
2241                Match {
2242                    expression: Box::new(resolved_scrutinee),
2243                    arms: resolved_arms,
2244                },
2245                encountered_type,
2246            )
2247        } else {
2248            let err_expr = self.create_err(ErrorKind::MatchArmsMustHaveTypes, &scrutinee.node);
2249
2250            (
2251                Match {
2252                    expression: Box::new(err_expr),
2253                    arms: resolved_arms.clone(),
2254                },
2255                self.types().unit(),
2256            )
2257        }
2258    }
2259
2260    fn analyze_arm(
2261        &mut self,
2262        arm: &swamp_ast::MatchArm,
2263        _expression: &Expression,
2264        type_context: &TypeContext,
2265        expected_condition_type: &TypeRef,
2266    ) -> (MatchArm, bool) {
2267        let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
2268            self.analyze_pattern(&arm.pattern, expected_condition_type);
2269
2270        let resolved_expression = self.analyze_expression(&arm.expression, type_context);
2271        if scope_was_pushed {
2272            self.pop_block_scope("analyze_arm");
2273        }
2274
2275        let resolved_type = resolved_expression.ty.clone();
2276
2277        (
2278            MatchArm {
2279                pattern: resolved_pattern,
2280                expression: Box::from(resolved_expression),
2281                expression_type: resolved_type,
2282            },
2283            anyone_wants_mutable,
2284        )
2285    }
2286
2287    fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
2288        let text = text.replace('_', "");
2289        text.strip_prefix("0x").map_or_else(
2290            || {
2291                text.strip_prefix("-0x").map_or_else(
2292                    || text.parse::<i32>(),
2293                    |rest| i32::from_str_radix(rest, 16).map(|x| -x),
2294                )
2295            },
2296            |rest| i32::from_str_radix(rest, 16),
2297        )
2298    }
2299
2300    fn str_to_unsigned_int(text: &str) -> Result<u32, ParseIntError> {
2301        let text = text.replace('_', "");
2302        text.strip_prefix("0x")
2303            .map_or_else(|| text.parse::<u32>(), |rest| u32::from_str_radix(rest, 16))
2304    }
2305
2306    fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
2307        text.parse::<f32>()
2308    }
2309
2310    fn str_to_bool(text: &str) -> Result<bool, ParseBoolError> {
2311        bool::from_str(text)
2312    }
2313
2314    fn analyze_pattern_literal(
2315        &mut self,
2316        node: &swamp_ast::Node,
2317        ast_literal: &swamp_ast::LiteralKind,
2318        expected_condition_type: &TypeRef,
2319    ) -> NormalPattern {
2320        let required_condition_type_context =
2321            TypeContext::new_argument(expected_condition_type, false);
2322        let literal = self.analyze_literal(node, ast_literal, &required_condition_type_context);
2323
2324        if !self
2325            .types()
2326            .compatible_with(&literal.ty, expected_condition_type)
2327        {
2328            return NormalPattern::Literal(self.create_err(
2329                ErrorKind::IncompatibleTypes {
2330                    expected: expected_condition_type.clone(),
2331                    found: literal.ty,
2332                },
2333                node,
2334            ));
2335        }
2336
2337        NormalPattern::Literal(literal)
2338    }
2339
2340    const fn to_node(&self, node: &swamp_ast::Node) -> Node {
2341        Node {
2342            span: Span {
2343                file_id: self.shared.file_id,
2344                offset: node.span.offset,
2345                length: node.span.length,
2346            },
2347        }
2348    }
2349
2350    fn get_module_path(&self, module_path: Option<&swamp_ast::ModulePath>) -> Vec<String> {
2351        module_path.as_ref().map_or_else(Vec::new, |found| {
2352            let mut strings = Vec::new();
2353            for path_item in &found.0 {
2354                strings.push(self.get_text(path_item).to_string());
2355            }
2356            strings
2357        })
2358    }
2359
2360    fn get_enum_variant_type(
2361        &mut self,
2362        qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2363        variant_name: &str,
2364    ) -> EnumVariantType {
2365        let Some((symbol_table, enum_name)) =
2366            self.get_symbol_table_and_name(qualified_type_identifier)
2367        else {
2368            self.add_err(
2369                ErrorKind::UnknownEnumVariantType,
2370                &qualified_type_identifier.name.0,
2371            );
2372            return EnumVariantType {
2373                common: EnumVariantCommon {
2374                    name: Default::default(),
2375                    assigned_name: String::new(),
2376                    container_index: 0,
2377                },
2378                payload_type: self.types().unit(),
2379            };
2380        };
2381
2382        if let Some(enum_name) = symbol_table.get_enum_variant_type(&enum_name, variant_name) {
2383            enum_name
2384        } else {
2385            self.add_err(
2386                ErrorKind::UnknownEnumVariantType,
2387                &qualified_type_identifier.name.0,
2388            );
2389            EnumVariantType {
2390                common: EnumVariantCommon {
2391                    name: Default::default(),
2392                    assigned_name: String::new(),
2393                    container_index: 0,
2394                },
2395                payload_type: self.types().unit(),
2396            }
2397        }
2398    }
2399
2400    pub(crate) fn get_symbol_table_and_name(
2401        &self,
2402        type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2403    ) -> Option<(&SymbolTable, String)> {
2404        let path = self.get_module_path(type_identifier.module_path.as_ref());
2405        let name = self.get_text(&type_identifier.name.0).to_string();
2406
2407        if let Some(found) = self.shared.get_symbol_table(&path) {
2408            Some((found, name))
2409        } else {
2410            None
2411        }
2412    }
2413
2414    const fn analyze_compound_operator(
2415        &self,
2416        ast_operator: &swamp_ast::CompoundOperator,
2417    ) -> CompoundOperator {
2418        let resolved_node = self.to_node(&ast_operator.node);
2419        let resolved_kind = match ast_operator.kind {
2420            swamp_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
2421            swamp_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
2422            swamp_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
2423            swamp_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
2424            swamp_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
2425        };
2426
2427        CompoundOperator {
2428            node: resolved_node,
2429            kind: resolved_kind,
2430        }
2431    }
2432
2433    const fn to_node_option(&self, maybe_node: Option<&swamp_ast::Node>) -> Option<Node> {
2434        match maybe_node {
2435            None => None,
2436            Some(node) => Some(self.to_node(node)),
2437        }
2438    }
2439
2440    const fn analyze_format_specifier(
2441        &self,
2442        ast_format_specifier: Option<&swamp_ast::FormatSpecifier>,
2443    ) -> Option<FormatSpecifier> {
2444        let f = match ast_format_specifier {
2445            None => return None,
2446            Some(ast_format) => match ast_format {
2447                swamp_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
2448                    node: self.to_node(node),
2449                    kind: FormatSpecifierKind::LowerHex,
2450                },
2451                swamp_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
2452                    node: self.to_node(node),
2453                    kind: FormatSpecifierKind::UpperHex,
2454                },
2455                swamp_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
2456                    node: self.to_node(node),
2457                    kind: FormatSpecifierKind::Binary,
2458                },
2459                swamp_ast::FormatSpecifier::Float(node) => FormatSpecifier {
2460                    node: self.to_node(node),
2461                    kind: FormatSpecifierKind::Float,
2462                },
2463                swamp_ast::FormatSpecifier::Precision(value, node, x) => {
2464                    let (precision_type, precision_node) = match x {
2465                        swamp_ast::PrecisionType::Float(node) => {
2466                            (PrecisionType::Float, self.to_node(node))
2467                        }
2468                        swamp_ast::PrecisionType::String(node) => {
2469                            (PrecisionType::String, self.to_node(node))
2470                        }
2471                    };
2472                    FormatSpecifier {
2473                        node: self.to_node(node),
2474                        kind: FormatSpecifierKind::Precision(
2475                            *value,
2476                            precision_node,
2477                            precision_type,
2478                        ),
2479                    }
2480                }
2481            },
2482        };
2483
2484        Some(f)
2485    }
2486
2487    fn analyze_with_expr(
2488        &mut self,
2489        context: &TypeContext,
2490        variables: &[swamp_ast::VariableBinding],
2491        expression: &swamp_ast::Expression,
2492    ) -> Expression {
2493        let mut variable_expressions = Vec::new();
2494
2495        for variable in variables {
2496            let any_context = TypeContext::new_anything_argument(false);
2497            let must_have_expression = if let Some(x) = &variable.expression {
2498                x
2499            } else {
2500                &swamp_ast::Expression {
2501                    kind: swamp_ast::ExpressionKind::VariableReference(variable.variable.clone()),
2502                    node: variable.variable.name.clone(),
2503                }
2504            };
2505
2506            // Determine the correct LocationSide based on the variable binding type
2507            let location_side = if variable.variable.is_mutable.is_some() {
2508                // For mutable variables in with statements, we need to check if this is an lvalue binding
2509                if let Some(expr) = &variable.expression {
2510                    // Use analyze_maybe_ref_expression to properly detect mutable references
2511                    let maybe_ref = self.analyze_maybe_ref_expression(expr);
2512                    if maybe_ref.has_borrow_mutable_reference.is_some() {
2513                        LocationSide::Mutable
2514                    } else {
2515                        LocationSide::Rhs
2516                    }
2517                } else {
2518                    // For cases like `with mut x` (no expression), it's an alias
2519                    LocationSide::Rhs
2520                }
2521            } else {
2522                // For immutable variables, always use Rhs
2523                LocationSide::Rhs
2524            };
2525
2526            let var = self.analyze_mut_or_immutable_expression(
2527                must_have_expression,
2528                &any_context,
2529                location_side,
2530            );
2531
2532            variable_expressions.push(var);
2533        }
2534
2535        self.push_closed_block_scope();
2536        let mut expressions = Vec::new();
2537        for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
2538            let initialize_variable_expression = self
2539                .create_variable_binding_for_with(&variable_binding.variable, resolved_expression);
2540
2541            // Always add the expression to ensure proper initialization/binding
2542            // Even for aliases (VariableAccess), we need the expression in the block
2543            // to establish the proper scope and binding
2544            expressions.push(initialize_variable_expression);
2545        }
2546
2547        let resolved_expression = self.analyze_expression(expression, context);
2548        // with statements are for side effects only, so they always return Unit type
2549        let block_type = self.types().unit();
2550        expressions.push(resolved_expression);
2551
2552        let block_expression_kind = ExpressionKind::Block(expressions);
2553        self.pop_closed_block_scope();
2554
2555        self.create_expr(block_expression_kind, block_type, &expression.node)
2556    }
2557
2558    fn analyze_when_expr(
2559        &mut self,
2560        context: &TypeContext,
2561        variables: &[swamp_ast::VariableBinding],
2562        true_expr: &swamp_ast::Expression,
2563        else_expr: Option<&swamp_ast::Expression>,
2564    ) -> Expression {
2565        // Since we are making new variable bindings, we have to push a scope for them
2566        self.push_block_scope("when");
2567        let mut bindings = Vec::new();
2568        for variable_binding in variables {
2569            let mut_expr = if let Some(found_expr) = &variable_binding.expression {
2570                let any_context = TypeContext::new_anything_argument(true); // we are not just having an alias binding to another value, so we can think of it having a target
2571                self.analyze_mut_or_immutable_expression(
2572                    found_expr,
2573                    &any_context,
2574                    LocationSide::Rhs,
2575                )
2576                .expect_immutable()
2577                .unwrap()
2578            } else {
2579                let same_var = self.find_variable(&variable_binding.variable);
2580
2581                // For when expressions, we always want to extract the value from the optional,
2582                // not create a mutable reference to the original variable
2583                let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
2584                self.create_expr(
2585                    generated_expr_kind,
2586                    same_var.resolved_type.clone(),
2587                    &variable_binding.variable.name,
2588                )
2589            };
2590
2591            let tk = &mut_expr.ty.kind;
2592
2593            if let TypeKind::Optional(found_ty) = &**tk {
2594                let variable_ref = self.create_variable(&variable_binding.variable, found_ty);
2595
2596                let binding = WhenBinding {
2597                    variable: variable_ref,
2598                    expr: mut_expr,
2599                };
2600                bindings.push(binding);
2601            } else {
2602                return self.create_err(ErrorKind::ExpectedOptional, &true_expr.node);
2603            }
2604        }
2605
2606        let resolved_true = self.analyze_expression(true_expr, context);
2607        let block_type = resolved_true.ty.clone();
2608
2609        self.pop_block_scope("when");
2610
2611        let maybe_resolved_else = if let Some(found_else) = else_expr {
2612            let block_type_for_true_context = context.we_know_expected_type(&block_type, false);
2613            Some(Box::new(self.analyze_expression(
2614                found_else,
2615                &block_type_for_true_context,
2616            )))
2617        } else {
2618            None
2619        };
2620
2621        let when_kind =
2622            ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
2623
2624        self.create_expr(when_kind, block_type, &true_expr.node)
2625    }
2626
2627    fn analyze_guard(
2628        &mut self,
2629        node: &swamp_ast::Node,
2630        context: &TypeContext,
2631        guard_expressions: &Vec<swamp_ast::GuardExpr>,
2632    ) -> Expression {
2633        let mut guards = Vec::new();
2634        let mut found_wildcard = None;
2635        let mut detected_type = context.expected_type.cloned();
2636
2637        for guard in guard_expressions {
2638            let resolved_condition = match &guard.clause {
2639                swamp_ast::GuardClause::Wildcard(x) => {
2640                    if found_wildcard.is_some() {
2641                        return self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node);
2642                    }
2643                    found_wildcard = Some(x);
2644                    None
2645                }
2646                swamp_ast::GuardClause::Expression(clause_expr) => {
2647                    if found_wildcard.is_some() {
2648                        return self.create_err(ErrorKind::WildcardMustBeLastInGuard, node);
2649                    }
2650                    Some(self.analyze_bool_argument_expression(clause_expr))
2651                }
2652            };
2653
2654            let resolved_result = self.analyze_expression(
2655                &guard.result,
2656                &context.with_expected_type(detected_type.as_ref(), false),
2657            );
2658            let ty = resolved_result.ty.clone();
2659            if detected_type.is_none() {
2660                detected_type = Some(ty.clone());
2661            }
2662
2663            guards.push(Guard {
2664                condition: resolved_condition,
2665                result: resolved_result,
2666            });
2667        }
2668
2669        if found_wildcard.is_none() {
2670            return self.create_err(ErrorKind::GuardMustHaveWildcard, node);
2671        }
2672
2673        let kind = ExpressionKind::Guard(guards);
2674
2675        if let Some(found_expecting_type) = detected_type {
2676            self.create_expr(kind, found_expecting_type, node)
2677        } else {
2678            self.create_err(ErrorKind::GuardHasNoType, node)
2679        }
2680    }
2681
2682    fn analyze_lambda(
2683        &mut self,
2684        node: &swamp_ast::Node,
2685        variables: &[swamp_ast::Variable],
2686        ast_expr: &swamp_ast::Expression,
2687        context: &TypeContext,
2688    ) -> Expression {
2689        let TypeKind::Function(signature) = &*context.expected_type.unwrap().kind else {
2690            return self.create_err(ErrorKind::ExpectedLambda, node);
2691        };
2692
2693        let return_block_type = TypeContext::new_argument(&signature.return_type, false);
2694
2695        // Create a lambda scope for proper variable scoping and shadowing
2696        // But the register allocation will "continue" from parent scope (no decrement on pop)
2697        self.push_lambda_scope("lambda");
2698
2699        let arity_required = signature.parameters.len();
2700        let variable_types_to_create = if variables.len() == arity_required {
2701            &signature.parameters
2702        } else if variables.len() + 1 == arity_required {
2703            &signature.parameters[1..].to_vec()
2704        } else {
2705            return self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node);
2706        };
2707
2708        let mut resolved_variables = Vec::new();
2709        for (variable, variable_type) in variables.iter().zip(variable_types_to_create) {
2710            let variable_ref = self.create_local_variable(
2711                &variable.name,
2712                variable.is_mutable.as_ref(),
2713                &variable_type.resolved_type,
2714                false,
2715            );
2716            resolved_variables.push(variable_ref);
2717        }
2718
2719        // Analyze the lambda body expression directly without creating additional block scopes
2720        // This ensures lambda variables are allocated in the lambda scope, not inner scopes
2721        let analyzed_expression = self.analyze_expression(ast_expr, &return_block_type);
2722
2723        self.pop_block_scope("lambda");
2724
2725        let function_type = self.types().function(signature.clone());
2726        self.create_expr(
2727            ExpressionKind::Lambda(resolved_variables, Box::new(analyzed_expression)),
2728            function_type,
2729            node,
2730        )
2731    }
2732
2733    #[must_use]
2734    pub fn chain_is_owned_result(
2735        start_of_chain: &StartOfChain,
2736        chains: &Vec<Postfix>,
2737    ) -> (bool, bool) {
2738        let mut is_owned_result = matches!(start_of_chain.kind, StartOfChainKind::Expression(_));
2739        let mut is_mutable = if let StartOfChainKind::Variable(var) = &start_of_chain.kind {
2740            var.is_mutable()
2741        } else {
2742            false
2743        };
2744
2745        for chain in chains {
2746            match chain.kind {
2747                PostfixKind::StructField(_, _) => {
2748                    is_owned_result = false;
2749                }
2750                PostfixKind::SliceViewSubscript(_, _) => {
2751                    is_owned_result = false;
2752                }
2753                PostfixKind::MemberCall(_, _) => {
2754                    is_owned_result = true;
2755                    is_mutable = false;
2756                }
2757                PostfixKind::OptionalChainingOperator => {
2758                    is_owned_result = true;
2759                    is_mutable = false;
2760                }
2761                PostfixKind::NoneCoalescingOperator(_) => {
2762                    is_owned_result = true;
2763                    is_mutable = false;
2764                }
2765                PostfixKind::VecSubscript(_, _) => {}
2766                PostfixKind::SparseSubscript(_, _) => {}
2767                PostfixKind::GridSubscript(_, _, _) => {}
2768                PostfixKind::MapSubscript(_, _) => {}
2769            }
2770        }
2771
2772        (is_owned_result, is_mutable)
2773    }
2774
2775    pub fn check_assignment_mode(
2776        &mut self,
2777        lhs_is_mutable: bool,
2778        source_expression: &Expression,
2779        ty: &TypeRef,
2780    ) -> AssignmentMode {
2781        if matches!(
2782            &source_expression.kind,
2783            _ | ExpressionKind::IntrinsicCallEx(_, _)
2784        ) {
2785            return AssignmentMode::OwnedValue;
2786        }
2787
2788        /* TODO:
2789        if ty.is_direct() {
2790            return AssignmentMode::OwnedValue;
2791        }
2792
2793         */
2794
2795        if let ExpressionKind::PostfixChain(start_chain, postfix) = &source_expression.kind {
2796            let (chain_is_owned, chain_is_mutable) =
2797                Self::chain_is_owned_result(start_chain, postfix);
2798            if lhs_is_mutable {
2799                return if chain_is_mutable {
2800                    AssignmentMode::CopyBlittable
2801                } else if lhs_is_mutable {
2802                    if chain_is_owned {
2803                        AssignmentMode::OwnedValue
2804                    } else {
2805                        AssignmentMode::CopyBlittable
2806                    }
2807                } else {
2808                    AssignmentMode::CopySharedPtr
2809                };
2810            }
2811            // if not mutable, it is always ok
2812        }
2813
2814        AssignmentMode::CopyBlittable
2815    }
2816
2817    pub const fn check_mutable_assignment(&mut self, assignment_mode: AssignmentMode, node: &Node) {
2818    }
2819
2820    pub const fn check_mutable_variable_assignment(
2821        &mut self,
2822        source_expression: &swamp_ast::Expression,
2823        ty: &TypeRef,
2824        variable: &swamp_ast::Variable,
2825    ) {
2826        //let is_allowed_to_assign = Self::check_mutable_assignment_is_valid(ty);
2827        //if !is_allowed_to_assign {
2828        //  error!(?ty, "variable is wrong");
2829        //return Err(self.create_err(ErrorKind::ArgumentIsNotMutable, &variable.name));
2830        //}
2831    }
2832
2833    /// # Errors
2834    ///
2835    pub fn analyze_variable_assignment(
2836        &mut self,
2837        variable: &swamp_ast::Variable,
2838        source_expression: &swamp_ast::Expression,
2839    ) -> Expression {
2840        let maybe_found_variable = self.try_find_variable(&variable.name);
2841
2842        let required_type = maybe_found_variable
2843            .as_ref()
2844            .map(|found_variable| found_variable.resolved_type.clone());
2845
2846        let source_expr = if let Some(target_type) = &required_type {
2847            self.analyze_expression_for_assignment_with_target_type(target_type, source_expression)
2848        } else {
2849            let any_type_context = TypeContext::new_anything_argument(true);
2850            self.analyze_expression(source_expression, &any_type_context)
2851        };
2852
2853        // Check if the variable type (target type) can be stored in a variable
2854        // Skip this check for parameters since they already have allocated storage
2855        let target_type = if let Some(found_var) = &maybe_found_variable {
2856            &found_var.resolved_type
2857        } else {
2858            &source_expr.ty
2859        };
2860
2861        // Only check blittable for local variables, not parameters
2862        let should_check_blittable = if let Some(found_var) = &maybe_found_variable {
2863            !matches!(found_var.variable_type, VariableType::Parameter)
2864        } else {
2865            true // New variable definitions need to be blittable
2866        };
2867
2868        if should_check_blittable && !target_type.is_blittable() {
2869            let debug_text = self.get_text(&variable.name);
2870            if !debug_text.starts_with('_') {
2871                return self.create_err(
2872                    ErrorKind::VariableTypeMustBeBlittable(target_type.clone()),
2873                    &variable.name,
2874                );
2875            }
2876        }
2877
2878        let kind: ExpressionKind = if let Some(found_var) = maybe_found_variable {
2879            if !found_var.is_mutable() {
2880                return self.create_err(ErrorKind::VariableIsNotMutable, &variable.name);
2881            }
2882            if !self
2883                .types()
2884                .compatible_with(&found_var.resolved_type, &source_expr.ty)
2885            {
2886                return self.create_err(
2887                    ErrorKind::IncompatibleTypes {
2888                        expected: source_expr.ty,
2889                        found: found_var.resolved_type.clone(),
2890                    },
2891                    &variable.name,
2892                );
2893            }
2894            self.check_mutable_variable_assignment(source_expression, &source_expr.ty, variable);
2895            ExpressionKind::VariableReassignment(found_var, Box::from(source_expr))
2896        } else {
2897            if !source_expr.ty.is_blittable() {
2898                let text = self.get_text(&variable.name);
2899                error!(?text, ?required_type, ?source_expr, "variable is wrong");
2900            }
2901
2902            // If it is mutable, we might need to clone the source
2903            // so make some extra verification
2904            if variable.is_mutable.is_some() {
2905                self.check_mutable_variable_assignment(
2906                    source_expression,
2907                    &source_expr.ty,
2908                    variable,
2909                );
2910            }
2911            let new_var = self.create_variable(variable, &source_expr.ty);
2912            ExpressionKind::VariableDefinition(new_var, Box::from(source_expr))
2913        };
2914
2915        let unit_type = self.shared.state.types.unit();
2916        self.create_expr(kind, unit_type, &variable.name)
2917    }
2918
2919    fn analyze_create_variable(
2920        &mut self,
2921        var: &swamp_ast::Variable,
2922        annotation_type: Option<&swamp_ast::Type>,
2923        source_expression: &swamp_ast::Expression,
2924    ) -> Expression {
2925        let maybe_annotated_type =
2926            annotation_type.map(|found_ast_type| self.analyze_type(found_ast_type));
2927
2928        let unsure_arg_context =
2929            TypeContext::new_unsure_argument(maybe_annotated_type.as_ref(), true);
2930
2931        let resolved_source = self.analyze_expression(source_expression, &unsure_arg_context);
2932
2933        let resulting_type = if let Some(annotated_type) = maybe_annotated_type {
2934            annotated_type
2935        } else {
2936            resolved_source.ty.clone()
2937        };
2938        let var_ref = self.create_local_variable(
2939            &var.name,
2940            Option::from(&var.is_mutable),
2941            &resulting_type,
2942            true,
2943        );
2944
2945        assert_ne!(&*resulting_type.kind, &TypeKind::Unit);
2946        let kind = ExpressionKind::VariableDefinition(var_ref, Box::from(resolved_source));
2947
2948        let unit_type = self.shared.state.types.unit();
2949
2950        self.create_expr(kind, unit_type, &var.name)
2951    }
2952
2953    fn add_location_item(
2954        &mut self,
2955        vec: &mut Vec<LocationAccess>,
2956        kind: LocationAccessKind,
2957        ty: TypeRef,
2958        ast_node: &swamp_ast::Node,
2959    ) {
2960        let resolved_node = self.to_node(ast_node);
2961        let postfix = LocationAccess {
2962            node: resolved_node,
2963            ty,
2964            kind,
2965        };
2966
2967        vec.push(postfix);
2968    }
2969
2970    fn extract_single_intrinsic_call(
2971        body: &Expression,
2972    ) -> Option<(IntrinsicFunction, Vec<ArgumentExpression>)> {
2973        if let ExpressionKind::Block(expressions) = &body.kind {
2974            let first_kind = &expressions[0].kind;
2975            if let ExpressionKind::IntrinsicCallEx(intrinsic_fn, args) = &first_kind {
2976                return Some((intrinsic_fn.clone(), args.clone()));
2977            }
2978        }
2979        None
2980    }
2981
2982    #[allow(clippy::too_many_lines)]
2983    fn analyze_chain_to_location(
2984        &mut self,
2985        chain: &swamp_ast::PostfixChain,
2986        context: &TypeContext,
2987        location_side: LocationSide,
2988    ) -> SingleLocationExpression {
2989        let mut items = Vec::new();
2990
2991        let nothing_context = TypeContext::new(None, true);
2992
2993        let base_expr = self.analyze_expression(&chain.base, &nothing_context);
2994        let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
2995            self.add_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node);
2996            let unit_type = self.types().unit();
2997            let err_variable = Variable {
2998                name: Default::default(),
2999                assigned_name: String::new(),
3000                resolved_type: unit_type,
3001                mutable_node: None,
3002                variable_type: VariableType::Local,
3003                scope_index: 0,
3004                variable_index: 0,
3005                unique_id_within_function: 0,
3006                virtual_register: 0,
3007                is_unused: false,
3008            };
3009            return SingleLocationExpression {
3010                kind: MutableReferenceKind::MutVariableRef,
3011                node: self.to_node(&chain.base.node),
3012                ty: self.shared.state.types.unit(),
3013                starting_variable: VariableRef::from(err_variable),
3014                access_chain: vec![],
3015            };
3016        };
3017
3018        if !start_variable.is_mutable() {
3019            self.add_err(ErrorKind::VariableIsNotMutable, &chain.base.node);
3020
3021            let unit_type = self.types().unit();
3022            let err_variable = Variable {
3023                name: Default::default(),
3024                assigned_name: String::new(),
3025                resolved_type: unit_type,
3026                mutable_node: None,
3027                variable_type: VariableType::Local,
3028                scope_index: 0,
3029                variable_index: 0,
3030                unique_id_within_function: 0,
3031                virtual_register: 0,
3032                is_unused: false,
3033            };
3034            return SingleLocationExpression {
3035                kind: MutableReferenceKind::MutVariableRef,
3036                node: self.to_node(&chain.base.node),
3037                ty: self.shared.state.types.unit(),
3038                starting_variable: VariableRef::from(err_variable),
3039                access_chain: vec![],
3040            };
3041        }
3042
3043        let mut ty = start_variable.resolved_type.clone();
3044        for (i, item) in chain.postfixes.iter().enumerate() {
3045            let is_absolute_last_in_chain = i == chain.postfixes.len() - 1;
3046            match &item {
3047                swamp_ast::Postfix::FieldAccess(field_name_node) => {
3048                    //let field_name_resolved = self.to_node(field_name_node)
3049                    let (struct_type_ref, index, return_type) =
3050                        self.analyze_struct_field(field_name_node, &ty);
3051
3052                    self.add_location_item(
3053                        &mut items,
3054                        LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
3055                        return_type.clone(),
3056                        field_name_node,
3057                    );
3058
3059                    ty = return_type.clone();
3060                }
3061                swamp_ast::Postfix::SubscriptTuple(x_expr, y_expr) => match &*ty.kind {
3062                    TypeKind::GridView(element_type)
3063                    | TypeKind::GridStorage(element_type, _, _) => {
3064                        let int_type = self.types().int();
3065                        let unsigned_int_context = TypeContext::new_argument(&int_type, true);
3066                        let unsigned_int_x_expr =
3067                            self.analyze_expression(x_expr, &unsigned_int_context);
3068
3069                        let unsigned_int_y_expr =
3070                            self.analyze_expression(y_expr, &unsigned_int_context);
3071
3072                        let grid_type = GridType {
3073                            element: element_type.clone(),
3074                        };
3075
3076                        self.add_location_item(
3077                            &mut items,
3078                            LocationAccessKind::GridSubscript(
3079                                grid_type,
3080                                unsigned_int_x_expr,
3081                                unsigned_int_y_expr,
3082                            ),
3083                            element_type.clone(),
3084                            &x_expr.node,
3085                        );
3086
3087                        ty = element_type.clone();
3088                    }
3089                    _ => panic!("not allowed"),
3090                },
3091                swamp_ast::Postfix::Subscript(ast_key_expression) => {
3092                    let underlying = &ty.kind;
3093                    match &**underlying {
3094                        TypeKind::SliceView(element_type)
3095                        | TypeKind::StackStorage(element_type, _)
3096                        | TypeKind::StackView(element_type)
3097                        | TypeKind::VecStorage(element_type, _)
3098                        | TypeKind::DynamicLengthVecView(element_type)
3099                        | TypeKind::FixedCapacityAndLengthArray(element_type, _) => {
3100                            let int_type = self.types().int();
3101                            let unsigned_int_context = TypeContext::new_argument(&int_type, false);
3102                            let unsigned_int_expr =
3103                                self.analyze_expression(ast_key_expression, &unsigned_int_context);
3104
3105                            let slice_type = SliceViewType {
3106                                element: element_type.clone(),
3107                            };
3108
3109                            self.add_location_item(
3110                                &mut items,
3111                                LocationAccessKind::SliceViewSubscript(
3112                                    slice_type,
3113                                    unsigned_int_expr,
3114                                ),
3115                                element_type.clone(),
3116                                &ast_key_expression.node,
3117                            );
3118
3119                            ty = element_type.clone();
3120                        }
3121                        TypeKind::SparseView(element_type)
3122                        | TypeKind::SparseStorage(element_type, _) => {
3123                            let int_type = self.types().int();
3124                            let unsigned_int_context = TypeContext::new_argument(&int_type, false);
3125                            let unsigned_int_expr =
3126                                self.analyze_expression(ast_key_expression, &unsigned_int_context);
3127
3128                            let slice_type = SparseType {
3129                                element: element_type.clone(),
3130                            };
3131
3132                            self.add_location_item(
3133                                &mut items,
3134                                LocationAccessKind::SparseSubscript(slice_type, unsigned_int_expr),
3135                                element_type.clone(),
3136                                &ast_key_expression.node,
3137                            );
3138
3139                            ty = element_type.clone();
3140                        }
3141                        TypeKind::MapStorage(key_type, value_type, ..)
3142                        | TypeKind::DynamicLengthMapView(key_type, value_type) => {
3143                            let key_index_context = TypeContext::new_argument(key_type, false);
3144                            let key_expr =
3145                                self.analyze_expression(ast_key_expression, &key_index_context);
3146
3147                            let map_like_type = MapType {
3148                                key: key_type.clone(),
3149                                value: value_type.clone(),
3150                            };
3151
3152                            match location_side {
3153                                LocationSide::Lhs => {
3154                                    // Only if it is the absolute last subscript in the chain that we should
3155                                    // create a new map entry, otherwise we should just lookup an existing entry and get the
3156                                    // address to it.
3157                                    let access_kind = if is_absolute_last_in_chain {
3158                                        LocationAccessKind::MapSubscriptCreateIfNeeded(
3159                                            map_like_type,
3160                                            key_expr,
3161                                        )
3162                                    } else {
3163                                        LocationAccessKind::MapSubscriptMustExist(
3164                                            map_like_type,
3165                                            key_expr,
3166                                        )
3167                                    };
3168
3169                                    self.add_location_item(
3170                                        &mut items,
3171                                        access_kind,
3172                                        value_type.clone(),
3173                                        &ast_key_expression.node,
3174                                    );
3175                                }
3176                                LocationSide::Mutable | LocationSide::Rhs => {
3177                                    self.add_location_item(
3178                                        &mut items,
3179                                        LocationAccessKind::MapSubscriptMustExist(
3180                                            map_like_type,
3181                                            key_expr,
3182                                        ),
3183                                        value_type.clone(),
3184                                        &ast_key_expression.node,
3185                                    );
3186                                }
3187                            }
3188                            ty = value_type.clone();
3189                        }
3190
3191                        _ => {
3192                            eprintln!("can not subscript with this type: {underlying}");
3193                            todo!()
3194                        }
3195                    }
3196                }
3197
3198                swamp_ast::Postfix::MemberCall(node, _generic_arguments, _regular_args) => {
3199                    return SingleLocationExpression {
3200                        kind: MutableReferenceKind::MutVariableRef,
3201                        node: self.to_node(node),
3202                        ty: self.shared.state.types.unit(),
3203                        starting_variable: start_variable,
3204                        access_chain: vec![],
3205                    };
3206                }
3207                /*
3208                swamp_ast::Postfix::AdvancedFunctionCall(_, node, ..) => {
3209                    return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
3210                }
3211
3212                 */
3213                swamp_ast::Postfix::FunctionCall(node, _generic_arguments, _regular_args) => {
3214                    return SingleLocationExpression {
3215                        kind: MutableReferenceKind::MutVariableRef,
3216                        node: self.to_node(node),
3217                        ty: self.shared.state.types.unit(),
3218                        starting_variable: start_variable,
3219                        access_chain: vec![],
3220                    };
3221                }
3222                swamp_ast::Postfix::OptionalChainingOperator(node) => {
3223                    return SingleLocationExpression {
3224                        kind: MutableReferenceKind::MutVariableRef,
3225                        node: self.to_node(node),
3226                        ty: self.shared.state.types.unit(),
3227                        starting_variable: start_variable,
3228                        access_chain: vec![],
3229                    };
3230                }
3231                swamp_ast::Postfix::NoneCoalescingOperator(expr) => {
3232                    return SingleLocationExpression {
3233                        kind: MutableReferenceKind::MutVariableRef,
3234                        node: self.to_node(&expr.node),
3235                        ty: self.shared.state.types.unit(),
3236                        starting_variable: start_variable,
3237                        access_chain: vec![],
3238                    };
3239                }
3240            }
3241        }
3242
3243        if let Some(found_expected_type) = context.expected_type {
3244            if !self.types().compatible_with(found_expected_type, &ty) {
3245                self.add_err(
3246                    ErrorKind::IncompatibleTypes {
3247                        expected: found_expected_type.clone(),
3248                        found: ty.clone(),
3249                    },
3250                    &chain.base.node,
3251                );
3252            }
3253        }
3254
3255        SingleLocationExpression {
3256            kind: MutableReferenceKind::MutVariableRef,
3257            node: self.to_node(&chain.base.node),
3258            ty,
3259            starting_variable: start_variable,
3260            access_chain: items,
3261        }
3262    }
3263
3264    fn analyze_to_location(
3265        &mut self,
3266        expr: &swamp_ast::Expression,
3267        context: &TypeContext,
3268        location_type: LocationSide,
3269    ) -> SingleLocationExpression {
3270        match &expr.kind {
3271            swamp_ast::ExpressionKind::PostfixChain(chain) => {
3272                self.analyze_chain_to_location(chain, context, location_type)
3273            }
3274            swamp_ast::ExpressionKind::VariableReference(variable) => {
3275                let var = self.find_variable(variable);
3276                if !var.is_mutable() {
3277                    self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3278                }
3279
3280                SingleLocationExpression {
3281                    kind: MutableReferenceKind::MutVariableRef,
3282                    node: self.to_node(&variable.name),
3283                    ty: var.resolved_type.clone(),
3284                    starting_variable: var,
3285                    access_chain: vec![],
3286                }
3287            }
3288            swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
3289                let generated_var = swamp_ast::Variable {
3290                    name: qualified_identifier.name.clone(),
3291                    is_mutable: None,
3292                };
3293                let var = self.find_variable(&generated_var);
3294                if !var.is_mutable() {
3295                    self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3296                }
3297                SingleLocationExpression {
3298                    kind: MutableReferenceKind::MutVariableRef,
3299                    node: self.to_node(&generated_var.name),
3300                    ty: var.resolved_type.clone(),
3301                    starting_variable: var,
3302                    access_chain: vec![],
3303                }
3304            }
3305            _ => {
3306                self.add_err(ErrorKind::NotValidLocationStartingPoint, &expr.node);
3307                let unit_type = self.types().unit();
3308                SingleLocationExpression {
3309                    kind: MutableReferenceKind::MutVariableRef,
3310                    node: self.to_node(&expr.node),
3311                    ty: unit_type.clone(),
3312                    starting_variable: Rc::new(Variable {
3313                        name: Default::default(),
3314                        assigned_name: String::new(),
3315                        resolved_type: unit_type,
3316                        mutable_node: None,
3317                        variable_type: VariableType::Local,
3318                        scope_index: 0,
3319                        variable_index: 0,
3320                        unique_id_within_function: 0,
3321                        virtual_register: 0,
3322                        is_unused: false,
3323                    }),
3324                    access_chain: vec![],
3325                }
3326            }
3327        }
3328    }
3329
3330    fn analyze_expression_for_assignment_compound(
3331        &mut self,
3332        target_expression: &swamp_ast::Expression,
3333        ast_source_expression: &swamp_ast::Expression,
3334    ) -> (TargetAssignmentLocation, Expression) {
3335        let any_argument_context = TypeContext::new_anything_argument(true);
3336        let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context);
3337        let source_expr_type_context = TypeContext::new_argument(&source_expr.ty, true);
3338
3339        let resolved_location = TargetAssignmentLocation(self.analyze_to_location(
3340            target_expression,
3341            &source_expr_type_context,
3342            LocationSide::Rhs,
3343        ));
3344
3345        (resolved_location, source_expr)
3346    }
3347
3348    /*
3349    fn try_convert_for_assignment(
3350        &mut self,
3351        expr: &Expression,
3352        target_type: &TypeRef,
3353        ast_node: &swamp_ast::Expression,
3354    ) -> Result<Option<Expression>, Error> {
3355        match (target_type, &expr.ty) {
3356            // Conversion cases that require transformation
3357            (TypeKind::VecStorage(target_elem, capacity), TypeKind::FixedSlice(source_elem, _)) => {
3358                // Create conversion with checks
3359                // ...
3360            }
3361
3362            (TypeKind::String, TypeKind::Int) => {
3363                // Create int-to-string conversion
3364                // ...
3365            }
3366
3367            // No conversion possible
3368            _ => Ok(None),
3369        }
3370    }
3371
3372     */
3373
3374    fn analyze_expression_for_assignment_with_target_type(
3375        &mut self,
3376        target_type: &TypeRef,
3377        ast_source_expression: &swamp_ast::Expression,
3378    ) -> Expression {
3379        let base_context = TypeContext::new_argument(target_type, true);
3380        let source_expr = self.analyze_expression(ast_source_expression, &base_context);
3381
3382        let final_expr = if self.types().compatible_with(target_type, &source_expr.ty) {
3383            source_expr
3384        } else {
3385            let source_type = source_expr.ty.clone();
3386            self.types_did_not_match_try_late_coerce_expression(
3387                source_expr,
3388                target_type,
3389                &source_type,
3390                &ast_source_expression.node,
3391            )
3392        };
3393
3394        let assignment_mode = self.check_assignment_mode(true, &final_expr, target_type); // TODO: Fill in correct lhs_is_mutable
3395
3396        self.check_mutable_assignment(assignment_mode, &final_expr.node);
3397
3398        final_expr
3399    }
3400
3401    fn analyze_expression_for_assignment(
3402        &mut self,
3403        ast_target_location_expression: &swamp_ast::Expression,
3404        ast_source_expression: &swamp_ast::Expression,
3405    ) -> (TargetAssignmentLocation, Expression) {
3406        let any_argument_context = TypeContext::new_anything_argument(true);
3407        let resolved_location = self.analyze_to_location(
3408            ast_target_location_expression,
3409            &any_argument_context,
3410            LocationSide::Lhs,
3411        );
3412
3413        let target_type = resolved_location.ty.clone();
3414        let mut_type = target_type; // Mutable references now use the same type
3415        let mut_location = TargetAssignmentLocation(resolved_location);
3416
3417        let final_expr = self
3418            .analyze_expression_for_assignment_with_target_type(&mut_type, ast_source_expression);
3419
3420        (mut_location, final_expr)
3421    }
3422
3423    fn analyze_assignment_compound(
3424        &mut self,
3425        target_expression: &swamp_ast::Expression,
3426        ast_op: &swamp_ast::CompoundOperator,
3427        ast_source_expression: &swamp_ast::Expression,
3428    ) -> Expression {
3429        let resolved_op = self.analyze_compound_operator(ast_op);
3430
3431        let (resolved_location, source_expr) = self
3432            .analyze_expression_for_assignment_compound(target_expression, ast_source_expression);
3433
3434        let kind = ExpressionKind::CompoundAssignment(
3435            resolved_location,
3436            resolved_op.kind,
3437            Box::from(source_expr),
3438        );
3439
3440        let unit_type = self.shared.state.types.unit();
3441
3442        self.create_expr(kind, unit_type, &target_expression.node)
3443    }
3444
3445    fn analyze_assignment_mode(lhs: SingleLocationExpression) {}
3446
3447    fn analyze_assignment(
3448        &mut self,
3449        target_location: &swamp_ast::Expression,
3450        ast_source_expression: &swamp_ast::Expression,
3451    ) -> Expression {
3452        let (mut_location, source_expr) =
3453            self.analyze_expression_for_assignment(target_location, ast_source_expression);
3454        let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
3455        let unit_type = self.shared.state.types.unit();
3456
3457        // Assignments are always of type Unit
3458
3459        self.create_expr(kind, unit_type, &target_location.node)
3460    }
3461
3462    #[must_use]
3463    pub const fn create_expr(
3464        &self,
3465        kind: ExpressionKind,
3466        ty: TypeRef,
3467        ast_node: &swamp_ast::Node,
3468    ) -> Expression {
3469        //info!(%ty, ?kind, "create_expr()");
3470        Expression {
3471            kind,
3472            ty,
3473            node: self.to_node(ast_node),
3474        }
3475    }
3476
3477    fn analyze_destructuring(
3478        &mut self,
3479        node: &swamp_ast::Node,
3480        target_ast_variables: &[swamp_ast::Variable],
3481        tuple_expression: &swamp_ast::Expression,
3482    ) -> Expression {
3483        let any_context = TypeContext::new_anything_argument(true);
3484        let tuple_resolved = self.analyze_expression(tuple_expression, &any_context);
3485        let tuple_expr_type = &tuple_resolved.ty;
3486        let unit = self.types().unit();
3487
3488        let mut variable_refs = Vec::new();
3489        if let TypeKind::Tuple(tuple) = &*tuple_expr_type.kind {
3490            if target_ast_variables.len() > tuple.len() {
3491                return self.create_err(ErrorKind::TooManyDestructureVariables, node);
3492            }
3493            for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
3494                let variable_ref = self.create_local_variable(
3495                    &ast_variable.name,
3496                    ast_variable.is_mutable.as_ref(),
3497                    &tuple_type,
3498                    true,
3499                );
3500                variable_refs.push(variable_ref);
3501            }
3502            let expr_kind = ExpressionKind::TupleDestructuring(
3503                variable_refs,
3504                tuple_expr_type.clone(),
3505                Box::from(tuple_resolved),
3506            );
3507
3508            self.create_expr(expr_kind, unit, node)
3509        } else {
3510            self.create_err(ErrorKind::CanNotDestructure, node)
3511        }
3512    }
3513
3514    fn analyze_normal_member_call(
3515        &mut self,
3516        type_that_member_is_on: &TypeRef,
3517        found_function: &FunctionRef,
3518        generic_arguments: Vec<TypeRef>,
3519        ast_arguments: &[swamp_ast::Expression],
3520        is_mutable: bool,
3521        node: &swamp_ast::Node,
3522    ) -> Signature {
3523        let resolved_node = self.to_node(node);
3524        // TODO:
3525
3526        found_function.signature().clone()
3527    }
3528
3529    fn queue_member_signature(
3530        &mut self,
3531        self_type: &TypeRef,
3532        key_type: Option<&TypeRef>,
3533        element_type: &TypeRef,
3534        field_name_str: &str,
3535        lambda_variable_count: usize,
3536        node: &swamp_ast::Node,
3537    ) -> Option<(IntrinsicFunction, Signature)> {
3538        let self_type_param = TypeForParameter {
3539            name: "self".to_string(),
3540            resolved_type: self_type.clone(),
3541            is_mutable: false,
3542            node: None,
3543        };
3544        let self_mutable_type_param = TypeForParameter {
3545            name: "self".to_string(),
3546            resolved_type: self_type.clone(),
3547            is_mutable: true,
3548            node: None,
3549        };
3550        let intrinsic_and_signature = match field_name_str {
3551            "enqueue" => (
3552                IntrinsicFunction::VecPush,
3553                Signature {
3554                    parameters: vec![
3555                        self_mutable_type_param,
3556                        TypeForParameter {
3557                            name: "element".to_string(),
3558                            resolved_type: element_type.clone(),
3559                            is_mutable: false,
3560                            node: None,
3561                        },
3562                    ],
3563                    return_type: self.types().unit(),
3564                },
3565            ),
3566            "dequeue" => (
3567                IntrinsicFunction::VecRemoveFirstIndexGetValue,
3568                Signature {
3569                    parameters: vec![self_mutable_type_param],
3570                    return_type: element_type.clone(),
3571                },
3572            ),
3573            _ => {
3574                self.slice_member_signature(
3575                    self_type,
3576                    key_type,
3577                    element_type,
3578                    field_name_str,
3579                    lambda_variable_count,
3580                    node,
3581                )
3582            }?,
3583        };
3584
3585        Some(intrinsic_and_signature)
3586    }
3587
3588    fn sparse_member_signature(
3589        &mut self,
3590        self_type: &TypeRef,
3591        element_type: &TypeRef,
3592        field_name_str: &str,
3593        lambda_variable_count: usize,
3594        node: &swamp_ast::Node,
3595    ) -> Option<(IntrinsicFunction, Signature)> {
3596        let key_type = self.types().int(); // TODO: SparseID
3597
3598        let self_type_param = TypeForParameter {
3599            name: "self".to_string(),
3600            resolved_type: self_type.clone(),
3601            is_mutable: false,
3602            node: None,
3603        };
3604        let self_mutable_type_param = TypeForParameter {
3605            name: "self".to_string(),
3606            resolved_type: self_type.clone(),
3607            is_mutable: true,
3608            node: None,
3609        };
3610        let intrinsic_and_signature = match field_name_str {
3611            "add" => (
3612                IntrinsicFunction::SparseAdd,
3613                Signature {
3614                    parameters: vec![
3615                        self_mutable_type_param,
3616                        TypeForParameter {
3617                            name: "element".to_string(),
3618                            resolved_type: element_type.clone(),
3619                            is_mutable: false,
3620                            node: None,
3621                        },
3622                    ],
3623                    return_type: self.types().int(),
3624                },
3625            ),
3626            "remove" => (
3627                IntrinsicFunction::SparseRemove,
3628                Signature {
3629                    parameters: vec![
3630                        self_mutable_type_param,
3631                        TypeForParameter {
3632                            name: "key".to_string(),
3633                            resolved_type: key_type,
3634                            is_mutable: false,
3635                            node: None,
3636                        },
3637                    ],
3638                    return_type: self.types().unit(),
3639                },
3640            ),
3641            "is_alive" => (
3642                IntrinsicFunction::SparseIsAlive,
3643                Signature {
3644                    parameters: vec![
3645                        self_type_param,
3646                        TypeForParameter {
3647                            name: "element".to_string(),
3648                            resolved_type: element_type.clone(),
3649                            is_mutable: false,
3650                            node: None,
3651                        },
3652                    ],
3653                    return_type: self.types().bool(),
3654                },
3655            ),
3656
3657            _ => {
3658                self.slice_member_signature(
3659                    self_type,
3660                    Option::from(key_type).as_ref(),
3661                    element_type,
3662                    field_name_str,
3663                    lambda_variable_count,
3664                    node,
3665                )
3666            }?,
3667        };
3668        Some(intrinsic_and_signature)
3669    }
3670
3671    fn vec_member_signature(
3672        &mut self,
3673        self_type: &TypeRef,
3674        element_type: &TypeRef,
3675        field_name_str: &str,
3676        lambda_variable_count: usize,
3677        node: &swamp_ast::Node,
3678    ) -> Option<(IntrinsicFunction, Signature)> {
3679        let key_type = self.types().int();
3680        let self_type_param = TypeForParameter {
3681            name: "self".to_string(),
3682            resolved_type: self_type.clone(),
3683            is_mutable: false,
3684            node: None,
3685        };
3686        let self_mutable_type_param = TypeForParameter {
3687            name: "self".to_string(),
3688            resolved_type: self_type.clone(),
3689            is_mutable: true,
3690            node: None,
3691        };
3692        let intrinsic_and_signature = match field_name_str {
3693            "prepend" => (
3694                IntrinsicFunction::VecPush,
3695                Signature {
3696                    parameters: vec![
3697                        self_mutable_type_param,
3698                        TypeForParameter {
3699                            name: "element".to_string(),
3700                            resolved_type: element_type.clone(),
3701                            is_mutable: false,
3702                            node: None,
3703                        },
3704                    ],
3705                    return_type: self.types().unit(),
3706                },
3707            ),
3708            "push" => (
3709                IntrinsicFunction::VecPush,
3710                Signature {
3711                    parameters: vec![
3712                        self_mutable_type_param,
3713                        TypeForParameter {
3714                            name: "element".to_string(),
3715                            resolved_type: element_type.clone(),
3716                            is_mutable: false,
3717                            node: None,
3718                        },
3719                    ],
3720                    return_type: self.types().unit(),
3721                },
3722            ),
3723            "pop" => (
3724                IntrinsicFunction::VecPop,
3725                Signature {
3726                    parameters: vec![self_mutable_type_param],
3727                    return_type: element_type.clone(),
3728                },
3729            ),
3730
3731            _ => {
3732                self.slice_member_signature(
3733                    self_type,
3734                    Option::from(key_type).as_ref(),
3735                    element_type,
3736                    field_name_str,
3737                    lambda_variable_count,
3738                    node,
3739                )
3740            }?,
3741        };
3742        Some(intrinsic_and_signature)
3743    }
3744
3745    #[allow(clippy::unnecessary_wraps)]
3746    fn grid_member_signature(
3747        &mut self,
3748        self_type: &TypeRef,
3749        element_type: &TypeRef,
3750        field_name_str: &str,
3751        node: &swamp_ast::Node,
3752    ) -> Option<(IntrinsicFunction, Signature)> {
3753        let self_type_param = TypeForParameter {
3754            name: "self".to_string(),
3755            resolved_type: self_type.clone(),
3756            is_mutable: false,
3757            node: None,
3758        };
3759        let self_mutable_type_param = TypeForParameter {
3760            name: "self".to_string(),
3761            resolved_type: self_type.clone(),
3762            is_mutable: true,
3763            node: None,
3764        };
3765        let element_param = TypeForParameter {
3766            name: "element".to_string(),
3767            resolved_type: element_type.clone(),
3768            is_mutable: false,
3769            node: None,
3770        };
3771        let int_type = self.types().int();
3772
3773        let int_param = TypeForParameter {
3774            name: "x_or_y".to_string(),
3775            resolved_type: int_type.clone(),
3776            is_mutable: false,
3777            node: None,
3778        };
3779        let intrinsic_and_signature = match field_name_str {
3780            "set" => (
3781                IntrinsicFunction::GridSet,
3782                Signature {
3783                    parameters: vec![self_type_param, int_param.clone(), int_param, element_param],
3784                    return_type: self.types().unit(),
3785                },
3786            ),
3787
3788            "get" => (
3789                IntrinsicFunction::GridGet,
3790                Signature {
3791                    parameters: vec![self_type_param, int_param.clone(), int_param],
3792                    return_type: element_type.clone(),
3793                },
3794            ),
3795
3796            "width" => (
3797                IntrinsicFunction::GridWidth,
3798                Signature {
3799                    parameters: vec![self_type_param],
3800                    return_type: int_type,
3801                },
3802            ),
3803
3804            "height" => (
3805                IntrinsicFunction::GridHeight,
3806                Signature {
3807                    parameters: vec![self_type_param],
3808                    return_type: int_type,
3809                },
3810            ),
3811
3812            _ => panic!("unknown grid method {field_name_str}"),
3813        };
3814
3815        Some(intrinsic_and_signature)
3816    }
3817
3818    fn basic_collection_member_signature(
3819        &mut self,
3820        self_type: &TypeRef,
3821        field_name_str: &str,
3822        node: &swamp_ast::Node,
3823    ) -> Option<(IntrinsicFunction, Signature)> {
3824        let self_type_param = TypeForParameter {
3825            name: "self".to_string(),
3826            resolved_type: self_type.clone(),
3827            is_mutable: false,
3828            node: None,
3829        };
3830        let self_mut_type_param = TypeForParameter {
3831            name: "self".to_string(),
3832            resolved_type: self_type.clone(),
3833            is_mutable: true,
3834            node: None,
3835        };
3836        let intrinsic_and_signature = match field_name_str {
3837            "len" => {
3838                let signature = Signature {
3839                    parameters: vec![self_type_param],
3840                    return_type: self.types().int(),
3841                };
3842                (IntrinsicFunction::VecLen, signature)
3843            }
3844            "is_empty" => (
3845                IntrinsicFunction::VecIsEmpty,
3846                Signature {
3847                    parameters: vec![self_type_param],
3848                    return_type: self.types().bool(),
3849                },
3850            ),
3851            "capacity" => {
3852                let signature = Signature {
3853                    parameters: vec![self_type_param],
3854                    return_type: self.types().int(),
3855                };
3856                (IntrinsicFunction::VecCapacity, signature)
3857            }
3858            _ => {
3859                self.add_err(ErrorKind::UnknownMemberFunction(self_type.clone()), node);
3860
3861                return None;
3862            }
3863        };
3864        Some(intrinsic_and_signature)
3865    }
3866
3867    #[allow(clippy::too_many_lines)]
3868    fn slice_member_signature(
3869        &mut self,
3870        self_type: &TypeRef,
3871        key_type: Option<&TypeRef>,
3872        element_type: &TypeRef,
3873        field_name_str: &str,
3874        lambda_variable_count: usize,
3875        node: &swamp_ast::Node,
3876    ) -> Option<(IntrinsicFunction, Signature)> {
3877        let slice_view_type = self.types().slice_view(&element_type.clone());
3878        let int_type = self.types().int();
3879        let self_type_param = TypeForParameter {
3880            name: "self".to_string(),
3881            resolved_type: slice_view_type.clone(),
3882            is_mutable: false,
3883            node: None,
3884        };
3885        let self_mut_type_param = TypeForParameter {
3886            name: "self".to_string(),
3887            resolved_type: slice_view_type,
3888            is_mutable: true,
3889            node: None,
3890        };
3891        let intrinsic_and_signature = match field_name_str {
3892            "for" => {
3893                let parameters = if lambda_variable_count == 2 {
3894                    vec![
3895                        TypeForParameter {
3896                            name: "key".to_string(),
3897                            resolved_type: key_type.unwrap().clone(),
3898                            is_mutable: false,
3899                            node: None,
3900                        },
3901                        TypeForParameter {
3902                            name: "element".to_string(),
3903                            resolved_type: element_type.clone(),
3904                            is_mutable: false,
3905                            node: None,
3906                        },
3907                    ]
3908                } else {
3909                    vec![TypeForParameter {
3910                        name: "element".to_string(),
3911                        resolved_type: element_type.clone(),
3912                        is_mutable: false,
3913                        node: None,
3914                    }]
3915                };
3916                let lambda_signature = Signature {
3917                    parameters,
3918                    return_type: self.types().unit(),
3919                };
3920                let lambda_function_type = self.types().function(lambda_signature);
3921                (
3922                    IntrinsicFunction::TransformerFor,
3923                    Signature {
3924                        parameters: vec![
3925                            self_type_param,
3926                            TypeForParameter {
3927                                name: "lambda".to_string(),
3928                                resolved_type: lambda_function_type,
3929                                is_mutable: false,
3930                                node: None,
3931                            },
3932                        ],
3933                        return_type: self.types().unit(), // VecFor is only used for side effects
3934                    },
3935                )
3936            }
3937            "while" => {
3938                let parameters = if lambda_variable_count == 2 {
3939                    vec![
3940                        TypeForParameter {
3941                            name: "key".to_string(),
3942                            resolved_type: key_type.unwrap().clone(),
3943                            is_mutable: false,
3944                            node: None,
3945                        },
3946                        TypeForParameter {
3947                            name: "element".to_string(),
3948                            resolved_type: element_type.clone(),
3949                            is_mutable: false,
3950                            node: None,
3951                        },
3952                    ]
3953                } else {
3954                    vec![TypeForParameter {
3955                        name: "element".to_string(),
3956                        resolved_type: element_type.clone(),
3957                        is_mutable: false,
3958                        node: None,
3959                    }]
3960                };
3961                let lambda_signature = Signature {
3962                    parameters,
3963                    return_type: self.types().bool(), // it returns if the while loop should continue
3964                };
3965                let lambda_function_type = self.types().function(lambda_signature);
3966                (
3967                    IntrinsicFunction::TransformerWhile,
3968                    Signature {
3969                        parameters: vec![
3970                            self_type_param,
3971                            TypeForParameter {
3972                                name: "lambda".to_string(),
3973                                resolved_type: lambda_function_type,
3974                                is_mutable: false,
3975                                node: None,
3976                            },
3977                        ],
3978                        return_type: self.types().unit(), // VecFor is only used for side effects
3979                    },
3980                )
3981            }
3982            "filter" => {
3983                let lambda_signature = Signature {
3984                    parameters: vec![TypeForParameter {
3985                        name: "element".to_string(),
3986                        resolved_type: element_type.clone(),
3987                        is_mutable: false,
3988                        node: None,
3989                    }],
3990                    return_type: self.types().bool(),
3991                };
3992                let lambda_function_type = self.types().function(lambda_signature);
3993                (
3994                    IntrinsicFunction::TransformerFilter,
3995                    Signature {
3996                        parameters: vec![
3997                            self_type_param,
3998                            TypeForParameter {
3999                                name: "lambda".to_string(),
4000                                resolved_type: lambda_function_type,
4001                                is_mutable: false,
4002                                node: None,
4003                            },
4004                        ],
4005                        return_type: self.shared.state.types.slice_view(&element_type.clone()),
4006                    },
4007                )
4008            }
4009            "find" => {
4010                let lambda_signature = Signature {
4011                    parameters: vec![TypeForParameter {
4012                        name: "element".to_string(),
4013                        resolved_type: element_type.clone(),
4014                        is_mutable: false,
4015                        node: None,
4016                    }],
4017                    return_type: self.types().bool(),
4018                };
4019                let lambda_function_type = self.types().function(lambda_signature);
4020                (
4021                    IntrinsicFunction::TransformerFind,
4022                    Signature {
4023                        parameters: vec![
4024                            self_type_param,
4025                            TypeForParameter {
4026                                name: "lambda".to_string(),
4027                                resolved_type: lambda_function_type,
4028                                is_mutable: false,
4029                                node: None,
4030                            },
4031                        ],
4032                        return_type: self.shared.state.types.optional(&element_type.clone()),
4033                    },
4034                )
4035            }
4036
4037            "remove" => {
4038                let signature = Signature {
4039                    parameters: vec![
4040                        self_mut_type_param,
4041                        TypeForParameter {
4042                            name: "index".to_string(),
4043                            resolved_type: int_type,
4044                            is_mutable: false,
4045                            node: None,
4046                        },
4047                    ],
4048                    return_type: self.types().unit(),
4049                };
4050                (IntrinsicFunction::VecRemoveIndex, signature)
4051            }
4052            _ => return self.basic_collection_member_signature(self_type, field_name_str, node),
4053        };
4054        Some(intrinsic_and_signature)
4055    }
4056
4057    #[allow(clippy::unnecessary_wraps, clippy::result_large_err)]
4058    fn map_member_signature(
4059        &mut self,
4060        self_type: &TypeRef,
4061        key_type: &TypeRef,
4062        value_type: &TypeRef,
4063        field_name_str: &str,
4064        node: &swamp_ast::Node,
4065    ) -> Option<(IntrinsicFunction, Signature)> {
4066        let self_type_param = TypeForParameter {
4067            name: "self".to_string(),
4068            resolved_type: self_type.clone(),
4069            is_mutable: false,
4070            node: None,
4071        };
4072
4073        let mutable_self_type_param = TypeForParameter {
4074            name: "self".to_string(),
4075            resolved_type: self_type.clone(),
4076            is_mutable: true,
4077            node: None,
4078        };
4079
4080        let intrinsic_and_signature = match field_name_str {
4081            "has" => (
4082                IntrinsicFunction::MapHas,
4083                Signature {
4084                    parameters: vec![
4085                        self_type_param,
4086                        TypeForParameter {
4087                            name: "key".to_string(),
4088                            resolved_type: key_type.clone(),
4089                            is_mutable: false,
4090                            node: None,
4091                        },
4092                    ],
4093                    return_type: self.types().bool(),
4094                },
4095            ),
4096            "remove" => (
4097                IntrinsicFunction::MapRemove,
4098                Signature {
4099                    parameters: vec![
4100                        mutable_self_type_param,
4101                        TypeForParameter {
4102                            name: "key".to_string(),
4103                            resolved_type: key_type.clone(),
4104                            is_mutable: false,
4105                            node: None,
4106                        },
4107                    ],
4108                    return_type: self.types().unit(),
4109                },
4110            ),
4111            "len" => (
4112                IntrinsicFunction::MapLen,
4113                Signature {
4114                    parameters: vec![self_type_param],
4115                    return_type: self.types().int(),
4116                },
4117            ),
4118            "capacity" => (
4119                IntrinsicFunction::MapCapacity,
4120                Signature {
4121                    parameters: vec![self_type_param],
4122                    return_type: self.types().int(),
4123                },
4124            ),
4125            "is_empty" => (
4126                IntrinsicFunction::MapIsEmpty,
4127                Signature {
4128                    parameters: vec![self_type_param],
4129                    return_type: self.types().bool(),
4130                },
4131            ),
4132            _ => todo!("unknown map member"),
4133        };
4134
4135        Some(intrinsic_and_signature)
4136    }
4137
4138    fn check_intrinsic_member_signature(
4139        &mut self,
4140        type_that_member_is_on: &TypeRef,
4141        field_name_str: &str,
4142        lambda_variables_count: usize,
4143        node: &swamp_ast::Node,
4144    ) -> Option<(IntrinsicFunction, Signature)> {
4145        let ty = type_that_member_is_on;
4146        let int_type = self.types().int();
4147        match &*ty.kind {
4148            TypeKind::GridStorage(element_type, ..) | TypeKind::GridView(element_type) => self
4149                .grid_member_signature(type_that_member_is_on, element_type, field_name_str, node),
4150            TypeKind::SparseStorage(element_type, ..) | TypeKind::SparseView(element_type) => self
4151                .sparse_member_signature(
4152                    type_that_member_is_on,
4153                    element_type,
4154                    field_name_str,
4155                    lambda_variables_count,
4156                    node,
4157                ),
4158            TypeKind::QueueStorage(element_type, ..) => self.queue_member_signature(
4159                type_that_member_is_on,
4160                None,
4161                element_type,
4162                field_name_str,
4163                lambda_variables_count,
4164                node,
4165            ),
4166            TypeKind::StackStorage(element_type, ..)
4167            | TypeKind::QueueStorage(element_type, ..)
4168            | TypeKind::VecStorage(element_type, ..)
4169            | TypeKind::DynamicLengthVecView(element_type) => self.vec_member_signature(
4170                type_that_member_is_on,
4171                element_type,
4172                field_name_str,
4173                lambda_variables_count,
4174                node,
4175            ),
4176            TypeKind::SliceView(element_type) => self.slice_member_signature(
4177                type_that_member_is_on,
4178                Some(&int_type),
4179                element_type,
4180                field_name_str,
4181                lambda_variables_count,
4182                node,
4183            ),
4184            TypeKind::DynamicLengthMapView(key, value) | TypeKind::MapStorage(key, value, _) => {
4185                self.map_member_signature(type_that_member_is_on, key, value, field_name_str, node)
4186            }
4187            TypeKind::FixedCapacityAndLengthArray(element_type, _) => self.slice_member_signature(
4188                type_that_member_is_on,
4189                Some(&int_type),
4190                element_type,
4191                field_name_str,
4192                lambda_variables_count,
4193                node,
4194            ),
4195            _ => {
4196                self.add_err(
4197                    ErrorKind::UnknownMemberFunction(type_that_member_is_on.clone()),
4198                    node,
4199                );
4200
4201                None
4202            }
4203        }
4204    }
4205
4206    fn analyze_member_call(
4207        &mut self,
4208        type_that_member_is_on: &TypeRef,
4209        field_name_str: &str,
4210        ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4211        ast_arguments: &[swamp_ast::Expression],
4212        chain_self_is_mutable: bool,
4213        node: &swamp_ast::Node,
4214    ) -> (PostfixKind, TypeRef) {
4215        let generic_arguments = if let Some(ast_generic_arguments) = ast_maybe_generic_arguments {
4216            let mut resolved_types = Vec::new();
4217            for ast_type in ast_generic_arguments {
4218                resolved_types.push(self.analyze_type(ast_type.get_type()));
4219            }
4220            resolved_types
4221        } else {
4222            vec![]
4223        };
4224
4225        let maybe_function = self
4226            .shared
4227            .state
4228            .associated_impls
4229            .get_member_function(type_that_member_is_on, field_name_str)
4230            .cloned();
4231
4232        let (function_ref, instantiated_signature) = if let Some(found_function) = maybe_function {
4233            let signature = self.analyze_normal_member_call(
4234                type_that_member_is_on,
4235                &found_function,
4236                generic_arguments,
4237                ast_arguments,
4238                chain_self_is_mutable,
4239                node,
4240            );
4241            (found_function, signature)
4242        } else {
4243            let lambda_variables_count = if ast_arguments.is_empty() {
4244                0
4245            } else if let swamp_ast::ExpressionKind::Lambda(variables, ..) = &ast_arguments[0].kind
4246            {
4247                variables.len()
4248            } else {
4249                0
4250            };
4251            let Some((intrinsic_fn, signature)) = self.check_intrinsic_member_signature(
4252                type_that_member_is_on,
4253                field_name_str,
4254                lambda_variables_count,
4255                node,
4256            ) else {
4257                return (PostfixKind::OptionalChainingOperator, self.types().unit());
4258            };
4259            let def = IntrinsicFunctionDefinition {
4260                name: field_name_str.to_string(),
4261                signature,
4262                intrinsic: intrinsic_fn,
4263            };
4264            let function_ref = FunctionRef::from(Function::Intrinsic(
4265                IntrinsicFunctionDefinitionRef::from(def.clone()),
4266            ));
4267            (function_ref, def.signature)
4268        };
4269
4270        let self_type_in_signature = &instantiated_signature.parameters[0];
4271        let binding = type_that_member_is_on.lowest_common_denominator_vec_like_view();
4272
4273        if self_type_in_signature.is_mutable && !chain_self_is_mutable {
4274            self.add_err(ErrorKind::SelfNotCorrectMutableState, node);
4275        }
4276
4277        let resolved_arguments = self.analyze_and_verify_parameters(
4278            node,
4279            &instantiated_signature.parameters[1..],
4280            ast_arguments,
4281        );
4282
4283        (
4284            PostfixKind::MemberCall(function_ref, resolved_arguments),
4285            TypeRef::from(instantiated_signature.return_type.clone()),
4286        )
4287    }
4288
4289    fn analyze_postfix_member_call(
4290        &mut self,
4291        type_that_member_is_on: &TypeRef,
4292        is_mutable: bool,
4293        member_name: &swamp_ast::Node,
4294        ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4295        ast_arguments: &[swamp_ast::Expression],
4296        suffixes: &mut Vec<Postfix>,
4297    ) -> TypeRef {
4298        let field_name_str = self.get_text(member_name).to_string();
4299
4300        let resolved_node = self.to_node(member_name);
4301
4302        let (kind, return_type) = self.analyze_member_call(
4303            type_that_member_is_on,
4304            &field_name_str,
4305            ast_maybe_generic_arguments,
4306            ast_arguments,
4307            is_mutable,
4308            member_name,
4309        );
4310        let postfix = Postfix {
4311            node: resolved_node,
4312            ty: return_type,
4313            kind,
4314        };
4315
4316        let last_type = postfix.ty.clone();
4317        suffixes.push(postfix);
4318
4319        last_type
4320    }
4321
4322    fn is_compatible_initializer_list_target(
4323        &mut self,
4324        target_type: &TypeRef,
4325        initializer_element_type: &TypeRef,
4326    ) -> bool {
4327        match &*target_type.kind {
4328            TypeKind::VecStorage(vec_element_type, _vec_capacity) => self
4329                .types()
4330                .compatible_with(vec_element_type, initializer_element_type),
4331            TypeKind::FixedCapacityAndLengthArray(array_element_type, _array_capacity) => self
4332                .types()
4333                .compatible_with(array_element_type, initializer_element_type),
4334            _ => false,
4335        }
4336    }
4337
4338    fn is_compatible_initializer_pair_list_target(
4339        &mut self,
4340        target_type: &TypeRef,
4341        initializer_key_type: &TypeRef,
4342        initializer_value_type: &TypeRef,
4343    ) -> bool {
4344        match &*target_type.kind {
4345            TypeKind::MapStorage(storage_key, storage_value, _) => {
4346                self.types()
4347                    .compatible_with(initializer_key_type, storage_key)
4348                    && self
4349                        .types()
4350                        .compatible_with(initializer_value_type, storage_value)
4351            }
4352            _ => false,
4353        }
4354    }
4355
4356    fn types_did_not_match_try_late_coerce_expression(
4357        &mut self,
4358        expr: Expression,
4359        special_expected_type: &TypeRef,
4360        special_encountered_type: &TypeRef,
4361        node: &swamp_ast::Node,
4362    ) -> Expression {
4363        let expected_type = special_expected_type;
4364        let encountered_type = special_encountered_type;
4365        let encountered_is_optional = matches!(&*encountered_type.kind, TypeKind::Optional(_));
4366        if let TypeKind::Optional(expected_inner_type) = &*expected_type.kind {
4367            let inner_is_also_optional =
4368                matches!(&*expected_inner_type.kind, TypeKind::Optional(_));
4369            // If an optional is expected, we can wrap it if this type has the exact same
4370            // inner type
4371            assert!(!inner_is_also_optional);
4372
4373            // First make sure it is not already an optional type. we can not wrap an option with an option
4374            // TODO: Improve error handling
4375            if !encountered_is_optional {
4376                // good it isn't, lets see if they share inner types
4377                if self
4378                    .types()
4379                    .compatible_with(expected_inner_type, encountered_type)
4380                {
4381                    // they share inner types as well, lets wrap it up
4382                    let wrapped = self.create_expr(
4383                        ExpressionKind::Option(Option::from(Box::new(expr))),
4384                        expected_type.clone(),
4385                        node,
4386                    );
4387                    return wrapped;
4388                }
4389            }
4390        }
4391        /*
4392        if let TypeKind::InternalInitializerPairList(slice_key, slice_value) = &*encountered_type.kind {
4393            if Self::is_compatible_initializer_pair_list_target(
4394                expected_type,
4395                slice_key,
4396                slice_value,
4397            ) {
4398                return Ok(expr);
4399            }
4400        } else if let TypeKind::InternalInitializerList(element_type) = &*encountered_type.kind {
4401            if Self::is_compatible_initializer_list_target(expected_type, element_type) {
4402                return Ok(expr);
4403            }
4404        } else*/
4405        if matches!(&*expected_type.kind, &TypeKind::Bool) {
4406            // if it has a mut or immutable optional, then it works well to wrap it
4407            if encountered_is_optional {
4408                let bool_type = self.types().bool();
4409                let wrapped = self.create_expr(
4410                    ExpressionKind::CoerceOptionToBool(Box::from(expr)),
4411                    bool_type,
4412                    node,
4413                );
4414                return wrapped;
4415            }
4416        }
4417
4418        error!(?expected_type, ?encountered_type, "incompatible");
4419        self.create_err(
4420            ErrorKind::IncompatibleTypes {
4421                expected: expected_type.clone(),
4422                found: encountered_type.clone(),
4423            },
4424            node,
4425        )
4426    }
4427
4428    #[must_use]
4429    pub fn analyze_generic_parameter_usize(&self, generic_parameter: &GenericParameter) -> usize {
4430        let usize_node = generic_parameter.get_unsigned_int_node();
4431        let usize_str = self.get_text(usize_node);
4432        Self::str_to_unsigned_int(usize_str).unwrap() as usize
4433    }
4434
4435    #[must_use]
4436    pub fn analyze_generic_parameter_usize_tuple(
4437        &self,
4438        generic_parameter: &GenericParameter,
4439    ) -> (usize, usize) {
4440        let (first, second) = generic_parameter.get_unsigned_int_tuple_nodes();
4441        let first_str = self.get_text(first);
4442        let second_str = self.get_text(second);
4443        let first_value = Self::str_to_unsigned_int(first_str).unwrap() as usize;
4444        let second_value = Self::str_to_unsigned_int(second_str).unwrap() as usize;
4445
4446        (first_value, second_value)
4447    }
4448
4449    pub fn analyze_special_named_type(
4450        &mut self,
4451        path: &[String],
4452        name: &str,
4453        ast_generic_parameters: &[GenericParameter],
4454    ) -> Option<TypeRef> {
4455        let converted_type = match name {
4456            "Vec" => {
4457                if ast_generic_parameters.len() == 1 {
4458                    let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4459                    let vec_type = self.shared.state.types.dynamic_vec_view(&element_type);
4460                    // Generate default functions for the new dynamic vec view type
4461                    let default_node = swamp_ast::Node::default();
4462                    self.add_default_functions(&vec_type, &default_node);
4463                    vec_type
4464                } else if ast_generic_parameters.len() == 2 {
4465                    let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4466                    let fixed_size =
4467                        self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4468                    let vec_storage_type = self
4469                        .shared
4470                        .state
4471                        .types
4472                        .vec_storage(&element_type, fixed_size);
4473                    // Generate default functions for the new vec storage type
4474                    let default_node = swamp_ast::Node::default();
4475                    self.add_default_functions(&vec_storage_type, &default_node);
4476                    vec_storage_type
4477                } else {
4478                    panic!("todo: make this into an error")
4479                }
4480            }
4481            "Stack" => {
4482                if ast_generic_parameters.len() == 1 {
4483                    let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4484                    let stack_view_type = self.shared.state.types.stack_view(&element_type);
4485                    // Generate default functions for the new stack view type
4486                    let default_node = swamp_ast::Node::default();
4487                    self.add_default_functions(&stack_view_type, &default_node);
4488                    stack_view_type
4489                } else if ast_generic_parameters.len() == 2 {
4490                    let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4491                    let fixed_size =
4492                        self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4493                    let stack_storage_type = self
4494                        .shared
4495                        .state
4496                        .types
4497                        .stack_storage(&element_type, fixed_size);
4498                    // Generate default functions for the new stack storage type
4499                    let default_node = swamp_ast::Node::default();
4500                    self.add_default_functions(&stack_storage_type, &default_node);
4501                    stack_storage_type
4502                } else {
4503                    panic!("todo: make this into an error")
4504                }
4505            }
4506            "Queue" => {
4507                if ast_generic_parameters.len() == 1 {
4508                    let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4509                    let queue_view_type = self.shared.state.types.queue_view(&element_type);
4510                    // Generate default functions for the new queue view type
4511                    let default_node = swamp_ast::Node::default();
4512                    self.add_default_functions(&queue_view_type, &default_node);
4513                    queue_view_type
4514                } else if ast_generic_parameters.len() == 2 {
4515                    let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4516                    let fixed_size =
4517                        self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4518                    let queue_storage_type = self
4519                        .shared
4520                        .state
4521                        .types
4522                        .queue_storage(&element_type, fixed_size);
4523                    // Generate default functions for the new queue storage type
4524                    let default_node = swamp_ast::Node::default();
4525                    self.add_default_functions(&queue_storage_type, &default_node);
4526                    queue_storage_type
4527                } else {
4528                    panic!("todo: make this into an error")
4529                }
4530            }
4531            "Sparse" => {
4532                if ast_generic_parameters.len() == 1 {
4533                    let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4534                    let sparse_view_type = self.shared.state.types.sparse_view(&element_type);
4535                    // Generate default functions for the new sparse view type
4536                    let default_node = swamp_ast::Node::default();
4537                    self.add_default_functions(&sparse_view_type, &default_node);
4538                    sparse_view_type
4539                } else if ast_generic_parameters.len() == 2 {
4540                    let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4541                    let fixed_size =
4542                        self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
4543                    let sparse_storage_type = self
4544                        .shared
4545                        .state
4546                        .types
4547                        .sparse_storage(&element_type, fixed_size);
4548                    // Generate default functions for the new sparse storage type
4549                    let default_node = swamp_ast::Node::default();
4550                    self.add_default_functions(&sparse_storage_type, &default_node);
4551                    sparse_storage_type
4552                } else {
4553                    panic!("todo: make this into an error")
4554                }
4555            }
4556
4557            "Grid" => {
4558                if ast_generic_parameters.len() == 1 {
4559                    let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4560                    let grid_view_type = self.shared.state.types.grid_view(&element_type);
4561                    // Generate default functions for the new grid view type
4562                    let default_node = swamp_ast::Node::default();
4563                    self.add_default_functions(&grid_view_type, &default_node);
4564                    grid_view_type
4565                } else if ast_generic_parameters.len() == 2 {
4566                    let element_type = self.analyze_type(ast_generic_parameters[0].get_type());
4567                    let (width, height) =
4568                        self.analyze_generic_parameter_usize_tuple(&ast_generic_parameters[1]);
4569                    let grid_storage_type =
4570                        self.shared
4571                            .state
4572                            .types
4573                            .grid_storage(&element_type, width, height);
4574                    // Generate default functions for the new grid storage type
4575                    let default_node = swamp_ast::Node::default();
4576                    self.add_default_functions(&grid_storage_type, &default_node);
4577                    grid_storage_type
4578                } else {
4579                    panic!("todo: make this into an error")
4580                }
4581            }
4582
4583            _ => return None,
4584        };
4585
4586        Some(converted_type)
4587    }
4588
4589    fn special_static_member(
4590        &self,
4591        type_identifier: &QualifiedTypeIdentifier,
4592        member_name_node: &swamp_ast::Node,
4593    ) -> Option<Function> {
4594        if type_identifier.generic_params.is_empty() {
4595            return None;
4596        }
4597
4598        if type_identifier.module_path.is_some() {
4599            return None;
4600        }
4601
4602        let member_name = self.get_text(member_name_node);
4603        let name = self.get_text(&type_identifier.name.0);
4604
4605        match name {
4606            "Stack" => None,
4607            _ => None,
4608        }
4609    }
4610}