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