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