swamp_script_analyzer/
def.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 */
5
6use crate::Analyzer;
7use crate::err::{Error, ErrorKind};
8use seq_map::SeqMap;
9use std::rc::Rc;
10use swamp_script_semantic::{
11    ExternalFunctionDefinition, Function, InternalFunctionDefinition, LocalIdentifier,
12    SemanticError, UseItem,
13};
14use swamp_script_types::prelude::*;
15use swamp_script_types::{
16    GenericAwareSignature, ParameterizedTypeBlueprint, ParameterizedTypeKind,
17};
18
19impl Analyzer<'_> {
20    fn general_import(
21        &mut self,
22        path: &[String],
23        import_items: &swamp_script_ast::ImportItems,
24        node: &swamp_script_ast::Node,
25    ) -> Result<(), Error> {
26        let found_module = self
27            .shared
28            .get_module(path)
29            .ok_or_else(|| self.create_err(ErrorKind::UnknownModule, node))?
30            .clone();
31
32        match import_items {
33            swamp_script_ast::ImportItems::Nothing => {
34                let last_name = path.last().unwrap();
35                if self
36                    .shared
37                    .lookup_table
38                    .get_module_link(last_name)
39                    .is_none()
40                {
41                    self.shared
42                        .lookup_table
43                        .add_module_link(last_name, found_module.clone())
44                        .map_err(|err| self.create_err(ErrorKind::SemanticError(err), node))?;
45                }
46            }
47            swamp_script_ast::ImportItems::Items(items) => {
48                for ast_items in items {
49                    match ast_items {
50                        swamp_script_ast::ImportItem::Identifier(node) => {
51                            let ident_resolved_node = self.to_node(&node.0);
52                            let ident = UseItem::Identifier(ident_resolved_node.clone());
53                            let ident_text =
54                                self.get_text_resolved(&ident_resolved_node).to_string();
55                            if let Some(found_symbol) =
56                                found_module.symbol_table.get_symbol(&ident_text)
57                            {
58                                self.shared
59                                    .lookup_table
60                                    .add_symbol(&ident_text, found_symbol.clone())
61                                    .map_err(|err| {
62                                        self.create_err(ErrorKind::SemanticError(err), &node.0)
63                                    })?;
64                            } else {
65                                return Err(self.create_err_resolved(
66                                    ErrorKind::UnknownTypeReference,
67                                    &ident_resolved_node,
68                                ));
69                            }
70                            ident
71                        }
72                        swamp_script_ast::ImportItem::Type(node) => {
73                            let ident_resolved_node = self.to_node(&node.0);
74                            let ident_text =
75                                self.get_text_resolved(&ident_resolved_node).to_string();
76                            if let Some(found_symbol) =
77                                found_module.symbol_table.get_symbol(&ident_text)
78                            {
79                                self.shared
80                                    .lookup_table
81                                    .add_symbol(&ident_text, found_symbol.clone())
82                                    .map_err(|err| {
83                                        self.create_err(ErrorKind::SemanticError(err), &node.0)
84                                    })?;
85                            } else {
86                                return Err(self.create_err_resolved(
87                                    ErrorKind::UnknownTypeReference,
88                                    &ident_resolved_node,
89                                ));
90                            }
91                            UseItem::TypeIdentifier(self.to_node(&node.0))
92                        }
93                    };
94                }
95            }
96            swamp_script_ast::ImportItems::All => {
97                self.shared
98                    .lookup_table
99                    .extend_from(&found_module.symbol_table)?;
100            }
101        }
102
103        Ok(())
104    }
105
106    fn analyze_mod_definition(
107        &mut self,
108        mod_definition: &swamp_script_ast::Mod,
109    ) -> Result<(), Error> {
110        let mut path = Vec::new();
111        for ast_node in &mod_definition.module_path.0 {
112            path.push(self.get_text(ast_node).to_string());
113        }
114
115        let mut nodes_copy = path.clone();
116        nodes_copy.insert(0, "crate".to_string());
117
118        self.general_import(
119            &nodes_copy,
120            &mod_definition.items,
121            &mod_definition.module_path.0[0],
122        )
123    }
124
125    fn analyze_use_definition(
126        &mut self,
127        use_definition: &swamp_script_ast::Use,
128    ) -> Result<(), Error> {
129        let mut nodes = Vec::new();
130        for ast_node in &use_definition.module_path.0 {
131            nodes.push(self.to_node(ast_node));
132        }
133
134        let path: Vec<String> = nodes
135            .iter()
136            .map(|node| {
137                let text = self.get_text_resolved(node);
138                text.to_string()
139            })
140            .collect();
141
142        self.general_import(
143            &path,
144            &use_definition.items,
145            &use_definition.module_path.0[0],
146        )
147    }
148
149    fn analyze_enum_type_definition(
150        &mut self,
151        enum_type_name: &swamp_script_ast::LocalTypeIdentifierWithOptionalTypeVariables,
152        ast_variants: &[swamp_script_ast::EnumVariantType],
153    ) -> Result<(), Error> {
154        let mut resolved_variants = SeqMap::new();
155
156        let mut new_enum_type = EnumType {
157            name: self.to_node(&enum_type_name.name),
158            assigned_name: self.get_text(&enum_type_name.name).to_string(),
159            module_path: vec![],
160            variants: SeqMap::default(),
161            instantiated_type_parameters: Vec::default(),
162        };
163
164        for (container_index_usize, ast_variant_type) in ast_variants.iter().enumerate() {
165            let variant_name_node = match ast_variant_type {
166                swamp_script_ast::EnumVariantType::Simple(name) => name,
167                swamp_script_ast::EnumVariantType::Tuple(name, _) => name,
168                swamp_script_ast::EnumVariantType::Struct(name, _) => name,
169            };
170
171            let common = EnumVariantCommon {
172                name: self.to_node(variant_name_node),
173                assigned_name: self.get_text(variant_name_node).to_string(),
174                container_index: container_index_usize as u8,
175            };
176
177            let variant_type = match ast_variant_type {
178                swamp_script_ast::EnumVariantType::Simple(_variant_name_node) => {
179                    let simple_ref = EnumVariantSimpleType { common };
180                    EnumVariantType::Nothing(EnumVariantSimpleType::from(simple_ref))
181                }
182                swamp_script_ast::EnumVariantType::Tuple(_variant_name_node, types) => {
183                    let mut vec = Vec::new();
184                    for tuple_type in types {
185                        let resolved_type = self.analyze_type(tuple_type)?;
186                        vec.push(resolved_type);
187                    }
188
189                    let resolved_tuple_type = EnumVariantTupleType {
190                        common,
191                        fields_in_order: vec,
192                    };
193
194                    EnumVariantType::Tuple(resolved_tuple_type)
195                }
196                swamp_script_ast::EnumVariantType::Struct(
197                    _variant_name_node,
198                    ast_struct_fields,
199                ) => {
200                    let mut fields = SeqMap::new();
201
202                    for field_with_type in &ast_struct_fields.fields {
203                        // TODO: Check the index
204                        let resolved_type = self.analyze_type(&field_with_type.field_type)?;
205                        let field_name_str =
206                            self.get_text(&field_with_type.field_name.0).to_string();
207
208                        let resolved_field = StructTypeField {
209                            identifier: Some(self.to_node(&field_with_type.field_name.0)),
210                            field_type: resolved_type,
211                        };
212
213                        fields.insert(field_name_str, resolved_field).map_err(|_| {
214                            self.create_err(
215                                ErrorKind::DuplicateFieldName,
216                                &field_with_type.field_name.0,
217                            )
218                        })?;
219                    }
220
221                    let enum_variant_struct_type = EnumVariantStructType {
222                        common,
223                        anon_struct: AnonymousStructType::new(fields),
224                    };
225
226                    EnumVariantType::Struct(enum_variant_struct_type)
227                }
228            };
229
230            let variant_name_str = self.get_text(variant_name_node).to_string();
231
232            resolved_variants
233                .insert(variant_name_str, variant_type.into())
234                .map_err(|_| self.create_err(ErrorKind::DuplicateFieldName, variant_name_node))?;
235        }
236
237        new_enum_type.variants = resolved_variants;
238
239        self.shared
240            .definition_table
241            .add_enum_type(new_enum_type.clone())
242            .map_err(|err| self.create_err(ErrorKind::SemanticError(err), &enum_type_name.name))?;
243
244        self.shared
245            .lookup_table
246            .add_enum_type_link(new_enum_type.clone())
247            .map_err(|err| self.create_err(ErrorKind::SemanticError(err), &enum_type_name.name))?;
248
249        Ok(())
250    }
251
252    /// # Errors
253    ///
254    pub fn analyze_alias_type_definition(
255        &mut self,
256        ast_alias: &swamp_script_ast::AliasType,
257    ) -> Result<AliasType, Error> {
258        let resolved_type = self.analyze_type(&ast_alias.referenced_type)?;
259
260        let alias_name_str = self.get_text(&ast_alias.identifier.0).to_string();
261        let resolved_alias = AliasType {
262            name: self.to_node(&ast_alias.identifier.0),
263            assigned_name: alias_name_str,
264            referenced_type: resolved_type,
265        };
266
267        let resolved_alias_ref = self
268            .shared
269            .definition_table
270            .add_alias(resolved_alias)
271            .map_err(|err| {
272                self.create_err(ErrorKind::SemanticError(err), &ast_alias.identifier.0)
273            })?;
274        self.shared
275            .lookup_table
276            .add_alias_link(resolved_alias_ref.clone())
277            .map_err(|err| {
278                self.create_err(ErrorKind::SemanticError(err), &ast_alias.identifier.0)
279            })?;
280
281        Ok(resolved_alias_ref)
282    }
283
284    /// # Errors
285    ///
286    pub fn analyze_anonymous_struct_type(
287        &mut self,
288        ast_struct: &swamp_script_ast::AnonymousStructType,
289    ) -> Result<AnonymousStructType, Error> {
290        let resolved_fields = self.analyze_anonymous_struct_type_fields(&ast_struct.fields)?;
291
292        let resolved_anon_struct = AnonymousStructType::new_and_sort_fields(&resolved_fields);
293
294        Ok(resolved_anon_struct)
295    }
296
297    /// # Errors
298    ///
299    pub fn analyze_anonymous_struct_type_fields(
300        &mut self,
301        ast_struct_fields: &[swamp_script_ast::StructTypeField],
302    ) -> Result<SeqMap<String, StructTypeField>, Error> {
303        let mut resolved_fields = SeqMap::new();
304
305        for field_name_and_type in ast_struct_fields {
306            let resolved_type = self.analyze_type(&field_name_and_type.field_type)?;
307            let name_string = self.get_text(&field_name_and_type.field_name.0).to_string();
308
309            let field_type = StructTypeField {
310                identifier: Some(self.to_node(&field_name_and_type.field_name.0)),
311                field_type: resolved_type,
312            };
313
314            resolved_fields
315                .insert(name_string, field_type)
316                .map_err(|_| {
317                    self.create_err(
318                        ErrorKind::DuplicateFieldName,
319                        &field_name_and_type.field_name.0,
320                    )
321                })?;
322        }
323
324        Ok(resolved_fields)
325    }
326
327    pub fn convert_to_type_variables(
328        &mut self,
329        ast_type_variables: &[swamp_script_ast::TypeVariable],
330    ) -> Vec<String> {
331        let mut types = Vec::new();
332        for ast_type_variable in ast_type_variables {
333            let name = self.get_text(&ast_type_variable.0).to_string();
334            types.push(name);
335        }
336        types
337    }
338
339    /// # Panics
340    ///
341    pub fn set_type_variables_to_extra_symbol_table(&mut self, type_variables: &[String]) {
342        self.shared
343            .type_variables
344            .push_type_scope_with_variables(type_variables);
345    }
346
347    /// # Errors
348    ///
349    pub fn analyze_named_struct_type_definition(
350        &mut self,
351        ast_struct_def: &swamp_script_ast::NamedStructDef,
352    ) -> Result<(), Error> {
353        let has_type_variables = !ast_struct_def.identifier.type_variables.is_empty();
354
355        let type_variables =
356            self.convert_to_type_variables(&ast_struct_def.identifier.type_variables);
357
358        if has_type_variables {
359            self.set_type_variables_to_extra_symbol_table(&type_variables);
360        }
361
362        let struct_name_str = self.get_text(&ast_struct_def.identifier.name).to_string();
363
364        let fields =
365            self.analyze_anonymous_struct_type_fields(&ast_struct_def.struct_type.fields)?;
366
367        let analyzed_anonymous_struct = AnonymousStructType::new(fields); // the order encountered in source should be kept
368
369        let named_struct_type = NamedStructType {
370            name: self.to_node(&ast_struct_def.identifier.name),
371            anon_struct_type: analyzed_anonymous_struct,
372            assigned_name: struct_name_str,
373            module_path: self.shared.definition_table.module_path(),
374            instantiated_type_parameters: Vec::default(),
375            blueprint_info: None,
376        };
377
378        if has_type_variables {
379            // It is a blueprint! Store it in the definition
380
381            self.shared.type_variables.pop_type_scope();
382
383            let blueprint_ref = self
384                .shared
385                .definition_table
386                .add_blueprint(ParameterizedTypeBlueprint {
387                    kind: ParameterizedTypeKind::Struct(named_struct_type),
388                    type_variables,
389                    defined_in_module_path: self.module_path.clone(),
390                })
391                .map_err(|err| {
392                    self.create_err(
393                        ErrorKind::SemanticError(err),
394                        &ast_struct_def.identifier.name,
395                    )
396                })?;
397
398            self.shared
399                .lookup_table
400                .add_blueprint_link(blueprint_ref)
401                .map_err(|err| {
402                    self.create_err(
403                        ErrorKind::SemanticError(err),
404                        &ast_struct_def.identifier.name,
405                    )
406                })?;
407
408            return Ok(());
409        }
410
411        let struct_ref = self
412            .shared
413            .definition_table
414            .add_struct(named_struct_type)
415            .map_err(|err| {
416                self.create_err(
417                    ErrorKind::SemanticError(err),
418                    &ast_struct_def.identifier.name,
419                )
420            })?;
421
422        self.shared
423            .lookup_table
424            .add_struct_link(struct_ref)
425            .map_err(|err| {
426                self.create_err(
427                    ErrorKind::SemanticError(err),
428                    &ast_struct_def.identifier.name,
429                )
430            })?;
431
432        Ok(())
433    }
434
435    pub(crate) fn analyze_function_definition(
436        &mut self,
437        function: &swamp_script_ast::Function,
438    ) -> Result<Function, Error> {
439        let func = match function {
440            swamp_script_ast::Function::Internal(function_data) => {
441                let parameters = self.analyze_parameters(&function_data.declaration.params)?;
442                let return_type = if let Some(found) = &function_data.declaration.return_type {
443                    self.analyze_type(found)?
444                } else {
445                    Type::Unit
446                };
447
448                self.scope.return_type = return_type.clone();
449
450                // Set up scope for function body
451                for param in &parameters {
452                    self.create_local_variable_resolved(
453                        &param.node.as_ref().unwrap().name,
454                        param.node.as_ref().unwrap().is_mutable.as_ref(),
455                        &param.resolved_type.clone(),
456                    )?;
457                }
458                let function_name = self
459                    .get_text(&function_data.declaration.name)
460                    .trim()
461                    .to_string();
462                let statements =
463                    self.analyze_function_body_expression(&function_data.body, &return_type)?;
464                self.scope.return_type = Type::Unit;
465
466                let internal = InternalFunctionDefinition {
467                    signature: GenericAwareSignature {
468                        signature: Signature {
469                            parameters,
470                            return_type: Box::new(return_type),
471                        },
472                        generic_type_variables: vec![],
473                    },
474                    body: statements,
475                    name: LocalIdentifier(self.to_node(&function_data.declaration.name)),
476                    assigned_name: self.get_text(&function_data.declaration.name).to_string(),
477                    variable_scopes: self.scope.clone(),
478                    function_scope_state: self.function_variables.clone(),
479                    program_unique_id: self.shared.state.allocate_internal_function_id(),
480                };
481
482                let function_ref = self
483                    .shared
484                    .definition_table
485                    .add_internal_function(&function_name, internal)
486                    .map_err(|err| {
487                        self.create_err(
488                            ErrorKind::SemanticError(err),
489                            &function_data.declaration.name,
490                        )
491                    })?;
492
493                self.shared
494                    .lookup_table
495                    .add_internal_function_link(&function_name, function_ref.clone())
496                    .map_err(|err| {
497                        self.create_err(
498                            ErrorKind::SemanticError(err),
499                            &function_data.declaration.name,
500                        )
501                    })?;
502
503                Function::Internal(function_ref)
504            }
505            swamp_script_ast::Function::External(ast_signature) => {
506                let parameters = self.analyze_parameters(&ast_signature.params)?;
507                let external_return_type = if let Some(found) = &ast_signature.return_type {
508                    self.analyze_type(found)?
509                } else {
510                    Type::Unit
511                };
512
513                let return_type = external_return_type;
514                let external_function_id = self.shared.state.allocate_external_function_id();
515
516                let external = ExternalFunctionDefinition {
517                    assigned_name: self.get_text(&ast_signature.name).to_string(),
518                    signature: Signature {
519                        parameters,
520                        return_type: Box::new(return_type),
521                    },
522                    name: Some(self.to_node(&ast_signature.name)),
523                    id: external_function_id,
524                };
525
526                let function_ref = self
527                    .shared
528                    .definition_table
529                    .add_external_function_declaration(external)
530                    .map_err(|err| {
531                        self.create_err(ErrorKind::SemanticError(err), &ast_signature.name)
532                    })?;
533
534                self.shared
535                    .lookup_table
536                    .add_external_function_declaration_link(function_ref.clone())
537                    .map_err(|err| {
538                        self.create_err(ErrorKind::SemanticError(err), &ast_signature.name)
539                    })?;
540
541                Function::External(function_ref)
542            }
543        };
544
545        Ok(func)
546    }
547
548    pub fn debug_definition(&self, definition: &swamp_script_ast::Definition) {
549        /*
550        let (line, col) = self
551            .shared
552            .source_map
553            .get_span_location_utf8(self.shared.file_id, definition.node.span.offset as usize);
554        let source_line = self
555            .shared
556            .source_map
557            .get_source_line(self.shared.file_id, line);
558
559         */
560    }
561
562    /// # Errors
563    ///
564    pub fn analyze_definition(
565        &mut self,
566        ast_def: &swamp_script_ast::Definition,
567    ) -> Result<(), Error> {
568        self.debug_definition(ast_def);
569        match ast_def {
570            swamp_script_ast::Definition::NamedStructDef(ast_struct) => {
571                self.analyze_named_struct_type_definition(ast_struct)?;
572            }
573            swamp_script_ast::Definition::AliasDef(alias_def) => {
574                self.analyze_alias_type_definition(alias_def)?;
575            }
576            swamp_script_ast::Definition::EnumDef(identifier, variants) => {
577                self.analyze_enum_type_definition(identifier, variants)?;
578            }
579            swamp_script_ast::Definition::FunctionDef(function) => {
580                let resolved_return_type = self.analyze_return_type(function)?;
581                self.start_function(resolved_return_type);
582                self.analyze_function_definition(function)?;
583
584                self.stop_function();
585            }
586            swamp_script_ast::Definition::ImplDef(type_identifier, functions) => {
587                self.analyze_impl_definition(type_identifier, functions)?;
588            }
589            swamp_script_ast::Definition::Mod(mod_info) => self.analyze_mod_definition(mod_info)?,
590            swamp_script_ast::Definition::Use(use_info) => self.analyze_use_definition(use_info)?,
591            swamp_script_ast::Definition::Constant(const_info) => {
592                self.analyze_constant_definition(const_info)?;
593            }
594        };
595
596        Ok(())
597    }
598
599    fn analyze_impl_definition(
600        &mut self,
601        attached_to_type: &swamp_script_ast::LocalTypeIdentifierWithOptionalTypeVariables,
602        functions: &[swamp_script_ast::Function],
603    ) -> Result<(), Error> {
604        let type_name_text = self.get_text(&attached_to_type.name).to_string();
605
606        let converted_type_variables_to_ast_types = attached_to_type
607            .type_variables
608            .iter()
609            .map(|x| {
610                swamp_script_ast::Type::Named(swamp_script_ast::QualifiedTypeIdentifier {
611                    name: swamp_script_ast::LocalTypeIdentifier(x.0.clone()),
612                    module_path: None,
613                    generic_params: vec![],
614                })
615            })
616            .collect();
617
618        let qualified = swamp_script_ast::QualifiedTypeIdentifier {
619            name: swamp_script_ast::LocalTypeIdentifier(attached_to_type.name.clone()),
620            module_path: None,
621            generic_params: converted_type_variables_to_ast_types,
622        };
623
624        let is_parameterized = !qualified.generic_params.is_empty();
625
626        let maybe_type_to_attach_to = if is_parameterized {
627            let type_variables = self.convert_to_type_variables(&attached_to_type.type_variables);
628            self.set_type_variables_to_extra_symbol_table(&type_variables);
629            if let Some(found_blueprint) = self.shared.lookup_table.get_blueprint(&type_name_text) {
630                Some(Type::Blueprint(found_blueprint.clone()))
631            } else {
632                panic!("must be something");
633            }
634        } else {
635            Some(self.analyze_named_type(&qualified)?)
636        };
637
638        if let Some(type_to_attach_to) = maybe_type_to_attach_to {
639            let function_refs: Vec<&swamp_script_ast::Function> = functions.iter().collect();
640
641            self.analyze_impl_functions(type_to_attach_to, &function_refs)?;
642
643            if is_parameterized {
644                self.shared.type_variables.pop_type_scope();
645            }
646
647            Ok(())
648        } else {
649            Err(self.create_err(
650                ErrorKind::CanNotAttachFunctionsToType,
651                &attached_to_type.name,
652            ))
653        }
654    }
655
656    /// # Errors
657    ///
658    pub fn analyze_impl_functions(
659        &mut self,
660        attach_to_type: Type, // Needed for self
661        functions: &[&swamp_script_ast::Function],
662    ) -> Result<(), Error> {
663        self.shared
664            .state
665            .instantiator
666            .associated_impls
667            .prepare(&attach_to_type);
668
669        for function in functions {
670            let new_return_type = self.analyze_return_type(function)?;
671            self.start_function(new_return_type);
672
673            let function_name = match function {
674                swamp_script_ast::Function::Internal(function_with_body) => {
675                    &function_with_body.declaration
676                }
677                swamp_script_ast::Function::External(external_declaration) => external_declaration,
678            };
679
680            let function_name_str = self.get_text(&function_name.name).to_string();
681
682            let resolved_function = self.analyze_impl_func(function, &attach_to_type)?;
683
684            let resolved_function_ref = Rc::new(resolved_function);
685
686            self.stop_function();
687
688            self.shared
689                .state
690                .instantiator
691                .associated_impls
692                .add_member_function(&attach_to_type, &function_name_str, resolved_function_ref)
693                .map_err(|err| {
694                    self.create_err(ErrorKind::SemanticError(err), &function_name.name)
695                })?;
696        }
697
698        Ok(())
699    }
700
701    pub(crate) fn push_type_scope_with_variables(
702        &mut self,
703        type_variables: &[swamp_script_ast::TypeVariable],
704    ) -> Result<(), SemanticError> {
705        self.shared.type_variables.push_type_scope();
706
707        for type_var in type_variables {
708            let variable_name_string = self.get_text(&type_var.0).to_string();
709            self.shared
710                .type_variables
711                .declare_type_variable(&variable_name_string)?;
712        }
713
714        Ok(())
715    }
716
717    #[allow(clippy::too_many_lines)]
718    fn analyze_impl_func(
719        &mut self,
720        function: &swamp_script_ast::Function,
721        self_type: &Type,
722    ) -> Result<Function, Error> {
723        let resolved_fn = match function {
724            swamp_script_ast::Function::Internal(function_data) => {
725                let has_function_local_generic_type_variables =
726                    !function_data.declaration.generic_variables.is_empty();
727                if has_function_local_generic_type_variables {
728                    self.push_type_scope_with_variables(
729                        &function_data.declaration.generic_variables,
730                    )?;
731                }
732
733                let mut parameters = Vec::new();
734
735                if let Some(found_self) = &function_data.declaration.self_parameter {
736                    parameters.push(TypeForParameter {
737                        name: self.get_text(&found_self.self_node).to_string(),
738                        resolved_type: self_type.clone(),
739                        is_mutable: found_self.is_mutable.is_some(),
740                        node: Option::from(ParameterNode {
741                            name: self.to_node(&found_self.self_node),
742                            is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
743                        }),
744                    });
745                }
746
747                for param in &function_data.declaration.params {
748                    let resolved_type = self.analyze_type(&param.param_type)?;
749
750                    parameters.push(TypeForParameter {
751                        name: self.get_text(&param.variable.name).to_string(),
752                        resolved_type,
753                        is_mutable: param.variable.is_mutable.is_some(),
754                        node: Option::from(ParameterNode {
755                            name: self.to_node(&param.variable.name),
756                            is_mutable: self
757                                .to_node_option(Option::from(&param.variable.is_mutable)),
758                        }),
759                    });
760                }
761
762                let return_type =
763                    self.analyze_maybe_type(Option::from(&function_data.declaration.return_type))?;
764
765                for param in &parameters {
766                    self.create_local_variable_resolved(
767                        &param.node.as_ref().unwrap().name,
768                        param.node.as_ref().unwrap().is_mutable.as_ref(),
769                        &param.resolved_type.clone(),
770                    )?;
771                }
772
773                let statements =
774                    self.analyze_function_body_expression(&function_data.body, &return_type)?;
775
776                if has_function_local_generic_type_variables {
777                    self.shared.type_variables.pop_type_scope();
778                }
779
780                let internal = InternalFunctionDefinition {
781                    signature: GenericAwareSignature {
782                        signature: Signature {
783                            parameters,
784                            return_type: Box::new(return_type),
785                        },
786                        generic_type_variables: vec![],
787                    },
788                    body: statements,
789                    name: LocalIdentifier(self.to_node(&function_data.declaration.name)),
790                    assigned_name: self.get_text(&function_data.declaration.name).to_string(),
791                    variable_scopes: self.scope.clone(),
792                    function_scope_state: self.function_variables.clone(),
793                    program_unique_id: self.shared.state.allocate_internal_function_id(),
794                };
795
796                let internal_ref = Rc::new(internal);
797
798                Function::Internal(internal_ref)
799            }
800
801            swamp_script_ast::Function::External(signature) => {
802                let mut parameters = Vec::new();
803
804                if let Some(found_self) = &signature.self_parameter {
805                    parameters.push(TypeForParameter {
806                        name: self.get_text(&found_self.self_node).to_string(),
807                        resolved_type: self_type.clone(),
808                        is_mutable: found_self.is_mutable.is_some(),
809                        node: Option::from(ParameterNode {
810                            name: self.to_node(&found_self.self_node),
811                            is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
812                        }),
813                    });
814                }
815
816                // Handle parameters, including self if present
817                for param in &signature.params {
818                    let resolved_type = self.analyze_type(&param.param_type)?;
819
820                    parameters.push(TypeForParameter {
821                        name: self.get_text(&param.variable.name).to_string(),
822                        resolved_type,
823                        is_mutable: param.variable.is_mutable.is_some(),
824                        node: Option::from(ParameterNode {
825                            name: self.to_node(&param.variable.name),
826                            is_mutable: self
827                                .to_node_option(Option::from(&param.variable.is_mutable)),
828                        }),
829                    });
830                }
831
832                let return_type = self.analyze_maybe_type(Option::from(&signature.return_type))?;
833
834                let external_id = self.shared.state.allocate_external_function_id();
835
836                let external = ExternalFunctionDefinition {
837                    assigned_name: self.get_text(&signature.name).to_string(),
838                    name: Some(self.to_node(&signature.name)),
839                    signature: Signature {
840                        parameters,
841                        return_type: Box::new(return_type),
842                    },
843                    id: external_id,
844                };
845
846                let external_ref = Rc::new(external);
847
848                Function::External(external_ref)
849            }
850        };
851        Ok(resolved_fn)
852    }
853}