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