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, UseItem,
12};
13use swamp_script_types::prelude::*;
14use swamp_script_types::{ParameterizedTypeBlueprint, ParameterizedTypeKind};
15
16use swamp_script_semantic::instantiator::TypeVariableScope;
17use tracing::trace;
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        let mut types = SeqMap::new();
343        for type_variable in type_variables {
344            types
345                .insert(
346                    type_variable.to_string(),
347                    Type::Variable(type_variable.clone()),
348                )
349                .unwrap();
350        }
351
352        let type_variables = TypeVariableScope::new(types);
353
354        self.shared.type_variables = Some(type_variables);
355    }
356
357    /// # Errors
358    ///
359    pub fn analyze_named_struct_type_definition(
360        &mut self,
361        ast_struct_def: &swamp_script_ast::NamedStructDef,
362    ) -> Result<(), Error> {
363        let has_type_variables = !ast_struct_def.identifier.type_variables.is_empty();
364
365        let type_variables =
366            self.convert_to_type_variables(&ast_struct_def.identifier.type_variables);
367        if has_type_variables {
368            self.set_type_variables_to_extra_symbol_table(&type_variables);
369        }
370
371        let struct_name_str = self.get_text(&ast_struct_def.identifier.name).to_string();
372
373        let fields =
374            self.analyze_anonymous_struct_type_fields(&ast_struct_def.struct_type.fields)?;
375
376        let analyzed_anonymous_struct = AnonymousStructType::new(fields); // the order encountered in source should be kept
377
378        let named_struct_type = NamedStructType {
379            name: self.to_node(&ast_struct_def.identifier.name),
380            anon_struct_type: analyzed_anonymous_struct,
381            assigned_name: struct_name_str,
382            module_path: self.shared.definition_table.module_path(),
383            instantiated_type_parameters: Vec::default(),
384            blueprint_info: None,
385        };
386
387        if has_type_variables {
388            // It is a blueprint! Store it in the definition
389
390            self.shared.type_variables = None;
391
392            let blueprint_ref = self
393                .shared
394                .definition_table
395                .add_blueprint(ParameterizedTypeBlueprint {
396                    kind: ParameterizedTypeKind::Struct(named_struct_type),
397                    type_variables,
398                    defined_in_module_path: self.module_path.clone(),
399                })
400                .map_err(|err| {
401                    self.create_err(
402                        ErrorKind::SemanticError(err),
403                        &ast_struct_def.identifier.name,
404                    )
405                })?;
406
407            self.shared
408                .lookup_table
409                .add_blueprint_link(blueprint_ref)
410                .map_err(|err| {
411                    self.create_err(
412                        ErrorKind::SemanticError(err),
413                        &ast_struct_def.identifier.name,
414                    )
415                })?;
416
417            return Ok(());
418        }
419
420        let struct_ref = self
421            .shared
422            .definition_table
423            .add_struct(named_struct_type)
424            .map_err(|err| {
425                self.create_err(
426                    ErrorKind::SemanticError(err),
427                    &ast_struct_def.identifier.name,
428                )
429            })?;
430
431        self.shared
432            .lookup_table
433            .add_struct_link(struct_ref)
434            .map_err(|err| {
435                self.create_err(
436                    ErrorKind::SemanticError(err),
437                    &ast_struct_def.identifier.name,
438                )
439            })?;
440
441        Ok(())
442    }
443
444    pub(crate) fn analyze_function_definition(
445        &mut self,
446        function: &swamp_script_ast::Function,
447    ) -> Result<Function, Error> {
448        let func = match function {
449            swamp_script_ast::Function::Internal(function_data) => {
450                let parameters = self.analyze_parameters(&function_data.declaration.params)?;
451                let return_type = if let Some(found) = &function_data.declaration.return_type {
452                    self.analyze_type(found)?
453                } else {
454                    Type::Unit
455                };
456
457                self.scope.return_type = return_type.clone();
458
459                // Set up scope for function body
460                for param in &parameters {
461                    self.create_local_variable_resolved(
462                        &param.node.as_ref().unwrap().name,
463                        param.node.as_ref().unwrap().is_mutable.as_ref(),
464                        &param.resolved_type.clone(),
465                    )?;
466                }
467                let function_name = self
468                    .get_text(&function_data.declaration.name)
469                    .trim()
470                    .to_string();
471                let statements =
472                    self.analyze_function_body_expression(&function_data.body, &return_type)?;
473                self.scope.return_type = Type::Unit;
474
475                let internal = InternalFunctionDefinition {
476                    signature: Signature {
477                        parameters,
478                        return_type: Box::new(return_type),
479                    },
480                    body: statements,
481                    name: LocalIdentifier(self.to_node(&function_data.declaration.name)),
482                    assigned_name: self.get_text(&function_data.declaration.name).to_string(),
483                    variable_scopes: self.scope.clone(),
484                    function_scope_state: self.function_variables.clone(),
485                    program_unique_id: self.shared.state.allocate_internal_function_id(),
486                };
487
488                let function_ref = self
489                    .shared
490                    .definition_table
491                    .add_internal_function(&function_name, internal)
492                    .map_err(|err| {
493                        self.create_err(
494                            ErrorKind::SemanticError(err),
495                            &function_data.declaration.name,
496                        )
497                    })?;
498
499                self.shared
500                    .lookup_table
501                    .add_internal_function_link(&function_name, function_ref.clone())
502                    .map_err(|err| {
503                        self.create_err(
504                            ErrorKind::SemanticError(err),
505                            &function_data.declaration.name,
506                        )
507                    })?;
508
509                Function::Internal(function_ref)
510            }
511            swamp_script_ast::Function::External(ast_signature) => {
512                let parameters = self.analyze_parameters(&ast_signature.params)?;
513                let external_return_type = if let Some(found) = &ast_signature.return_type {
514                    self.analyze_type(found)?
515                } else {
516                    Type::Unit
517                };
518
519                let return_type = external_return_type;
520                let external_function_id = self.shared.state.allocate_external_function_id();
521
522                let external = ExternalFunctionDefinition {
523                    assigned_name: self.get_text(&ast_signature.name).to_string(),
524                    signature: Signature {
525                        parameters,
526                        return_type: Box::new(return_type),
527                    },
528                    name: Some(self.to_node(&ast_signature.name)),
529                    id: external_function_id,
530                };
531
532                let function_ref = self
533                    .shared
534                    .definition_table
535                    .add_external_function_declaration(external)
536                    .map_err(|err| {
537                        self.create_err(ErrorKind::SemanticError(err), &ast_signature.name)
538                    })?;
539
540                self.shared
541                    .lookup_table
542                    .add_external_function_declaration_link(function_ref.clone())
543                    .map_err(|err| {
544                        self.create_err(ErrorKind::SemanticError(err), &ast_signature.name)
545                    })?;
546
547                Function::External(function_ref)
548            }
549        };
550
551        Ok(func)
552    }
553
554    pub fn debug_definition(&self, definition: &swamp_script_ast::Definition) {
555        /*
556        let (line, col) = self
557            .shared
558            .source_map
559            .get_span_location_utf8(self.shared.file_id, definition.node.span.offset as usize);
560        let source_line = self
561            .shared
562            .source_map
563            .get_source_line(self.shared.file_id, line);
564
565         */
566    }
567
568    /// # Errors
569    ///
570    pub fn analyze_definition(
571        &mut self,
572        ast_def: &swamp_script_ast::Definition,
573    ) -> Result<(), Error> {
574        self.debug_definition(ast_def);
575        match ast_def {
576            swamp_script_ast::Definition::NamedStructDef(ast_struct) => {
577                self.analyze_named_struct_type_definition(ast_struct)?;
578            }
579            swamp_script_ast::Definition::AliasDef(alias_def) => {
580                self.analyze_alias_type_definition(alias_def)?;
581            }
582            swamp_script_ast::Definition::EnumDef(identifier, variants) => {
583                self.analyze_enum_type_definition(identifier, variants)?;
584            }
585            swamp_script_ast::Definition::FunctionDef(function) => {
586                let resolved_return_type = self.analyze_return_type(function)?;
587                self.start_function(resolved_return_type);
588                self.analyze_function_definition(function)?;
589
590                self.stop_function();
591            }
592            swamp_script_ast::Definition::ImplDef(type_identifier, functions) => {
593                self.analyze_impl_definition(type_identifier, functions)?;
594            }
595            swamp_script_ast::Definition::Mod(mod_info) => self.analyze_mod_definition(mod_info)?,
596            swamp_script_ast::Definition::Use(use_info) => self.analyze_use_definition(use_info)?,
597            swamp_script_ast::Definition::Constant(const_info) => {
598                self.analyze_constant_definition(const_info)?;
599            }
600        };
601
602        Ok(())
603    }
604
605    fn analyze_impl_definition(
606        &mut self,
607        attached_to_type: &swamp_script_ast::LocalTypeIdentifierWithOptionalTypeVariables,
608        functions: &[swamp_script_ast::Function],
609    ) -> Result<(), Error> {
610        let type_name_text = self.get_text(&attached_to_type.name).to_string();
611
612        let converted_type_variables_to_ast_types = attached_to_type
613            .type_variables
614            .iter()
615            .map(|x| {
616                swamp_script_ast::Type::Named(swamp_script_ast::QualifiedTypeIdentifier {
617                    name: swamp_script_ast::LocalTypeIdentifier(x.0.clone()),
618                    module_path: None,
619                    generic_params: vec![],
620                })
621            })
622            .collect();
623
624        let qualified = swamp_script_ast::QualifiedTypeIdentifier {
625            name: swamp_script_ast::LocalTypeIdentifier(attached_to_type.name.clone()),
626            module_path: None,
627            generic_params: converted_type_variables_to_ast_types,
628        };
629
630        let is_parameterized = !qualified.generic_params.is_empty();
631
632        let maybe_type_to_attach_to = if is_parameterized {
633            let type_variables = self.convert_to_type_variables(&attached_to_type.type_variables);
634            self.set_type_variables_to_extra_symbol_table(&type_variables);
635            if let Some(found_blueprint) = self.shared.lookup_table.get_blueprint(&type_name_text) {
636                Some(Type::Blueprint(found_blueprint.clone()))
637            } else {
638                panic!("must be something");
639            }
640        } else {
641            Some(self.analyze_named_type(&qualified)?)
642        };
643
644        if let Some(type_to_attach_to) = maybe_type_to_attach_to {
645            let function_refs: Vec<&swamp_script_ast::Function> = functions.iter().collect();
646
647            self.analyze_impl_functions(type_to_attach_to, &function_refs)?;
648
649            if is_parameterized {
650                self.shared.type_variables = None;
651            }
652
653            Ok(())
654        } else {
655            Err(self.create_err(
656                ErrorKind::CanNotAttachFunctionsToType,
657                &attached_to_type.name,
658            ))
659        }
660    }
661
662    /// # Errors
663    ///
664    pub fn analyze_impl_functions(
665        &mut self,
666        attach_to_type: Type, // Needed for self
667        functions: &[&swamp_script_ast::Function],
668    ) -> Result<(), Error> {
669        self.shared
670            .state
671            .instantiator
672            .associated_impls
673            .prepare(&attach_to_type);
674
675        for function in functions {
676            let new_return_type = self.analyze_return_type(function)?;
677            self.start_function(new_return_type);
678
679            let function_name = match function {
680                swamp_script_ast::Function::Internal(function_with_body) => {
681                    &function_with_body.declaration
682                }
683                swamp_script_ast::Function::External(external_declaration) => external_declaration,
684            };
685
686            let function_name_str = self.get_text(&function_name.name).to_string();
687
688            let resolved_function = self.analyze_impl_func(function, &attach_to_type)?;
689
690            let resolved_function_ref = Rc::new(resolved_function);
691
692            self.stop_function();
693
694            self.shared
695                .state
696                .instantiator
697                .associated_impls
698                .add_member_function(&attach_to_type, &function_name_str, resolved_function_ref)
699                .map_err(|err| {
700                    self.create_err(ErrorKind::SemanticError(err), &function_name.name)
701                })?;
702        }
703
704        Ok(())
705    }
706
707    fn analyze_impl_func(
708        &mut self,
709        function: &swamp_script_ast::Function,
710        self_type: &Type,
711    ) -> Result<Function, Error> {
712        let resolved_fn = match function {
713            swamp_script_ast::Function::Internal(function_data) => {
714                let mut parameters = Vec::new();
715
716                if let Some(found_self) = &function_data.declaration.self_parameter {
717                    parameters.push(TypeForParameter {
718                        name: self.get_text(&found_self.self_node).to_string(),
719                        resolved_type: self_type.clone(),
720                        is_mutable: found_self.is_mutable.is_some(),
721                        node: Option::from(ParameterNode {
722                            name: self.to_node(&found_self.self_node),
723                            is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
724                        }),
725                    });
726                }
727
728                for param in &function_data.declaration.params {
729                    let resolved_type = self.analyze_type(&param.param_type)?;
730
731                    parameters.push(TypeForParameter {
732                        name: self.get_text(&param.variable.name).to_string(),
733                        resolved_type,
734                        is_mutable: param.variable.is_mutable.is_some(),
735                        node: Option::from(ParameterNode {
736                            name: self.to_node(&param.variable.name),
737                            is_mutable: self
738                                .to_node_option(Option::from(&param.variable.is_mutable)),
739                        }),
740                    });
741                }
742
743                let return_type =
744                    self.analyze_maybe_type(Option::from(&function_data.declaration.return_type))?;
745
746                for param in &parameters {
747                    self.create_local_variable_resolved(
748                        &param.node.as_ref().unwrap().name,
749                        param.node.as_ref().unwrap().is_mutable.as_ref(),
750                        &param.resolved_type.clone(),
751                    )?;
752                }
753
754                let statements =
755                    self.analyze_function_body_expression(&function_data.body, &return_type)?;
756
757                let internal = InternalFunctionDefinition {
758                    signature: Signature {
759                        parameters,
760                        return_type: Box::new(return_type),
761                    },
762                    body: statements,
763                    name: LocalIdentifier(self.to_node(&function_data.declaration.name)),
764                    assigned_name: self.get_text(&function_data.declaration.name).to_string(),
765                    variable_scopes: self.scope.clone(),
766                    function_scope_state: self.function_variables.clone(),
767                    program_unique_id: self.shared.state.allocate_internal_function_id(),
768                };
769
770                let internal_ref = Rc::new(internal);
771
772                Function::Internal(internal_ref)
773            }
774
775            swamp_script_ast::Function::External(signature) => {
776                let mut parameters = Vec::new();
777
778                if let Some(found_self) = &signature.self_parameter {
779                    parameters.push(TypeForParameter {
780                        name: self.get_text(&found_self.self_node).to_string(),
781                        resolved_type: self_type.clone(),
782                        is_mutable: found_self.is_mutable.is_some(),
783                        node: Option::from(ParameterNode {
784                            name: self.to_node(&found_self.self_node),
785                            is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
786                        }),
787                    });
788                }
789
790                // Handle parameters, including self if present
791                for param in &signature.params {
792                    let resolved_type = self.analyze_type(&param.param_type)?;
793
794                    parameters.push(TypeForParameter {
795                        name: self.get_text(&param.variable.name).to_string(),
796                        resolved_type,
797                        is_mutable: param.variable.is_mutable.is_some(),
798                        node: Option::from(ParameterNode {
799                            name: self.to_node(&param.variable.name),
800                            is_mutable: self
801                                .to_node_option(Option::from(&param.variable.is_mutable)),
802                        }),
803                    });
804                }
805
806                let return_type = self.analyze_maybe_type(Option::from(&signature.return_type))?;
807
808                let external_id = self.shared.state.allocate_external_function_id();
809
810                let external = ExternalFunctionDefinition {
811                    assigned_name: self.get_text(&signature.name).to_string(),
812                    name: Some(self.to_node(&signature.name)),
813                    signature: Signature {
814                        parameters,
815                        return_type: Box::new(return_type),
816                    },
817                    id: external_id,
818                };
819
820                let external_ref = Rc::new(external);
821
822                Function::External(external_ref)
823            }
824        };
825        Ok(resolved_fn)
826    }
827}