swamp_script_analyzer/
lib.rs

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