swamp_script_analyzer/
lib.rs

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