swamp_script_analyzer/
lib.rs

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