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