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