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