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