swamp_script_analyzer/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/script
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5pub mod access;
6pub mod call;
7pub mod constant;
8pub mod def;
9pub mod err;
10pub mod literal;
11pub mod operator;
12pub mod pattern;
13pub mod prelude;
14mod structure;
15pub mod types;
16pub mod variable;
17
18use crate::err::{Error, ErrorKind};
19use seq_map::SeqMap;
20use std::mem::take;
21use std::num::{ParseFloatError, ParseIntError};
22use swamp_script_ast::TypeVariable;
23use swamp_script_modules::prelude::*;
24use swamp_script_modules::symtbl::{SymbolTableRef, TypeGeneratorKind};
25use swamp_script_node::{FileId, Node, Span};
26use swamp_script_semantic::prelude::*;
27use swamp_script_semantic::type_var_stack::SemanticContext;
28use swamp_script_semantic::{
29    ArgumentExpressionOrLocation, BlockScope, BlockScopeMode, FunctionScopeState,
30    InternalMainExpression, LocationAccess, LocationAccessKind, MutOrImmutableExpression,
31    NormalPattern, Postfix, PostfixKind, SingleLocationExpression, SingleLocationExpressionKind,
32    SingleMutLocationExpression, TypeWithMut, WhenBinding,
33};
34use swamp_script_source_map::SourceMap;
35use swamp_script_types::all_types_are_concrete_or_unit;
36use swamp_script_types::prelude::*;
37use tracing::info;
38use tracing::{error, trace};
39
40#[derive(Copy, Clone, Eq, PartialEq, Debug)]
41pub enum LocationSide {
42    Lhs,
43    Rhs,
44}
45
46#[derive(Debug)]
47pub struct Program {
48    pub state: ProgramState,
49    pub modules: Modules,
50    pub default_symbol_table: SymbolTable,
51}
52
53impl Default for Program {
54    fn default() -> Self {
55        Self::new(ProgramState::new(), Modules::new(), SymbolTable::new(&[]))
56    }
57}
58
59impl Program {
60    #[must_use]
61    pub const fn new(
62        state: ProgramState,
63        modules: Modules,
64        default_symbol_table: SymbolTable,
65    ) -> Self {
66        Self {
67            state,
68            modules,
69            default_symbol_table,
70        }
71    }
72}
73
74#[must_use]
75pub const fn convert_span(without: &swamp_script_ast::SpanWithoutFileId, file_id: FileId) -> Span {
76    Span {
77        file_id,
78        offset: without.offset,
79        length: without.length,
80    }
81}
82
83/// Type checking context
84#[derive(Debug, Clone)]
85pub struct TypeContext<'a> {
86    /// Expected type for the current expression
87    pub expected_type: Option<&'a Type>,
88}
89
90impl<'a> TypeContext<'a> {
91    #[must_use]
92    pub const fn new(expected_type: Option<&'a Type>) -> Self {
93        Self { expected_type }
94    }
95
96    #[must_use]
97    pub const fn new_argument(required_type: &'a Type) -> Self {
98        Self {
99            expected_type: Some(required_type),
100        }
101    }
102
103    #[must_use]
104    pub const fn new_unsure_argument(expected_type: Option<&'a Type>) -> Self {
105        Self { expected_type }
106    }
107
108    #[must_use]
109    pub const fn new_anything_argument() -> Self {
110        Self {
111            expected_type: None,
112        }
113    }
114
115    #[must_use]
116    pub const fn new_function(required_type: &'a Type) -> Self {
117        Self {
118            expected_type: Some(required_type),
119        }
120    }
121
122    #[must_use]
123    pub const fn with_expected_type(&self, expected_type: Option<&'a Type>) -> Self {
124        Self { expected_type }
125    }
126
127    pub(crate) const fn we_know_expected_type(&self, found_type: &'a Type) -> Self {
128        self.with_expected_type(Some(found_type))
129    }
130}
131
132pub struct SharedState<'a> {
133    pub state: &'a mut ProgramState,
134    pub lookup_table: SymbolTable,
135    pub definition_table: SymbolTable,
136    pub modules: &'a Modules,
137    pub source_map: &'a SourceMap,
138    pub file_id: FileId,
139    pub core_symbol_table: SymbolTableRef,
140    pub type_variables: SemanticContext,
141}
142
143impl<'a> SharedState<'a> {
144    #[must_use]
145    pub fn get_symbol_table(&'a self, path: &[String]) -> Option<&'a SymbolTable> {
146        if path.is_empty() {
147            return Some(&self.lookup_table);
148        }
149        self.get_module(path).map(|module| &module.symbol_table)
150    }
151
152    #[must_use]
153    pub fn get_module(&'a self, path: &[String]) -> Option<&'a ModuleRef> {
154        let resolved_path = {
155            self.lookup_table.get_package_version(&path[0]).map_or_else(
156                || path.to_vec(),
157                |found_version| {
158                    let mut new_path = path.to_vec();
159                    let complete_name = format!("{}-{found_version}", path[0]);
160                    new_path[0] = complete_name;
161                    new_path
162                    //path.to_vec()
163                },
164            )
165        };
166
167        if path.len() == 1 {
168            if let Some(module_ref) = self.lookup_table.get_module_link(&path[0]) {
169                return Some(module_ref);
170            }
171        }
172
173        if let Some(x) = self.modules.get(&resolved_path) {
174            return Some(x);
175        }
176
177        None
178    }
179}
180
181pub struct Analyzer<'a> {
182    pub shared: SharedState<'a>,
183    scope: FunctionScopeState,
184    function_variables: Vec<VariableRef>,
185    global: FunctionScopeState,
186    module_path: Vec<String>,
187}
188
189impl<'a> Analyzer<'a> {
190    #[must_use]
191    pub const fn scopes(&self) -> &FunctionScopeState {
192        &self.scope
193    }
194}
195
196impl<'a> Analyzer<'a> {
197    pub fn new(
198        state: &'a mut ProgramState,
199        modules: &'a Modules,
200        core_symbol_table: SymbolTableRef,
201        source_map: &'a SourceMap,
202        module_path: &[String],
203        file_id: FileId,
204    ) -> Self {
205        let shared = SharedState {
206            state,
207            lookup_table: SymbolTable::new(&[]),
208            definition_table: SymbolTable::new(module_path),
209            modules,
210            core_symbol_table,
211            source_map,
212            file_id,
213            type_variables: SemanticContext::default(),
214        };
215        Self {
216            scope: FunctionScopeState::new(Type::Unit),
217            global: FunctionScopeState::new(Type::Unit),
218            shared,
219            module_path: module_path.to_vec(),
220            function_variables: Vec::new(),
221        }
222    }
223
224    fn start_function(&mut self, return_type: Type) {
225        self.global.block_scope_stack = take(&mut self.scope.block_scope_stack);
226        self.scope = FunctionScopeState::new(return_type);
227        self.function_variables.clear();
228    }
229
230    fn stop_function(&mut self) {
231        self.scope.block_scope_stack = take(&mut self.global.block_scope_stack);
232        self.function_variables.clear();
233    }
234
235    fn analyze_if_expression(
236        &mut self,
237        condition: &swamp_script_ast::Expression,
238        true_expression: &swamp_script_ast::Expression,
239        maybe_false_expression: Option<&swamp_script_ast::Expression>,
240        context: &TypeContext,
241    ) -> Result<Expression, Error> {
242        let resolved_condition = self.analyze_bool_argument_expression(condition)?;
243
244        let branch_context = context;
245
246        let true_expr = self.analyze_expression(true_expression, &branch_context)?;
247        let resolved_true = Box::new(true_expr);
248
249        let mut detected = context.expected_type.cloned();
250        if detected.is_none() && !matches!(resolved_true.ty, Type::Never) {
251            detected = Some(resolved_true.ty.clone());
252        }
253
254        // Analyze the false branch if it exists
255        let else_statements = if let Some(false_expression) = maybe_false_expression {
256            let else_context = branch_context.with_expected_type(detected.as_ref());
257            let else_expr = self.analyze_expression(false_expression, &else_context)?;
258            if detected.is_none() && !matches!(else_expr.ty, Type::Never) {
259                detected = Some(else_expr.ty.clone());
260            }
261
262            Some(Box::new(else_expr))
263        } else {
264            None
265        };
266
267        Ok(self.create_expr(
268            ExpressionKind::If(resolved_condition, resolved_true, else_statements),
269            detected.unwrap(),
270            &condition.node,
271        ))
272    }
273
274    fn get_text(&self, ast_node: &swamp_script_ast::Node) -> &str {
275        let span = Span {
276            file_id: self.shared.file_id,
277            offset: ast_node.span.offset,
278            length: ast_node.span.length,
279        };
280        self.shared.source_map.get_span_source(
281            self.shared.file_id,
282            span.offset as usize,
283            span.length as usize,
284        )
285    }
286
287    fn get_text_resolved(&self, resolved_node: &Node) -> &str {
288        let span = Span {
289            file_id: self.shared.file_id,
290            offset: resolved_node.span.offset,
291            length: resolved_node.span.length,
292        };
293        self.shared.source_map.get_span_source(
294            self.shared.file_id,
295            span.offset as usize,
296            span.length as usize,
297        )
298    }
299
300    fn get_path(&self, ident: &swamp_script_ast::QualifiedTypeIdentifier) -> (Vec<String>, String) {
301        let path = ident
302            .module_path
303            .as_ref()
304            .map_or_else(Vec::new, |found_path| {
305                let mut v = Vec::new();
306                for p in &found_path.0 {
307                    v.push(self.get_text(p).to_string());
308                }
309                v
310            });
311        (path, self.get_text(&ident.name.0).to_string())
312    }
313
314    fn analyze_return_type(
315        &mut self,
316        function: &swamp_script_ast::Function,
317    ) -> Result<Type, Error> {
318        let ast_return_type = match function {
319            swamp_script_ast::Function::Internal(x) => &x.declaration.return_type,
320            swamp_script_ast::Function::External(x) => &x.return_type,
321        };
322
323        let resolved_return_type = match ast_return_type {
324            None => Type::Unit,
325            Some(x) => self.analyze_type(x)?,
326        };
327
328        Ok(resolved_return_type)
329    }
330
331    fn analyze_function_body_expression(
332        &mut self,
333        expression: &swamp_script_ast::Expression,
334        return_type: &Type,
335    ) -> Result<Expression, Error> {
336        let context = TypeContext::new_function(return_type);
337        let resolved_statement = self.analyze_expression(expression, &context)?;
338
339        Ok(resolved_statement)
340    }
341
342    fn analyze_maybe_type(
343        &mut self,
344        maybe_type: Option<&swamp_script_ast::Type>,
345    ) -> Result<Type, Error> {
346        let found_type = match maybe_type {
347            None => Type::Unit,
348            Some(ast_type) => self.analyze_type(ast_type)?,
349        };
350        Ok(found_type)
351    }
352
353    fn analyze_for_pattern(
354        &mut self,
355        pattern: &swamp_script_ast::ForPattern,
356        key_type: Option<&Type>,
357        value_type: &Type,
358    ) -> Result<ForPattern, Error> {
359        match pattern {
360            swamp_script_ast::ForPattern::Single(var) => {
361                let variable_ref = self.create_local_variable(
362                    &var.identifier,
363                    Option::from(&var.is_mut),
364                    value_type,
365                )?;
366                Ok(ForPattern::Single(variable_ref))
367            }
368            swamp_script_ast::ForPattern::Pair(first, second) => {
369                let found_key = key_type.unwrap();
370                let first_var_ref = self.create_local_variable(
371                    &first.identifier,
372                    Option::from(&first.is_mut),
373                    found_key,
374                )?;
375                let second_var_ref = self.create_local_variable(
376                    &second.identifier,
377                    Option::from(&second.is_mut),
378                    value_type,
379                )?;
380                Ok(ForPattern::Pair(first_var_ref, second_var_ref))
381            }
382        }
383    }
384
385    fn analyze_parameters(
386        &mut self,
387        parameters: &Vec<swamp_script_ast::Parameter>,
388    ) -> Result<Vec<TypeForParameter>, Error> {
389        let mut resolved_parameters = Vec::new();
390        for parameter in parameters {
391            let param_type = self.analyze_type(&parameter.param_type)?;
392            resolved_parameters.push(TypeForParameter {
393                name: self.get_text(&parameter.variable.name).to_string(),
394                resolved_type: param_type,
395                is_mutable: parameter.variable.is_mutable.is_some(),
396                node: Some(ParameterNode {
397                    is_mutable: self.to_node_option(Option::from(&parameter.variable.is_mutable)),
398                    name: self.to_node(&parameter.variable.name),
399                }),
400            });
401        }
402        Ok(resolved_parameters)
403    }
404
405    /// # Errors
406    ///
407    pub fn analyze_start_chain_expression_get_mutability(
408        &mut self,
409        ast_expression: &swamp_script_ast::Expression,
410        expected_type: Option<&Type>,
411    ) -> Result<(Expression, bool), Error> {
412        let any_parameter_context = TypeContext::new_unsure_argument(expected_type);
413        let resolved = self.analyze_expression(ast_expression, &any_parameter_context)?;
414        let mutability = match resolved.kind {
415            ExpressionKind::VariableAccess(ref resolved_variable) => resolved_variable.is_mutable(),
416            _ => false,
417        };
418
419        Ok((resolved, mutability))
420    }
421
422    pub fn debug_expression(&self, expr: &swamp_script_ast::Expression) {
423        let (line, col) = self
424            .shared
425            .source_map
426            .get_span_location_utf8(self.shared.file_id, expr.node.span.offset as usize);
427        let source_line = self
428            .shared
429            .source_map
430            .get_source_line(self.shared.file_id, line);
431        trace!(?line, ?col, ?source_line, "analyzing");
432    }
433
434    pub fn analyze_main_expression(
435        &mut self,
436        ast_expression: &swamp_script_ast::Expression,
437    ) -> Result<InternalMainExpression, Error> {
438        let expected_type = Type::Unit;
439        self.start_function(expected_type.clone());
440
441        let context = TypeContext::new_argument(&expected_type);
442        let analyzed_expr = self.analyze_expression(ast_expression, &context)?;
443        let main_expr = InternalMainExpression {
444            expression: analyzed_expr,
445            function_scope_state: self.function_variables.clone(),
446            program_unique_id: self.shared.state.allocate_internal_function_id(),
447        };
448
449        self.stop_function();
450
451        Ok(main_expr)
452    }
453
454    /// # Errors
455    ///
456    #[allow(clippy::too_many_lines)]
457    pub fn analyze_expression(
458        &mut self,
459        ast_expression: &swamp_script_ast::Expression,
460        context: &TypeContext,
461    ) -> Result<Expression, Error> {
462        // self.debug_expression(&ast_expression);
463
464        let expr = self.analyze_expression_internal(ast_expression, context)?;
465
466        let encountered_type = expr.ty.clone();
467
468        if let Some(found_expected_type) = context.expected_type {
469            if found_expected_type.compatible_with(&encountered_type) {
470                return Ok(expr);
471            }
472
473            let result = self.types_did_not_match_try_late_coerce_expression(
474                expr,
475                found_expected_type,
476                &encountered_type,
477                &ast_expression.node,
478            )?;
479
480            return Ok(result);
481        }
482
483        Ok(expr)
484    }
485
486    /// # Errors
487    ///
488    #[allow(clippy::too_many_lines)]
489    pub fn analyze_expression_internal(
490        &mut self,
491        ast_expression: &swamp_script_ast::Expression,
492        context: &TypeContext,
493    ) -> Result<Expression, Error> {
494        let expression = match &ast_expression.kind {
495            // Lookups
496            swamp_script_ast::ExpressionKind::PostfixChain(postfix_chain) => {
497                self.analyze_postfix_chain(postfix_chain)?
498            }
499
500            swamp_script_ast::ExpressionKind::VariableDefinition(
501                variable,
502                maybe_annotation,
503                source_expression,
504            ) => self.analyze_create_variable(
505                variable,
506                Option::from(maybe_annotation),
507                source_expression,
508            )?,
509
510            swamp_script_ast::ExpressionKind::VariableAssignment(variable, source_expression) => {
511                self.analyze_variable_assignment(variable, source_expression)?
512            }
513            swamp_script_ast::ExpressionKind::DestructuringAssignment(variables, expression) => {
514                self.analyze_destructuring(&ast_expression.node, variables, expression)?
515            }
516
517            swamp_script_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
518                self.analyze_identifier(qualified_identifier)?
519            }
520            swamp_script_ast::ExpressionKind::VariableReference(variable) => {
521                // TODO: investigate why this is not called?
522                self.analyze_variable_reference(&variable.name)?
523            }
524
525            swamp_script_ast::ExpressionKind::StaticMemberFunctionReference(
526                type_identifier,
527                member_name,
528            ) => self.analyze_static_member_access(type_identifier, member_name)?,
529
530            swamp_script_ast::ExpressionKind::ConstantReference(constant_identifier) => {
531                self.analyze_constant_access(constant_identifier)?
532            }
533
534            swamp_script_ast::ExpressionKind::Assignment(location, source) => {
535                self.analyze_assignment(location, source)?
536            }
537            swamp_script_ast::ExpressionKind::CompoundAssignment(target, op, source) => {
538                self.analyze_assignment_compound(target, op, source)?
539            }
540
541            // Operator
542            swamp_script_ast::ExpressionKind::BinaryOp(resolved_a, operator, resolved_b) => {
543                let (resolved_op, result_type) =
544                    self.analyze_binary_op(resolved_a, operator, resolved_b)?;
545
546                self.create_expr(
547                    ExpressionKind::BinaryOp(resolved_op),
548                    result_type,
549                    &ast_expression.node,
550                )
551            }
552            swamp_script_ast::ExpressionKind::UnaryOp(operator, expression) => {
553                let (resolved_op, result_type) = self.analyze_unary_op(operator, expression)?;
554                self.create_expr(
555                    ExpressionKind::UnaryOp(resolved_op),
556                    result_type,
557                    &ast_expression.node,
558                )
559            }
560
561            swamp_script_ast::ExpressionKind::Block(expressions) => {
562                let (block, resulting_type) =
563                    self.analyze_block(&ast_expression.node, context, expressions)?;
564                self.create_expr(
565                    ExpressionKind::Block(block),
566                    resulting_type,
567                    &ast_expression.node,
568                )
569            }
570
571            swamp_script_ast::ExpressionKind::With(variable_bindings, expression) => {
572                self.analyze_with_expr(context, variable_bindings, expression)?
573            }
574
575            swamp_script_ast::ExpressionKind::When(variable_bindings, true_expr, else_expr) => {
576                self.analyze_when_expr(context, variable_bindings, true_expr, else_expr.as_deref())?
577            }
578
579            swamp_script_ast::ExpressionKind::InterpolatedString(string_parts) => {
580                let kind = ExpressionKind::InterpolatedString(
581                    self.analyze_interpolated_string(string_parts)?,
582                );
583
584                self.create_expr(kind, Type::String, &ast_expression.node)
585            }
586
587            // Creation
588            swamp_script_ast::ExpressionKind::NamedStructLiteral(
589                struct_identifier,
590                fields,
591                has_rest,
592            ) => self.analyze_struct_instantiation(struct_identifier, fields, *has_rest)?,
593
594            swamp_script_ast::ExpressionKind::AnonymousStructLiteral(
595                fields,
596                rest_was_specified,
597            ) => self.analyze_anonymous_struct_literal(
598                &ast_expression.node,
599                fields,
600                *rest_was_specified,
601                context,
602            )?,
603
604            swamp_script_ast::ExpressionKind::Range(min_value, max_value, range_mode) => {
605                self.analyze_range(min_value, max_value, range_mode, &ast_expression.node)?
606            }
607
608            swamp_script_ast::ExpressionKind::Literal(literal) => {
609                self.analyze_complex_literal_to_expression(&ast_expression.node, literal, context)?
610            }
611
612            swamp_script_ast::ExpressionKind::ForLoop(
613                pattern,
614                iterable_expression,
615                guard_expr,
616                statements,
617            ) => {
618                let _analyzed_guard = if let Some(found_guard) = guard_expr {
619                    // TODO: Remove guard in for loops
620                    Some(self.analyze_bool_argument_expression(found_guard)?)
621                } else {
622                    None
623                };
624
625                let resolved_iterator =
626                    self.analyze_iterable(pattern.any_mut(), &iterable_expression.expression)?;
627
628                self.push_block_scope("for_loop");
629                let pattern = self.analyze_for_pattern(
630                    pattern,
631                    resolved_iterator.key_type.as_ref(),
632                    &resolved_iterator.value_type,
633                )?;
634                let resolved_statements = self.analyze_expression(statements, &context)?;
635                self.pop_block_scope("for_loop");
636                let resolved_type = resolved_statements.ty.clone();
637                self.create_expr(
638                    ExpressionKind::ForLoop(
639                        pattern,
640                        resolved_iterator,
641                        Box::from(resolved_statements),
642                    ),
643                    resolved_type,
644                    &ast_expression.node,
645                )
646            }
647            swamp_script_ast::ExpressionKind::WhileLoop(expression, statements) => {
648                let condition = self.analyze_bool_argument_expression(expression)?;
649                //self.push_block_scope("while_loop");
650                let resolved_statements = self.analyze_expression(statements, context)?;
651                let resolved_type = resolved_statements.ty.clone();
652                //self.pop_block_scope("while_loop");
653
654                self.create_expr(
655                    ExpressionKind::WhileLoop(condition, Box::from(resolved_statements)),
656                    resolved_type,
657                    &ast_expression.node,
658                )
659            }
660
661            swamp_script_ast::ExpressionKind::If(
662                expression,
663                true_expression,
664                maybe_false_expression,
665            ) => self.analyze_if_expression(
666                expression,
667                true_expression,
668                maybe_false_expression.as_deref(),
669                context,
670            )?,
671
672            swamp_script_ast::ExpressionKind::Match(expression, arms) => {
673                let (match_expr, return_type) = self.analyze_match(expression, context, arms)?;
674                self.create_expr(
675                    ExpressionKind::Match(match_expr),
676                    return_type,
677                    &ast_expression.node,
678                )
679            }
680            swamp_script_ast::ExpressionKind::Guard(guard_expressions) => {
681                self.analyze_guard(&ast_expression.node, context, guard_expressions)?
682            }
683
684            swamp_script_ast::ExpressionKind::Lambda(variables, expression) => {
685                self.analyze_lambda(&ast_expression.node, variables, &**expression, context)?
686            }
687        };
688
689        //info!(ty=%expression.ty, kind=?expression.kind,  "resolved expression");
690
691        Ok(expression)
692    }
693
694    fn get_struct_type(
695        &mut self,
696        qualified_type_identifier: &swamp_script_ast::QualifiedTypeIdentifier,
697    ) -> Result<NamedStructType, Error> {
698        let maybe_struct_type = self.analyze_named_type(qualified_type_identifier)?;
699        match maybe_struct_type {
700            Type::NamedStruct(struct_type) => Ok(struct_type),
701            _ => Err(self.create_err(
702                // For other Type variants that are not Struct
703                ErrorKind::UnknownStructTypeReference,
704                &qualified_type_identifier.name.0,
705            )),
706        }
707    }
708
709    pub(crate) fn analyze_named_type(
710        &mut self,
711        type_name_to_find: &swamp_script_ast::QualifiedTypeIdentifier,
712    ) -> Result<Type, Error> {
713        let (path, name) = self.get_path(type_name_to_find);
714
715        if path.is_empty() {
716            // Check if it is a type variable first!
717            if let Some(found_type) = self.shared.type_variables.resolve_type_variable(&name) {
718                return Ok(found_type.clone());
719            }
720        }
721
722        let symbol = {
723            let maybe_symbol_table = self.shared.get_symbol_table(&path);
724            let symbol_table = maybe_symbol_table.ok_or_else(|| {
725                self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
726            })?;
727            symbol_table
728                .get_symbol(&name)
729                .ok_or_else(|| {
730                    self.create_err(ErrorKind::UnknownSymbol, &type_name_to_find.name.0)
731                })?
732                .clone()
733        };
734
735        let mut analyzed_type_parameters = Vec::new();
736
737        for analyzed_type in &type_name_to_find.generic_params {
738            let ty = self.analyze_type(analyzed_type)?;
739
740            analyzed_type_parameters.push(ty);
741        }
742
743        let result_type = if !analyzed_type_parameters.is_empty() {
744            self.analyze_generic_type(
745                &symbol,
746                &analyzed_type_parameters,
747                &type_name_to_find.name.0,
748            )?
749        } else {
750            match &symbol {
751                Symbol::Type(base_type) => base_type.clone(),
752                Symbol::Alias(alias_type) => alias_type.referenced_type.clone(),
753                _ => {
754                    return Err(
755                        self.create_err(ErrorKind::UnexpectedType, &type_name_to_find.name.0)
756                    );
757                }
758            }
759        };
760
761        Ok(result_type)
762    }
763
764    fn create_default_value_for_type(
765        &mut self,
766        node: &swamp_script_ast::Node,
767        field_type: &Type,
768    ) -> Result<Expression, Error> {
769        let kind = match field_type {
770            Type::Bool => ExpressionKind::Literal(Literal::BoolLiteral(false)),
771            Type::Int => ExpressionKind::Literal(Literal::IntLiteral(0)),
772            Type::Float => ExpressionKind::Literal(Literal::FloatLiteral(Fp::zero())),
773            Type::String => ExpressionKind::Literal(Literal::StringLiteral(String::new())),
774            Type::Tuple(tuple_type_ref) => {
775                let mut expressions = Vec::new();
776                for resolved_type in tuple_type_ref {
777                    let expr = self.create_default_value_for_type(node, resolved_type)?;
778                    expressions.push(expr);
779                }
780                ExpressionKind::Literal(Literal::TupleLiteral(tuple_type_ref.clone(), expressions))
781            }
782            Type::Optional(_optional_type) => ExpressionKind::Literal(Literal::NoneLiteral),
783
784            Type::NamedStruct(struct_ref) => {
785                self.create_default_static_call(node, &Type::NamedStruct(struct_ref.clone()))?
786            }
787            _ => {
788                return Err(
789                    self.create_err(ErrorKind::NoDefaultImplemented(field_type.clone()), node)
790                );
791            }
792        };
793
794        let expr = self.create_expr(kind, field_type.clone(), node);
795        Ok(expr)
796    }
797
798    fn create_static_call(
799        &mut self,
800        function_name: &str,
801        arguments: &[ArgumentExpressionOrLocation],
802        node: &swamp_script_ast::Node,
803        ty: &Type,
804    ) -> Result<ExpressionKind, Error> {
805        self.lookup_associated_function(ty, function_name)
806            .map_or_else(
807                || {
808                    Err(self.create_err(
809                        ErrorKind::NoAssociatedFunction(ty.clone(), function_name.to_string()),
810                        node,
811                    ))
812                },
813                |function| {
814                    let kind = match &*function {
815                        Function::Internal(internal_function) => {
816                            ExpressionKind::InternalFunctionAccess(internal_function.clone())
817                        }
818                        Function::External(external_function) => {
819                            ExpressionKind::ExternalFunctionAccess(external_function.clone())
820                        }
821                    };
822
823                    let base_expr =
824                        self.create_expr(kind, Type::Function(function.signature().clone()), node);
825
826                    let empty_call_postfix = Postfix {
827                        node: self.to_node(node),
828                        ty: *function.signature().return_type.clone(),
829                        kind: PostfixKind::FunctionCall(arguments.to_vec()),
830                    };
831
832                    let kind =
833                        ExpressionKind::PostfixChain(Box::new(base_expr), vec![empty_call_postfix]);
834
835                    Ok(kind)
836                },
837            )
838    }
839
840    fn create_default_static_call(
841        &mut self,
842        node: &swamp_script_ast::Node,
843        ty: &Type,
844    ) -> Result<ExpressionKind, Error> {
845        self.create_static_call("default", &[], node, ty)
846    }
847
848    fn add_postfix(
849        &mut self,
850        vec: &mut Vec<Postfix>,
851        kind: PostfixKind,
852        ty: Type,
853        node: &swamp_script_ast::Node,
854    ) {
855        let resolved_node = self.to_node(node);
856        let postfix = Postfix {
857            node: resolved_node,
858            ty,
859            kind,
860        };
861
862        vec.push(postfix);
863    }
864
865    /// # Panics
866    ///
867    /// # Errors
868    ///
869    pub fn analyze_struct_field(
870        &mut self,
871        field_name: &swamp_script_ast::Node,
872        tv: Type,
873    ) -> Result<(AnonymousStructType, usize, Type), Error> {
874        let field_name_str = self.get_text(field_name).to_string();
875
876        let anon_struct_ref = match &tv {
877            Type::NamedStruct(struct_type) => struct_type.anon_struct_type.clone(),
878            Type::AnonymousStruct(anon_struct) => anon_struct.clone(),
879            _ => return Err(self.create_err(ErrorKind::UnknownStructField, field_name)),
880        };
881
882        if let Some(found_field) = anon_struct_ref
883            .field_name_sorted_fields
884            .get(&field_name_str)
885        {
886            let index = anon_struct_ref
887                .field_name_sorted_fields
888                .get_index(&field_name_str)
889                .expect("checked earlier");
890
891            return Ok((
892                anon_struct_ref.clone(),
893                index,
894                found_field.field_type.clone(),
895            ));
896        }
897
898        Err(self.create_err(ErrorKind::UnknownStructField, field_name))
899    }
900
901    #[allow(clippy::too_many_lines)]
902    fn analyze_postfix_chain(
903        &mut self,
904        chain: &swamp_script_ast::PostfixChain,
905    ) -> Result<Expression, Error> {
906        let (start, is_mutable) =
907            self.analyze_start_chain_expression_get_mutability(&chain.base, None)?;
908
909        if let ExpressionKind::IntrinsicFunctionAccess(some_access) = &start.kind {
910            assert_eq!(chain.postfixes.len(), 1);
911            let call_postifx = &chain.postfixes[0];
912            if let swamp_script_ast::Postfix::FunctionCall(_member, arguments) = &call_postifx {
913                let resolved_arguments = self.analyze_and_verify_parameters(
914                    &start.node,
915                    &some_access.signature.parameters,
916                    arguments,
917                )?;
918
919                return Ok(self.create_expr(
920                    ExpressionKind::IntrinsicCallEx(
921                        some_access.intrinsic.clone(),
922                        resolved_arguments,
923                    ),
924                    *some_access.signature.return_type.clone(),
925                    &chain.base.node,
926                ));
927            } else {
928                panic!("not sure here");
929            }
930        }
931
932        let mut tv = TypeWithMut {
933            resolved_type: start.ty.clone(),
934            is_mutable,
935        };
936
937        let mut uncertain = false;
938
939        let mut suffixes = Vec::new();
940
941        for item in &chain.postfixes {
942            match item {
943                swamp_script_ast::Postfix::FieldAccess(field_name) => {
944                    let (struct_type_ref, index, return_type) =
945                        self.analyze_struct_field(&field_name.clone(), tv.resolved_type)?;
946                    self.add_postfix(
947                        &mut suffixes,
948                        PostfixKind::StructField(struct_type_ref.clone(), index),
949                        return_type.clone(),
950                        field_name,
951                    );
952
953                    tv.resolved_type = return_type.clone();
954                    // keep previous `is_mutable`
955                }
956                swamp_script_ast::Postfix::MemberCall(member_name, ast_arguments) => {
957                    let member_name_str = self.get_text(member_name).to_string();
958
959                    if let Some(_found_member) = self
960                        .shared
961                        .state
962                        .instantiator
963                        .associated_impls
964                        .get_member_function(&tv.resolved_type, &member_name_str)
965                    {
966                        let return_type = self.analyze_postfix_member_call(
967                            &tv.resolved_type,
968                            tv.is_mutable,
969                            member_name,
970                            ast_arguments,
971                            &mut suffixes,
972                        )?;
973
974                        //self.add_postfix(&mut suffixes, kind, return_type.clone(), member_name);
975                        tv.resolved_type = return_type.clone();
976                        tv.is_mutable = false;
977                    } else {
978                        return Err(self.create_err(ErrorKind::UnknownMemberFunction, member_name));
979                    }
980                }
981                swamp_script_ast::Postfix::FunctionCall(node, arguments) => {
982                    if let Type::Function(signature) = &tv.resolved_type {
983                        let resolved_node = self.to_node(node);
984                        let resolved_arguments = self.analyze_and_verify_parameters(
985                            &resolved_node,
986                            &signature.parameters,
987                            arguments,
988                        )?;
989
990                        let call_kind = PostfixKind::FunctionCall(resolved_arguments);
991
992                        self.add_postfix(
993                            &mut suffixes,
994                            call_kind,
995                            *signature.return_type.clone(),
996                            node,
997                        );
998
999                        tv.resolved_type = *signature.return_type.clone();
1000                        tv.is_mutable = false;
1001                    } else {
1002                        panic!("{}", &format!("what is this type {:?} ", tv.resolved_type))
1003                    }
1004                }
1005
1006                swamp_script_ast::Postfix::Subscript(index_expr) => {
1007                    let collection_type = tv.resolved_type.clone();
1008
1009                    let temp_lookup_context = TypeContext::new_anything_argument();
1010                    let temp_analyzed_expr =
1011                        self.analyze_expression(index_expr, &temp_lookup_context)?;
1012
1013                    let mut subscript_function_name = "subscript";
1014
1015                    if let Type::NamedStruct(named_struct) = temp_analyzed_expr.ty {
1016                        if named_struct.assigned_name == "Range"
1017                            && named_struct.module_path == vec!["core-0.0.0".to_string()]
1018                        {
1019                            subscript_function_name = "subscript_range";
1020                        }
1021                    };
1022
1023                    if let Some(found) = self
1024                        .shared
1025                        .state
1026                        .instantiator
1027                        .associated_impls
1028                        .get_member_function(&tv.resolved_type, subscript_function_name)
1029                        .cloned()
1030                    {
1031                        let cloned = found.clone();
1032                        let required_type = &found.signature().parameters[1].resolved_type;
1033                        let subscript_lookup_context = TypeContext::new_argument(&required_type);
1034                        let analyzed_expr =
1035                            self.analyze_expression(index_expr, &subscript_lookup_context)?;
1036
1037                        let return_type = *found.signature().return_type.clone();
1038
1039                        let argument = ArgumentExpressionOrLocation::Expression(analyzed_expr);
1040                        self.add_postfix(
1041                            &mut suffixes,
1042                            PostfixKind::MemberCall(cloned, vec![argument]),
1043                            return_type.clone(),
1044                            &index_expr.node,
1045                        );
1046                        tv.resolved_type = return_type.clone();
1047                    } else {
1048                        error!(
1049                            ?collection_type,
1050                            subscript_function_name, "missing subscript"
1051                        );
1052                        return Err(
1053                            self.create_err(ErrorKind::MissingSubscriptMember, &index_expr.node)
1054                        );
1055                    }
1056                }
1057
1058                swamp_script_ast::Postfix::NoneCoalescingOperator(default_expr) => {
1059                    let unwrapped_type = if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1060                        unwrapped_type
1061                    } else if uncertain {
1062                        &tv.resolved_type
1063                    } else {
1064                        return Err(
1065                            self.create_err(ErrorKind::CanNotNoneCoalesce, &default_expr.node)
1066                        );
1067                    };
1068
1069                    let unwrapped_type_context = TypeContext::new_argument(unwrapped_type);
1070                    let resolved_default_expr =
1071                        self.analyze_expression(default_expr, &unwrapped_type_context)?;
1072                    self.add_postfix(
1073                        &mut suffixes,
1074                        PostfixKind::NoneCoalescingOperator(resolved_default_expr),
1075                        unwrapped_type.clone(),
1076                        &default_expr.node,
1077                    );
1078                    tv.resolved_type = unwrapped_type.clone();
1079                    uncertain = false; // the chain is safe, because this will always solve None
1080                }
1081
1082                swamp_script_ast::Postfix::OptionalChainingOperator(option_node) => {
1083                    if let Type::Optional(unwrapped_type) = &tv.resolved_type {
1084                        uncertain = true;
1085                        self.add_postfix(
1086                            &mut suffixes,
1087                            PostfixKind::OptionalChainingOperator,
1088                            *unwrapped_type.clone(),
1089                            option_node,
1090                        );
1091                        tv.resolved_type = *unwrapped_type.clone();
1092                    } else {
1093                        return Err(self.create_err(ErrorKind::ExpectedOptional, option_node));
1094                    }
1095                }
1096            }
1097        }
1098
1099        if uncertain {
1100            if let Type::Optional(_) = tv.resolved_type {
1101            } else {
1102                tv.resolved_type = Type::Optional(Box::from(tv.resolved_type.clone()));
1103            }
1104        }
1105
1106        Ok(self.create_expr(
1107            ExpressionKind::PostfixChain(Box::new(start), suffixes),
1108            tv.resolved_type,
1109            &chain.base.node,
1110        ))
1111    }
1112
1113    fn analyze_bool_argument_expression(
1114        &mut self,
1115        expression: &swamp_script_ast::Expression,
1116    ) -> Result<BooleanExpression, Error> {
1117        let bool_context = TypeContext::new_argument(&Type::Bool);
1118        let resolved_expression = self.analyze_expression(expression, &bool_context)?;
1119        let expr_type = resolved_expression.ty.clone();
1120
1121        let bool_expression = match expr_type {
1122            Type::Bool => resolved_expression,
1123            Type::Optional(_) => self.create_expr(
1124                ExpressionKind::CoerceOptionToBool(Box::new(resolved_expression)),
1125                Type::Bool,
1126                &expression.node,
1127            ),
1128            _ => {
1129                return Err(self.create_err(ErrorKind::ExpectedBooleanExpression, &expression.node));
1130            }
1131        };
1132
1133        Ok(BooleanExpression {
1134            expression: Box::from(bool_expression),
1135        })
1136    }
1137
1138    fn analyze_iterable(
1139        &mut self,
1140        force_mut: Option<swamp_script_ast::Node>,
1141        expression: &swamp_script_ast::MutableOrImmutableExpression,
1142    ) -> Result<Iterable, Error> {
1143        let any_context = TypeContext::new_anything_argument();
1144        let resolved_expression: MutOrImmutableExpression = if force_mut.is_some() {
1145            let resolved_node = self.to_node(&force_mut.unwrap());
1146            MutOrImmutableExpression {
1147                expression_or_location: ArgumentExpressionOrLocation::Location(
1148                    self.analyze_to_location(
1149                        &expression.expression,
1150                        &any_context,
1151                        LocationSide::Rhs,
1152                    )?,
1153                ),
1154                is_mutable: Some(resolved_node),
1155            }
1156        } else {
1157            self.analyze_mut_or_immutable_expression(expression, &any_context, LocationSide::Rhs)?
1158        };
1159
1160        let resolved_type = &resolved_expression.ty().clone();
1161        let (key_type, value_type): (Option<Type>, Type) = match resolved_type {
1162            Type::String => (Some(Type::Int), Type::String),
1163
1164            _ => {
1165                if let Some(found_iter_fn) = self
1166                    .shared
1167                    .state
1168                    .instantiator
1169                    .associated_impls
1170                    .get_internal_member_function(resolved_type, "iter")
1171                {
1172                    let ret_type = found_iter_fn.signature.signature.return_type.clone();
1173                    match *ret_type {
1174                        Type::Tuple(tuple_items) => {
1175                            (Some(tuple_items[0].clone()), tuple_items[1].clone())
1176                        }
1177                        _ => {
1178                            return Err(self.create_err(
1179                                ErrorKind::NotAnIterator,
1180                                &expression.expression.node,
1181                            ));
1182                        }
1183                    }
1184                } else {
1185                    return Err(
1186                        self.create_err(ErrorKind::NotAnIterator, &expression.expression.node)
1187                    );
1188                }
1189            }
1190        };
1191
1192        Ok(Iterable {
1193            key_type,
1194            value_type,
1195            resolved_expression: Box::new(resolved_expression),
1196        })
1197    }
1198
1199    fn analyze_argument_expressions(
1200        &mut self,
1201        expected_type: Option<&Type>,
1202        ast_expressions: &[swamp_script_ast::Expression],
1203    ) -> Result<Vec<Expression>, Error> {
1204        let mut resolved_expressions = Vec::new();
1205        let argument_expressions_context = TypeContext::new_unsure_argument(expected_type);
1206        for expression in ast_expressions {
1207            resolved_expressions
1208                .push(self.analyze_expression(expression, &argument_expressions_context)?);
1209        }
1210        Ok(resolved_expressions)
1211    }
1212
1213    fn analyze_block(
1214        &mut self,
1215        _node: &swamp_script_ast::Node,
1216        context: &TypeContext,
1217        ast_expressions: &[swamp_script_ast::Expression],
1218    ) -> Result<(Vec<Expression>, Type), Error> {
1219        if ast_expressions.is_empty() {
1220            return Ok((vec![], Type::Unit));
1221        }
1222
1223        self.push_block_scope("block");
1224
1225        let mut resolved_expressions = Vec::with_capacity(ast_expressions.len());
1226
1227        for expression in &ast_expressions[..ast_expressions.len() - 1] {
1228            let stmt_context = context.with_expected_type(Some(&Type::Unit));
1229            let expr = self.analyze_expression(expression, &stmt_context)?;
1230
1231            if matches!(expr.ty, Type::Never) {
1232                resolved_expressions.push(expr);
1233                return Ok((resolved_expressions, Type::Never));
1234            }
1235
1236            resolved_expressions.push(expr);
1237        }
1238
1239        // Process the last expression - it determines the block's type
1240        let last_expr =
1241            self.analyze_expression(&ast_expressions[ast_expressions.len() - 1], context)?;
1242        let last_type = last_expr.ty.clone();
1243        resolved_expressions.push(last_expr);
1244
1245        self.pop_block_scope("block");
1246
1247        Ok((resolved_expressions, last_type))
1248    }
1249
1250    fn analyze_interpolated_string(
1251        &mut self,
1252        string_parts: &[swamp_script_ast::StringPart],
1253    ) -> Result<Vec<StringPart>, Error> {
1254        let mut resolved_parts = Vec::new();
1255        for part in string_parts {
1256            let resolved_string_part = match part {
1257                swamp_script_ast::StringPart::Literal(string_node, processed_string) => {
1258                    StringPart::Literal(self.to_node(string_node), processed_string.to_string())
1259                }
1260                swamp_script_ast::StringPart::Interpolation(expression, format_specifier) => {
1261                    let any_context = TypeContext::new_anything_argument();
1262                    let expr = self.analyze_expression(expression, &any_context)?;
1263                    let resolved_format_specifier =
1264                        self.analyze_format_specifier(Option::from(format_specifier));
1265                    StringPart::Interpolation(expr, resolved_format_specifier)
1266                }
1267            };
1268
1269            resolved_parts.push(resolved_string_part);
1270        }
1271
1272        Ok(resolved_parts)
1273    }
1274
1275    pub(crate) fn analyze_identifier(
1276        &self,
1277        qualified_func_name: &swamp_script_ast::QualifiedIdentifier,
1278    ) -> Result<Expression, Error> {
1279        // Must check variable first, since that is more intuitive for the user.
1280        // local variables before other functions
1281        if qualified_func_name.module_path.is_none()
1282            && qualified_func_name.generic_params.is_empty()
1283        {
1284            if let Some(found_variable) = self.try_find_variable(&qualified_func_name.name) {
1285                return Ok(self.create_expr(
1286                    ExpressionKind::VariableAccess(found_variable.clone()),
1287                    found_variable.resolved_type.clone(),
1288                    &qualified_func_name.name,
1289                ));
1290            }
1291        }
1292
1293        let path = self.get_module_path(qualified_func_name.module_path.as_ref());
1294        let function_name = self.get_text(&qualified_func_name.name);
1295
1296        if let Some(found_table) = self.shared.get_symbol_table(&path) {
1297            if let Some(found_func) = found_table.get_function(function_name) {
1298                let (kind, signature) = match found_func {
1299                    FuncDef::Internal(internal_fn) => (
1300                        ExpressionKind::InternalFunctionAccess(internal_fn.clone()),
1301                        &internal_fn.signature.signature,
1302                    ),
1303                    FuncDef::External(external_fn) => (
1304                        ExpressionKind::ExternalFunctionAccess(external_fn.clone()),
1305                        &external_fn.signature,
1306                    ),
1307                    // Can not have a reference to an intrinsic function
1308                    FuncDef::Intrinsic(intrinsic_fn) => (
1309                        ExpressionKind::IntrinsicFunctionAccess(intrinsic_fn.clone()),
1310                        &intrinsic_fn.signature,
1311                    ),
1312                };
1313
1314                return Ok(self.create_expr(
1315                    kind,
1316                    Type::Function(signature.clone()),
1317                    &qualified_func_name.name,
1318                ));
1319            }
1320        }
1321        Err(self.create_err(
1322            ErrorKind::UnknownIdentifier(function_name.to_string()),
1323            &qualified_func_name.name,
1324        ))
1325    }
1326
1327    // The ast assumes it is something similar to a variable, but it can be a function reference as well.
1328    fn analyze_variable_reference(
1329        &self,
1330        var_node: &swamp_script_ast::Node,
1331    ) -> Result<Expression, Error> {
1332        if let Some(found_variable) = self.try_find_variable(var_node) {
1333            return Ok(self.create_expr(
1334                ExpressionKind::VariableAccess(found_variable.clone()),
1335                found_variable.resolved_type.clone(),
1336                var_node,
1337            ));
1338        }
1339        let text = self.get_text(var_node);
1340        Err(self.create_err(ErrorKind::UnknownIdentifier(text.to_string()), var_node))
1341    }
1342
1343    fn analyze_slice_type_helper(
1344        &mut self,
1345        _node: &swamp_script_ast::Node,
1346        items: &[swamp_script_ast::Expression],
1347    ) -> Result<(Type, Vec<Expression>), Error> {
1348        let expressions = self.analyze_argument_expressions(None, items)?;
1349        let element_type = if expressions.is_empty() {
1350            Type::Unit
1351        } else {
1352            expressions[0].ty.clone()
1353        };
1354
1355        Ok((element_type, expressions))
1356    }
1357
1358    fn function_scope(&self) -> &FunctionScopeState {
1359        &self.scope
1360    }
1361
1362    fn push_block_scope(&mut self, _debug_str: &str) {
1363        self.scope.block_scope_stack.push(BlockScope {
1364            mode: BlockScopeMode::Open,
1365            variables: SeqMap::default(),
1366        });
1367    }
1368
1369    fn pop_block_scope(&mut self, _debug_str: &str) {
1370        self.scope.block_scope_stack.pop();
1371    }
1372
1373    fn push_closed_block_scope(&mut self) {
1374        self.scope.block_scope_stack.push(BlockScope {
1375            mode: BlockScopeMode::Closed,
1376            variables: SeqMap::default(),
1377        });
1378    }
1379
1380    fn pop_closed_block_scope(&mut self) {
1381        self.scope.block_scope_stack.pop();
1382    }
1383
1384    fn analyze_enum_variant_ref(
1385        &self,
1386        qualified_type_identifier: &swamp_script_ast::QualifiedTypeIdentifier,
1387        variant_name: &swamp_script_ast::LocalTypeIdentifier,
1388    ) -> Result<EnumVariantType, Error> {
1389        let variant_name_string = self.get_text(&variant_name.0).to_string();
1390        self.get_enum_variant_type(qualified_type_identifier, &variant_name_string)
1391    }
1392
1393    fn analyze_match(
1394        &mut self,
1395        scrutinee: &swamp_script_ast::MutableOrImmutableExpression,
1396        default_context: &TypeContext,
1397        arms: &Vec<swamp_script_ast::MatchArm>,
1398    ) -> Result<(Match, Type), Error> {
1399        let mut known_type = default_context.expected_type.cloned();
1400        let own_context = default_context.clone();
1401        // Analyze the scrutinee with no specific expected type
1402        let scrutinee_context = TypeContext::new_anything_argument();
1403        let resolved_scrutinee = self.analyze_mut_or_immutable_expression(
1404            scrutinee,
1405            &scrutinee_context,
1406            LocationSide::Rhs,
1407        )?;
1408        let scrutinee_type = resolved_scrutinee.ty().clone();
1409
1410        // Ensure we have at least one arm
1411        if arms.is_empty() {
1412            return Err(self.create_err(ErrorKind::EmptyMatch, &scrutinee.expression.node));
1413        }
1414
1415        let mut resolved_arms = Vec::with_capacity(arms.len());
1416
1417        for arm in arms {
1418            let (resolved_arm, _anyone_wants_mutable) = self.analyze_arm(
1419                arm,
1420                &resolved_scrutinee,
1421                &own_context.with_expected_type(known_type.as_ref()),
1422                &scrutinee_type,
1423            )?;
1424
1425            if known_type.is_none() && !matches!(resolved_arm.expression.ty, Type::Never) {
1426                known_type = Some(resolved_arm.expression.ty.clone());
1427            }
1428            resolved_arms.push(resolved_arm);
1429        }
1430
1431        known_type.map_or_else(
1432            || {
1433                Err(self.create_err(
1434                    ErrorKind::MatchArmsMustHaveTypes,
1435                    &scrutinee.expression.node,
1436                ))
1437            },
1438            |encountered_type| {
1439                if matches!(encountered_type, Type::Never) {
1440                    Err(self.create_err(
1441                        ErrorKind::IncompatibleTypes {
1442                            expected: Type::Never,
1443                            found: encountered_type,
1444                        },
1445                        &scrutinee.expression.node,
1446                    ))
1447                } else {
1448                    Ok((
1449                        Match {
1450                            expression: Box::new(resolved_scrutinee),
1451                            arms: resolved_arms,
1452                        },
1453                        encountered_type,
1454                    ))
1455                }
1456            },
1457        )
1458    }
1459
1460    fn analyze_arm(
1461        &mut self,
1462        arm: &swamp_script_ast::MatchArm,
1463        _expression: &MutOrImmutableExpression,
1464        type_context: &TypeContext,
1465        expected_condition_type: &Type,
1466    ) -> Result<(MatchArm, bool), Error> {
1467        let (resolved_pattern, scope_was_pushed, anyone_wants_mutable) =
1468            self.analyze_pattern(&arm.pattern, expected_condition_type)?;
1469
1470        let resolved_expression = self.analyze_expression(&arm.expression, type_context)?;
1471        if scope_was_pushed {
1472            self.pop_block_scope("analyze_arm");
1473        }
1474
1475        let resolved_type = resolved_expression.ty.clone();
1476
1477        Ok((
1478            MatchArm {
1479                pattern: resolved_pattern,
1480                expression: Box::from(resolved_expression),
1481                expression_type: resolved_type,
1482            },
1483            anyone_wants_mutable,
1484        ))
1485    }
1486
1487    fn str_to_int(text: &str) -> Result<i32, ParseIntError> {
1488        let text = text.replace('_', "");
1489        text.strip_prefix("0x").map_or_else(
1490            || {
1491                text.strip_prefix("-0x").map_or_else(
1492                    || text.parse::<i32>(),
1493                    |rest| i32::from_str_radix(rest, 16).map(|x| -x),
1494                )
1495            },
1496            |rest| i32::from_str_radix(rest, 16),
1497        )
1498    }
1499
1500    fn str_to_float(text: &str) -> Result<f32, ParseFloatError> {
1501        text.parse::<f32>()
1502    }
1503
1504    fn analyze_pattern_literal(
1505        &mut self,
1506        node: &swamp_script_ast::Node,
1507        ast_literal: &swamp_script_ast::LiteralKind,
1508        expected_condition_type: &Type,
1509    ) -> Result<NormalPattern, Error> {
1510        let required_condition_type_context = TypeContext::new_argument(expected_condition_type);
1511        let (literal, ty) =
1512            self.analyze_literal(node, ast_literal, &required_condition_type_context)?;
1513
1514        if !ty.compatible_with(expected_condition_type) {
1515            return Err(self.create_err(
1516                ErrorKind::IncompatibleTypes {
1517                    expected: expected_condition_type.clone(),
1518                    found: ty,
1519                },
1520                node,
1521            ));
1522        }
1523
1524        Ok(NormalPattern::Literal(literal))
1525    }
1526
1527    const fn to_node(&self, node: &swamp_script_ast::Node) -> Node {
1528        Node {
1529            span: Span {
1530                file_id: self.shared.file_id,
1531                offset: node.span.offset,
1532                length: node.span.length,
1533            },
1534        }
1535    }
1536
1537    fn get_module_path(&self, module_path: Option<&swamp_script_ast::ModulePath>) -> Vec<String> {
1538        module_path.as_ref().map_or_else(Vec::new, |found| {
1539            let mut strings = Vec::new();
1540            for path_item in &found.0 {
1541                strings.push(self.get_text(path_item).to_string());
1542            }
1543            strings
1544        })
1545    }
1546
1547    fn get_enum_variant_type(
1548        &self,
1549        qualified_type_identifier: &swamp_script_ast::QualifiedTypeIdentifier,
1550        variant_name: &str,
1551    ) -> Result<EnumVariantType, Error> {
1552        let (symbol_table, enum_name) =
1553            self.get_symbol_table_and_name(qualified_type_identifier)?;
1554        symbol_table
1555            .get_enum_variant_type(&enum_name, variant_name)
1556            .ok_or_else(|| {
1557                self.create_err(
1558                    ErrorKind::UnknownEnumVariantType,
1559                    &qualified_type_identifier.name.0,
1560                )
1561            })
1562    }
1563
1564    pub(crate) fn get_symbol_table_and_name(
1565        &self,
1566        type_identifier: &swamp_script_ast::QualifiedTypeIdentifier,
1567    ) -> Result<(&SymbolTable, String), Error> {
1568        let path = self.get_module_path(type_identifier.module_path.as_ref());
1569        let name = self.get_text(&type_identifier.name.0).to_string();
1570
1571        let maybe_symbol_table = self.shared.get_symbol_table(&path);
1572        maybe_symbol_table.map_or_else(
1573            || Err(self.create_err(ErrorKind::UnknownModule, &type_identifier.name.0)),
1574            |symbol_table| Ok((symbol_table, name)),
1575        )
1576    }
1577
1578    const fn analyze_compound_operator(
1579        &self,
1580        ast_operator: &swamp_script_ast::CompoundOperator,
1581    ) -> CompoundOperator {
1582        let resolved_node = self.to_node(&ast_operator.node);
1583        let resolved_kind = match ast_operator.kind {
1584            swamp_script_ast::CompoundOperatorKind::Add => CompoundOperatorKind::Add,
1585            swamp_script_ast::CompoundOperatorKind::Sub => CompoundOperatorKind::Sub,
1586            swamp_script_ast::CompoundOperatorKind::Mul => CompoundOperatorKind::Mul,
1587            swamp_script_ast::CompoundOperatorKind::Div => CompoundOperatorKind::Div,
1588            swamp_script_ast::CompoundOperatorKind::Modulo => CompoundOperatorKind::Modulo,
1589        };
1590
1591        CompoundOperator {
1592            node: resolved_node,
1593            kind: resolved_kind,
1594        }
1595    }
1596
1597    const fn to_node_option(&self, maybe_node: Option<&swamp_script_ast::Node>) -> Option<Node> {
1598        match maybe_node {
1599            None => None,
1600            Some(node) => Some(self.to_node(node)),
1601        }
1602    }
1603
1604    const fn analyze_format_specifier(
1605        &self,
1606        ast_format_specifier: Option<&swamp_script_ast::FormatSpecifier>,
1607    ) -> Option<FormatSpecifier> {
1608        let f = match ast_format_specifier {
1609            None => return None,
1610            Some(ast_format) => match ast_format {
1611                swamp_script_ast::FormatSpecifier::LowerHex(node) => FormatSpecifier {
1612                    node: self.to_node(node),
1613                    kind: FormatSpecifierKind::LowerHex,
1614                },
1615                swamp_script_ast::FormatSpecifier::UpperHex(node) => FormatSpecifier {
1616                    node: self.to_node(node),
1617                    kind: FormatSpecifierKind::UpperHex,
1618                },
1619                swamp_script_ast::FormatSpecifier::Binary(node) => FormatSpecifier {
1620                    node: self.to_node(node),
1621                    kind: FormatSpecifierKind::Binary,
1622                },
1623                swamp_script_ast::FormatSpecifier::Float(node) => FormatSpecifier {
1624                    node: self.to_node(node),
1625                    kind: FormatSpecifierKind::Float,
1626                },
1627                swamp_script_ast::FormatSpecifier::Precision(value, node, x) => {
1628                    let (precision_type, precision_node) = match x {
1629                        swamp_script_ast::PrecisionType::Float(node) => {
1630                            (PrecisionType::Float, self.to_node(node))
1631                        }
1632                        swamp_script_ast::PrecisionType::String(node) => {
1633                            (PrecisionType::String, self.to_node(node))
1634                        }
1635                    };
1636                    FormatSpecifier {
1637                        node: self.to_node(node),
1638                        kind: FormatSpecifierKind::Precision(
1639                            *value,
1640                            precision_node,
1641                            precision_type,
1642                        ),
1643                    }
1644                }
1645            },
1646        };
1647
1648        Some(f)
1649    }
1650
1651    fn analyze_with_expr(
1652        &mut self,
1653        context: &TypeContext,
1654        variables: &[swamp_script_ast::VariableBinding],
1655        expression: &swamp_script_ast::Expression,
1656    ) -> Result<Expression, Error> {
1657        let mut variable_expressions = Vec::new();
1658
1659        for variable in variables {
1660            let any_context = TypeContext::new_anything_argument();
1661            let var = self.analyze_mut_or_immutable_expression(
1662                &variable.expression,
1663                &any_context,
1664                LocationSide::Rhs,
1665            )?;
1666
1667            variable_expressions.push(var);
1668        }
1669
1670        self.push_closed_block_scope();
1671        let mut expressions = Vec::new();
1672        for (variable_binding, resolved_expression) in variables.iter().zip(variable_expressions) {
1673            let initialize_variable_expression = self.create_variable_binding_for_with(
1674                &variable_binding.variable,
1675                resolved_expression,
1676            )?;
1677            expressions.push(initialize_variable_expression);
1678        }
1679
1680        let resolved_expression = self.analyze_expression(expression, context)?;
1681        let block_type = resolved_expression.ty.clone();
1682        expressions.push(resolved_expression);
1683
1684        let block_expression_kind = ExpressionKind::Block(expressions);
1685        self.pop_closed_block_scope();
1686
1687        let block_expr = self.create_expr(block_expression_kind, block_type, &expression.node);
1688        Ok(block_expr)
1689    }
1690
1691    fn analyze_when_expr(
1692        &mut self,
1693        context: &TypeContext,
1694        variables: &[swamp_script_ast::WhenBinding],
1695        true_expr: &swamp_script_ast::Expression,
1696        else_expr: Option<&swamp_script_ast::Expression>,
1697    ) -> Result<Expression, Error> {
1698        // Since we are making new variable bindings, we have to push a scope for them
1699        self.push_block_scope("when");
1700        let mut bindings = Vec::new();
1701        for variable_binding in variables {
1702            let mut_expr = if let Some(found_expr) = &variable_binding.expression {
1703                let any_context = TypeContext::new_anything_argument();
1704                self.analyze_mut_or_immutable_expression(
1705                    found_expr,
1706                    &any_context,
1707                    LocationSide::Rhs,
1708                )?
1709            } else {
1710                let same_var = self.find_variable(&variable_binding.variable)?;
1711
1712                let is_mutable = same_var.mutable_node.clone();
1713                let argument_expression = if same_var.is_mutable() {
1714                    let loc = SingleLocationExpression {
1715                        kind: SingleLocationExpressionKind::MutVariableRef,
1716                        node: self.to_node(&variable_binding.variable.name),
1717                        ty: Type::MutableReference(Box::from(same_var.resolved_type.clone())),
1718                        starting_variable: same_var,
1719                        access_chain: vec![],
1720                    };
1721                    ArgumentExpressionOrLocation::Location(loc)
1722                } else {
1723                    let generated_expr_kind = ExpressionKind::VariableAccess(same_var.clone());
1724                    let generated_expression = self.create_expr(
1725                        generated_expr_kind,
1726                        same_var.resolved_type.clone(),
1727                        &variable_binding.variable.name,
1728                    );
1729                    ArgumentExpressionOrLocation::Expression(generated_expression)
1730                };
1731
1732                MutOrImmutableExpression {
1733                    expression_or_location: argument_expression,
1734                    is_mutable,
1735                }
1736            };
1737
1738            let ty = mut_expr.ty();
1739
1740            if let Type::Optional(found_ty) = ty {
1741                let variable_ref = self.create_variable(&variable_binding.variable, found_ty)?;
1742
1743                let binding = WhenBinding {
1744                    variable: variable_ref,
1745                    expr: mut_expr,
1746                };
1747                bindings.push(binding);
1748            } else {
1749                return Err(self.create_err(ErrorKind::ExpectedOptional, &true_expr.node));
1750            }
1751        }
1752
1753        let resolved_true = self.analyze_expression(true_expr, context)?;
1754        let block_type = resolved_true.ty.clone();
1755
1756        self.pop_block_scope("when");
1757
1758        let maybe_resolved_else = if let Some(found_else) = else_expr {
1759            let block_type_for_true_context = context.we_know_expected_type(&block_type);
1760            Some(Box::new(self.analyze_expression(
1761                found_else,
1762                &block_type_for_true_context,
1763            )?))
1764        } else {
1765            None
1766        };
1767
1768        let when_kind =
1769            ExpressionKind::When(bindings, Box::from(resolved_true), maybe_resolved_else);
1770
1771        let block_expr = self.create_expr(when_kind, block_type, &true_expr.node);
1772        Ok(block_expr)
1773    }
1774
1775    fn analyze_guard(
1776        &mut self,
1777        node: &swamp_script_ast::Node,
1778        context: &TypeContext,
1779        guard_expressions: &Vec<swamp_script_ast::GuardExpr>,
1780    ) -> Result<Expression, Error> {
1781        let mut guards = Vec::new();
1782        let mut found_wildcard = None;
1783        let mut detected_type = context.expected_type.cloned();
1784
1785        for guard in guard_expressions {
1786            let resolved_condition = match &guard.clause {
1787                swamp_script_ast::GuardClause::Wildcard(x) => {
1788                    if found_wildcard.is_some() {
1789                        return Err(
1790                            self.create_err(ErrorKind::GuardCanNotHaveMultipleWildcards, node)
1791                        );
1792                    }
1793                    found_wildcard = Some(x);
1794                    None
1795                }
1796                swamp_script_ast::GuardClause::Expression(clause_expr) => {
1797                    if found_wildcard.is_some() {
1798                        return Err(self.create_err(ErrorKind::WildcardMustBeLastInGuard, node));
1799                    }
1800                    Some(self.analyze_bool_argument_expression(clause_expr)?)
1801                }
1802            };
1803
1804            let resolved_result = self.analyze_expression(
1805                &guard.result,
1806                &context.with_expected_type(detected_type.as_ref()),
1807            )?;
1808            let ty = resolved_result.ty.clone();
1809            if detected_type.is_none() && !matches!(ty, Type::Never) {
1810                detected_type = Some(ty.clone());
1811            }
1812
1813            guards.push(Guard {
1814                condition: resolved_condition,
1815                result: resolved_result,
1816            });
1817        }
1818
1819        if found_wildcard.is_none() {
1820            return Err(self.create_err(ErrorKind::GuardMustHaveWildcard, node));
1821        }
1822
1823        let kind = ExpressionKind::Guard(guards);
1824
1825        detected_type.map_or_else(
1826            || Err(self.create_err(ErrorKind::GuardHasNoType, node)),
1827            |found_expecting_type| {
1828                let expr = self.create_expr(kind, found_expecting_type, node);
1829                Ok(expr)
1830            },
1831        )
1832    }
1833
1834    fn analyze_lambda(
1835        &mut self,
1836        node: &swamp_script_ast::Node,
1837        variables: &[swamp_script_ast::Variable],
1838        ast_expr: &swamp_script_ast::Expression,
1839        context: &TypeContext,
1840    ) -> Result<Expression, Error> {
1841        let Type::Function(signature) = &context.expected_type.unwrap() else {
1842            return Err(self.create_err(ErrorKind::ExpectedLambda, node));
1843        };
1844        info!(?signature, "LAMBDA SIGN");
1845
1846        let return_block_type = TypeContext::new_argument(&signature.return_type);
1847
1848        self.push_block_scope("lambda");
1849
1850        let arity_required = signature.parameters.len();
1851        let variable_types_to_create = if variables.len() == arity_required {
1852            &signature.parameters
1853        } else if variables.len() + 1 == arity_required {
1854            &signature.parameters[1..].to_vec()
1855        } else {
1856            return Err(self.create_err(ErrorKind::WrongNumberOfArguments(0, 0), node));
1857        };
1858
1859        let mut resolved_variables = Vec::new();
1860        for (variable, variable_type) in variables.iter().zip(variable_types_to_create) {
1861            let variable_ref = self.create_local_variable(
1862                &variable.name,
1863                Some(node),
1864                &variable_type.resolved_type,
1865            )?;
1866            info!(?variable_ref, ?variable_type.resolved_type, "variable type");
1867            resolved_variables.push(variable_ref);
1868        }
1869
1870        info!(scope =%self.scope, "scopes");
1871
1872        let analyzed_expression = self.analyze_expression(ast_expr, &return_block_type)?;
1873
1874        self.pop_block_scope("lambda");
1875
1876        Ok(self.create_expr(
1877            ExpressionKind::Lambda(resolved_variables, Box::new(analyzed_expression)),
1878            Type::Function(signature.clone()),
1879            node,
1880        ))
1881    }
1882
1883    /// # Errors
1884    ///
1885    pub fn analyze_variable_assignment(
1886        &mut self,
1887        variable: &swamp_script_ast::Variable,
1888        source_expression: &swamp_script_ast::MutableOrImmutableExpression,
1889    ) -> Result<Expression, Error> {
1890        let maybe_found_variable = self.try_find_variable(&variable.name);
1891
1892        let required_type = maybe_found_variable
1893            .as_ref()
1894            .map(|found_variable| found_variable.resolved_type.clone());
1895
1896        let context = TypeContext::new_unsure_argument(required_type.as_ref());
1897
1898        let source_expr = self.analyze_mut_or_immutable_expression(
1899            source_expression,
1900            &context,
1901            LocationSide::Rhs,
1902        )?;
1903        let ty = source_expr.ty().clone();
1904        if !ty.is_concrete() {
1905            return Err(self.create_err(ErrorKind::VariableTypeMustBeConcrete, &variable.name));
1906        }
1907
1908        let kind: ExpressionKind = if let Some(found_var) = maybe_found_variable {
1909            if !found_var.is_mutable() {
1910                return Err(self.create_err(ErrorKind::VariableIsNotMutable, &variable.name));
1911            }
1912            if !found_var.resolved_type.assignable_type(&ty) {
1913                return Err(self.create_err(
1914                    ErrorKind::IncompatibleTypes {
1915                        expected: ty,
1916                        found: found_var.resolved_type.clone(),
1917                    },
1918                    &variable.name,
1919                ));
1920            }
1921            ExpressionKind::VariableReassignment(found_var, Box::from(source_expr))
1922        } else {
1923            let new_var = self.create_variable(variable, &ty)?;
1924            ExpressionKind::VariableDefinition(new_var, Box::from(source_expr))
1925        };
1926
1927        Ok(self.create_expr(kind, Type::Unit, &variable.name))
1928    }
1929
1930    fn analyze_create_variable(
1931        &mut self,
1932        var: &swamp_script_ast::Variable,
1933        annotation_type: Option<&swamp_script_ast::Type>,
1934        source_expression: &swamp_script_ast::MutableOrImmutableExpression,
1935    ) -> Result<Expression, Error> {
1936        let ty = if let Some(found_ast_type) = annotation_type {
1937            Some(self.analyze_type(found_ast_type)?)
1938        } else {
1939            None
1940        };
1941
1942        let unsure_arg_context = TypeContext::new_unsure_argument(ty.as_ref());
1943
1944        let resolved_source = self.analyze_mut_or_immutable_expression(
1945            source_expression,
1946            &unsure_arg_context,
1947            LocationSide::Rhs,
1948        )?;
1949
1950        let var_ref = self.create_local_variable(
1951            &var.name,
1952            Option::from(&var.is_mutable),
1953            resolved_source.ty(),
1954        )?;
1955
1956        let resolved_type = resolved_source.ty().clone();
1957        assert_ne!(resolved_type, Type::Unit);
1958        let kind = ExpressionKind::VariableDefinition(var_ref, Box::from(resolved_source));
1959
1960        let resolved_expr = self.create_expr(kind, Type::Unit, &var.name);
1961
1962        Ok(resolved_expr)
1963    }
1964
1965    fn add_location_item(
1966        &mut self,
1967        vec: &mut Vec<LocationAccess>,
1968        kind: LocationAccessKind,
1969        ty: Type,
1970        ast_node: &swamp_script_ast::Node,
1971    ) {
1972        let resolved_node = self.to_node(ast_node);
1973        let postfix = LocationAccess {
1974            node: resolved_node.clone(),
1975            ty,
1976            kind,
1977        };
1978
1979        vec.push(postfix);
1980    }
1981
1982    fn extract_single_intrinsic_call(body: &Expression) -> Option<IntrinsicFunction> {
1983        match &body.kind {
1984            ExpressionKind::Block(expressions) => {
1985                let first_kind = &expressions[0].kind;
1986                if let ExpressionKind::IntrinsicCallEx(intrinsic_fn, _args) = first_kind {
1987                    return Some(intrinsic_fn.clone());
1988                }
1989            }
1990            _ => {}
1991        }
1992        None
1993    }
1994
1995    #[allow(clippy::too_many_lines)]
1996    fn analyze_chain_to_location(
1997        &mut self,
1998        chain: &swamp_script_ast::PostfixChain,
1999        context: &TypeContext,
2000        location_side: LocationSide,
2001    ) -> Result<SingleLocationExpression, Error> {
2002        let mut items = Vec::new();
2003
2004        let nothing_context = TypeContext::new(None);
2005
2006        let base_expr = self.analyze_expression(&chain.base, &nothing_context)?;
2007        let ExpressionKind::VariableAccess(start_variable) = base_expr.kind else {
2008            return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &chain.base.node));
2009        };
2010
2011        if !start_variable.is_mutable() {
2012            return Err(self.create_err(ErrorKind::VariableIsNotMutable, &chain.base.node));
2013        }
2014
2015        let mut ty = start_variable.resolved_type.clone();
2016        for (i, item) in chain.postfixes.iter().enumerate() {
2017            match &item {
2018                swamp_script_ast::Postfix::FieldAccess(field_name_node) => {
2019                    //let field_name_resolved = self.to_node(field_name_node)
2020                    let (struct_type_ref, index, return_type) =
2021                        self.analyze_struct_field(field_name_node, ty)?;
2022                    self.add_location_item(
2023                        &mut items,
2024                        LocationAccessKind::FieldIndex(struct_type_ref.clone(), index),
2025                        return_type.clone(),
2026                        field_name_node,
2027                    );
2028
2029                    ty = return_type.clone();
2030                }
2031                swamp_script_ast::Postfix::Subscript(key_expression) => {
2032                    let is_last_in_chain = i == chain.postfixes.len() - 1;
2033                    let create_if_not_exists =
2034                        is_last_in_chain && location_side == LocationSide::Lhs;
2035
2036                    let subscript_member_function_name = if create_if_not_exists {
2037                        "subscript_mut_create_if_needed"
2038                    } else {
2039                        "subscript_mut"
2040                    };
2041
2042                    if let Some(found) = self
2043                        .shared
2044                        .state
2045                        .instantiator
2046                        .associated_impls
2047                        .get_internal_member_function(&ty, subscript_member_function_name)
2048                        .cloned()
2049                    {
2050                        let intrinsic_to_call =
2051                            Self::extract_single_intrinsic_call(&found.body).expect("must exist");
2052
2053                        let create_if_not_exists_bool_expr = self.create_expr(
2054                            ExpressionKind::Literal(Literal::BoolLiteral(create_if_not_exists)),
2055                            Type::Bool,
2056                            &chain.base.node,
2057                        );
2058
2059                        let required_type = &found.signature.signature.parameters[1].resolved_type;
2060                        let subscript_lookup_context = TypeContext::new_argument(required_type);
2061                        let analyzed_key_expression =
2062                            self.analyze_expression(key_expression, &subscript_lookup_context)?;
2063                        let return_type = *found.signature.signature.return_type.clone();
2064                        ty = return_type.clone();
2065                        //let argument = ArgumentExpressionOrLocation::Expression(analyzed_expr);
2066                        self.add_location_item(
2067                            &mut items,
2068                            LocationAccessKind::IntrinsicCallMut(
2069                                intrinsic_to_call,
2070                                vec![analyzed_key_expression, create_if_not_exists_bool_expr],
2071                            ),
2072                            return_type,
2073                            &key_expression.node,
2074                        );
2075                    } else {
2076                        return Err(self
2077                            .create_err(ErrorKind::MissingSubscriptMember, &key_expression.node));
2078                    }
2079                }
2080
2081                swamp_script_ast::Postfix::MemberCall(node, _) => {
2082                    return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2083                }
2084
2085                swamp_script_ast::Postfix::FunctionCall(node, _) => {
2086                    return Err(self.create_err(ErrorKind::CallsCanNotBePartOfChain, node));
2087                }
2088                swamp_script_ast::Postfix::OptionalChainingOperator(node) => {
2089                    return Err(self.create_err(ErrorKind::UnwrapCanNotBePartOfChain, node));
2090                }
2091                swamp_script_ast::Postfix::NoneCoalescingOperator(expr) => {
2092                    return Err(
2093                        self.create_err(ErrorKind::NoneCoalesceCanNotBePartOfChain, &expr.node)
2094                    );
2095                }
2096            }
2097        }
2098
2099        if let Some(found_expected_type) = context.expected_type {
2100            if !ty.compatible_with(found_expected_type) {
2101                return Err(self.create_err(
2102                    ErrorKind::IncompatibleTypes {
2103                        expected: found_expected_type.clone(),
2104                        found: ty,
2105                    },
2106                    &chain.base.node,
2107                ));
2108            }
2109        }
2110
2111        let location = SingleLocationExpression {
2112            kind: SingleLocationExpressionKind::MutVariableRef,
2113            node: self.to_node(&chain.base.node),
2114            ty,
2115            starting_variable: start_variable,
2116            access_chain: items,
2117        };
2118        Ok(location)
2119    }
2120
2121    fn analyze_to_location(
2122        &mut self,
2123        expr: &swamp_script_ast::Expression,
2124        context: &TypeContext,
2125        location_type: LocationSide,
2126    ) -> Result<SingleLocationExpression, Error> {
2127        match &expr.kind {
2128            swamp_script_ast::ExpressionKind::PostfixChain(chain) => {
2129                self.analyze_chain_to_location(chain, context, location_type)
2130            }
2131            swamp_script_ast::ExpressionKind::VariableReference(variable) => {
2132                let var = self.find_variable(variable)?;
2133                if var.is_mutable() {
2134                    Ok(SingleLocationExpression {
2135                        kind: SingleLocationExpressionKind::MutVariableRef,
2136                        node: self.to_node(&variable.name),
2137                        ty: Type::MutableReference(Box::from(var.resolved_type.clone())),
2138                        starting_variable: var,
2139                        access_chain: vec![],
2140                    })
2141                } else {
2142                    Err(self.create_err(ErrorKind::VariableIsNotMutable, &expr.node))
2143                }
2144            }
2145            swamp_script_ast::ExpressionKind::IdentifierReference(qualified_identifier) => {
2146                let generated_var = swamp_script_ast::Variable {
2147                    name: qualified_identifier.name.clone(),
2148                    is_mutable: None,
2149                };
2150                let var = self.find_variable(&generated_var)?;
2151                if var.is_mutable() {
2152                    Ok(SingleLocationExpression {
2153                        kind: SingleLocationExpressionKind::MutVariableRef,
2154                        node: self.to_node(&generated_var.name),
2155                        ty: Type::MutableReference(Box::from(var.resolved_type.clone())),
2156                        starting_variable: var,
2157                        access_chain: vec![],
2158                    })
2159                } else {
2160                    Err(self.create_err(ErrorKind::VariableIsNotMutable, &expr.node))
2161                }
2162            }
2163            _ => {
2164                error!(?expr.kind, "error");
2165                Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, &expr.node))
2166            }
2167        }
2168    }
2169
2170    fn analyze_assignment_compound(
2171        &mut self,
2172        target_expression: &swamp_script_ast::Expression,
2173        ast_op: &swamp_script_ast::CompoundOperator,
2174        ast_source_expression: &swamp_script_ast::Expression,
2175    ) -> Result<Expression, Error> {
2176        let resolved_op = self.analyze_compound_operator(ast_op);
2177        let any_argument_context = TypeContext::new_anything_argument();
2178        let source_expr = self.analyze_expression(ast_source_expression, &any_argument_context)?;
2179        let source_expr_type_context = TypeContext::new_argument(&source_expr.ty);
2180
2181        let resolved_location = SingleMutLocationExpression(self.analyze_to_location(
2182            target_expression,
2183            &source_expr_type_context,
2184            LocationSide::Rhs,
2185        )?);
2186
2187        let kind = ExpressionKind::CompoundAssignment(
2188            resolved_location,
2189            resolved_op.kind,
2190            Box::from(source_expr),
2191        );
2192
2193        let expr = self.create_expr(kind, Type::Unit, &target_expression.node);
2194
2195        Ok(expr)
2196    }
2197
2198    fn analyze_assignment(
2199        &mut self,
2200        target_location: &swamp_script_ast::Expression,
2201        ast_source_expression: &swamp_script_ast::Expression,
2202    ) -> Result<Expression, Error> {
2203        let any_argument_context = TypeContext::new_anything_argument();
2204        let resolved_location =
2205            self.analyze_to_location(target_location, &any_argument_context, LocationSide::Lhs)?;
2206
2207        let ty = resolved_location.ty.clone();
2208        if ty == Type::Unit {
2209            error!(?ast_source_expression, "unit problem");
2210        }
2211
2212        let lhs_argument_context = TypeContext::new_argument(&ty);
2213        let source_expr = self.analyze_expression(ast_source_expression, &lhs_argument_context)?;
2214
2215        let mut_location = SingleMutLocationExpression(resolved_location);
2216
2217        let kind = ExpressionKind::Assignment(Box::from(mut_location), Box::from(source_expr));
2218
2219        let expr = self.create_expr(kind, Type::Unit, &target_location.node); // Assignments are always of type Unit
2220
2221        Ok(expr)
2222    }
2223
2224    #[must_use]
2225    pub const fn create_expr(
2226        &self,
2227        kind: ExpressionKind,
2228        ty: Type,
2229        ast_node: &swamp_script_ast::Node,
2230    ) -> Expression {
2231        //info!(%ty, ?kind, "create_expr()");
2232        Expression {
2233            kind,
2234            ty,
2235            node: self.to_node(ast_node),
2236        }
2237    }
2238
2239    #[must_use]
2240    pub fn create_expr_resolved(
2241        &self,
2242        kind: ExpressionKind,
2243        ty: Type,
2244        ast_node: &Node,
2245    ) -> Expression {
2246        Expression {
2247            kind,
2248            ty,
2249            node: ast_node.clone(),
2250        }
2251    }
2252
2253    fn analyze_destructuring(
2254        &mut self,
2255        node: &swamp_script_ast::Node,
2256        target_ast_variables: &[swamp_script_ast::Variable],
2257        tuple_expression: &swamp_script_ast::Expression,
2258    ) -> Result<Expression, Error> {
2259        let any_context = TypeContext::new_anything_argument();
2260        let tuple_resolved = self.analyze_expression(tuple_expression, &any_context)?;
2261        let tuple_expr_type = &tuple_resolved.ty;
2262
2263        let mut variable_refs = Vec::new();
2264        if let Type::Tuple(tuple) = tuple_expr_type.clone() {
2265            if target_ast_variables.len() > tuple.len() {
2266                return Err(self.create_err(ErrorKind::TooManyDestructureVariables, node));
2267            }
2268            for (ast_variable, tuple_type) in target_ast_variables.iter().zip(tuple.clone()) {
2269                let variable_ref = self.create_local_variable(
2270                    &ast_variable.name,
2271                    ast_variable.is_mutable.as_ref(),
2272                    &tuple_type,
2273                )?;
2274                variable_refs.push(variable_ref);
2275            }
2276            let expr_kind =
2277                ExpressionKind::TupleDestructuring(variable_refs, tuple, Box::from(tuple_resolved));
2278
2279            Ok(self.create_expr(expr_kind, Type::Unit, node))
2280        } else {
2281            Err(self.create_err(ErrorKind::CanNotDestructure, node))
2282        }
2283    }
2284
2285    fn analyze_postfix_member_func_call(
2286        &mut self,
2287        resolved_node: &Node,
2288        found_function: &FunctionRef,
2289        encountered_self_type: &Type,
2290        is_mutable: bool,
2291        arguments: &[swamp_script_ast::MutableOrImmutableExpression],
2292    ) -> Result<Postfix, Error> {
2293        let signature = found_function.signature();
2294
2295        let self_type = &signature.parameters[0];
2296        if !self_type
2297            .resolved_type
2298            .compatible_with(encountered_self_type)
2299            || self_type.is_mutable && !is_mutable
2300        {
2301            return Err(self.create_err_resolved(ErrorKind::SelfNotCorrectType, resolved_node));
2302        }
2303
2304        let resolved_arguments = self.analyze_and_verify_parameters(
2305            resolved_node,
2306            &signature.parameters[1..],
2307            arguments,
2308        )?;
2309
2310        let kind = PostfixKind::MemberCall(found_function.clone(), resolved_arguments);
2311
2312        let postfix = Postfix {
2313            node: resolved_node.clone(),
2314            ty: *signature.return_type.clone(),
2315            kind,
2316        };
2317
2318        Ok(postfix)
2319    }
2320
2321    fn analyze_postfix_member_call(
2322        &mut self,
2323        type_that_member_is_on: &Type,
2324        is_mutable: bool,
2325        member_name: &swamp_script_ast::Node,
2326        arguments: &[swamp_script_ast::MutableOrImmutableExpression],
2327        suffixes: &mut Vec<Postfix>,
2328    ) -> Result<Type, Error> {
2329        let field_name_str = self.get_text(member_name).to_string();
2330
2331        let resolved_node = self.to_node(member_name);
2332
2333        let maybe_function = self
2334            .shared
2335            .state
2336            .instantiator
2337            .associated_impls
2338            .get_member_function(type_that_member_is_on, &field_name_str)
2339            .cloned();
2340
2341        let postfixes = match maybe_function {
2342            Some(found_function_member) => {
2343                let postfix = self.analyze_postfix_member_func_call(
2344                    &resolved_node,
2345                    &found_function_member,
2346                    type_that_member_is_on,
2347                    is_mutable,
2348                    arguments,
2349                )?;
2350                vec![postfix]
2351            }
2352            _ => {
2353                return Err(self.create_err(ErrorKind::NotValidLocationStartingPoint, member_name));
2354            } // TODO: Support function calls
2355        };
2356
2357        let last_type = postfixes.last().unwrap().ty.clone();
2358        suffixes.extend(postfixes);
2359
2360        Ok(last_type)
2361    }
2362
2363    fn types_did_not_match_try_late_coerce_expression(
2364        &self,
2365        expr: Expression,
2366        expected_type: &Type,
2367        encountered_type: &Type,
2368        node: &swamp_script_ast::Node,
2369    ) -> Result<Expression, Error> {
2370        if let Type::Optional(expected_inner_type) = expected_type {
2371            // If an optional is expected, we can wrap it if this type has the exact same
2372            // inner type
2373            assert!(
2374                expected_inner_type
2375                    .inner_optional_mut_or_immutable()
2376                    .is_none()
2377            );
2378
2379            // First make sure it is not already an optional type. we can not wrap an option with an option
2380            if encountered_type.inner_optional_mut_or_immutable().is_none() {
2381                // good it isn't, lets see if they share inner types
2382                if expected_inner_type.compatible_ignore_mutability_of(encountered_type) {
2383                    // they share inner types as well, lets wrap it up
2384                    let wrapped = self.create_expr(
2385                        ExpressionKind::Option(Option::from(Box::new(expr))),
2386                        expected_type.clone(),
2387                        node,
2388                    );
2389                    return Ok(wrapped);
2390                }
2391            }
2392        } else if matches!(expected_type, &Type::Bool) {
2393            // if it has a mut or immutable optional, then it works well to wrap it
2394            if encountered_type.inner_optional_mut_or_immutable().is_some() {
2395                let wrapped = self.create_expr(
2396                    ExpressionKind::CoerceOptionToBool(Box::from(expr)),
2397                    Type::Bool,
2398                    node,
2399                );
2400                return Ok(wrapped);
2401            }
2402        }
2403
2404        error!(?expected_type, ?encountered_type, "incompatible types");
2405        Err(self.create_err(
2406            ErrorKind::IncompatibleTypes {
2407                expected: expected_type.clone(),
2408                found: encountered_type.clone(),
2409            },
2410            &node,
2411        ))
2412    }
2413
2414    #[allow(clippy::too_many_lines)]
2415    fn analyze_generic_type(
2416        &mut self,
2417        symbol: &Symbol,
2418        analyzed_type_parameters: &[Type],
2419        node: &swamp_script_ast::Node,
2420    ) -> Result<Type, Error> {
2421        let ty = match symbol {
2422            //            Symbol::Type(base_type) => base_type.clone(),
2423            //          Symbol::Alias(alias_type) => alias_type.referenced_type.clone(),
2424            Symbol::Blueprint(blueprint) => {
2425                if all_types_are_concrete_or_unit(analyzed_type_parameters) {
2426                    self.shared
2427                        .state
2428                        .instantiator
2429                        .instantiate_blueprint_and_members(blueprint, analyzed_type_parameters)?
2430                } else {
2431                    Type::Generic(blueprint.clone(), analyzed_type_parameters.to_vec())
2432                }
2433            }
2434            Symbol::TypeGenerator(type_gen) => match type_gen.kind {
2435                TypeGeneratorKind::Slice => {
2436                    //assert!(analyzed_type_parameters[0].is_concrete());
2437                    Type::Slice(Box::new(analyzed_type_parameters[0].clone()))
2438                }
2439                TypeGeneratorKind::SlicePair => {
2440                    //assert!(analyzed_type_parameters[0].is_concrete());
2441                    //assert!(analyzed_type_parameters[1].is_concrete());
2442                    Type::SlicePair(
2443                        Box::new(analyzed_type_parameters[0].clone()),
2444                        Box::new(analyzed_type_parameters[1].clone()),
2445                    )
2446                }
2447            },
2448            _ => return Err(self.create_err(ErrorKind::UnknownSymbol, node)),
2449        };
2450
2451        Ok(ty)
2452    }
2453}