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