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