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::{MAX_VIRTUAL_REGISTER, VariableSlot};
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 {
1558            } else {
1559                tv.resolved_type = self.shared.state.types.optional(&tv.resolved_type.clone());
1560            }
1561        }
1562
1563        self.create_expr(
1564            ExpressionKind::PostfixChain(start_of_chain, suffixes),
1565            tv.resolved_type,
1566            &chain.base.node,
1567        )
1568    }
1569
1570    fn analyze_bool_argument_expression(
1571        &mut self,
1572        expression: &swamp_ast::Expression,
1573    ) -> BooleanExpression {
1574        let bool_type = self.shared.state.types.bool();
1575        let bool_context = TypeContext::new_argument(&bool_type, false);
1576        let resolved_expression = self.analyze_expression(expression, &bool_context);
1577        let expr_type = resolved_expression.ty.clone();
1578
1579        let bool_expression = match &*expr_type.kind {
1580            TypeKind::Bool => resolved_expression,
1581            TypeKind::Optional(_) => {
1582                let bool = self.types().bool();
1583                self.create_expr(
1584                    ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1585                    bool,
1586                    &expression.node,
1587                )
1588            }
1589            _ => self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node),
1590        };
1591
1592        BooleanExpression {
1593            expression: Box::from(bool_expression),
1594        }
1595    }
1596
1597    /// Check if an expression is a function call that returns an aggregate type
1598    fn is_aggregate_function_call(expression: &swamp_ast::Expression) -> bool {
1599        match &expression.kind {
1600            swamp_ast::ExpressionKind::PostfixChain(chain) => {
1601                if chain.postfixes.is_empty() {
1602                    return false;
1603                }
1604
1605                for postfix in &chain.postfixes {
1606                    if let swamp_ast::Postfix::FunctionCall(_, _, _) = postfix {
1607                        return true;
1608                    }
1609                }
1610                false
1611            }
1612            _ => false, // Other expressions (variables, literals, etc.) are not function calls
1613        }
1614    }
1615
1616    fn analyze_iterable(
1617        &mut self,
1618        mut_requested_for_value_variable: Option<swamp_ast::Node>,
1619        expression: &swamp_ast::Expression,
1620    ) -> Iterable {
1621        // Only set has_lvalue_target=false for function calls that return aggregates
1622        // Variables/parameters already have storage, so they should have has_lvalue_target=true
1623        let has_lvalue_target = !Self::is_aggregate_function_call(expression);
1624        let any_context = TypeContext::new_anything_argument(has_lvalue_target);
1625
1626        let resolved_expression = self.analyze_expression(expression, &any_context);
1627
1628        let resolved_type = &resolved_expression.ty.clone();
1629        let int_type = Some(self.types().int());
1630        let (key_type, value_type): (Option<TypeRef>, TypeRef) = match &*resolved_type.kind {
1631            TypeKind::StringView(_, char) | TypeKind::StringStorage(_, char, _) => {
1632                (int_type, char.clone())
1633            }
1634            TypeKind::SliceView(element_type) => (int_type, element_type.clone()),
1635            TypeKind::VecStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1636            TypeKind::SparseStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1637            TypeKind::StackStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1638            TypeKind::StackView(element_type) => (int_type, element_type.clone()),
1639            TypeKind::QueueStorage(element_type, _fixed_size) => (int_type, element_type.clone()),
1640            TypeKind::QueueView(element_type) => (int_type, element_type.clone()),
1641            TypeKind::DynamicLengthVecView(element_type) => (int_type, element_type.clone()),
1642            TypeKind::SparseView(element_type) => (int_type, element_type.clone()),
1643            TypeKind::FixedCapacityAndLengthArray(element_type, _fixed_size) => {
1644                (int_type, element_type.clone())
1645            }
1646            TypeKind::DynamicLengthMapView(key_type, value_type)
1647            | TypeKind::MapStorage(key_type, value_type, _) => {
1648                (Some(key_type.clone()), value_type.clone())
1649            }
1650            TypeKind::Range(_) => (None, self.types().int()),
1651            _ => {
1652                error!(?resolved_type, "not an iterator");
1653                return Iterable {
1654                    key_type: None,
1655                    value_type: self.shared.state.types.unit(),
1656                    resolved_expression: Box::new(
1657                        self.create_err(ErrorKind::NotAnIterator, &expression.node),
1658                    ),
1659                };
1660            }
1661        };
1662
1663        if mut_requested_for_value_variable.is_some() {
1664            // we check if we can get to a lvalue, otherwise it is not mutable:
1665            let _resulting_location =
1666                self.analyze_to_location(expression, &any_context, LocationSide::Mutable);
1667            // Note: mutable references are now handled through SingleLocationExpression
1668            // The value_type stays the same, mutability is tracked separately
1669        }
1670
1671        Iterable {
1672            key_type,
1673            value_type,
1674            resolved_expression: Box::new(resolved_expression),
1675        }
1676    }
1677
1678    fn analyze_argument_expressions(
1679        &mut self,
1680        expected_type: Option<&TypeRef>,
1681        context: &TypeContext,
1682        ast_expressions: &[swamp_ast::Expression],
1683    ) -> Vec<Expression> {
1684        let mut resolved_expressions = Vec::new();
1685        // Function arguments should not have lvalue targets by default - they need proper storage allocation
1686        let argument_expressions_context = TypeContext::new_unsure_argument(expected_type, false);
1687
1688        for expression in ast_expressions {
1689            resolved_expressions
1690                .push(self.analyze_expression(expression, &argument_expressions_context));
1691        }
1692        resolved_expressions
1693    }
1694
1695    fn analyze_block(
1696        &mut self,
1697        _node: &swamp_ast::Node,
1698        context: &TypeContext,
1699        ast_expressions: &[swamp_ast::Expression],
1700    ) -> (Vec<Expression>, TypeRef) {
1701        if ast_expressions.is_empty() {
1702            return (vec![], self.shared.state.types.unit());
1703        }
1704
1705        self.push_block_scope("block");
1706
1707        let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1708
1709        for expression in &ast_expressions[..ast_expressions.len() - 1] {
1710            let unit_type = self.shared.state.types.unit();
1711            let stmt_context =
1712                context.with_expected_type(Some(&unit_type), context.has_lvalue_target);
1713            let expr = self.analyze_expression(expression, &stmt_context);
1714
1715            resolved_expressions.push(expr);
1716        }
1717
1718        // Process the last expression - it determines the block's type
1719        let last_expr =
1720            self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context);
1721        let last_type = last_expr.ty.clone();
1722        resolved_expressions.push(last_expr);
1723
1724        self.pop_block_scope("block");
1725
1726        (resolved_expressions, last_type)
1727    }
1728
1729    fn analyze_interpolated_string_lowering(
1730        &mut self,
1731        node: &swamp_ast::Node,
1732        string_parts: &[swamp_ast::StringPart],
1733    ) -> Expression {
1734        let mut last_expression: Option<Expression> = None;
1735        for part in string_parts {
1736            let created_expression = match part {
1737                swamp_ast::StringPart::Literal(string_node, processed_string) => {
1738                    let string_literal =
1739                        ExpressionKind::StringLiteral(processed_string.to_string());
1740                    let basic_literal = string_literal;
1741                    let string_type = self.shared.state.types.string();
1742                    self.add_default_functions(&string_type, node);
1743                    self.create_expr(basic_literal, string_type, string_node)
1744                }
1745                swamp_ast::StringPart::Interpolation(expression, format_specifier) => {
1746                    let any_context = TypeContext::new_anything_argument(false); // String interpolation context has no lvalue target for storage
1747
1748                    let expr = self.analyze_expression(expression, &any_context);
1749
1750                    let tk = (*expr.ty.kind).clone();
1751
1752                    let maybe_to_string = self
1753                        .shared
1754                        .state
1755                        .associated_impls
1756                        .get_internal_member_function(&expr.ty, "string");
1757
1758                    if matches!(tk, TypeKind::StringView { .. })
1759                        || matches!(tk, TypeKind::StringStorage(..))
1760                    {
1761                        expr
1762                    } else {
1763                        let underlying = expr.ty.clone();
1764
1765                        // Check if the expression needs storage validation before proceeding
1766                        if self.needs_storage_error(&expr, true, &any_context, &expression.node) {
1767                            return self.create_err(ErrorKind::NeedStorage, &expression.node);
1768                        }
1769
1770                        let call_expr_kind = if maybe_to_string.is_none() {
1771                            let string_type = self.types().string();
1772
1773                            ExpressionKind::StringLiteral(format!(
1774                                "missing to_string for: {string_type}"
1775                            ))
1776                            /* TODO:
1777
1778                                       return self.create_err(
1779                                           ErrorKind::MissingToString(string_type),
1780                                           &expression.node,
1781                                       );
1782
1783                            */
1784                        } else {
1785                            let expr_as_param = ArgumentExpression::Expression(expr);
1786                            self.create_static_member_call(
1787                                "string",
1788                                &[expr_as_param.clone()],
1789                                &expression.node,
1790                                &underlying,
1791                            )
1792                        };
1793
1794                        /*
1795                        TODO: SUPPORT FORMAT SPEC
1796                        let resolved_format_specifier =
1797                            self.analyze_format_specifier(Option::from(format_specifier));
1798
1799                         */
1800
1801                        let string_type = self.shared.state.types.string();
1802                        self.create_expr(call_expr_kind, string_type, &expression.node)
1803                    }
1804                }
1805            };
1806
1807            let x_last_expr = if let Some(last_expr) = last_expression.clone() {
1808                let op_kind = BinaryOperatorKind::Add;
1809                let node = created_expression.node.clone();
1810                let op = BinaryOperator {
1811                    left: Box::new(last_expr),
1812                    right: Box::new(created_expression),
1813                    kind: op_kind,
1814                    node: node.clone(),
1815                };
1816
1817                let string_type = self.shared.state.types.string();
1818                create_expr_resolved(ExpressionKind::BinaryOp(op), string_type, &node)
1819            } else {
1820                created_expression
1821            };
1822
1823            last_expression = Some(x_last_expr);
1824        }
1825
1826        // if we have no last_expression, then it means the whole
1827        // interpolation was completely was empty (`''`)
1828        if let Some(last) = last_expression {
1829            last
1830        } else {
1831            let string_type = self.shared.state.types.string();
1832            self.create_expr(
1833                ExpressionKind::StringLiteral(String::new()),
1834                string_type,
1835                node,
1836            )
1837        }
1838    }
1839
1840    pub(crate) fn analyze_identifier(
1841        &mut self,
1842        qualified_func_name: &swamp_ast::QualifiedIdentifier,
1843    ) -> Expression {
1844        // Must check variable first, since that is more intuitive for the user.
1845        // local variables before other functions
1846        if qualified_func_name.module_path.is_none()
1847            && qualified_func_name.generic_params.is_empty()
1848            && let Some(found_variable) = self.try_find_variable(&qualified_func_name.name)
1849        {
1850            return self.create_expr(
1851                ExpressionKind::VariableAccess(found_variable.clone()),
1852                found_variable.resolved_type.clone(),
1853                &qualified_func_name.name,
1854            );
1855        }
1856
1857        let text = self.get_text(&qualified_func_name.name);
1858        self.create_err(
1859            ErrorKind::UnknownIdentifier(text.to_string()),
1860            &qualified_func_name.name,
1861        )
1862    }
1863
1864    // The ast assumes it is something similar to a variable, but it can be a function reference as well.
1865    fn analyze_variable_reference(&mut self, var_node: &swamp_ast::Node) -> Expression {
1866        if let Some(found_variable) = self.try_find_variable(var_node) {
1867            let name_node = self.to_node(var_node);
1868
1869            self.shared
1870                .state
1871                .refs
1872                .add(found_variable.symbol_id.into(), name_node.clone());
1873            self.shared
1874                .definition_table
1875                .refs
1876                .add(found_variable.symbol_id.into(), name_node);
1877
1878            return self.create_expr(
1879                ExpressionKind::VariableAccess(found_variable.clone()),
1880                found_variable.resolved_type.clone(),
1881                var_node,
1882            );
1883        }
1884        let text = self.get_text(var_node);
1885        self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node)
1886    }
1887
1888    fn analyze_internal_initializer_pair_list(
1889        &mut self,
1890        node: &swamp_ast::Node,
1891        items: &[(swamp_ast::Expression, swamp_ast::Expression)],
1892        context: &TypeContext,
1893    ) -> (TypeRef, Vec<(Expression, Expression)>) {
1894        let (collection_type, key_type, value_type) = if let Some(expected_type) =
1895            context.expected_type
1896        {
1897            match &*expected_type.kind {
1898                TypeKind::MapStorage(key, value, capacity) => {
1899                    if items.len() > *capacity {
1900                        self.add_err(
1901                            ErrorKind::TooManyInitializerListElementsForStorage {
1902                                capacity: *capacity,
1903                            },
1904                            node,
1905                        );
1906                        return (self.types().unit(), vec![]);
1907                    }
1908                    (expected_type.clone(), key.clone(), value.clone())
1909                }
1910                TypeKind::DynamicLengthMapView(key, value) => {
1911                    (expected_type.clone(), key.clone(), value.clone())
1912                }
1913                _ => {
1914                    self.add_err(ErrorKind::ExpectedSlice, node);
1915                    return (self.types().unit(), vec![]);
1916                }
1917            }
1918        } else if items.is_empty() {
1919            self.add_err(ErrorKind::NoInferredTypeForEmptyInitializer, node);
1920            return (self.types().unit(), vec![]);
1921        } else {
1922            // Try to detect, by checking the first
1923            let maybe_key_context = TypeContext::new_anything_argument(true);
1924
1925            let first_key_expression = self.analyze_expression(&items[0].0, &maybe_key_context);
1926
1927            let maybe_value_context = TypeContext::new_anything_argument(true);
1928            let first_value_expression = self.analyze_expression(&items[0].1, &maybe_value_context);
1929
1930            let required_key_type = first_key_expression.ty;
1931            let required_value_type = first_value_expression.ty;
1932
1933            let inferred_type =
1934                self.types()
1935                    .map_storage(&required_key_type, &required_value_type, items.len());
1936
1937            (inferred_type, required_key_type, required_value_type)
1938        };
1939
1940        assert!(!matches!(*key_type.kind, TypeKind::Unit));
1941        assert!(!matches!(*value_type.kind, TypeKind::Unit));
1942
1943        let required_key_context = TypeContext::new_argument(&key_type, true);
1944        let required_value_context = TypeContext::new_argument(&value_type, true);
1945
1946        let mut resolved_items = Vec::new();
1947
1948        for (key_expr, value_expr) in items {
1949            let analyzed_key_expr = self.analyze_expression(key_expr, &required_key_context);
1950            let analyzed_value_expr = self.analyze_expression(value_expr, &required_value_context);
1951            resolved_items.push((analyzed_key_expr, analyzed_value_expr));
1952        }
1953
1954        (collection_type, resolved_items)
1955    }
1956
1957    fn analyze_internal_initializer_list(
1958        &mut self,
1959        node: &swamp_ast::Node,
1960        items: &[swamp_ast::Expression],
1961        context: &TypeContext,
1962    ) -> (TypeRef, Vec<Expression>) {
1963        let (collection_type, element_type) = if let Some(expected_type) = context.expected_type {
1964            match &*expected_type.kind {
1965                TypeKind::GridStorage(element_type, width, height) => {
1966                    let capacity = width * height;
1967                    if items.len() > capacity {
1968                        return (
1969                            self.types().unit(),
1970                            self.create_err_vec(
1971                                ErrorKind::TooManyInitializerListElementsForStorage { capacity },
1972                                node,
1973                            ),
1974                        );
1975                    }
1976                    (expected_type.clone(), element_type.clone())
1977                }
1978                TypeKind::StackStorage(element_type, capacity)
1979                | TypeKind::QueueStorage(element_type, capacity)
1980                | TypeKind::SparseStorage(element_type, capacity)
1981                | TypeKind::VecStorage(element_type, capacity) => {
1982                    if items.len() > *capacity {
1983                        return (
1984                            self.types().unit(),
1985                            self.create_err_vec(
1986                                ErrorKind::TooManyInitializerListElementsForStorage {
1987                                    capacity: *capacity,
1988                                },
1989                                node,
1990                            ),
1991                        );
1992                    }
1993                    (expected_type.clone(), element_type.clone())
1994                }
1995                TypeKind::QueueView(element_type) => {
1996                    // For QueueView expected type, infer QueueStorage for the literal
1997                    let inferred_storage_type =
1998                        self.types().queue_storage(element_type, items.len());
1999                    let default_node = swamp_ast::Node::default();
2000                    self.add_default_functions(&inferred_storage_type, &default_node);
2001                    (inferred_storage_type, element_type.clone())
2002                }
2003                TypeKind::SparseView(element_type) => {
2004                    // For SparseView expected type, infer SparseStorage for the literal
2005                    let inferred_storage_type =
2006                        self.types().sparse_storage(element_type, items.len());
2007                    let default_node = swamp_ast::Node::default();
2008                    self.add_default_functions(&inferred_storage_type, &default_node);
2009                    (inferred_storage_type, element_type.clone())
2010                }
2011                TypeKind::StackView(element_type) => {
2012                    // For StackView expected type, infer StackStorage for the literal
2013                    let inferred_storage_type =
2014                        self.types().stack_storage(element_type, items.len());
2015                    let default_node = swamp_ast::Node::default();
2016                    self.add_default_functions(&inferred_storage_type, &default_node);
2017                    (inferred_storage_type, element_type.clone())
2018                }
2019                TypeKind::GridView(element_type) => {
2020                    // For GridView, we can't infer dimensions from a 1D list, so keep the expected type
2021                    (expected_type.clone(), element_type.clone())
2022                }
2023                TypeKind::DynamicLengthVecView(element_type) => {
2024                    // For DynamicLengthVecView expected type, infer VecStorage for the literal
2025                    let inferred_storage_type = self.types().vec_storage(element_type, items.len());
2026                    let default_node = swamp_ast::Node::default();
2027                    self.add_default_functions(&inferred_storage_type, &default_node);
2028                    (inferred_storage_type, element_type.clone())
2029                }
2030                TypeKind::SliceView(element_type) => {
2031                    // For SliceView expected type, infer VecStorage for the literal
2032                    let inferred_storage_type = self.types().vec_storage(element_type, items.len());
2033                    let default_node = swamp_ast::Node::default();
2034                    self.add_default_functions(&inferred_storage_type, &default_node);
2035                    (inferred_storage_type, element_type.clone())
2036                }
2037                TypeKind::FixedCapacityAndLengthArray(element_type, _size) => {
2038                    (expected_type.clone(), element_type.clone())
2039                }
2040                _ => {
2041                    return (
2042                        self.types().unit(),
2043                        self.create_err_vec(
2044                            ErrorKind::ExpectedInitializerTarget {
2045                                destination_type: expected_type.clone(),
2046                            },
2047                            node,
2048                        ),
2049                    );
2050                }
2051            }
2052        } else if items.is_empty() {
2053            return (
2054                self.types().unit(),
2055                self.create_err_vec(ErrorKind::NoInferredTypeForEmptyInitializer, node),
2056            );
2057        } else {
2058            // Try to detect, by checking the first
2059            let maybe_context = TypeContext::new_anything_argument(true);
2060            let first = self.analyze_expression(&items[0], &maybe_context);
2061            let required_type = first.ty;
2062            let inferred_vec_storage_type = self.types().vec_storage(&required_type, items.len());
2063            // Generate default functions for the inferred vec storage type
2064            let default_node = swamp_ast::Node::default();
2065            self.add_default_functions(&inferred_vec_storage_type, &default_node);
2066            (inferred_vec_storage_type, required_type)
2067        };
2068
2069        let required_context = TypeContext::new_argument(&element_type, true);
2070        let mut resolved_items = Vec::new();
2071        for item in items {
2072            let resolved_expr = self.analyze_expression(item, &required_context);
2073            resolved_items.push(resolved_expr);
2074        }
2075        (collection_type, resolved_items)
2076    }
2077
2078    fn push_block_scope(&mut self, debug_str: &str) {
2079        let register_watermark = self.scope.total_scopes.current_register;
2080        //info!("-> SCOPE {debug_str} hwm:{register_watermark}");
2081
2082        self.scope.active_scope.block_scope_stack.push(BlockScope {
2083            mode: BlockScopeMode::Open,
2084            lookup: Default::default(),
2085            variables: SeqMap::default(),
2086            register_watermark,
2087        });
2088    }
2089
2090    fn push_lambda_scope(&mut self, debug_str: &str) {
2091        // Lambda scopes are virtual and completely transparent to register allocation
2092        // They don't save any watermark and don't affect register allocation
2093        self.scope.active_scope.block_scope_stack.push(BlockScope {
2094            mode: BlockScopeMode::Lambda,
2095            lookup: SeqMap::default(),
2096            variables: SeqMap::default(),
2097            register_watermark: 0, // Not used for lambda scopes
2098        });
2099    }
2100
2101    fn pop_block_scope(&mut self, debug_str: &str) {
2102        //info!("<- SCOPE {debug_str}");
2103        self.pop_any_block_scope();
2104    }
2105
2106    fn push_closed_block_scope(&mut self) {
2107        let register_watermark = self.scope.total_scopes.current_register;
2108        //info!("-> Push CLOSED SCOPE  hwm:{register_watermark}");
2109        self.scope.active_scope.block_scope_stack.push(BlockScope {
2110            mode: BlockScopeMode::Closed,
2111            lookup: Default::default(),
2112            variables: SeqMap::default(),
2113            register_watermark,
2114        });
2115    }
2116
2117    fn pop_closed_block_scope(&mut self) {
2118        //self.scope.active_scope.block_scope_stack.pop();
2119        self.pop_any_block_scope();
2120    }
2121
2122    fn pop_any_block_scope(&mut self) {
2123        let scope = self.scope.active_scope.block_scope_stack.pop().unwrap();
2124
2125        // Record the highest watermark (greatest depth of virtual registers)
2126        if self.scope.total_scopes.current_register
2127            > self.scope.total_scopes.highest_virtual_register
2128        {
2129            self.scope.total_scopes.highest_virtual_register =
2130                self.scope.total_scopes.current_register;
2131        }
2132
2133        // Check if we're inside a lambda scope - if so, don't restore register counter
2134        let is_inside_lambda = self
2135            .scope
2136            .active_scope
2137            .block_scope_stack
2138            .iter()
2139            .any(|s| matches!(s.mode, BlockScopeMode::Lambda));
2140
2141        if matches!(scope.mode, BlockScopeMode::Lambda) {
2142            // lambda scope - completely transparent, no register changes
2143        } else if is_inside_lambda {
2144            // block scope inside lambda - virtual, no register restoration
2145        } else {
2146            // Regular scopes restore their watermark to free up registers
2147            // This enables register reuse when variables go out of scope
2148
2149            //info!( scope.register_watermark, "<- pop any block scope: restoring hwm");
2150            self.scope.total_scopes.current_register = scope.register_watermark;
2151        }
2152    }
2153
2154    fn analyze_match(
2155        &mut self,
2156        scrutinee: &swamp_ast::Expression,
2157        default_context: &TypeContext,
2158        arms: &Vec<swamp_ast::MatchArm>,
2159    ) -> (Match, TypeRef) {
2160        let mut known_type = default_context.expected_type.cloned();
2161        let own_context = default_context.clone();
2162
2163        self.push_block_scope("match block");
2164        // Analyze the scrutinee with no specific expected type
2165        let scrutinee_context = TypeContext::new_anything_argument(true); // we just using the pointer, so pretend that it is a target
2166        let resolved_scrutinee = self.analyze_expression(scrutinee, &scrutinee_context);
2167        let scrutinee_type = resolved_scrutinee.ty.clone();
2168
2169        let mut resolved_arms = Vec::with_capacity(arms.len());
2170
2171        // Ensure we have at least one arm
2172        if arms.is_empty() {
2173            let err_match = Match {
2174                expression: Box::new(
2175                    self.create_err(ErrorKind::MatchMustHaveAtLeastOneArm, &scrutinee.node),
2176                ),
2177                arms: resolved_arms,
2178            };
2179            return (err_match, self.types().unit());
2180        }
2181
2182        for arm in arms {
2183            let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
2184                arm,
2185                &resolved_scrutinee,
2186                &own_context.with_expected_type(known_type.as_ref(), false),
2187                &scrutinee_type,
2188            );
2189
2190            if known_type.is_none() {
2191                known_type = Some(resolved_arm.expression.ty.clone());
2192            }
2193            resolved_arms.push(resolved_arm);
2194        }
2195
2196        self.pop_block_scope("match block");
2197
2198        if let Some(encountered_type) = known_type {
2199            (
2200                Match {
2201                    expression: Box::new(resolved_scrutinee),
2202                    arms: resolved_arms,
2203                },
2204                encountered_type,
2205            )
2206        } else {
2207            let err_expr = self.create_err(ErrorKind::MatchArmsMustHaveTypes, &scrutinee.node);
2208
2209            (
2210                Match {
2211                    expression: Box::new(err_expr),
2212                    arms: resolved_arms.clone(),
2213                },
2214                self.types().unit(),
2215            )
2216        }
2217    }
2218
2219    fn analyze_arm(
2220        &mut self,
2221        arm: &swamp_ast::MatchArm,
2222        _expression: &Expression,
2223        type_context: &TypeContext,
2224        expected_condition_type: &TypeRef,
2225    ) -> (MatchArm, bool) {
2226        let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
2227            self.analyze_pattern(&arm.pattern, expected_condition_type);
2228
2229        let resolved_expression = self.analyze_expression(&arm.expression, type_context);
2230        if scope_was_pushed {
2231            self.pop_block_scope(&format!("analyze_arm {:?}", arm.expression));
2232        }
2233
2234        let resolved_type = resolved_expression.ty.clone();
2235
2236        (
2237            MatchArm {
2238                pattern: resolved_pattern,
2239                expression: Box::from(resolved_expression),
2240                expression_type: resolved_type,
2241            },
2242            anyone_wants_mutable,
2243        )
2244    }
2245
2246    fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
2247        let text = text.replace('_', "");
2248        text.strip_prefix("0x").map_or_else(
2249            || {
2250                text.strip_prefix("-0x").map_or_else(
2251                    || text.parse::<i32>(),
2252                    |rest| i32::from_str_radix(rest, 16).map(|x| -x),
2253                )
2254            },
2255            |rest| i32::from_str_radix(rest, 16),
2256        )
2257    }
2258
2259    pub fn str_to_byte(text: &str) -> Result<u8, ParseByteError> {
2260        // TODO: Fix better parsing so you don't get text for the whole node
2261        let inner = text
2262            .strip_prefix("b'")
2263            .and_then(|s| s.strip_suffix("'"))
2264            .ok_or(ParseByteError::InvalidFormat)?;
2265
2266        let mut chars = inner.chars();
2267        let first = chars.next().ok_or(ParseByteError::InvalidFormat)?;
2268
2269        if first == '\\' {
2270            let esc = chars.next().ok_or(ParseByteError::InvalidEscape)?;
2271            if chars.next().is_some() {
2272                return Err(ParseByteError::InvalidFormat);
2273            }
2274            return match esc {
2275                'n' => Ok(b'\n'),
2276                'r' => Ok(b'\r'),
2277                't' => Ok(b'\t'),
2278                '0' => Ok(b'\0'),
2279                '\\' => Ok(b'\\'),
2280                '\'' => Ok(b'\''),
2281                _ => Err(ParseByteError::InvalidEscape),
2282            };
2283        }
2284
2285        if first.is_ascii() && chars.next().is_none() {
2286            return Ok(first as u8);
2287        }
2288
2289        Err(ParseByteError::InvalidFormat)
2290    }
2291    fn str_to_unsigned_int(text: &str) -> Result<u32, ParseIntError> {
2292        let text = text.replace('_', "");
2293        text.strip_prefix("0x")
2294            .map_or_else(|| text.parse::<u32>(), |rest| u32::from_str_radix(rest, 16))
2295    }
2296
2297    fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
2298        text.parse::<f32>()
2299    }
2300
2301    fn str_to_bool(text: &str) -> Result<bool, ParseBoolError> {
2302        bool::from_str(text)
2303    }
2304
2305    fn analyze_pattern_literal(
2306        &mut self,
2307        node: &swamp_ast::Node,
2308        ast_literal: &swamp_ast::LiteralKind,
2309        expected_condition_type: &TypeRef,
2310    ) -> NormalPattern {
2311        let required_condition_type_context =
2312            TypeContext::new_argument(expected_condition_type, false);
2313        let literal = self.analyze_literal(
2314            node,
2315            ast_literal,
2316            &required_condition_type_context,
2317            &required_condition_type_context,
2318        );
2319
2320        if !self
2321            .types()
2322            .compatible_with(&literal.ty, expected_condition_type)
2323        {
2324            return NormalPattern::Literal(self.create_err(
2325                ErrorKind::IncompatibleTypes {
2326                    expected: expected_condition_type.clone(),
2327                    found: literal.ty,
2328                },
2329                node,
2330            ));
2331        }
2332
2333        NormalPattern::Literal(literal)
2334    }
2335
2336    const fn to_node(&self, node: &swamp_ast::Node) -> Node {
2337        Node {
2338            span: Span {
2339                file_id: self.shared.file_id,
2340                offset: node.span.offset,
2341                length: node.span.length,
2342            },
2343        }
2344    }
2345
2346    fn get_module_path(&self, module_path: Option<&swamp_ast::ModulePath>) -> Vec<String> {
2347        module_path.as_ref().map_or_else(Vec::new, |found| {
2348            let mut strings = Vec::new();
2349            for path_item in &found.0 {
2350                strings.push(self.get_text(path_item).to_string());
2351            }
2352            strings
2353        })
2354    }
2355
2356    fn get_enum_variant_type(
2357        &mut self,
2358        qualified_type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2359        variant_name: &str,
2360    ) -> EnumVariantType {
2361        let Some((symbol_table, enum_name)) =
2362            self.get_symbol_table_and_name(qualified_type_identifier)
2363        else {
2364            self.add_err(
2365                ErrorKind::UnknownEnumVariantType,
2366                &qualified_type_identifier.name.0,
2367            );
2368            return EnumVariantType {
2369                common: EnumVariantCommon {
2370                    symbol_id: TopLevelSymbolId::new_illegal(),
2371                    name: Default::default(),
2372                    assigned_name: String::new(),
2373                    container_index: 0,
2374                },
2375                payload_type: self.types().unit(),
2376            };
2377        };
2378
2379        if let Some(enum_name) = symbol_table.get_enum_variant_type(&enum_name, variant_name) {
2380            enum_name
2381        } else {
2382            self.add_err(
2383                ErrorKind::UnknownEnumVariantType,
2384                &qualified_type_identifier.name.0,
2385            );
2386            EnumVariantType {
2387                common: EnumVariantCommon {
2388                    symbol_id: TopLevelSymbolId::new_illegal(),
2389                    name: Default::default(),
2390                    assigned_name: String::new(),
2391                    container_index: 0,
2392                },
2393                payload_type: self.types().unit(),
2394            }
2395        }
2396    }
2397
2398    pub(crate) fn get_symbol_table_and_name(
2399        &self,
2400        type_identifier: &swamp_ast::QualifiedTypeIdentifier,
2401    ) -> Option<(&DefinitionTable, String)> {
2402        let path = self.get_module_path(type_identifier.module_path.as_ref());
2403        let name = self.get_text(&type_identifier.name.0).to_string();
2404
2405        if let Some(found) = self.shared.get_definition_table(&path) {
2406            Some((found, name))
2407        } else {
2408            None
2409        }
2410    }
2411
2412    const fn analyze_compound_operator(
2413        &self,
2414        ast_operator: &swamp_ast::CompoundOperator,
2415    ) -> CompoundOperator {
2416        let resolved_node = self.to_node(&ast_operator.node);
2417        let resolved_kind = match ast_operator.kind {
2418            swamp_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
2419            swamp_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
2420            swamp_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
2421            swamp_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
2422            swamp_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
2423        };
2424
2425        CompoundOperator {
2426            node: resolved_node,
2427            kind: resolved_kind,
2428        }
2429    }
2430
2431    const fn to_node_option(&self, maybe_node: Option<&swamp_ast::Node>) -> Option<Node> {
2432        match maybe_node {
2433            None => None,
2434            Some(node) => Some(self.to_node(node)),
2435        }
2436    }
2437
2438    const fn analyze_format_specifier(
2439        &self,
2440        ast_format_specifier: Option<&swamp_ast::FormatSpecifier>,
2441    ) -> Option<FormatSpecifier> {
2442        let f = match ast_format_specifier {
2443            None => return None,
2444            Some(ast_format) => match ast_format {
2445                swamp_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
2446                    node: self.to_node(node),
2447                    kind: FormatSpecifierKind::LowerHex,
2448                },
2449                swamp_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
2450                    node: self.to_node(node),
2451                    kind: FormatSpecifierKind::UpperHex,
2452                },
2453                swamp_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
2454                    node: self.to_node(node),
2455                    kind: FormatSpecifierKind::Binary,
2456                },
2457                swamp_ast::FormatSpecifier::Float(node) => FormatSpecifier {
2458                    node: self.to_node(node),
2459                    kind: FormatSpecifierKind::Float,
2460                },
2461                swamp_ast::FormatSpecifier::Precision(value, node, x) => {
2462                    let (precision_type, precision_node) = match x {
2463                        swamp_ast::PrecisionType::Float(node) => {
2464                            (PrecisionType::Float, self.to_node(node))
2465                        }
2466                        swamp_ast::PrecisionType::String(node) => {
2467                            (PrecisionType::String, self.to_node(node))
2468                        }
2469                    };
2470                    FormatSpecifier {
2471                        node: self.to_node(node),
2472                        kind: FormatSpecifierKind::Precision(
2473                            *value,
2474                            precision_node,
2475                            precision_type,
2476                        ),
2477                    }
2478                }
2479            },
2480        };
2481
2482        Some(f)
2483    }
2484
2485    fn analyze_with_expr(
2486        &mut self,
2487        context: &TypeContext,
2488        variables: &[swamp_ast::VariableBinding],
2489        expression: &swamp_ast::Expression,
2490    ) -> Expression {
2491        let mut variable_expressions = Vec::new();
2492
2493        for variable in variables {
2494            let any_context = TypeContext::new_anything_argument(false);
2495            let must_have_expression = if let Some(x) = &variable.expression {
2496                x
2497            } else {
2498                &swamp_ast::Expression {
2499                    kind: swamp_ast::ExpressionKind::VariableReference(variable.variable.clone()),
2500                    node: variable.variable.name.clone(),
2501                }
2502            };
2503
2504            // Determine the correct LocationSide based on the variable binding type
2505            let location_side = if variable.variable.is_mutable.is_some() {
2506                // For mutable variables in with statements, we need to check if this is an lvalue binding
2507                if let Some(expr) = &variable.expression {
2508                    // Use analyze_maybe_ref_expression to properly detect mutable references
2509                    let maybe_ref = self.analyze_maybe_ref_expression(expr);
2510                    if maybe_ref.has_borrow_mutable_reference.is_some() {
2511                        LocationSide::Mutable
2512                    } else {
2513                        LocationSide::Rhs
2514                    }
2515                } else {
2516                    // For cases like `with mut x` (no expression), it's an alias
2517                    LocationSide::Rhs
2518                }
2519            } else {
2520                // For immutable variables, always use Rhs
2521                LocationSide::Rhs
2522            };
2523
2524            let var = self.analyze_mut_or_immutable_expression(
2525                must_have_expression,
2526                &any_context,
2527                location_side,
2528            );
2529
2530            variable_expressions.push(var);
2531        }
2532
2533        self.push_closed_block_scope();
2534        let mut expressions = Vec::new();
2535        for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
2536            let initialize_variable_expression = self
2537                .create_variable_binding_for_with(&variable_binding.variable, resolved_expression);
2538
2539            // Always add the expression to ensure proper initialization/binding
2540            // Even for aliases (VariableAccess), we need the expression in the block
2541            // to establish the proper scope and binding
2542            expressions.push(initialize_variable_expression);
2543        }
2544
2545        let resolved_expression = self.analyze_expression(expression, context);
2546        // with statements are for side effects only, so they always return Unit type
2547        let block_type = self.types().unit();
2548        expressions.push(resolved_expression);
2549
2550        let block_expression_kind = ExpressionKind::Block(expressions);
2551        self.pop_closed_block_scope();
2552
2553        self.create_expr(block_expression_kind, block_type, &expression.node)
2554    }
2555
2556    fn analyze_when_expr(
2557        &mut self,
2558        context: &TypeContext,
2559        variables: &[swamp_ast::VariableBinding],
2560        true_expr: &swamp_ast::Expression,
2561        else_expr: Option<&swamp_ast::Expression>,
2562    ) -> Expression {
2563        // Since we are making new variable bindings, we have to push a scope for them
2564        self.push_block_scope("when");
2565        let mut bindings = Vec::new();
2566        for variable_binding in variables {
2567            let mut_expr = if let Some(found_expr) = &variable_binding.expression {
2568                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
2569                self.analyze_mut_or_immutable_expression(
2570                    found_expr,
2571                    &any_context,
2572                    LocationSide::Rhs,
2573                )
2574                .expect_immutable()
2575                .unwrap()
2576            } else {
2577                let same_var = self.find_variable(&variable_binding.variable);
2578
2579                // For when expressions, we always want to extract the value from the optional,
2580                // not create a mutable reference to the original variable
2581                let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
2582                self.create_expr(
2583                    generated_expr_kind,
2584                    same_var.resolved_type.clone(),
2585                    &variable_binding.variable.name,
2586                )
2587            };
2588
2589            let tk = &mut_expr.ty.kind;
2590
2591            if let TypeKind::Optional(found_ty) = &**tk {
2592                // TODO: In the future we should check if this binding variable is just the payload of the variable
2593                // given to it. in that case we should just create a param like variable, in the sense
2594                // that it is *not* allocated in the stack frame, but is just represented as a register
2595                let variable_ref = { //variable_binding.expression.is_some() || variable_binding.variable.is_mutable.is_some() {
2596                    self.create_variable(&variable_binding.variable, found_ty)
2597                }/* else {
2598                    self.create_local_variable_parameter_like(&variable_binding.variable.name, Option::from(&variable_binding.variable.is_mutable), found_ty, false)
2599                }*/;
2600
2601                let binding = WhenBinding {
2602                    variable: variable_ref,
2603                    expr: mut_expr,
2604                };
2605                bindings.push(binding);
2606            } else {
2607                return self.create_err(ErrorKind::ExpectedOptional, &true_expr.node);
2608            }
2609        }
2610
2611        let resolved_true = self.analyze_expression(true_expr, context);
2612        let block_type = resolved_true.ty.clone();
2613
2614        self.pop_block_scope("when");
2615
2616        let maybe_resolved_else = if let Some(found_else) = else_expr {
2617            let block_type_for_true_context = context.we_know_expected_type(&block_type, false);
2618            Some(Box::new(self.analyze_expression(
2619                found_else,
2620                &block_type_for_true_context,
2621            )))
2622        } else {
2623            None
2624        };
2625
2626        let when_kind =
2627            ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
2628
2629        self.create_expr(when_kind, block_type, &true_expr.node)
2630    }
2631
2632    fn analyze_guard(
2633        &mut self,
2634        node: &swamp_ast::Node,
2635        context: &TypeContext,
2636        guard_expressions: &Vec<swamp_ast::GuardExpr>,
2637    ) -> Expression {
2638        let mut guards = Vec::new();
2639        let mut found_wildcard = None;
2640        let mut detected_type = context.expected_type.cloned();
2641
2642        for guard in guard_expressions {
2643            let resolved_condition = match &guard.clause {
2644                swamp_ast::GuardClause::Wildcard(x) => {
2645                    if found_wildcard.is_some() {
2646                        return self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node);
2647                    }
2648                    found_wildcard = Some(x);
2649                    None
2650                }
2651                swamp_ast::GuardClause::Expression(clause_expr) => {
2652                    if found_wildcard.is_some() {
2653                        return self.create_err(ErrorKind::WildcardMustBeLastInGuard, node);
2654                    }
2655                    Some(self.analyze_bool_argument_expression(clause_expr))
2656                }
2657            };
2658
2659            let resolved_result = self.analyze_expression(
2660                &guard.result,
2661                &context.with_expected_type(detected_type.as_ref(), false),
2662            );
2663            let ty = resolved_result.ty.clone();
2664            if detected_type.is_none() {
2665                detected_type = Some(ty.clone());
2666            }
2667
2668            guards.push(Guard {
2669                condition: resolved_condition,
2670                result: resolved_result,
2671            });
2672        }
2673
2674        if found_wildcard.is_none() {
2675            return self.create_err(ErrorKind::GuardMustHaveWildcard, node);
2676        }
2677
2678        let kind = ExpressionKind::Guard(guards);
2679
2680        if let Some(found_expecting_type) = detected_type {
2681            self.create_expr(kind, found_expecting_type, node)
2682        } else {
2683            self.create_err(ErrorKind::GuardHasNoType, node)
2684        }
2685    }
2686
2687    fn analyze_lambda(
2688        &mut self,
2689        node: &swamp_ast::Node,
2690        variables: &[swamp_ast::Variable],
2691        ast_expr: &swamp_ast::Expression,
2692        context: &TypeContext,
2693    ) -> Expression {
2694        let TypeKind::Function(signature) = &*context.expected_type.unwrap().kind else {
2695            return self.create_err(ErrorKind::ExpectedLambda, node);
2696        };
2697
2698        let return_block_type = TypeContext::new_argument(&signature.return_type, false);
2699
2700        // Create a lambda scope for proper variable scoping and shadowing
2701        // But the register allocation will "continue" from parent scope (no decrement on pop)
2702        self.push_lambda_scope("lambda");
2703
2704        let arity_required = signature.parameters.len();
2705        let variable_types_to_create = if variables.len() == arity_required {
2706            &signature.parameters
2707        } else if variables.len() + 1 == arity_required {
2708            &signature.parameters[1..].to_vec()
2709        } else {
2710            return self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node);
2711        };
2712
2713        let mut resolved_variables = Vec::new();
2714        for (variable, variable_type) in variables.iter().zip(variable_types_to_create) {
2715            let variable_ref = self.create_local_variable(
2716                &variable.name,
2717                variable.is_mutable.as_ref(),
2718                &variable_type.resolved_type,
2719                false,
2720            );
2721            resolved_variables.push(variable_ref);
2722        }
2723
2724        // Analyze the lambda body expression directly without creating additional block scopes
2725        // This ensures lambda variables are allocated in the lambda scope, not inner scopes
2726        let analyzed_expression = self.analyze_expression(ast_expr, &return_block_type);
2727
2728        self.pop_block_scope("lambda");
2729
2730        let function_type = self.types().function(signature.clone());
2731        self.create_expr(
2732            ExpressionKind::Lambda(resolved_variables, Box::new(analyzed_expression)),
2733            function_type,
2734            node,
2735        )
2736    }
2737
2738    #[must_use]
2739    pub fn chain_is_owned_result(
2740        start_of_chain: &StartOfChain,
2741        chains: &Vec<Postfix>,
2742    ) -> (bool, bool) {
2743        let mut is_owned_result = matches!(start_of_chain.kind, StartOfChainKind::Expression(_));
2744        let mut is_mutable = if let StartOfChainKind::Variable(var) = &start_of_chain.kind {
2745            var.is_mutable()
2746        } else {
2747            false
2748        };
2749
2750        for chain in chains {
2751            match chain.kind {
2752                PostfixKind::StructField(_, _) => {
2753                    is_owned_result = false;
2754                }
2755                PostfixKind::MemberCall(_, _) => {
2756                    is_owned_result = true;
2757                    is_mutable = false;
2758                }
2759                PostfixKind::OptionalChainingOperator => {
2760                    is_owned_result = true;
2761                    is_mutable = false;
2762                }
2763                PostfixKind::VecSubscript(_, _) => {}
2764                PostfixKind::VecSubscriptRange(_, _) => {}
2765                PostfixKind::SparseSubscript(_, _) => {}
2766                PostfixKind::GridSubscript(_, _, _) => {}
2767                PostfixKind::MapSubscript(_, _) => {}
2768            }
2769        }
2770
2771        (is_owned_result, is_mutable)
2772    }
2773
2774    pub fn check_assignment_mode(
2775        &mut self,
2776        lhs_is_mutable: bool,
2777        source_expression: &Expression,
2778        ty: &TypeRef,
2779    ) -> AssignmentMode {
2780        if matches!(
2781            &source_expression.kind,
2782            _ | ExpressionKind::IntrinsicCallEx(_, _)
2783        ) {
2784            return AssignmentMode::OwnedValue;
2785        }
2786
2787        /* TODO:
2788        if ty.is_direct() {
2789            return AssignmentMode::OwnedValue;
2790        }
2791
2792         */
2793
2794        if let ExpressionKind::PostfixChain(start_chain, postfix) = &source_expression.kind {
2795            let (chain_is_owned, chain_is_mutable) =
2796                Self::chain_is_owned_result(start_chain, postfix);
2797            if lhs_is_mutable {
2798                return if chain_is_mutable {
2799                    AssignmentMode::CopyBlittable
2800                } else if lhs_is_mutable {
2801                    if chain_is_owned {
2802                        AssignmentMode::OwnedValue
2803                    } else {
2804                        AssignmentMode::CopyBlittable
2805                    }
2806                } else {
2807                    AssignmentMode::CopySharedPtr
2808                };
2809            }
2810            // if not mutable, it is always ok
2811        }
2812
2813        AssignmentMode::CopyBlittable
2814    }
2815
2816    pub const fn check_mutable_assignment(&mut self, assignment_mode: AssignmentMode, node: &Node) {
2817    }
2818
2819    pub const fn check_mutable_variable_assignment(
2820        &mut self,
2821        source_expression: &swamp_ast::Expression,
2822        ty: &TypeRef,
2823        variable: &swamp_ast::Variable,
2824    ) {
2825        //let is_allowed_to_assign = Self::check_mutable_assignment_is_valid(ty);
2826        //if !is_allowed_to_assign {
2827        //  error!(?ty, "variable is wrong");
2828        //return Err(self.create_err(ErrorKind::ArgumentIsNotMutable, &variable.name));
2829        //}
2830    }
2831
2832    /// # Errors
2833    ///
2834    pub fn analyze_variable_definition(
2835        &mut self,
2836        variable: &swamp_ast::Variable,
2837        annotation_type: &Option<swamp_ast::Type>,
2838        source_expression: &swamp_ast::Expression,
2839    ) -> Expression {
2840        let maybe_found_variable = self.try_find_variable(&variable.name);
2841        if maybe_found_variable.is_some() {
2842            return self.create_err(ErrorKind::OverwriteVariableNotAllowedHere, &variable.name);
2843        }
2844
2845        let node = self.to_node(&variable.name);
2846
2847        let Some(variable_slot) = self.reserve_slot(&node) else {
2848            return self.create_err(ErrorKind::OutOfVirtualRegisters, &variable.name);
2849        };
2850
2851        let maybe_annotated_type = annotation_type.as_ref().map(|found_ast_type| {
2852            self.analyze_type(found_ast_type, &TypeAnalyzeContext::default())
2853        });
2854
2855        self.common_variable_util(
2856            VariableResolution::ReservedSlot(variable_slot, variable.clone(), maybe_annotated_type),
2857            &variable.name,
2858            source_expression,
2859        )
2860    }
2861
2862    /// # Errors
2863    ///
2864    pub fn analyze_variable_assignment(
2865        &mut self,
2866        variable: &swamp_ast::Variable,
2867        source_expression: &swamp_ast::Expression,
2868    ) -> Expression {
2869        let maybe_found_variable = self.try_find_variable(&variable.name);
2870
2871        let node = self.to_node(&variable.name);
2872        let resolution = if let Some(found_var) = maybe_found_variable {
2873            VariableResolution::ExistingVariable(found_var)
2874        } else {
2875            let Some(variable_slot) = self.reserve_slot(&node) else {
2876                return self.create_err(ErrorKind::OutOfVirtualRegisters, &variable.name);
2877            };
2878
2879            VariableResolution::ReservedSlot(variable_slot, variable.clone(), None)
2880        };
2881
2882        self.common_variable_util(resolution, &variable.name, source_expression)
2883    }
2884
2885    pub fn common_variable_util(
2886        &mut self,
2887        variable_resolution: VariableResolution,
2888        ast_node: &swamp_ast::Node,
2889        source_expression: &swamp_ast::Expression,
2890    ) -> Expression {
2891        let node = self.to_node(ast_node);
2892
2893        let maybe_annotated_type = match &variable_resolution {
2894            VariableResolution::ExistingVariable(existing_var) => {
2895                Some(existing_var.resolved_type.clone())
2896            }
2897            VariableResolution::ReservedSlot(_, _, maybe_annotated) => maybe_annotated.clone(),
2898        };
2899
2900        let (final_variable_type, final_source_expression) =
2901            self.resolve_variable_expression(maybe_annotated_type, source_expression);
2902
2903        let variable_type = match &variable_resolution {
2904            VariableResolution::ExistingVariable(existing) => existing.variable_type.clone(),
2905            VariableResolution::ReservedSlot(_, _, _) => VariableType::Local,
2906        };
2907
2908        let debug_text = self.get_text(ast_node);
2909        let unused_var = debug_text.starts_with('_');
2910
2911        if !unused_var {
2912            // verify the type now
2913            match variable_type {
2914                VariableType::Local => {
2915                    if !final_variable_type.can_be_stored_in_variable() {
2916                        return self.create_err_resolved(
2917                            ErrorKind::VariableTypeMustBeAtLeastTransient(final_variable_type),
2918                            &node,
2919                        );
2920                    }
2921                }
2922
2923                VariableType::Parameter => {
2924                    if !final_variable_type.allowed_as_return_type() {
2925                        return self.create_err_resolved(
2926                            ErrorKind::VariableTypeMustBeAtLeastTransient(final_variable_type),
2927                            &node,
2928                        );
2929                    }
2930                }
2931            }
2932        }
2933
2934        let kind = match variable_resolution {
2935            VariableResolution::ExistingVariable(found_variable) => {
2936                self.shared
2937                    .state
2938                    .refs
2939                    .add(found_variable.symbol_id.into(), node.clone());
2940                self.shared
2941                    .definition_table
2942                    .refs
2943                    .add(found_variable.symbol_id.into(), node.clone());
2944
2945                ExpressionKind::VariableReassignment(
2946                    found_variable,
2947                    Box::from(final_source_expression),
2948                )
2949            }
2950            VariableResolution::ReservedSlot(reserved_slot, ast_variable, maybe_annotated) => {
2951                let final_type = if let Some(annotated_type) = maybe_annotated {
2952                    annotated_type
2953                } else {
2954                    final_source_expression.ty.clone()
2955                };
2956
2957                let (found_variable, _some_string) = self.create_local_variable_with_reserved_slot(
2958                    reserved_slot,
2959                    ast_variable,
2960                    &final_type,
2961                );
2962                ExpressionKind::VariableDefinition(
2963                    found_variable,
2964                    Box::from(final_source_expression),
2965                )
2966            }
2967        };
2968
2969        let unit_type = self.shared.state.types.unit();
2970        self.create_expr(kind, unit_type, ast_node)
2971    }
2972
2973    // Tries to infer the source expression needed
2974    // as well as the variable final type
2975    pub fn resolve_variable_expression(
2976        &mut self,
2977        maybe_annotated_type: Option<TypeRef>,
2978        source_expression: &swamp_ast::Expression,
2979    ) -> (TypeRef, Expression) {
2980        let source_expr = if let Some(target_type) = &maybe_annotated_type {
2981            self.analyze_expression_for_assignment_with_target_type(target_type, source_expression)
2982        } else {
2983            let any_type_context = TypeContext::new_anything_argument(true);
2984            self.analyze_expression(source_expression, &any_type_context)
2985        };
2986
2987        // Check if the variable type (target type) can be stored in a variable
2988        // Skip this check for parameters since they already have allocated storage
2989        let determined_variable_type = if let Some(found_type) = &maybe_annotated_type {
2990            found_type
2991        } else {
2992            &source_expr.ty.clone()
2993        };
2994
2995        // Check special conversion
2996
2997        (determined_variable_type.clone(), source_expr)
2998    }
2999
3000    /*
3001    /// # Errors
3002    ///
3003    pub fn analyze_variable_assignment_util(
3004        &mut self,
3005        variable: &swamp_ast::Variable,
3006        variable_type: VariableType,
3007        maybe_annotated_type: Option<TypeRef>,
3008        is_reassign: bool,
3009        source_expression: &swamp_ast::Expression,
3010    ) -> Expression {
3011        info!(?target_type.kind,"1vari assignment");
3012
3013        // Only check blittable for local variables, not parameters
3014        let only_check_ephemeral = variable_type == VariableType::Parameter;
3015
3016        if only_check_ephemeral && !target_type.can_be_stored_in_variable() {
3017            let debug_text = self.get_text(&variable.name);
3018            if !debug_text.starts_with('_') {
3019                return self.create_err(
3020                    ErrorKind::VariableTypeMustBeAtLeastTransient(target_type.clone()),
3021                    &variable.name,
3022                );
3023            }
3024        }
3025
3026        info!(?target_type.kind,"vari assignment");
3027
3028        let kind: ExpressionKind = if is_reassign {
3029            if !variable.is_mutable() {
3030                return self.create_err(ErrorKind::VariableIsNotMutable, &variable.name);
3031            }
3032
3033            let Some(resolved_type) = maybe_annotated_type else {
3034                return self.create_err(ErrorKind::UnexpectedType, &variable.name);
3035            };
3036
3037            if !self
3038                .types()
3039                .compatible_with(&resolved_type, &real_source_expr.ty)
3040            {
3041                return self.create_err(
3042                    ErrorKind::IncompatibleTypes {
3043                        expected: real_source_expr.ty,
3044                        found: resolved_type.clone(),
3045                    },
3046                    &variable.name,
3047                );
3048            }
3049
3050            self.check_mutable_variable_assignment(source_expression, &real_source_expr.ty, variable);
3051
3052            let name_node = self.to_node(&variable.name);
3053
3054
3055            ExpressionKind::VariableReassignment(found_var.clone(), Box::from(real_source_expr.clone()))
3056        } else {
3057            if !real_source_expr.ty.can_be_stored_in_variable() {
3058                let text = self.get_text(&variable.name);
3059                error!(?text, ?maybe_annotated_type, ?real_source_expr, "variable is wrong");
3060            }
3061
3062            // If it is mutable, we might need to clone the source
3063            // so make some extra verification
3064            if variable.is_mutable.is_some() {
3065                self.check_mutable_variable_assignment(
3066                    source_expression,
3067                    &real_source_expr.ty,
3068                    variable,
3069                );
3070            }
3071            let new_var = self.create_variable(variable, &real_source_expr.ty.clone());
3072        };
3073
3074
3075        let unit_type = self.shared.state.types.unit();
3076        self.create_expr(kind, unit_type, &variable.name)
3077    }
3078    */
3079
3080    /*
3081    fn analyze_create_variable(
3082        &mut self,
3083        var: &swamp_ast::Variable,
3084        annotation_type: Option<&swamp_ast::Type>,
3085        source_expression: &swamp_ast::Expression,
3086    ) -> Expression {
3087        let maybe_annotated_type = annotation_type.map(|found_ast_type| {
3088            self.analyze_type(found_ast_type, &TypeAnalyzeContext::default())
3089        });
3090
3091        let unsure_arg_context =
3092            TypeContext::new_unsure_argument(maybe_annotated_type.as_ref(), true);
3093
3094        let resolved_source = self.analyze_expression(source_expression, &unsure_arg_context);
3095
3096        let resulting_type = if let Some(annotated_type) = maybe_annotated_type {
3097            annotated_type
3098        } else {
3099            resolved_source.ty.clone()
3100        };
3101
3102
3103        if *resulting_type.kind == TypeKind::Unit {
3104            return self.create_err(
3105                ErrorKind::VariableTypeMustBeAtLeastTransient(resulting_type),
3106                &var.name,
3107            );
3108        }
3109        assert_ne!(&*resulting_type.kind, &TypeKind::Unit);
3110        let kind = ExpressionKind::VariableDefinition(var_ref, Box::from(resolved_source));
3111
3112        let unit_type = self.shared.state.types.unit();
3113
3114        self.create_expr(kind, unit_type, &var.name)
3115    }
3116
3117     */
3118
3119    fn add_location_item(
3120        &mut self,
3121        vec: &mut Vec<LocationAccess>,
3122        kind: LocationAccessKind,
3123        ty: TypeRef,
3124        ast_node: &swamp_ast::Node,
3125    ) {
3126        let resolved_node = self.to_node(ast_node);
3127        let postfix = LocationAccess {
3128            node: resolved_node,
3129            ty,
3130            kind,
3131        };
3132
3133        vec.push(postfix);
3134    }
3135
3136    fn extract_single_intrinsic_call(
3137        body: &Expression,
3138    ) -> Option<(IntrinsicFunction, Vec<ArgumentExpression>)> {
3139        if let ExpressionKind::Block(expressions) = &body.kind {
3140            let first_kind = &expressions[0].kind;
3141            if let ExpressionKind::IntrinsicCallEx(intrinsic_fn, args) = &first_kind {
3142                return Some((intrinsic_fn.clone(), args.clone()));
3143            }
3144        }
3145        None
3146    }
3147
3148    #[allow(clippy::too_many_lines)]
3149    fn analyze_chain_to_location(
3150        &mut self,
3151        chain: &swamp_ast::PostfixChain,
3152        context: &TypeContext,
3153        location_side: LocationSide,
3154    ) -> SingleLocationExpression {
3155        let mut items = Vec::new();
3156
3157        let nothing_context = TypeContext::new(None, true);
3158
3159        let base_expr = self.analyze_expression(&chain.base, &nothing_context);
3160        let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
3161            self.add_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node);
3162            let unit_type = self.types().unit();
3163            let err_variable = Variable {
3164                symbol_id: ScopedSymbolId::new_illegal(),
3165                name: Default::default(),
3166                assigned_name: String::new(),
3167                resolved_type: unit_type,
3168                mutable_node: None,
3169                variable_type: VariableType::Local,
3170                scope_index: 0,
3171                variable_index: 0,
3172                unique_id_within_function: 0,
3173                virtual_register: 0,
3174                is_unused: false,
3175            };
3176            return SingleLocationExpression {
3177                kind: MutableReferenceKind::MutVariableRef,
3178                node: self.to_node(&chain.base.node),
3179                ty: self.shared.state.types.unit(),
3180                starting_variable: VariableRef::from(err_variable),
3181                access_chain: vec![],
3182            };
3183        };
3184
3185        if !start_variable.is_mutable() {
3186            self.add_err(ErrorKind::VariableIsNotMutable, &chain.base.node);
3187
3188            let unit_type = self.types().unit();
3189            let err_variable = Variable {
3190                symbol_id: ScopedSymbolId::new_illegal(),
3191                name: Default::default(),
3192                assigned_name: String::new(),
3193                resolved_type: unit_type,
3194                mutable_node: None,
3195                variable_type: VariableType::Local,
3196                scope_index: 0,
3197                variable_index: 0,
3198                unique_id_within_function: 0,
3199                virtual_register: 0,
3200                is_unused: false,
3201            };
3202            return SingleLocationExpression {
3203                kind: MutableReferenceKind::MutVariableRef,
3204                node: self.to_node(&chain.base.node),
3205                ty: self.shared.state.types.unit(),
3206                starting_variable: VariableRef::from(err_variable),
3207                access_chain: vec![],
3208            };
3209        }
3210
3211        let mut ty = start_variable.resolved_type.clone();
3212        for (i, item) in chain.postfixes.iter().enumerate() {
3213            let is_absolute_last_in_chain = i == chain.postfixes.len() - 1;
3214            match &item {
3215                swamp_ast::Postfix::FieldAccess(field_name_node) => {
3216                    //let field_name_resolved = self.to_node(field_name_node)
3217                    let (struct_type_ref, index, return_type) =
3218                        self.analyze_struct_field(field_name_node, &ty);
3219
3220                    self.add_location_item(
3221                        &mut items,
3222                        LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
3223                        return_type.clone(),
3224                        field_name_node,
3225                    );
3226
3227                    ty = return_type.clone();
3228                }
3229                swamp_ast::Postfix::SubscriptTuple(x_expr, y_expr) => match &*ty.kind {
3230                    TypeKind::GridView(element_type)
3231                    | TypeKind::GridStorage(element_type, _, _) => {
3232                        let int_type = self.types().int();
3233                        let unsigned_int_context = TypeContext::new_argument(&int_type, true);
3234                        let unsigned_int_x_expr =
3235                            self.analyze_expression(x_expr, &unsigned_int_context);
3236
3237                        let unsigned_int_y_expr =
3238                            self.analyze_expression(y_expr, &unsigned_int_context);
3239
3240                        let grid_type = GridType {
3241                            element: element_type.clone(),
3242                        };
3243
3244                        self.add_location_item(
3245                            &mut items,
3246                            LocationAccessKind::GridSubscript(
3247                                grid_type,
3248                                unsigned_int_x_expr,
3249                                unsigned_int_y_expr,
3250                            ),
3251                            element_type.clone(),
3252                            &x_expr.node,
3253                        );
3254
3255                        ty = element_type.clone();
3256                    }
3257                    _ => {
3258                        self.add_err_resolved(
3259                            ErrorKind::CanNotSubscriptWithThatType,
3260                            &base_expr.node,
3261                        );
3262
3263                        return SingleLocationExpression {
3264                            kind: MutableReferenceKind::MutVariableRef,
3265                            node: Default::default(),
3266                            ty,
3267                            starting_variable: Rc::new(Variable {
3268                                symbol_id: ScopedSymbolId::new_illegal(),
3269                                name: Default::default(),
3270                                assigned_name: String::new(),
3271                                resolved_type: Rc::new(Type {
3272                                    id: TypeId::new(0),
3273                                    flags: Default::default(),
3274                                    kind: Rc::new(TypeKind::Byte),
3275                                }),
3276                                mutable_node: None,
3277                                variable_type: VariableType::Local,
3278                                scope_index: 0,
3279                                variable_index: 0,
3280                                unique_id_within_function: 0,
3281                                virtual_register: 0,
3282                                is_unused: false,
3283                            }),
3284                            access_chain: vec![],
3285                        };
3286                    }
3287                },
3288                swamp_ast::Postfix::Subscript(ast_key_expression) => {
3289                    let underlying = &ty.kind;
3290                    match &**underlying {
3291                        TypeKind::SliceView(element_type)
3292                        | TypeKind::StackStorage(element_type, _)
3293                        | TypeKind::StackView(element_type)
3294                        | TypeKind::VecStorage(element_type, _)
3295                        | TypeKind::DynamicLengthVecView(element_type)
3296                        | TypeKind::FixedCapacityAndLengthArray(element_type, _) => {
3297                            let int_type = self.types().int();
3298                            let unsigned_int_context = TypeContext::new_argument(&int_type, false);
3299                            let unsigned_int_expr =
3300                                self.analyze_expression(ast_key_expression, &unsigned_int_context);
3301
3302                            let slice_type = SliceViewType {
3303                                element: element_type.clone(),
3304                            };
3305
3306                            self.add_location_item(
3307                                &mut items,
3308                                LocationAccessKind::SliceViewSubscript(
3309                                    slice_type,
3310                                    unsigned_int_expr,
3311                                ),
3312                                element_type.clone(),
3313                                &ast_key_expression.node,
3314                            );
3315
3316                            ty = element_type.clone();
3317                        }
3318                        TypeKind::SparseView(element_type)
3319                        | TypeKind::SparseStorage(element_type, _) => {
3320                            let int_type = self.types().int();
3321                            let unsigned_int_context = TypeContext::new_argument(&int_type, false);
3322                            let unsigned_int_expr =
3323                                self.analyze_expression(ast_key_expression, &unsigned_int_context);
3324
3325                            let slice_type = SparseType {
3326                                element: element_type.clone(),
3327                            };
3328
3329                            self.add_location_item(
3330                                &mut items,
3331                                LocationAccessKind::SparseSubscript(slice_type, unsigned_int_expr),
3332                                element_type.clone(),
3333                                &ast_key_expression.node,
3334                            );
3335
3336                            ty = element_type.clone();
3337                        }
3338                        TypeKind::MapStorage(key_type, value_type, ..)
3339                        | TypeKind::DynamicLengthMapView(key_type, value_type) => {
3340                            let key_index_context = TypeContext::new_argument(key_type, false);
3341                            let key_expr =
3342                                self.analyze_expression(ast_key_expression, &key_index_context);
3343
3344                            let map_like_type = MapType {
3345                                key: key_type.clone(),
3346                                value: value_type.clone(),
3347                            };
3348
3349                            match location_side {
3350                                LocationSide::Lhs => {
3351                                    // Only if it is the absolute last subscript in the chain that we should
3352                                    // create a new map entry, otherwise we should just lookup an existing entry and get the
3353                                    // address to it.
3354                                    let access_kind = if is_absolute_last_in_chain {
3355                                        LocationAccessKind::MapSubscriptCreateIfNeeded(
3356                                            map_like_type,
3357                                            key_expr,
3358                                        )
3359                                    } else {
3360                                        LocationAccessKind::MapSubscriptMustExist(
3361                                            map_like_type,
3362                                            key_expr,
3363                                        )
3364                                    };
3365
3366                                    self.add_location_item(
3367                                        &mut items,
3368                                        access_kind,
3369                                        value_type.clone(),
3370                                        &ast_key_expression.node,
3371                                    );
3372                                }
3373                                LocationSide::Mutable | LocationSide::Rhs => {
3374                                    self.add_location_item(
3375                                        &mut items,
3376                                        LocationAccessKind::MapSubscriptMustExist(
3377                                            map_like_type,
3378                                            key_expr,
3379                                        ),
3380                                        value_type.clone(),
3381                                        &ast_key_expression.node,
3382                                    );
3383                                }
3384                            }
3385                            ty = value_type.clone();
3386                        }
3387
3388                        _ => {
3389                            self.add_err_resolved(
3390                                ErrorKind::CanNotSubscriptWithThatType,
3391                                &base_expr.node,
3392                            );
3393
3394                            return SingleLocationExpression {
3395                                kind: MutableReferenceKind::MutVariableRef,
3396                                node: Default::default(),
3397                                ty,
3398                                starting_variable: Rc::new(Variable {
3399                                    symbol_id: ScopedSymbolId::new_illegal(),
3400                                    name: Default::default(),
3401                                    assigned_name: String::new(),
3402                                    resolved_type: Rc::new(Type {
3403                                        id: TypeId::new(0),
3404                                        flags: Default::default(),
3405                                        kind: Rc::new(TypeKind::Byte),
3406                                    }),
3407                                    mutable_node: None,
3408                                    variable_type: VariableType::Local,
3409                                    scope_index: 0,
3410                                    variable_index: 0,
3411                                    unique_id_within_function: 0,
3412                                    virtual_register: 0,
3413                                    is_unused: false,
3414                                }),
3415                                access_chain: vec![],
3416                            };
3417                        }
3418                    }
3419                }
3420
3421                swamp_ast::Postfix::MemberCall(node, _generic_arguments, _regular_args) => {
3422                    return SingleLocationExpression {
3423                        kind: MutableReferenceKind::MutVariableRef,
3424                        node: self.to_node(node),
3425                        ty: self.shared.state.types.unit(),
3426                        starting_variable: start_variable,
3427                        access_chain: vec![],
3428                    };
3429                }
3430                /*
3431                swamp_ast::Postfix::AdvancedFunctionCall(_, node, ..) => {
3432                    return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
3433                }
3434
3435                 */
3436                swamp_ast::Postfix::FunctionCall(node, _generic_arguments, _regular_args) => {
3437                    return SingleLocationExpression {
3438                        kind: MutableReferenceKind::MutVariableRef,
3439                        node: self.to_node(node),
3440                        ty: self.shared.state.types.unit(),
3441                        starting_variable: start_variable,
3442                        access_chain: vec![],
3443                    };
3444                }
3445                swamp_ast::Postfix::OptionalChainingOperator(node) => {
3446                    return SingleLocationExpression {
3447                        kind: MutableReferenceKind::MutVariableRef,
3448                        node: self.to_node(node),
3449                        ty: self.shared.state.types.unit(),
3450                        starting_variable: start_variable,
3451                        access_chain: vec![],
3452                    };
3453                }
3454            }
3455        }
3456
3457        if let Some(found_expected_type) = context.expected_type
3458            && !self.types().compatible_with(found_expected_type, &ty)
3459        {
3460            self.add_err(
3461                ErrorKind::IncompatibleTypes {
3462                    expected: found_expected_type.clone(),
3463                    found: ty.clone(),
3464                },
3465                &chain.base.node,
3466            );
3467        }
3468
3469        SingleLocationExpression {
3470            kind: MutableReferenceKind::MutVariableRef,
3471            node: self.to_node(&chain.base.node),
3472            ty,
3473            starting_variable: start_variable,
3474            access_chain: items,
3475        }
3476    }
3477
3478    fn analyze_to_location(
3479        &mut self,
3480        expr: &swamp_ast::Expression,
3481        context: &TypeContext,
3482        location_type: LocationSide,
3483    ) -> SingleLocationExpression {
3484        match &expr.kind {
3485            swamp_ast::ExpressionKind::PostfixChain(chain) => {
3486                self.analyze_chain_to_location(chain, context, location_type)
3487            }
3488            swamp_ast::ExpressionKind::VariableReference(variable) => {
3489                let var = self.find_variable(variable);
3490                if !var.is_mutable() {
3491                    self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3492                }
3493
3494                let name_node = self.to_node(&variable.name);
3495                self.shared
3496                    .state
3497                    .refs
3498                    .add(var.symbol_id.into(), name_node.clone());
3499                self.shared
3500                    .definition_table
3501                    .refs
3502                    .add(var.symbol_id.into(), name_node.clone());
3503
3504                SingleLocationExpression {
3505                    kind: MutableReferenceKind::MutVariableRef,
3506                    node: name_node,
3507                    ty: var.resolved_type.clone(),
3508                    starting_variable: var,
3509                    access_chain: vec![],
3510                }
3511            }
3512            swamp_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
3513                let generated_var = swamp_ast::Variable {
3514                    name: qualified_identifier.name.clone(),
3515                    is_mutable: None,
3516                };
3517                let var = self.find_variable(&generated_var);
3518                if !var.is_mutable() {
3519                    self.add_err(ErrorKind::VariableIsNotMutable, &expr.node);
3520                }
3521
3522                let var_node = self.to_node(&generated_var.name);
3523                self.shared
3524                    .state
3525                    .refs
3526                    .add(var.symbol_id.into(), var_node.clone());
3527                self.shared
3528                    .definition_table
3529                    .refs
3530                    .add(var.symbol_id.into(), var_node.clone());
3531
3532                SingleLocationExpression {
3533                    kind: MutableReferenceKind::MutVariableRef,
3534                    node: var_node,
3535                    ty: var.resolved_type.clone(),
3536                    starting_variable: var,
3537                    access_chain: vec![],
3538                }
3539            }
3540            _ => {
3541                self.add_err(ErrorKind::NotValidLocationStartingPoint, &expr.node);
3542                let unit_type = self.types().unit();
3543                SingleLocationExpression {
3544                    kind: MutableReferenceKind::MutVariableRef,
3545                    node: self.to_node(&expr.node),
3546                    ty: unit_type.clone(),
3547                    starting_variable: Rc::new(Variable {
3548                        symbol_id: ScopedSymbolId::new_illegal(),
3549                        name: Default::default(),
3550                        assigned_name: String::new(),
3551                        resolved_type: unit_type,
3552                        mutable_node: None,
3553                        variable_type: VariableType::Local,
3554                        scope_index: 0,
3555                        variable_index: 0,
3556                        unique_id_within_function: 0,
3557                        virtual_register: 0,
3558                        is_unused: false,
3559                    }),
3560                    access_chain: vec![],
3561                }
3562            }
3563        }
3564    }
3565
3566    fn analyze_expression_for_assignment_compound(
3567        &mut self,
3568        target_expression: &swamp_ast::Expression,
3569        ast_source_expression: &swamp_ast::Expression,
3570    ) -> (TargetAssignmentLocation, Expression) {
3571        let any_argument_context = TypeContext::new_anything_argument(true);
3572        let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context);
3573        let source_expr_type_context = TypeContext::new_argument(&source_expr.ty, true);
3574
3575        let resolved_location = TargetAssignmentLocation(self.analyze_to_location(
3576            target_expression,
3577            &source_expr_type_context,
3578            LocationSide::Rhs,
3579        ));
3580
3581        (resolved_location, source_expr)
3582    }
3583
3584    /*
3585    fn try_convert_for_assignment(
3586        &mut self,
3587        expr: &Expression,
3588        target_type: &TypeRef,
3589        ast_node: &swamp_ast::Expression,
3590    ) -> Result<Option<Expression>, Error> {
3591        match (target_type, &expr.ty) {
3592            // Conversion cases that require transformation
3593            (TypeKind::VecStorage(target_elem, capacity), TypeKind::FixedSlice(source_elem, _)) => {
3594                // Create conversion with checks
3595                // ...
3596            }
3597
3598            (TypeKind::String, TypeKind::Int) => {
3599                // Create int-to-string conversion
3600                // ...
3601            }
3602
3603            // No conversion possible
3604            _ => Ok(None),
3605        }
3606    }
3607
3608     */
3609
3610    fn analyze_expression_for_assignment_with_target_type(
3611        &mut self,
3612        target_type: &TypeRef,
3613        ast_source_expression: &swamp_ast::Expression,
3614    ) -> Expression {
3615        let base_context = TypeContext::new_argument(target_type, true);
3616        let source_expr = self.analyze_expression(ast_source_expression, &base_context);
3617
3618        let final_expr = if self.types().compatible_with(target_type, &source_expr.ty) {
3619            source_expr
3620        } else {
3621            let source_type = source_expr.ty.clone();
3622            self.types_did_not_match_try_late_coerce_expression(
3623                source_expr,
3624                target_type,
3625                &source_type,
3626                &ast_source_expression.node,
3627            )
3628        };
3629
3630        let assignment_mode = self.check_assignment_mode(true, &final_expr, target_type); // TODO: Fill in correct lhs_is_mutable
3631
3632        self.check_mutable_assignment(assignment_mode, &final_expr.node);
3633
3634        final_expr
3635    }
3636
3637    fn analyze_expression_for_assignment(
3638        &mut self,
3639        ast_target_location_expression: &swamp_ast::Expression,
3640        ast_source_expression: &swamp_ast::Expression,
3641    ) -> (TargetAssignmentLocation, Expression) {
3642        self.push_block_scope("fake outer scope to keep lvalue alive");
3643        let any_argument_context = TypeContext::new_anything_argument(true);
3644        let resolved_location = self.analyze_to_location(
3645            ast_target_location_expression,
3646            &any_argument_context,
3647            LocationSide::Lhs,
3648        );
3649
3650        self.push_block_scope("fake scope to keep lvalue alive");
3651        let target_type = resolved_location.ty.clone();
3652        let mut_type = target_type; // Mutable references now use the same type
3653        let mut_location = TargetAssignmentLocation(resolved_location);
3654
3655        let final_expr = self
3656            .analyze_expression_for_assignment_with_target_type(&mut_type, ast_source_expression);
3657        self.pop_block_scope("fake scope for lvalue alive");
3658        self.pop_block_scope("fake outer scope for lvalue alive");
3659
3660        (mut_location, final_expr)
3661    }
3662
3663    fn analyze_assignment_compound(
3664        &mut self,
3665        target_expression: &swamp_ast::Expression,
3666        ast_op: &swamp_ast::CompoundOperator,
3667        ast_source_expression: &swamp_ast::Expression,
3668    ) -> Expression {
3669        let resolved_op = self.analyze_compound_operator(ast_op);
3670
3671        let (resolved_location, source_expr) = self
3672            .analyze_expression_for_assignment_compound(target_expression, ast_source_expression);
3673
3674        let kind = ExpressionKind::CompoundAssignment(
3675            resolved_location,
3676            resolved_op.kind,
3677            Box::from(source_expr),
3678        );
3679
3680        let unit_type = self.shared.state.types.unit();
3681
3682        self.create_expr(kind, unit_type, &target_expression.node)
3683    }
3684
3685    fn analyze_assignment_mode(lhs: SingleLocationExpression) {}
3686
3687    fn analyze_assignment(
3688        &mut self,
3689        target_location: &swamp_ast::Expression,
3690        ast_source_expression: &swamp_ast::Expression,
3691    ) -> Expression {
3692        let (mut_location, source_expr) =
3693            self.analyze_expression_for_assignment(target_location, ast_source_expression);
3694        let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
3695        let unit_type = self.shared.state.types.unit();
3696
3697        // Assignments are always of type Unit
3698
3699        self.create_expr(kind, unit_type, &target_location.node)
3700    }
3701
3702    #[must_use]
3703    pub const fn create_expr(
3704        &self,
3705        kind: ExpressionKind,
3706        ty: TypeRef,
3707        ast_node: &swamp_ast::Node,
3708    ) -> Expression {
3709        //info!(%ty, ?kind, "create_expr()");
3710        Expression {
3711            kind,
3712            ty,
3713            node: self.to_node(ast_node),
3714        }
3715    }
3716
3717    fn analyze_destructuring(
3718        &mut self,
3719        node: &swamp_ast::Node,
3720        target_ast_variables: &[swamp_ast::Variable],
3721        tuple_expression: &swamp_ast::Expression,
3722    ) -> Expression {
3723        let any_context = TypeContext::new_anything_argument(true);
3724        let tuple_resolved = self.analyze_expression(tuple_expression, &any_context);
3725        let tuple_expr_type = &tuple_resolved.ty;
3726        let unit = self.types().unit();
3727
3728        let mut variable_refs = Vec::new();
3729        if let TypeKind::Tuple(tuple) = &*tuple_expr_type.kind {
3730            if target_ast_variables.len() > tuple.len() {
3731                return self.create_err(ErrorKind::TooManyDestructureVariables, node);
3732            }
3733            for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
3734                let variable_ref = self.create_local_variable(
3735                    &ast_variable.name,
3736                    ast_variable.is_mutable.as_ref(),
3737                    &tuple_type,
3738                    true,
3739                );
3740                variable_refs.push(variable_ref);
3741            }
3742            let expr_kind = ExpressionKind::TupleDestructuring(
3743                variable_refs,
3744                tuple_expr_type.clone(),
3745                Box::from(tuple_resolved),
3746            );
3747
3748            self.create_expr(expr_kind, unit, node)
3749        } else {
3750            self.create_err(ErrorKind::CanNotDestructure, node)
3751        }
3752    }
3753
3754    fn analyze_normal_member_call(
3755        &mut self,
3756        type_that_member_is_on: &TypeRef,
3757        found_function: &FunctionRef,
3758        generic_arguments: Vec<TypeRef>,
3759        ast_arguments: &[swamp_ast::Expression],
3760        is_mutable: bool,
3761        node: &swamp_ast::Node,
3762    ) -> Signature {
3763        let resolved_node = self.to_node(node);
3764        // TODO:
3765
3766        found_function.signature().clone()
3767    }
3768
3769    fn enum_member_signature(
3770        &mut self,
3771        self_type: &TypeRef,
3772        field_name_str: &str,
3773        node: &swamp_ast::Node,
3774    ) -> Option<(IntrinsicFunction, Signature)> {
3775        let self_type_param = TypeForParameter {
3776            name: "self".to_string(),
3777            resolved_type: self_type.clone(),
3778            is_mutable: false,
3779            node: None,
3780        };
3781
3782        let self_mutable_type_param = TypeForParameter {
3783            name: "self".to_string(),
3784            resolved_type: self_type.clone(),
3785            is_mutable: true,
3786            node: None,
3787        };
3788
3789        let intrinsic_and_signature = match field_name_str {
3790            "discriminant" => (
3791                IntrinsicFunction::EnumDiscriminant,
3792                Signature {
3793                    parameters: vec![self_type_param],
3794                    return_type: self.types().int(),
3795                },
3796            ),
3797
3798            "from_discriminant" => (
3799                IntrinsicFunction::EnumFromDiscriminant,
3800                Signature {
3801                    parameters: vec![
3802                        self_mutable_type_param,
3803                        TypeForParameter {
3804                            name: "discriminant".to_string(),
3805                            resolved_type: self.types().int(),
3806                            is_mutable: false,
3807                            node: None,
3808                        },
3809                    ],
3810                    return_type: self.types().unit(),
3811                },
3812            ),
3813            _ => {
3814                self.add_err(ErrorKind::UnknownMemberFunction(self_type.clone()), node);
3815
3816                return None;
3817            }
3818        };
3819
3820        Some(intrinsic_and_signature)
3821    }
3822
3823    fn queue_member_signature(
3824        &mut self,
3825        self_type: &TypeRef,
3826        key_type: Option<&TypeRef>,
3827        element_type: &TypeRef,
3828        field_name_str: &str,
3829        lambda_variable_count: usize,
3830        node: &swamp_ast::Node,
3831    ) -> Option<(IntrinsicFunction, Signature)> {
3832        let self_type_param = TypeForParameter {
3833            name: "self".to_string(),
3834            resolved_type: self_type.clone(),
3835            is_mutable: false,
3836            node: None,
3837        };
3838        let self_mutable_type_param = TypeForParameter {
3839            name: "self".to_string(),
3840            resolved_type: self_type.clone(),
3841            is_mutable: true,
3842            node: None,
3843        };
3844        let intrinsic_and_signature = match field_name_str {
3845            "enqueue" => (
3846                IntrinsicFunction::VecPush,
3847                Signature {
3848                    parameters: vec![
3849                        self_mutable_type_param,
3850                        TypeForParameter {
3851                            name: "element".to_string(),
3852                            resolved_type: element_type.clone(),
3853                            is_mutable: false,
3854                            node: None,
3855                        },
3856                    ],
3857                    return_type: self.types().unit(),
3858                },
3859            ),
3860            "dequeue" => (
3861                IntrinsicFunction::VecRemoveFirstIndexGetValue,
3862                Signature {
3863                    parameters: vec![self_mutable_type_param],
3864                    return_type: element_type.clone(),
3865                },
3866            ),
3867            _ => {
3868                self.slice_member_signature(
3869                    self_type,
3870                    key_type,
3871                    element_type,
3872                    field_name_str,
3873                    lambda_variable_count,
3874                    node,
3875                )
3876            }?,
3877        };
3878
3879        Some(intrinsic_and_signature)
3880    }
3881
3882    fn sparse_member_signature(
3883        &mut self,
3884        self_type: &TypeRef,
3885        element_type: &TypeRef,
3886        field_name_str: &str,
3887        lambda_variable_count: usize,
3888        node: &swamp_ast::Node,
3889    ) -> Option<(IntrinsicFunction, Signature)> {
3890        let key_type = self.types().int(); // TODO: SparseID
3891
3892        let self_type_param = TypeForParameter {
3893            name: "self".to_string(),
3894            resolved_type: self_type.clone(),
3895            is_mutable: false,
3896            node: None,
3897        };
3898        let self_mutable_type_param = TypeForParameter {
3899            name: "self".to_string(),
3900            resolved_type: self_type.clone(),
3901            is_mutable: true,
3902            node: None,
3903        };
3904        let intrinsic_and_signature = match field_name_str {
3905            "add" => (
3906                IntrinsicFunction::SparseAdd,
3907                Signature {
3908                    parameters: vec![
3909                        self_mutable_type_param,
3910                        TypeForParameter {
3911                            name: "element".to_string(),
3912                            resolved_type: element_type.clone(),
3913                            is_mutable: false,
3914                            node: None,
3915                        },
3916                    ],
3917                    return_type: self.types().int(),
3918                },
3919            ),
3920            "remove" => (
3921                IntrinsicFunction::SparseRemove,
3922                Signature {
3923                    parameters: vec![
3924                        self_mutable_type_param,
3925                        TypeForParameter {
3926                            name: "key".to_string(),
3927                            resolved_type: key_type,
3928                            is_mutable: false,
3929                            node: None,
3930                        },
3931                    ],
3932                    return_type: self.types().unit(),
3933                },
3934            ),
3935            "is_alive" => (
3936                IntrinsicFunction::SparseIsAlive,
3937                Signature {
3938                    parameters: vec![
3939                        self_type_param,
3940                        TypeForParameter {
3941                            name: "element".to_string(),
3942                            resolved_type: element_type.clone(),
3943                            is_mutable: false,
3944                            node: None,
3945                        },
3946                    ],
3947                    return_type: self.types().bool(),
3948                },
3949            ),
3950
3951            _ => {
3952                self.slice_member_signature(
3953                    self_type,
3954                    Option::from(key_type).as_ref(),
3955                    element_type,
3956                    field_name_str,
3957                    lambda_variable_count,
3958                    node,
3959                )
3960            }?,
3961        };
3962        Some(intrinsic_and_signature)
3963    }
3964
3965    fn vec_member_signature(
3966        &mut self,
3967        self_type: &TypeRef,
3968        element_type: &TypeRef,
3969        field_name_str: &str,
3970        lambda_variable_count: usize,
3971        node: &swamp_ast::Node,
3972    ) -> Option<(IntrinsicFunction, Signature)> {
3973        let key_type = self.types().int();
3974        let self_type_param = TypeForParameter {
3975            name: "self".to_string(),
3976            resolved_type: self_type.clone(),
3977            is_mutable: false,
3978            node: None,
3979        };
3980        let self_mutable_type_param = TypeForParameter {
3981            name: "self".to_string(),
3982            resolved_type: self_type.clone(),
3983            is_mutable: true,
3984            node: None,
3985        };
3986        let intrinsic_and_signature = match field_name_str {
3987            "prepend" => (
3988                IntrinsicFunction::VecPush,
3989                Signature {
3990                    parameters: vec![
3991                        self_mutable_type_param,
3992                        TypeForParameter {
3993                            name: "element".to_string(),
3994                            resolved_type: element_type.clone(),
3995                            is_mutable: false,
3996                            node: None,
3997                        },
3998                    ],
3999                    return_type: self.types().unit(),
4000                },
4001            ),
4002            "push" => (
4003                IntrinsicFunction::VecPush,
4004                Signature {
4005                    parameters: vec![
4006                        self_mutable_type_param,
4007                        TypeForParameter {
4008                            name: "element".to_string(),
4009                            resolved_type: element_type.clone(),
4010                            is_mutable: false,
4011                            node: None,
4012                        },
4013                    ],
4014                    return_type: self.types().unit(),
4015                },
4016            ),
4017            "extend" => (
4018                IntrinsicFunction::VecExtend,
4019                Signature {
4020                    parameters: vec![
4021                        self_mutable_type_param,
4022                        TypeForParameter {
4023                            name: "other_vec".to_string(),
4024                            resolved_type: self.types().dynamic_vec_view(&element_type.clone()),
4025                            is_mutable: false,
4026                            node: None,
4027                        },
4028                    ],
4029                    return_type: self.types().unit(),
4030                },
4031            ),
4032            "pop" => (
4033                IntrinsicFunction::VecPop,
4034                Signature {
4035                    parameters: vec![self_mutable_type_param],
4036                    return_type: element_type.clone(),
4037                },
4038            ),
4039
4040            "slice" => {
4041                let range_type = self.types().range_int();
4042                (
4043                    IntrinsicFunction::VecSlice,
4044                    Signature {
4045                        parameters: vec![
4046                            self_type_param,
4047                            TypeForParameter {
4048                                name: "range".to_string(),
4049                                resolved_type: range_type,
4050                                is_mutable: false,
4051                                node: None,
4052                            },
4053                        ],
4054                        return_type: self_type.clone(),
4055                    },
4056                )
4057            }
4058
4059            _ => {
4060                self.slice_member_signature(
4061                    self_type,
4062                    Option::from(key_type).as_ref(),
4063                    element_type,
4064                    field_name_str,
4065                    lambda_variable_count,
4066                    node,
4067                )
4068            }?,
4069        };
4070        Some(intrinsic_and_signature)
4071    }
4072
4073    #[allow(clippy::unnecessary_wraps)]
4074    fn grid_member_signature(
4075        &mut self,
4076        self_type: &TypeRef,
4077        element_type: &TypeRef,
4078        field_name_str: &str,
4079        node: &swamp_ast::Node,
4080    ) -> Option<(IntrinsicFunction, Signature)> {
4081        let self_type_param = TypeForParameter {
4082            name: "self".to_string(),
4083            resolved_type: self_type.clone(),
4084            is_mutable: false,
4085            node: None,
4086        };
4087        let self_mutable_type_param = TypeForParameter {
4088            name: "self".to_string(),
4089            resolved_type: self_type.clone(),
4090            is_mutable: true,
4091            node: None,
4092        };
4093        let element_param = TypeForParameter {
4094            name: "element".to_string(),
4095            resolved_type: element_type.clone(),
4096            is_mutable: false,
4097            node: None,
4098        };
4099        let int_type = self.types().int();
4100
4101        let int_param = TypeForParameter {
4102            name: "x_or_y".to_string(),
4103            resolved_type: int_type.clone(),
4104            is_mutable: false,
4105            node: None,
4106        };
4107        let intrinsic_and_signature = match field_name_str {
4108            "set" => (
4109                IntrinsicFunction::GridSet,
4110                Signature {
4111                    parameters: vec![self_type_param, int_param.clone(), int_param, element_param],
4112                    return_type: self.types().unit(),
4113                },
4114            ),
4115
4116            "get" => (
4117                IntrinsicFunction::GridGet,
4118                Signature {
4119                    parameters: vec![self_type_param, int_param.clone(), int_param],
4120                    return_type: element_type.clone(),
4121                },
4122            ),
4123
4124            "width" => (
4125                IntrinsicFunction::GridWidth,
4126                Signature {
4127                    parameters: vec![self_type_param],
4128                    return_type: int_type,
4129                },
4130            ),
4131
4132            "height" => (
4133                IntrinsicFunction::GridHeight,
4134                Signature {
4135                    parameters: vec![self_type_param],
4136                    return_type: int_type,
4137                },
4138            ),
4139
4140            _ => panic!("unknown grid method {field_name_str}"),
4141        };
4142
4143        Some(intrinsic_and_signature)
4144    }
4145
4146    fn ptr_member_signature(
4147        &mut self,
4148        self_type: &TypeRef,
4149        field_name_str: &str,
4150        node: &swamp_ast::Node,
4151    ) -> Option<(IntrinsicFunction, Signature)> {
4152        let self_type_param = TypeForParameter {
4153            name: "self".to_string(),
4154            resolved_type: self_type.clone(),
4155            is_mutable: false,
4156            node: None,
4157        };
4158        let self_mut_type_param = TypeForParameter {
4159            name: "self".to_string(),
4160            resolved_type: self_type.clone(),
4161            is_mutable: true,
4162            node: None,
4163        };
4164
4165        let intrinsic_and_signature = match field_name_str {
4166            "from_u32" => {
4167                let signature = Signature {
4168                    parameters: vec![TypeForParameter {
4169                        name: "addr".to_string(),
4170                        resolved_type: self.types().int(),
4171                        is_mutable: false,
4172                        node: None,
4173                    }],
4174                    return_type: self.types().int(),
4175                };
4176                (IntrinsicFunction::VecLen, signature)
4177            }
4178            _ => return None,
4179        };
4180
4181        Some(intrinsic_and_signature)
4182    }
4183
4184    fn basic_collection_member_signature(
4185        &mut self,
4186        self_type: &TypeRef,
4187        field_name_str: &str,
4188        node: &swamp_ast::Node,
4189    ) -> Option<(IntrinsicFunction, Signature)> {
4190        let self_type_param = TypeForParameter {
4191            name: "self".to_string(),
4192            resolved_type: self_type.clone(),
4193            is_mutable: false,
4194            node: None,
4195        };
4196        let self_mut_type_param = TypeForParameter {
4197            name: "self".to_string(),
4198            resolved_type: self_type.clone(),
4199            is_mutable: true,
4200            node: None,
4201        };
4202        let intrinsic_and_signature = match field_name_str {
4203            "len" => {
4204                let signature = Signature {
4205                    parameters: vec![self_type_param],
4206                    return_type: self.types().int(),
4207                };
4208                (IntrinsicFunction::VecLen, signature)
4209            }
4210            "is_empty" => (
4211                IntrinsicFunction::VecIsEmpty,
4212                Signature {
4213                    parameters: vec![self_type_param],
4214                    return_type: self.types().bool(),
4215                },
4216            ),
4217            "clear" => {
4218                let signature = Signature {
4219                    parameters: vec![self_mut_type_param],
4220                    return_type: self.types().unit(),
4221                };
4222                (IntrinsicFunction::VecClear, signature)
4223            }
4224            "capacity" => {
4225                let signature = Signature {
4226                    parameters: vec![self_type_param],
4227                    return_type: self.types().int(),
4228                };
4229                (IntrinsicFunction::VecCapacity, signature)
4230            }
4231            _ => {
4232                self.add_err(ErrorKind::UnknownMemberFunction(self_type.clone()), node);
4233
4234                return None;
4235            }
4236        };
4237        Some(intrinsic_and_signature)
4238    }
4239    #[allow(clippy::too_many_lines)]
4240    fn codepoint_member_signature(
4241        &mut self,
4242        self_type: &TypeRef,
4243        key_type: Option<&TypeRef>,
4244        element_type: &TypeRef,
4245        field_name_str: &str,
4246        lambda_variable_count: usize,
4247        node: &swamp_ast::Node,
4248    ) -> Option<(IntrinsicFunction, Signature)> {
4249        let self_type_param = TypeForParameter {
4250            name: "self".to_string(),
4251            resolved_type: self_type.clone(),
4252            is_mutable: false,
4253            node: None,
4254        };
4255
4256        match field_name_str {
4257            "int" => Some((
4258                IntrinsicFunction::CodepointToInt,
4259                Signature {
4260                    parameters: vec![self_type_param],
4261                    return_type: self.types().int(),
4262                },
4263            )),
4264            "char" => Some((
4265                IntrinsicFunction::ByteToCodepoint,
4266                Signature {
4267                    parameters: vec![self_type_param],
4268                    return_type: self.types().codepoint(),
4269                },
4270            )),
4271            _ => None,
4272        }
4273    }
4274
4275    #[allow(clippy::too_many_lines)]
4276    fn byte_member_signature(
4277        &mut self,
4278        self_type: &TypeRef,
4279        key_type: Option<&TypeRef>,
4280        element_type: &TypeRef,
4281        field_name_str: &str,
4282        lambda_variable_count: usize,
4283        node: &swamp_ast::Node,
4284    ) -> Option<(IntrinsicFunction, Signature)> {
4285        let self_type_param = TypeForParameter {
4286            name: "self".to_string(),
4287            resolved_type: self_type.clone(),
4288            is_mutable: false,
4289            node: None,
4290        };
4291
4292        match field_name_str {
4293            "int" => Some((
4294                IntrinsicFunction::ByteToInt,
4295                Signature {
4296                    parameters: vec![self_type_param],
4297                    return_type: self.types().int(),
4298                },
4299            )),
4300            "float" => Some((
4301                IntrinsicFunction::ByteToFloat,
4302                Signature {
4303                    parameters: vec![self_type_param],
4304                    return_type: self.types().float(),
4305                },
4306            )),
4307            "char" => Some((
4308                IntrinsicFunction::ByteToCodepoint,
4309                Signature {
4310                    parameters: vec![self_type_param],
4311                    return_type: self.types().codepoint(),
4312                },
4313            )),
4314            _ => None,
4315        }
4316    }
4317
4318    #[allow(clippy::too_many_lines)]
4319    fn string_member_signature(
4320        &mut self,
4321        self_type: &TypeRef,
4322        key_type: Option<&TypeRef>,
4323        element_type: &TypeRef,
4324        field_name_str: &str,
4325        lambda_variable_count: usize,
4326        node: &swamp_ast::Node,
4327    ) -> Option<(IntrinsicFunction, Signature)> {
4328        let self_type_param = TypeForParameter {
4329            name: "self".to_string(),
4330            resolved_type: self_type.clone(),
4331            is_mutable: false,
4332            node: None,
4333        };
4334
4335        let x = match field_name_str {
4336            "starts_with" => (
4337                IntrinsicFunction::StringStartsWith,
4338                Signature {
4339                    parameters: vec![
4340                        self_type_param,
4341                        TypeForParameter {
4342                            name: "str".to_string(),
4343                            resolved_type: self.types().string(),
4344                            is_mutable: false,
4345                            node: None,
4346                        },
4347                    ],
4348                    return_type: self.types().bool(),
4349                },
4350            ),
4351            _ => {
4352                return self.vec_member_signature(
4353                    self_type,
4354                    element_type,
4355                    field_name_str,
4356                    lambda_variable_count,
4357                    node,
4358                );
4359            }
4360        };
4361
4362        Some(x)
4363    }
4364
4365    #[allow(clippy::too_many_lines)]
4366    fn slice_member_signature(
4367        &mut self,
4368        self_type: &TypeRef,
4369        key_type: Option<&TypeRef>,
4370        element_type: &TypeRef,
4371        field_name_str: &str,
4372        lambda_variable_count: usize,
4373        node: &swamp_ast::Node,
4374    ) -> Option<(IntrinsicFunction, Signature)> {
4375        let slice_view_type = self.types().slice_view(&element_type.clone());
4376        let int_type = self.types().int();
4377        let self_type_param = TypeForParameter {
4378            name: "self".to_string(),
4379            resolved_type: slice_view_type.clone(),
4380            is_mutable: false,
4381            node: None,
4382        };
4383        let self_mut_type_param = TypeForParameter {
4384            name: "self".to_string(),
4385            resolved_type: slice_view_type,
4386            is_mutable: true,
4387            node: None,
4388        };
4389        let intrinsic_and_signature = match field_name_str {
4390            "for" => {
4391                let parameters = if lambda_variable_count == 2 {
4392                    vec![
4393                        TypeForParameter {
4394                            name: "key".to_string(),
4395                            resolved_type: key_type.unwrap().clone(),
4396                            is_mutable: false,
4397                            node: None,
4398                        },
4399                        TypeForParameter {
4400                            name: "element".to_string(),
4401                            resolved_type: element_type.clone(),
4402                            is_mutable: false,
4403                            node: None,
4404                        },
4405                    ]
4406                } else {
4407                    vec![TypeForParameter {
4408                        name: "element".to_string(),
4409                        resolved_type: element_type.clone(),
4410                        is_mutable: false,
4411                        node: None,
4412                    }]
4413                };
4414                let lambda_signature = Signature {
4415                    parameters,
4416                    return_type: self.types().unit(),
4417                };
4418                let lambda_function_type = self.types().function(lambda_signature);
4419                (
4420                    IntrinsicFunction::TransformerFor,
4421                    Signature {
4422                        parameters: vec![
4423                            self_type_param,
4424                            TypeForParameter {
4425                                name: "lambda".to_string(),
4426                                resolved_type: lambda_function_type,
4427                                is_mutable: false,
4428                                node: None,
4429                            },
4430                        ],
4431                        return_type: self.types().unit(), // VecFor is only used for side effects
4432                    },
4433                )
4434            }
4435            "while" => {
4436                let parameters = if lambda_variable_count == 2 {
4437                    vec![
4438                        TypeForParameter {
4439                            name: "key".to_string(),
4440                            resolved_type: key_type.unwrap().clone(),
4441                            is_mutable: false,
4442                            node: None,
4443                        },
4444                        TypeForParameter {
4445                            name: "element".to_string(),
4446                            resolved_type: element_type.clone(),
4447                            is_mutable: false,
4448                            node: None,
4449                        },
4450                    ]
4451                } else {
4452                    vec![TypeForParameter {
4453                        name: "element".to_string(),
4454                        resolved_type: element_type.clone(),
4455                        is_mutable: false,
4456                        node: None,
4457                    }]
4458                };
4459                let lambda_signature = Signature {
4460                    parameters,
4461                    return_type: self.types().bool(), // it returns if the while loop should continue
4462                };
4463                let lambda_function_type = self.types().function(lambda_signature);
4464                (
4465                    IntrinsicFunction::TransformerWhile,
4466                    Signature {
4467                        parameters: vec![
4468                            self_type_param,
4469                            TypeForParameter {
4470                                name: "lambda".to_string(),
4471                                resolved_type: lambda_function_type,
4472                                is_mutable: false,
4473                                node: None,
4474                            },
4475                        ],
4476                        return_type: self.types().unit(), // VecFor is only used for side effects
4477                    },
4478                )
4479            }
4480            "filter" => {
4481                let lambda_signature = Signature {
4482                    parameters: vec![TypeForParameter {
4483                        name: "element".to_string(),
4484                        resolved_type: element_type.clone(),
4485                        is_mutable: false,
4486                        node: None,
4487                    }],
4488                    return_type: self.types().bool(),
4489                };
4490                let lambda_function_type = self.types().function(lambda_signature);
4491                (
4492                    IntrinsicFunction::TransformerFilter,
4493                    Signature {
4494                        parameters: vec![
4495                            self_type_param,
4496                            TypeForParameter {
4497                                name: "lambda".to_string(),
4498                                resolved_type: lambda_function_type,
4499                                is_mutable: false,
4500                                node: None,
4501                            },
4502                        ],
4503                        return_type: self.shared.state.types.slice_view(&element_type.clone()),
4504                    },
4505                )
4506            }
4507            "find" => {
4508                let lambda_signature = Signature {
4509                    parameters: vec![TypeForParameter {
4510                        name: "element".to_string(),
4511                        resolved_type: element_type.clone(),
4512                        is_mutable: false,
4513                        node: None,
4514                    }],
4515                    return_type: self.types().bool(),
4516                };
4517                let lambda_function_type = self.types().function(lambda_signature);
4518                (
4519                    IntrinsicFunction::TransformerFind,
4520                    Signature {
4521                        parameters: vec![
4522                            self_type_param,
4523                            TypeForParameter {
4524                                name: "lambda".to_string(),
4525                                resolved_type: lambda_function_type,
4526                                is_mutable: false,
4527                                node: None,
4528                            },
4529                        ],
4530                        return_type: self.shared.state.types.optional(&element_type.clone()),
4531                    },
4532                )
4533            }
4534
4535            "remove" => {
4536                let signature = Signature {
4537                    parameters: vec![
4538                        self_mut_type_param,
4539                        TypeForParameter {
4540                            name: "index".to_string(),
4541                            resolved_type: int_type,
4542                            is_mutable: false,
4543                            node: None,
4544                        },
4545                    ],
4546                    return_type: self.types().unit(),
4547                };
4548                (IntrinsicFunction::VecRemoveIndex, signature)
4549            }
4550            _ => return self.basic_collection_member_signature(self_type, field_name_str, node),
4551        };
4552        Some(intrinsic_and_signature)
4553    }
4554
4555    #[allow(clippy::unnecessary_wraps, clippy::result_large_err)]
4556    fn map_member_signature(
4557        &mut self,
4558        self_type: &TypeRef,
4559        key_type: &TypeRef,
4560        value_type: &TypeRef,
4561        field_name_str: &str,
4562        node: &swamp_ast::Node,
4563    ) -> Option<(IntrinsicFunction, Signature)> {
4564        let self_type_param = TypeForParameter {
4565            name: "self".to_string(),
4566            resolved_type: self_type.clone(),
4567            is_mutable: false,
4568            node: None,
4569        };
4570
4571        let mutable_self_type_param = TypeForParameter {
4572            name: "self".to_string(),
4573            resolved_type: self_type.clone(),
4574            is_mutable: true,
4575            node: None,
4576        };
4577
4578        let intrinsic_and_signature = match field_name_str {
4579            "has" => (
4580                IntrinsicFunction::MapHas,
4581                Signature {
4582                    parameters: vec![
4583                        self_type_param,
4584                        TypeForParameter {
4585                            name: "key".to_string(),
4586                            resolved_type: key_type.clone(),
4587                            is_mutable: false,
4588                            node: None,
4589                        },
4590                    ],
4591                    return_type: self.types().bool(),
4592                },
4593            ),
4594            "remove" => (
4595                IntrinsicFunction::MapRemove,
4596                Signature {
4597                    parameters: vec![
4598                        mutable_self_type_param,
4599                        TypeForParameter {
4600                            name: "key".to_string(),
4601                            resolved_type: key_type.clone(),
4602                            is_mutable: false,
4603                            node: None,
4604                        },
4605                    ],
4606                    return_type: self.types().unit(),
4607                },
4608            ),
4609            "len" => (
4610                IntrinsicFunction::MapLen,
4611                Signature {
4612                    parameters: vec![self_type_param],
4613                    return_type: self.types().int(),
4614                },
4615            ),
4616            "capacity" => (
4617                IntrinsicFunction::MapCapacity,
4618                Signature {
4619                    parameters: vec![self_type_param],
4620                    return_type: self.types().int(),
4621                },
4622            ),
4623            "is_empty" => (
4624                IntrinsicFunction::MapIsEmpty,
4625                Signature {
4626                    parameters: vec![self_type_param],
4627                    return_type: self.types().bool(),
4628                },
4629            ),
4630            _ => todo!("unknown map member"),
4631        };
4632
4633        Some(intrinsic_and_signature)
4634    }
4635
4636    fn check_intrinsic_member_signature(
4637        &mut self,
4638        type_that_member_is_on: &TypeRef,
4639        field_name_str: &str,
4640        lambda_variables_count: usize,
4641        node: &swamp_ast::Node,
4642    ) -> Option<(IntrinsicFunction, Signature)> {
4643        let ty = type_that_member_is_on;
4644        let int_type = self.types().int();
4645        match &*ty.kind {
4646            TypeKind::GridStorage(element_type, ..) | TypeKind::GridView(element_type) => self
4647                .grid_member_signature(type_that_member_is_on, element_type, field_name_str, node),
4648            TypeKind::SparseStorage(element_type, ..) | TypeKind::SparseView(element_type) => self
4649                .sparse_member_signature(
4650                    type_that_member_is_on,
4651                    element_type,
4652                    field_name_str,
4653                    lambda_variables_count,
4654                    node,
4655                ),
4656            TypeKind::Enum(enum_type) => self.enum_member_signature(ty, field_name_str, node),
4657            TypeKind::QueueStorage(element_type, ..) => self.queue_member_signature(
4658                type_that_member_is_on,
4659                None,
4660                element_type,
4661                field_name_str,
4662                lambda_variables_count,
4663                node,
4664            ),
4665            TypeKind::StackStorage(element_type, ..)
4666            | TypeKind::QueueStorage(element_type, ..)
4667            | TypeKind::VecStorage(element_type, ..)
4668            | TypeKind::DynamicLengthVecView(element_type) => self.vec_member_signature(
4669                type_that_member_is_on,
4670                element_type,
4671                field_name_str,
4672                lambda_variables_count,
4673                node,
4674            ),
4675            TypeKind::SliceView(element_type) => self.slice_member_signature(
4676                type_that_member_is_on,
4677                Some(&int_type),
4678                element_type,
4679                field_name_str,
4680                lambda_variables_count,
4681                node,
4682            ),
4683            TypeKind::Pointer(inner) => {
4684                self.ptr_member_signature(type_that_member_is_on, field_name_str, node)
4685            }
4686            TypeKind::Byte => {
4687                let element_type = self.shared.state.types.byte();
4688                self.byte_member_signature(
4689                    type_that_member_is_on,
4690                    Some(&int_type),
4691                    &element_type,
4692                    field_name_str,
4693                    lambda_variables_count,
4694                    node,
4695                )
4696            }
4697            TypeKind::Codepoint => {
4698                let element_type = self.shared.state.types.codepoint();
4699                self.codepoint_member_signature(
4700                    type_that_member_is_on,
4701                    Some(&int_type),
4702                    &element_type,
4703                    field_name_str,
4704                    lambda_variables_count,
4705                    node,
4706                )
4707            }
4708            TypeKind::StringView { .. } | TypeKind::StringStorage(..) => {
4709                let element_type = self.shared.state.types.byte();
4710                self.string_member_signature(
4711                    type_that_member_is_on,
4712                    Some(&int_type),
4713                    &element_type,
4714                    field_name_str,
4715                    lambda_variables_count,
4716                    node,
4717                )
4718            }
4719            TypeKind::DynamicLengthMapView(key, value) | TypeKind::MapStorage(key, value, _) => {
4720                self.map_member_signature(type_that_member_is_on, key, value, field_name_str, node)
4721            }
4722
4723            TypeKind::FixedCapacityAndLengthArray(element_type, _) => self.slice_member_signature(
4724                type_that_member_is_on,
4725                Some(&int_type),
4726                element_type,
4727                field_name_str,
4728                lambda_variables_count,
4729                node,
4730            ),
4731            _ => {
4732                self.add_err(
4733                    ErrorKind::UnknownMemberFunction(type_that_member_is_on.clone()),
4734                    node,
4735                );
4736
4737                None
4738            }
4739        }
4740    }
4741
4742    fn analyze_member_call(
4743        &mut self,
4744        type_that_member_is_on: &TypeRef,
4745        field_name_str: &str,
4746        ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4747        ast_arguments: &[swamp_ast::Expression],
4748        chain_self_is_mutable: bool,
4749        node: &swamp_ast::Node,
4750    ) -> (PostfixKind, TypeRef) {
4751        let generic_arguments = if let Some(ast_generic_arguments) = ast_maybe_generic_arguments {
4752            let mut resolved_types = Vec::new();
4753            for ast_type in ast_generic_arguments {
4754                resolved_types
4755                    .push(self.analyze_type(ast_type.get_type(), &TypeAnalyzeContext::default()));
4756            }
4757            resolved_types
4758        } else {
4759            vec![]
4760        };
4761
4762        let maybe_function = self
4763            .shared
4764            .state
4765            .associated_impls
4766            .get_member_function(type_that_member_is_on, field_name_str)
4767            .cloned();
4768
4769        let (function_ref, instantiated_signature) = if let Some(found_function) = maybe_function {
4770            let signature = self.analyze_normal_member_call(
4771                type_that_member_is_on,
4772                &found_function,
4773                generic_arguments,
4774                ast_arguments,
4775                chain_self_is_mutable,
4776                node,
4777            );
4778            (found_function, signature)
4779        } else {
4780            let lambda_variables_count = if ast_arguments.is_empty() {
4781                0
4782            } else if let swamp_ast::ExpressionKind::Lambda(variables, ..) = &ast_arguments[0].kind
4783            {
4784                variables.len()
4785            } else {
4786                0
4787            };
4788            let Some((intrinsic_fn, signature)) = self.check_intrinsic_member_signature(
4789                type_that_member_is_on,
4790                field_name_str,
4791                lambda_variables_count,
4792                node,
4793            ) else {
4794                return (PostfixKind::OptionalChainingOperator, self.types().unit());
4795            };
4796            let def = IntrinsicFunctionDefinition {
4797                name: field_name_str.to_string(),
4798                signature,
4799                intrinsic: intrinsic_fn,
4800            };
4801            let function_ref = FunctionRef::from(Function::Intrinsic(
4802                IntrinsicFunctionDefinitionRef::from(def.clone()),
4803            ));
4804            (function_ref, def.signature)
4805        };
4806
4807        let self_type_in_signature = &instantiated_signature.parameters[0];
4808
4809        if self_type_in_signature.is_mutable && !chain_self_is_mutable {
4810            self.add_err(ErrorKind::SelfNotCorrectMutableState, node);
4811        }
4812
4813        let resolved_arguments = self.analyze_and_verify_parameters(
4814            node,
4815            &instantiated_signature.parameters[1..],
4816            ast_arguments,
4817        );
4818
4819        let name_node = self.to_node(node);
4820        self.shared
4821            .state
4822            .refs
4823            .add(function_ref.symbol_id().into(), name_node.clone());
4824        self.shared
4825            .definition_table
4826            .refs
4827            .add(function_ref.symbol_id().into(), name_node);
4828
4829        (
4830            PostfixKind::MemberCall(function_ref, resolved_arguments),
4831            TypeRef::from(instantiated_signature.return_type.clone()),
4832        )
4833    }
4834
4835    fn analyze_postfix_member_call(
4836        &mut self,
4837        type_that_member_is_on: &TypeRef,
4838        is_mutable: bool,
4839        member_name: &swamp_ast::Node,
4840        ast_maybe_generic_arguments: Option<Vec<swamp_ast::GenericParameter>>,
4841        ast_arguments: &[swamp_ast::Expression],
4842        suffixes: &mut Vec<Postfix>,
4843    ) -> TypeRef {
4844        let field_name_str = self.get_text(member_name).to_string();
4845
4846        let resolved_node = self.to_node(member_name);
4847
4848        let (kind, return_type) = self.analyze_member_call(
4849            type_that_member_is_on,
4850            &field_name_str,
4851            ast_maybe_generic_arguments,
4852            ast_arguments,
4853            is_mutable,
4854            member_name,
4855        );
4856        let postfix = Postfix {
4857            node: resolved_node,
4858            ty: return_type,
4859            kind,
4860        };
4861
4862        let last_type = postfix.ty.clone();
4863        suffixes.push(postfix);
4864
4865        last_type
4866    }
4867
4868    fn is_compatible_initializer_list_target(
4869        &mut self,
4870        target_type: &TypeRef,
4871        initializer_element_type: &TypeRef,
4872    ) -> bool {
4873        match &*target_type.kind {
4874            TypeKind::VecStorage(vec_element_type, _vec_capacity) => self
4875                .types()
4876                .compatible_with(vec_element_type, initializer_element_type),
4877            TypeKind::FixedCapacityAndLengthArray(array_element_type, _array_capacity) => self
4878                .types()
4879                .compatible_with(array_element_type, initializer_element_type),
4880            _ => false,
4881        }
4882    }
4883
4884    fn is_compatible_initializer_pair_list_target(
4885        &mut self,
4886        target_type: &TypeRef,
4887        initializer_key_type: &TypeRef,
4888        initializer_value_type: &TypeRef,
4889    ) -> bool {
4890        match &*target_type.kind {
4891            TypeKind::MapStorage(storage_key, storage_value, _) => {
4892                self.types()
4893                    .compatible_with(initializer_key_type, storage_key)
4894                    && self
4895                        .types()
4896                        .compatible_with(initializer_value_type, storage_value)
4897            }
4898            _ => false,
4899        }
4900    }
4901
4902    fn types_did_not_match_try_late_coerce_expression(
4903        &mut self,
4904        expr: Expression,
4905        special_expected_type: &TypeRef,
4906        special_encountered_type: &TypeRef,
4907        node: &swamp_ast::Node,
4908    ) -> Expression {
4909        let expected_type = special_expected_type;
4910        let encountered_type = special_encountered_type;
4911
4912        if matches!(&*expected_type.kind, TypeKind::Any) && encountered_type.is_storage() {
4913            let wrapped = self.create_expr(
4914                ExpressionKind::CoerceToAny(Box::new(expr)),
4915                expected_type.clone(),
4916                node,
4917            );
4918            return wrapped;
4919        }
4920
4921        let encountered_is_optional = matches!(&*encountered_type.kind, TypeKind::Optional(_));
4922        if let TypeKind::Optional(expected_inner_type) = &*expected_type.kind {
4923            let inner_is_also_optional =
4924                matches!(&*expected_inner_type.kind, TypeKind::Optional(_));
4925            // If an optional is expected, we can wrap it if this type has the exact same
4926            // inner type
4927            assert!(!inner_is_also_optional);
4928
4929            // First make sure it is not already an optional type. we can not wrap an option with an option
4930            // TODO: Improve error handling
4931            if !encountered_is_optional {
4932                // good it isn't, lets see if they share inner types
4933                if self
4934                    .types()
4935                    .compatible_with(expected_inner_type, encountered_type)
4936                {
4937                    // they share inner types as well, lets wrap it up
4938                    let wrapped = self.create_expr(
4939                        ExpressionKind::Option(Option::from(Box::new(expr))),
4940                        expected_type.clone(),
4941                        node,
4942                    );
4943                    return wrapped;
4944                }
4945            }
4946        }
4947
4948        if matches!(&*expected_type.kind, &TypeKind::Bool) {
4949            // if it has a mut or immutable optional, then it works well to wrap it
4950            if encountered_is_optional {
4951                let bool_type = self.types().bool();
4952                let wrapped = self.create_expr(
4953                    ExpressionKind::CoerceOptionToBool(Box::from(expr)),
4954                    bool_type,
4955                    node,
4956                );
4957                return wrapped;
4958            }
4959        }
4960
4961        if matches!(
4962            (&*expected_type.kind, &*encountered_type.kind),
4963            (TypeKind::Codepoint, TypeKind::Int)
4964        ) {
4965            let coerced = self.create_expr(
4966                ExpressionKind::CoerceIntToChar(Box::new(expr)),
4967                expected_type.clone(),
4968                node,
4969            );
4970            return coerced;
4971        }
4972
4973        if matches!(
4974            (&*expected_type.kind, &*encountered_type.kind),
4975            (TypeKind::Byte, TypeKind::Int)
4976        ) {
4977            let coerced = self.create_expr(
4978                ExpressionKind::CoerceIntToByte(Box::new(expr)),
4979                expected_type.clone(),
4980                node,
4981            );
4982            return coerced;
4983        }
4984
4985        error!(?expected_type, ?encountered_type, "incompatible");
4986        self.create_err(
4987            ErrorKind::IncompatibleTypes {
4988                expected: expected_type.clone(),
4989                found: encountered_type.clone(),
4990            },
4991            node,
4992        )
4993    }
4994
4995    #[must_use]
4996    pub fn analyze_generic_parameter_usize(&self, generic_parameter: &GenericParameter) -> usize {
4997        let usize_node = generic_parameter.get_unsigned_int_node();
4998        let usize_str = self.get_text(usize_node);
4999        Self::str_to_unsigned_int(usize_str).unwrap() as usize
5000    }
5001
5002    #[must_use]
5003    pub fn analyze_generic_parameter_usize_tuple(
5004        &self,
5005        generic_parameter: &GenericParameter,
5006    ) -> (usize, usize) {
5007        let (first, second) = generic_parameter.get_unsigned_int_tuple_nodes();
5008        let first_str = self.get_text(first);
5009        let second_str = self.get_text(second);
5010        let first_value = Self::str_to_unsigned_int(first_str).unwrap() as usize;
5011        let second_value = Self::str_to_unsigned_int(second_str).unwrap() as usize;
5012
5013        (first_value, second_value)
5014    }
5015
5016    pub fn analyze_special_named_type(
5017        &mut self,
5018        path: &[String],
5019        name: &str,
5020        ast_generic_parameters: &[GenericParameter],
5021    ) -> Option<TypeRef> {
5022        let converted_type = match name {
5023            "Any" => self.shared.state.types.any(),
5024            "Ptr" => {
5025                if self.shared.allow_unsafe {
5026                    let inner_type = if ast_generic_parameters.len() == 1 {
5027                        self.analyze_type(
5028                            ast_generic_parameters[0].get_type(),
5029                            &TypeAnalyzeContext::default(),
5030                        )
5031                    } else if ast_generic_parameters.is_empty() {
5032                        self.shared.state.types.byte() // byte is the default pointer size
5033                    } else {
5034                        self.add_err_resolved(ErrorKind::UnexpectedType, &Node::default());
5035                        return None;
5036                    };
5037                    let new_type = self.shared.state.types.ptr(inner_type);
5038                    self.shared.state.associated_impls.prepare(&new_type);
5039                    new_type
5040                } else {
5041                    panic!("unsafe Ptr is not allowed");
5042                }
5043            }
5044            "String" => {
5045                if ast_generic_parameters.len() == 1 {
5046                    let fixed_size =
5047                        self.analyze_generic_parameter_usize(&ast_generic_parameters[0]);
5048                    let new_type = self.shared.state.types.string_storage(fixed_size);
5049                    let default_node = swamp_ast::Node::default();
5050                    self.add_default_functions(&new_type, &default_node);
5051                    new_type
5052                } else {
5053                    return None;
5054                }
5055            }
5056            "Vec" => {
5057                if ast_generic_parameters.len() == 1 {
5058                    let element_type = self.analyze_type(
5059                        ast_generic_parameters[0].get_type(),
5060                        &TypeAnalyzeContext::default(),
5061                    );
5062                    let vec_type = self.shared.state.types.dynamic_vec_view(&element_type);
5063                    // Generate default functions for the new dynamic vec view type
5064                    let default_node = swamp_ast::Node::default();
5065                    self.add_default_functions(&vec_type, &default_node);
5066                    vec_type
5067                } else if ast_generic_parameters.len() == 2 {
5068                    let element_type = self.analyze_type(
5069                        ast_generic_parameters[0].get_type(),
5070                        &TypeAnalyzeContext::default(),
5071                    );
5072                    let fixed_size =
5073                        self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5074                    let vec_storage_type = self
5075                        .shared
5076                        .state
5077                        .types
5078                        .vec_storage(&element_type, fixed_size);
5079                    // Generate default functions for the new vec storage type
5080                    let default_node = swamp_ast::Node::default();
5081                    self.add_default_functions(&vec_storage_type, &default_node);
5082                    vec_storage_type
5083                } else {
5084                    panic!("todo: make this into an error")
5085                }
5086            }
5087            "Stack" => {
5088                if ast_generic_parameters.len() == 1 {
5089                    let element_type = self.analyze_type(
5090                        ast_generic_parameters[0].get_type(),
5091                        &TypeAnalyzeContext::default(),
5092                    );
5093                    let stack_view_type = self.shared.state.types.stack_view(&element_type);
5094                    // Generate default functions for the new stack view type
5095                    let default_node = swamp_ast::Node::default();
5096                    self.add_default_functions(&stack_view_type, &default_node);
5097                    stack_view_type
5098                } else if ast_generic_parameters.len() == 2 {
5099                    let element_type = self.analyze_type(
5100                        ast_generic_parameters[0].get_type(),
5101                        &TypeAnalyzeContext::default(),
5102                    );
5103                    let fixed_size =
5104                        self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5105                    let stack_storage_type = self
5106                        .shared
5107                        .state
5108                        .types
5109                        .stack_storage(&element_type, fixed_size);
5110                    // Generate default functions for the new stack storage type
5111                    let default_node = swamp_ast::Node::default();
5112                    self.add_default_functions(&stack_storage_type, &default_node);
5113                    stack_storage_type
5114                } else {
5115                    panic!("todo: make this into an error")
5116                }
5117            }
5118            "Queue" => {
5119                if ast_generic_parameters.len() == 1 {
5120                    let element_type = self.analyze_type(
5121                        ast_generic_parameters[0].get_type(),
5122                        &TypeAnalyzeContext::default(),
5123                    );
5124                    let queue_view_type = self.shared.state.types.queue_view(&element_type);
5125                    // Generate default functions for the new queue view type
5126                    let default_node = swamp_ast::Node::default();
5127                    self.add_default_functions(&queue_view_type, &default_node);
5128                    queue_view_type
5129                } else if ast_generic_parameters.len() == 2 {
5130                    let element_type = self.analyze_type(
5131                        ast_generic_parameters[0].get_type(),
5132                        &TypeAnalyzeContext::default(),
5133                    );
5134                    let fixed_size =
5135                        self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5136                    let queue_storage_type = self
5137                        .shared
5138                        .state
5139                        .types
5140                        .queue_storage(&element_type, fixed_size);
5141                    // Generate default functions for the new queue storage type
5142                    let default_node = swamp_ast::Node::default();
5143                    self.add_default_functions(&queue_storage_type, &default_node);
5144                    queue_storage_type
5145                } else {
5146                    panic!("todo: make this into an error")
5147                }
5148            }
5149            "Sparse" => {
5150                if ast_generic_parameters.len() == 1 {
5151                    let element_type = self.analyze_type(
5152                        ast_generic_parameters[0].get_type(),
5153                        &TypeAnalyzeContext::default(),
5154                    );
5155                    let sparse_view_type = self.shared.state.types.sparse_view(&element_type);
5156                    // Generate default functions for the new sparse view type
5157                    let default_node = swamp_ast::Node::default();
5158                    self.add_default_functions(&sparse_view_type, &default_node);
5159                    sparse_view_type
5160                } else if ast_generic_parameters.len() == 2 {
5161                    let element_type = self.analyze_type(
5162                        ast_generic_parameters[0].get_type(),
5163                        &TypeAnalyzeContext::default(),
5164                    );
5165                    let fixed_size =
5166                        self.analyze_generic_parameter_usize(&ast_generic_parameters[1]);
5167                    let sparse_storage_type = self
5168                        .shared
5169                        .state
5170                        .types
5171                        .sparse_storage(&element_type, fixed_size);
5172                    // Generate default functions for the new sparse storage type
5173                    let default_node = swamp_ast::Node::default();
5174                    self.add_default_functions(&sparse_storage_type, &default_node);
5175                    sparse_storage_type
5176                } else {
5177                    panic!("todo: make this into an error")
5178                }
5179            }
5180
5181            "Grid" => {
5182                if ast_generic_parameters.len() == 1 {
5183                    let element_type = self.analyze_type(
5184                        ast_generic_parameters[0].get_type(),
5185                        &TypeAnalyzeContext::default(),
5186                    );
5187                    let grid_view_type = self.shared.state.types.grid_view(&element_type);
5188                    // Generate default functions for the new grid view type
5189                    let default_node = swamp_ast::Node::default();
5190                    self.add_default_functions(&grid_view_type, &default_node);
5191                    grid_view_type
5192                } else if ast_generic_parameters.len() == 2 {
5193                    let element_type = self.analyze_type(
5194                        ast_generic_parameters[0].get_type(),
5195                        &TypeAnalyzeContext::default(),
5196                    );
5197                    let (width, height) =
5198                        self.analyze_generic_parameter_usize_tuple(&ast_generic_parameters[1]);
5199                    let grid_storage_type =
5200                        self.shared
5201                            .state
5202                            .types
5203                            .grid_storage(&element_type, width, height);
5204                    // Generate default functions for the new grid storage type
5205                    let default_node = swamp_ast::Node::default();
5206                    self.add_default_functions(&grid_storage_type, &default_node);
5207                    grid_storage_type
5208                } else {
5209                    panic!("todo: make this into an error")
5210                }
5211            }
5212
5213            _ => return None,
5214        };
5215
5216        Some(converted_type)
5217    }
5218
5219    fn special_static_member(
5220        &self,
5221        type_identifier: &QualifiedTypeIdentifier,
5222        member_name_node: &swamp_ast::Node,
5223    ) -> Option<Function> {
5224        if type_identifier.generic_params.is_empty() {
5225            return None;
5226        }
5227
5228        if type_identifier.module_path.is_some() {
5229            return None;
5230        }
5231
5232        let member_name = self.get_text(member_name_node);
5233        let name = self.get_text(&type_identifier.name.0);
5234
5235        match name {
5236            "Stack" => None,
5237            _ => None,
5238        }
5239    }
5240
5241    fn analyze_subscript_int(
5242        &mut self,
5243        collection_type: TypeRef,
5244        unsigned_int_expression: Expression,
5245    ) -> (Postfix, TypeRef) {
5246        let node = &unsigned_int_expression.node;
5247        match &*collection_type.kind {
5248            TypeKind::QueueStorage(element_type, _)
5249            | TypeKind::StackStorage(element_type, _)
5250            | TypeKind::StackView(element_type)
5251            | TypeKind::VecStorage(element_type, _)
5252            | TypeKind::StringStorage(element_type, _, _)
5253            | TypeKind::StringView(element_type, _)
5254            | TypeKind::FixedCapacityAndLengthArray(element_type, _)
5255            | TypeKind::DynamicLengthVecView(element_type)
5256            | TypeKind::SliceView(element_type) => {
5257                let vec_type = VecType {
5258                    element: element_type.clone(),
5259                };
5260
5261                let postfix = Postfix {
5262                    node: node.clone(),
5263                    ty: collection_type.clone(),
5264                    kind: PostfixKind::VecSubscript(vec_type, unsigned_int_expression),
5265                };
5266
5267                (postfix, element_type.clone())
5268            }
5269            // Sparse
5270            TypeKind::SparseStorage(element_type, _) | TypeKind::SparseView(element_type) => {
5271                let sparse_type = SparseType {
5272                    element: element_type.clone(),
5273                };
5274
5275                let postfix = Postfix {
5276                    node: node.clone(),
5277                    ty: collection_type.clone(),
5278                    kind: PostfixKind::SparseSubscript(sparse_type, unsigned_int_expression),
5279                };
5280
5281                (postfix, element_type.clone())
5282            }
5283
5284            _ => {
5285                self.add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, node);
5286
5287                let error_vec_type = VecType {
5288                    element: self.types().unit(),
5289                };
5290
5291                let error_postfix = Postfix {
5292                    node: node.clone(),
5293                    ty: collection_type.clone(),
5294                    kind: PostfixKind::VecSubscript(error_vec_type, unsigned_int_expression),
5295                };
5296
5297                (error_postfix, self.types().unit())
5298            }
5299        }
5300    }
5301
5302    fn analyze_subscript_range(
5303        &mut self,
5304        collection_type: TypeRef,
5305        range_expression: Expression,
5306    ) -> (Postfix, TypeRef) {
5307        let node = &range_expression.node;
5308        match &*collection_type.kind {
5309            TypeKind::QueueStorage(element_type, _)
5310            | TypeKind::StackStorage(element_type, _)
5311            | TypeKind::StackView(element_type)
5312            | TypeKind::VecStorage(element_type, _)
5313            | TypeKind::StringStorage(element_type, _, _)
5314            | TypeKind::StringView(element_type, _)
5315            | TypeKind::FixedCapacityAndLengthArray(element_type, _)
5316            | TypeKind::DynamicLengthVecView(element_type)
5317            | TypeKind::SliceView(element_type) => {
5318                let vec_type = VecType {
5319                    element: element_type.clone(),
5320                };
5321
5322                let postfix = Postfix {
5323                    node: node.clone(),
5324                    ty: collection_type.clone(),
5325                    kind: PostfixKind::VecSubscriptRange(vec_type, range_expression),
5326                };
5327
5328                // A range subscript returns the same type again
5329                (postfix, collection_type.clone())
5330            }
5331
5332            _ => {
5333                self.add_err_resolved(ErrorKind::CanNotSubscriptWithThatType, node);
5334
5335                let error_vec_type = VecType {
5336                    element: self.types().unit(),
5337                };
5338
5339                let error_postfix = Postfix {
5340                    node: node.clone(),
5341                    ty: collection_type.clone(),
5342                    kind: PostfixKind::VecSubscriptRange(error_vec_type, range_expression),
5343                };
5344
5345                (error_postfix, self.types().unit())
5346            }
5347        }
5348    }
5349    fn analyze_map_subscript(
5350        &mut self,
5351        key_type: &TypeRef,
5352        value_type: &TypeRef,
5353        lookup_expr: &swamp_ast::Expression,
5354    ) -> (Postfix, TypeRef) {
5355        let key_context = TypeContext::new_argument(key_type, false);
5356        let key_expression = self.analyze_expression(lookup_expr, &key_context);
5357
5358        let map_type = MapType {
5359            key: key_type.clone(),
5360            value: value_type.clone(),
5361        };
5362
5363        let postfix = Postfix {
5364            node: self.to_node(&lookup_expr.node),
5365            ty: key_type.clone(),
5366            kind: PostfixKind::MapSubscript(map_type, key_expression),
5367        };
5368
5369        (postfix, value_type.clone())
5370    }
5371}