swamp_analyzer/
def.rs

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