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::to_string::{
7    ExpressionGenerator, internal_generate_to_pretty_string_function_for_type,
8    internal_generate_to_short_string_function_for_type,
9    internal_generate_to_string_function_for_type,
10};
11use seq_map::SeqMap;
12use std::rc::Rc;
13use swamp_ast::Node;
14use swamp_attributes::Attributes;
15use swamp_modules::symtbl::AliasType;
16use swamp_semantic::err::ErrorKind;
17use swamp_semantic::{
18    ExternalFunctionDefinition, ExternalFunctionId, Function, InternalFunctionDefinition,
19    InternalFunctionId, LocalIdentifier, UseItem,
20};
21use swamp_types::prelude::*;
22use tracing::debug;
23
24impl Analyzer<'_> {
25    fn general_import(
26        &mut self,
27        path: &[String],
28        import_items: &swamp_ast::ImportItems,
29        node: &swamp_ast::Node,
30    ) {
31        // Clone the module reference to avoid borrowing conflicts
32        let found_module = if let Some(module) = self.shared.get_module(path) {
33            module.clone()
34        } else {
35            self.add_err(ErrorKind::UnknownModule, node);
36            return;
37        };
38
39        match import_items {
40            swamp_ast::ImportItems::Nothing => {
41                let last_name = path.last().unwrap();
42                if self
43                    .shared
44                    .lookup_table
45                    .get_module_link(last_name)
46                    .is_none()
47                {
48                    match self
49                        .shared
50                        .lookup_table
51                        .add_module_link(last_name, found_module.clone())
52                    {
53                        Ok(_x) => {}
54                        Err(err) => {
55                            self.add_err(ErrorKind::SemanticError(err), node);
56                        }
57                    }
58                }
59            }
60            swamp_ast::ImportItems::Items(items) => {
61                for ast_items in items {
62                    match ast_items {
63                        swamp_ast::ImportItem::Identifier(node) => {
64                            let ident_resolved_node = self.to_node(&node.0);
65                            let ident = UseItem::Identifier(ident_resolved_node.clone());
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                                if let Err(sem_err) = self
72                                    .shared
73                                    .lookup_table
74                                    .add_symbol(&ident_text, found_symbol.clone())
75                                {
76                                    self.add_err(ErrorKind::SemanticError(sem_err), &node.0);
77                                    return;
78                                }
79                            } else {
80                                return self.add_err_resolved(
81                                    ErrorKind::UnknownTypeReference,
82                                    &ident_resolved_node,
83                                );
84                            }
85                            ident
86                        }
87                        swamp_ast::ImportItem::Type(node) => {
88                            let ident_resolved_node = self.to_node(&node.0);
89                            let ident_text =
90                                self.get_text_resolved(&ident_resolved_node).to_string();
91                            if let Some(found_symbol) =
92                                found_module.symbol_table.get_symbol(&ident_text)
93                            {
94                                if let Err(sem_err) = self
95                                    .shared
96                                    .lookup_table
97                                    .add_symbol(&ident_text, found_symbol.clone())
98                                {
99                                    self.add_err(ErrorKind::SemanticError(sem_err), &node.0);
100                                    return;
101                                }
102                            } else {
103                                return self.add_err_resolved(
104                                    ErrorKind::UnknownTypeReference,
105                                    &ident_resolved_node,
106                                );
107                            }
108                            UseItem::TypeIdentifier(self.to_node(&node.0))
109                        }
110                    };
111                }
112            }
113            swamp_ast::ImportItems::All => {
114                if let Err(sem_err) = self
115                    .shared
116                    .lookup_table
117                    .extend_from(&found_module.symbol_table)
118                {
119                    self.add_err(ErrorKind::SemanticError(sem_err), node);
120                }
121            }
122        }
123    }
124
125    fn analyze_mod_definition(&mut self, mod_definition: &swamp_ast::Mod) {
126        let mut path = Vec::new();
127        for ast_node in &mod_definition.module_path.0 {
128            path.push(self.get_text(ast_node).to_string());
129        }
130
131        let mut nodes_copy = path.clone();
132        nodes_copy.insert(0, "crate".to_string());
133
134        self.general_import(
135            &nodes_copy,
136            &mod_definition.items,
137            &mod_definition.module_path.0[0],
138        );
139    }
140
141    fn analyze_use_definition(&mut self, use_definition: &swamp_ast::Use) {
142        let mut nodes = Vec::new();
143        for ast_node in &use_definition.module_path.0 {
144            nodes.push(self.to_node(ast_node));
145        }
146
147        let path: Vec<String> = nodes
148            .iter()
149            .map(|node| {
150                let text = self.get_text_resolved(node);
151                text.to_string()
152            })
153            .collect();
154
155        self.general_import(
156            &path,
157            &use_definition.items,
158            &use_definition.module_path.0[0],
159        );
160    }
161
162    fn analyze_enum_type_definition(
163        &mut self,
164        enum_type_name: &swamp_ast::LocalTypeIdentifierWithOptionalTypeVariables,
165        ast_variants: &[swamp_ast::EnumVariantType],
166    ) {
167        let mut resolved_variants = SeqMap::new();
168
169        let mut new_enum_type = EnumType {
170            name: self.to_node(&enum_type_name.name),
171            assigned_name: self.get_text(&enum_type_name.name).to_string(),
172            module_path: vec![],
173            variants: SeqMap::default(),
174            instantiated_type_parameters: Vec::default(),
175        };
176
177        for (container_index_usize, ast_variant_type) in ast_variants.iter().enumerate() {
178            let variant_name_node = match ast_variant_type {
179                swamp_ast::EnumVariantType::Simple(name) => name,
180                swamp_ast::EnumVariantType::Direct(name, _) => name,
181                swamp_ast::EnumVariantType::Tuple(name, _) => name,
182                swamp_ast::EnumVariantType::Struct(name, _) => name,
183            };
184
185            let common = EnumVariantCommon {
186                name: self.to_node(variant_name_node),
187                assigned_name: self.get_text(variant_name_node).to_string(),
188                container_index: container_index_usize as u8,
189            };
190
191            let payload_type = match ast_variant_type {
192                swamp_ast::EnumVariantType::Simple(_variant_name_node) => self.types().unit(),
193                swamp_ast::EnumVariantType::Direct(_variant_name_node, direct_type) => {
194                    let analyzed_type = self.analyze_type(direct_type);
195                    // If the direct_type is actually a single-element tuple, unwrap it
196                    match &*analyzed_type.kind {
197                        TypeKind::Tuple(elements) if elements.len() == 1 => elements[0].clone(),
198                        _ => analyzed_type,
199                    }
200                }
201                swamp_ast::EnumVariantType::Tuple(_variant_name_node, types) => {
202                    let mut vec = Vec::new();
203                    for tuple_type in types {
204                        let resolved_type = self.analyze_type(tuple_type);
205                        vec.push(resolved_type);
206                    }
207
208                    // Single-element tuples should be treated as direct types
209                    if vec.len() == 1 {
210                        vec.into_iter().next().unwrap()
211                    } else {
212                        self.types().tuple(vec)
213                    }
214                }
215                swamp_ast::EnumVariantType::Struct(_variant_name_node, ast_struct_fields) => {
216                    let mut fields = SeqMap::new();
217
218                    for field_with_type in &ast_struct_fields.fields {
219                        let resolved_type = self.analyze_type(&field_with_type.field_type);
220                        let field_name_str =
221                            self.get_text(&field_with_type.field_name.0).to_string();
222
223                        let resolved_field = StructTypeField {
224                            identifier: Some(self.to_node(&field_with_type.field_name.0)),
225                            field_type: resolved_type,
226                        };
227
228                        if let Err(seq_map_err) = fields.insert(field_name_str, resolved_field) {
229                            return self.add_err(
230                                ErrorKind::DuplicateFieldName,
231                                &field_with_type.field_name.0,
232                            );
233                        }
234                    }
235
236                    let anonymous_struct_type = AnonymousStructType {
237                        field_name_sorted_fields: fields,
238                    };
239
240                    self.types().anonymous_struct(anonymous_struct_type)
241                }
242            };
243
244            let enum_variant_type = swamp_types::prelude::EnumVariantType {
245                common,
246                payload_type,
247            };
248
249            let variant_name_str = self.get_text(variant_name_node).to_string();
250
251            if let Err(_seq_map_err) = resolved_variants.insert(variant_name_str, enum_variant_type)
252            {
253                return self.add_err(ErrorKind::DuplicateFieldName, variant_name_node);
254            }
255        }
256
257        new_enum_type.variants = resolved_variants;
258
259        let enum_type_ref = self.shared.state.types.enum_type(new_enum_type);
260
261        if let Err(sem_err) = self
262            .shared
263            .definition_table
264            .add_named_type(enum_type_ref.clone())
265        {
266            return self.add_err(ErrorKind::SemanticError(sem_err), &enum_type_name.name);
267        }
268
269        if let Err(sem_err) = self
270            .shared
271            .lookup_table
272            .add_named_type(enum_type_ref.clone())
273        {
274            return self.add_err(ErrorKind::SemanticError(sem_err), &enum_type_name.name);
275        }
276
277        self.add_default_functions(&enum_type_ref, &enum_type_name.name);
278    }
279
280    /// # Errors
281    ///
282    pub fn analyze_alias_type_definition(&mut self, ast_alias: &swamp_ast::AliasType) -> AliasType {
283        let resolved_type = self.analyze_type(&ast_alias.referenced_type);
284
285        let alias_name_str = self.get_text(&ast_alias.identifier.0).to_string();
286        let resolved_alias = AliasType {
287            name: None,
288            ty: resolved_type,
289            assigned_name: alias_name_str,
290        };
291
292        let resolved_alias_ref = match self.shared.definition_table.add_alias(resolved_alias) {
293            Ok(re) => re,
294
295            Err(err) => {
296                self.add_err(ErrorKind::SemanticError(err), &ast_alias.identifier.0);
297                AliasType {
298                    name: None,
299                    assigned_name: "err".to_string(),
300                    ty: self.types().unit(),
301                }
302            }
303        };
304
305        if let Err(sem_err) = self
306            .shared
307            .lookup_table
308            .add_alias_link(resolved_alias_ref.clone())
309        {
310            self.add_err(ErrorKind::SemanticError(sem_err), &ast_alias.identifier.0);
311            AliasType {
312                name: None,
313                assigned_name: "err".to_string(),
314                ty: self.types().unit(),
315            }
316        } else {
317            resolved_alias_ref
318        }
319    }
320
321    /// # Errors
322    ///
323    pub fn analyze_anonymous_struct_type(
324        &mut self,
325        ast_struct: &swamp_ast::AnonymousStructType,
326    ) -> AnonymousStructType {
327        let resolved_fields = self.analyze_anonymous_struct_type_fields(&ast_struct.fields);
328
329        AnonymousStructType::new_and_sort_fields(&resolved_fields)
330    }
331
332    /// # Errors
333    ///
334    pub fn analyze_anonymous_struct_type_fields(
335        &mut self,
336        ast_struct_fields: &[swamp_ast::StructTypeField],
337    ) -> SeqMap<String, StructTypeField> {
338        let mut resolved_fields = SeqMap::new();
339
340        for field_name_and_type in ast_struct_fields {
341            let resolved_type = self.analyze_type(&field_name_and_type.field_type);
342            let name_string = self.get_text(&field_name_and_type.field_name.0).to_string();
343
344            if !resolved_type.can_be_stored_in_transient_field() {
345                self.add_err(ErrorKind::NeedStorage, &field_name_and_type.field_name.0);
346                return resolved_fields;
347            }
348
349            if !resolved_type.can_be_stored_in_field() {
350                self.add_hint(ErrorKind::NeedStorage, &field_name_and_type.field_name.0);
351            }
352
353            let field_type = StructTypeField {
354                identifier: Some(self.to_node(&field_name_and_type.field_name.0)),
355                field_type: resolved_type,
356            };
357
358            if let Err(_seq_map_err) = resolved_fields.insert(name_string, field_type) {
359                self.add_err(
360                    ErrorKind::DuplicateFieldName,
361                    &field_name_and_type.field_name.0,
362                );
363            }
364        }
365
366        resolved_fields
367    }
368
369    /// # Errors
370    ///
371    pub fn analyze_named_struct_type_definition(
372        &mut self,
373        ast_struct_def: &swamp_ast::NamedStructDef,
374    ) {
375        let struct_name_str = self.get_text(&ast_struct_def.identifier.name).to_string();
376
377        let fields = self.analyze_anonymous_struct_type_fields(&ast_struct_def.struct_type.fields);
378
379        let analyzed_anonymous_struct = AnonymousStructType::new(fields);
380
381        let anon_struct_type_ref = self
382            .shared
383            .state
384            .types
385            .anonymous_struct(analyzed_anonymous_struct);
386
387        let named_struct_type = NamedStructType {
388            name: self.to_node(&ast_struct_def.identifier.name),
389            anon_struct_type: anon_struct_type_ref,
390            assigned_name: struct_name_str,
391            module_path: self.shared.definition_table.module_path(),
392            instantiated_type_parameters: Vec::default(),
393        };
394
395        let named_struct_type_ref = self.shared.state.types.named_struct(named_struct_type);
396
397        match self
398            .shared
399            .definition_table
400            .add_named_type(named_struct_type_ref.clone())
401        {
402            Ok(()) => {}
403            Err(sem_err) => {
404                return self.add_err(
405                    ErrorKind::SemanticError(sem_err),
406                    &ast_struct_def.identifier.name,
407                );
408            }
409        }
410
411        match self
412            .shared
413            .lookup_table
414            .add_named_type(named_struct_type_ref.clone())
415        {
416            Ok(()) => {}
417            Err(sem_err) => {
418                return self.add_err(
419                    ErrorKind::SemanticError(sem_err),
420                    &ast_struct_def.identifier.name,
421                );
422            }
423        }
424
425        self.add_default_functions(&named_struct_type_ref, &ast_struct_def.identifier.name);
426    }
427
428    #[allow(clippy::too_many_lines)]
429    pub(crate) fn analyze_function_definition(
430        &mut self,
431        function: &swamp_ast::Function,
432        attributes: &Attributes,
433    ) -> Option<Function> {
434        let func = match &function {
435            swamp_ast::Function::Internal(function_data) => {
436                let parameters = self.analyze_parameters(&function_data.declaration.params);
437                let return_type = if let Some(found) = &function_data.declaration.return_type {
438                    let analyzed_return_type = self.analyze_type(found);
439                    if !analyzed_return_type.allowed_as_return_type() {
440                        self.add_err(
441                            ErrorKind::NotAllowedAsReturnType(analyzed_return_type),
442                            function.node(),
443                        );
444                        return None;
445                    }
446                    analyzed_return_type
447                } else {
448                    self.shared.state.types.unit()
449                };
450
451                for param in &parameters {
452                    let param_type = &param.resolved_type;
453                    let actual_type = param_type.clone();
454                    self.create_parameter_resolved(
455                        &param.node.as_ref().unwrap().name,
456                        param.node.as_ref().unwrap().is_mutable.as_ref(),
457                        &actual_type,
458                    );
459                }
460                let function_name = self
461                    .get_text(&function_data.declaration.name)
462                    .trim()
463                    .to_string();
464                let statements =
465                    self.analyze_function_body_expression(&function_data.body, &return_type);
466
467                let internal = InternalFunctionDefinition {
468                    signature: Signature {
469                        parameters,
470                        return_type,
471                    },
472                    body: statements,
473                    name: LocalIdentifier(self.to_node(&function_data.declaration.name)),
474                    assigned_name: self.get_text(&function_data.declaration.name).to_string(),
475                    associated_with_type: None,
476                    defined_in_module_path: self.module_path.clone(),
477                    function_variables: self.scope.total_scopes.clone(),
478                    program_unique_id: self.shared.state.allocate_internal_function_id(),
479                    attributes: attributes.clone(),
480                };
481
482                let function_ref = match self
483                    .shared
484                    .definition_table
485                    .add_internal_function(&function_name, internal)
486                {
487                    Ok(func_def) => func_def,
488                    Err(sem_err) => {
489                        self.add_err(
490                            ErrorKind::SemanticError(sem_err),
491                            &function_data.declaration.name,
492                        );
493                        return None;
494                    }
495                };
496
497                match self
498                    .shared
499                    .lookup_table
500                    .add_internal_function_link(&function_name, function_ref.clone())
501                {
502                    Ok(()) => {}
503                    Err(sem_err) => {
504                        self.add_err(
505                            ErrorKind::SemanticError(sem_err),
506                            &function_data.declaration.name,
507                        );
508                        return None;
509                    }
510                }
511
512                Function::Internal(function_ref)
513            }
514            swamp_ast::Function::External(int_node, ast_signature) => {
515                let parameters = self.analyze_parameters(&ast_signature.params);
516                let external_return_type = if let Some(found) = &ast_signature.return_type {
517                    self.analyze_type(found)
518                } else {
519                    self.shared.state.types.unit()
520                };
521
522                let return_type = external_return_type;
523
524                let int_string = self.get_text(int_node);
525                let external_function_id_int = Self::str_to_int(int_string).unwrap() as u32;
526
527                let external_function_id = external_function_id_int as ExternalFunctionId;
528
529                let external = ExternalFunctionDefinition {
530                    assigned_name: self.get_text(&ast_signature.name).to_string(),
531                    signature: Signature {
532                        parameters,
533                        return_type,
534                    },
535                    name: Some(self.to_node(&ast_signature.name)),
536                    id: external_function_id,
537                };
538
539                let function_ref = match self
540                    .shared
541                    .definition_table
542                    .add_external_function_declaration(external)
543                {
544                    Ok(func_ref) => func_ref,
545                    Err(sem_err) => {
546                        self.add_err(ErrorKind::SemanticError(sem_err), &ast_signature.name);
547                        return None;
548                    }
549                };
550
551                if let Err(sem_err) = self
552                    .shared
553                    .lookup_table
554                    .add_external_function_declaration_link(function_ref.clone())
555                {
556                    self.add_err(ErrorKind::SemanticError(sem_err), &ast_signature.name);
557                    return None;
558                }
559
560                Function::External(function_ref)
561            }
562        };
563
564        Some(func)
565    }
566
567    pub fn debug_definition(&self, definition: &swamp_ast::Definition) {
568        let (line, col) = self
569            .shared
570            .source_map
571            .get_span_location_utf8(self.shared.file_id, definition.node.span.offset as usize);
572        let source_line = self
573            .shared
574            .source_map
575            .get_source_line(self.shared.file_id, line)
576            .unwrap();
577        debug!(?line, ?col, ?source_line);
578    }
579
580    /// # Errors
581    ///
582    pub fn analyze_definition(&mut self, ast_def: &swamp_ast::Definition) {
583        //self.debug_definition(ast_def);
584
585        let analyzed_attributes = self.analyze_attributes(&ast_def.attributes);
586
587        match &ast_def.kind {
588            swamp_ast::DefinitionKind::NamedStructDef(ast_struct) => {
589                self.analyze_named_struct_type_definition(ast_struct);
590            }
591            swamp_ast::DefinitionKind::AliasDef(alias_def) => {
592                self.analyze_alias_type_definition(alias_def);
593            }
594            swamp_ast::DefinitionKind::EnumDef(identifier, variants) => {
595                self.analyze_enum_type_definition(identifier, variants);
596            }
597            swamp_ast::DefinitionKind::FunctionDef(function) => {
598                let _resolved_return_type = self.analyze_return_type(function);
599                self.start_function();
600                self.analyze_function_definition(function, &analyzed_attributes);
601                self.stop_function();
602            }
603            swamp_ast::DefinitionKind::ImplDef(type_identifier, functions) => {
604                self.analyze_impl_definition(type_identifier, functions);
605            }
606            swamp_ast::DefinitionKind::Mod(mod_info) => self.analyze_mod_definition(mod_info),
607            swamp_ast::DefinitionKind::Use(use_info) => self.analyze_use_definition(use_info),
608            swamp_ast::DefinitionKind::Constant(const_info) => {
609                self.analyze_constant_definition(const_info);
610            }
611        }
612    }
613
614    fn analyze_impl_definition(
615        &mut self,
616        attached_to_type: &swamp_ast::LocalTypeIdentifierWithOptionalTypeVariables,
617        functions: &[swamp_ast::Function],
618    ) {
619        let converted_type_variables_to_ast_types = attached_to_type
620            .type_variables
621            .iter()
622            .map(|x| {
623                swamp_ast::GenericParameter::Type(swamp_ast::Type::Named(
624                    swamp_ast::QualifiedTypeIdentifier {
625                        name: swamp_ast::LocalTypeIdentifier(x.0.clone()),
626                        module_path: None,
627                        generic_params: vec![],
628                    },
629                ))
630            })
631            .collect();
632
633        let qualified = swamp_ast::QualifiedTypeIdentifier {
634            name: swamp_ast::LocalTypeIdentifier(attached_to_type.name.clone()),
635            module_path: None,
636            generic_params: converted_type_variables_to_ast_types,
637        };
638
639        let maybe_type_to_attach_to = Some(self.analyze_named_type(&qualified));
640        if let Some(type_to_attach_to) = maybe_type_to_attach_to {
641            let function_refs: Vec<&swamp_ast::Function> = functions.iter().collect();
642            self.analyze_impl_functions(&type_to_attach_to, &function_refs);
643        } else {
644            self.add_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: &TypeRef,
656        functions: &[&swamp_ast::Function],
657    ) {
658        if !self
659            .shared
660            .state
661            .associated_impls
662            .is_prepared(attach_to_type)
663        {
664            self.shared.state.associated_impls.prepare(attach_to_type);
665        }
666
667        for function in functions {
668            self.start_function();
669
670            let function_name = match function {
671                swamp_ast::Function::Internal(function_with_body) => {
672                    &function_with_body.declaration
673                }
674                swamp_ast::Function::External(_, external_declaration) => external_declaration,
675            };
676
677            let function_name_str = self.get_text(&function_name.name).to_string();
678
679            let existing_function_id = if matches!(
680                function_name_str.as_str(),
681                "to_string" | "to_short_string" | "to_pretty_string" | "default"
682            ) {
683                self.shared
684                    .state
685                    .associated_impls
686                    .get_internal_member_function(attach_to_type, &function_name_str)
687                    .map(|existing_fn| existing_fn.program_unique_id)
688            } else {
689                None
690            };
691
692            let resolved_function =
693                self.analyze_impl_func(function, attach_to_type, existing_function_id);
694
695            let resolved_function_ref = Rc::new(resolved_function);
696
697            self.stop_function();
698
699            let is_built_in = matches!(
700                function_name_str.as_str(),
701                "to_string" | "to_short_string" | "to_pretty_string" | "default"
702            );
703            if is_built_in {
704                self.shared
705                    .state
706                    .associated_impls
707                    .remove_internal_function_if_exists(attach_to_type, &function_name_str);
708            }
709
710            if let Err(sem_err) = self.shared.state.associated_impls.add_member_function(
711                attach_to_type,
712                &function_name_str,
713                resolved_function_ref,
714            ) {
715                return self.add_err(ErrorKind::SemanticError(sem_err), &function_name.name);
716            }
717        }
718    }
719
720    #[allow(clippy::too_many_lines)]
721    fn analyze_impl_func(
722        &mut self,
723        function: &swamp_ast::Function,
724        self_type: &TypeRef,
725        existing_function_id: Option<InternalFunctionId>,
726    ) -> Function {
727        match function {
728            swamp_ast::Function::Internal(function_data) => {
729                let mut parameters = Vec::new();
730
731                if let Some(found_self) = &function_data.declaration.self_parameter {
732                    let actual_self_type = self_type.clone();
733                    parameters.push(TypeForParameter {
734                        name: self.get_text(&found_self.self_node).to_string(),
735                        resolved_type: actual_self_type,
736                        is_mutable: found_self.is_mutable.is_some(),
737                        node: Option::from(ParameterNode {
738                            name: self.to_node(&found_self.self_node),
739                            is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
740                        }),
741                    });
742                }
743
744                for param in &function_data.declaration.params {
745                    let resolved_type = self.analyze_type(&param.param_type);
746
747                    let resolved_param = TypeForParameter {
748                        name: self.get_text(&param.variable.name).to_string(),
749                        resolved_type,
750                        is_mutable: param.variable.is_mutable.is_some(),
751                        node: Option::from(ParameterNode {
752                            name: self.to_node(&param.variable.name),
753                            is_mutable: self
754                                .to_node_option(Option::from(&param.variable.is_mutable)),
755                        }),
756                    };
757
758                    parameters.push(resolved_param);
759                }
760
761                let return_type =
762                    if let Some(ast_return_type) = &function_data.declaration.return_type {
763                        self.analyze_type(ast_return_type)
764                    } else {
765                        self.shared.state.types.unit()
766                    };
767
768                for param in &parameters {
769                    self.create_parameter_resolved(
770                        &param.node.as_ref().unwrap().name,
771                        param.node.as_ref().unwrap().is_mutable.as_ref(),
772                        &param.resolved_type.clone(),
773                    );
774                }
775
776                let statements =
777                    self.analyze_function_body_expression(&function_data.body, &return_type);
778
779                let attributes = self.analyze_attributes(&function_data.attributes);
780
781                let internal = InternalFunctionDefinition {
782                    signature: Signature {
783                        parameters,
784                        return_type,
785                    },
786                    body: statements,
787                    name: LocalIdentifier(self.to_node(&function_data.declaration.name)),
788                    assigned_name: self.get_text(&function_data.declaration.name).to_string(),
789                    defined_in_module_path: self.module_path.clone(),
790                    associated_with_type: Some(self_type.clone()),
791                    function_variables: self.scope.total_scopes.clone(),
792                    program_unique_id: existing_function_id
793                        .unwrap_or_else(|| self.shared.state.allocate_internal_function_id()),
794                    attributes,
795                };
796
797                let internal_ref = Rc::new(internal);
798
799                Function::Internal(internal_ref)
800            }
801
802            swamp_ast::Function::External(int_node, signature) => {
803                let mut parameters = Vec::new();
804
805                if let Some(found_self) = &signature.self_parameter {
806                    let param = TypeForParameter {
807                        name: self.get_text(&found_self.self_node).to_string(),
808                        resolved_type: self_type.clone(),
809                        is_mutable: found_self.is_mutable.is_some(),
810                        node: Option::from(ParameterNode {
811                            name: self.to_node(&found_self.self_node),
812                            is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
813                        }),
814                    };
815
816                    parameters.push(param);
817                }
818
819                for param in &signature.params {
820                    let resolved_type = self.analyze_type(&param.param_type);
821
822                    parameters.push(TypeForParameter {
823                        name: self.get_text(&param.variable.name).to_string(),
824                        resolved_type,
825                        is_mutable: param.variable.is_mutable.is_some(),
826                        node: Option::from(ParameterNode {
827                            name: self.to_node(&param.variable.name),
828                            is_mutable: self
829                                .to_node_option(Option::from(&param.variable.is_mutable)),
830                        }),
831                    });
832                }
833
834                let return_type = self.analyze_maybe_type(Option::from(&signature.return_type));
835
836                let int_string = self.get_text(int_node);
837                let external_function_id_int = Self::str_to_int(int_string).unwrap() as u32;
838
839                let external_function_id = external_function_id_int as ExternalFunctionId;
840
841                let external = ExternalFunctionDefinition {
842                    assigned_name: self.get_text(&signature.name).to_string(),
843                    name: Some(self.to_node(&signature.name)),
844                    signature: Signature {
845                        parameters,
846                        return_type,
847                    },
848                    id: external_function_id,
849                };
850
851                let external_ref = Rc::new(external);
852
853                Function::External(external_ref)
854            }
855        }
856    }
857
858    // Helper method to check if a type needs any string functions
859    fn needs_any_string_functions(&self, ty: &TypeRef) -> bool {
860        let should_have_string_functions = matches!(
861            &*ty.kind,
862            TypeKind::Enum(_)
863                | TypeKind::NamedStruct(_)
864                | TypeKind::AnonymousStruct(_)
865                | TypeKind::Tuple(_)
866                | TypeKind::FixedCapacityAndLengthArray(_, _)
867                | TypeKind::SliceView(_)
868                | TypeKind::DynamicLengthVecView(_)
869                | TypeKind::VecStorage(_, _)
870                | TypeKind::StackView(_)
871                | TypeKind::QueueView(_)
872                | TypeKind::StringStorage(_, _, _)
873                | TypeKind::StackStorage(_, _)
874                | TypeKind::QueueStorage(_, _)
875                | TypeKind::SparseView(_)
876                | TypeKind::SparseStorage(_, _)
877                | TypeKind::GridView(_)
878                | TypeKind::GridStorage(_, _, _)
879                | TypeKind::MapStorage(_, _, _)
880                | TypeKind::DynamicLengthMapView(_, _)
881                | TypeKind::Optional(_)
882        );
883
884        if !should_have_string_functions {
885            return false;
886        }
887
888        if !self.shared.state.associated_impls.is_prepared(ty) {
889            return true;
890        }
891
892        let has_to_string = self
893            .shared
894            .state
895            .associated_impls
896            .get_internal_member_function(ty, "to_string")
897            .is_some();
898
899        let has_to_short_string = self
900            .shared
901            .state
902            .associated_impls
903            .get_internal_member_function(ty, "to_short_string")
904            .is_some();
905
906        let has_to_pretty_string = self
907            .shared
908            .state
909            .associated_impls
910            .get_internal_member_function(ty, "to_pretty_string")
911            .is_some();
912
913        !has_to_string || !has_to_short_string || !has_to_pretty_string
914    }
915
916    pub fn add_default_functions(&mut self, type_to_attach_to: &TypeRef, node: &swamp_ast::Node) {
917        if let TypeKind::Enum(enum_type) = &*type_to_attach_to.kind {
918            for (_, variant) in &enum_type.variants {
919                if !matches!(&*variant.payload_type.kind, TypeKind::Unit)
920                    && !TypeRef::ptr_eq(&variant.payload_type, type_to_attach_to)
921                {
922                    let needs_string_functions =
923                        self.needs_any_string_functions(&variant.payload_type);
924
925                    if needs_string_functions {
926                        self.add_default_functions(&variant.payload_type, node);
927                    }
928                }
929            }
930        }
931
932        let underlying = type_to_attach_to;
933
934        if self.needs_any_string_functions(underlying) {
935            if !self
936                .shared
937                .state
938                .associated_impls
939                .is_prepared(type_to_attach_to)
940            {
941                self.shared
942                    .state
943                    .associated_impls
944                    .prepare(type_to_attach_to);
945            }
946
947            if self
948                .shared
949                .state
950                .associated_impls
951                .get_internal_member_function(underlying, "to_string")
952                .is_none()
953            {
954                let to_string_function =
955                    self.generate_to_string_function_for_type(type_to_attach_to, node);
956                self.shared
957                    .state
958                    .associated_impls
959                    .add_internal_function(type_to_attach_to, to_string_function)
960                    .unwrap();
961            }
962
963            if self
964                .shared
965                .state
966                .associated_impls
967                .get_internal_member_function(underlying, "to_short_string")
968                .is_none()
969            {
970                let to_short_string_function =
971                    self.generate_to_short_string_function_for_type(type_to_attach_to, node);
972                self.shared
973                    .state
974                    .associated_impls
975                    .add_internal_function(type_to_attach_to, to_short_string_function)
976                    .unwrap();
977            }
978
979            if self
980                .shared
981                .state
982                .associated_impls
983                .get_internal_member_function(underlying, "to_pretty_string")
984                .is_none()
985            {
986                let to_pretty_string_function =
987                    self.generate_to_pretty_string_function_for_type(type_to_attach_to, node);
988                self.shared
989                    .state
990                    .associated_impls
991                    .add_internal_function(type_to_attach_to, to_pretty_string_function)
992                    .unwrap();
993            }
994        }
995    }
996
997    fn generate_to_string_function_for_type(
998        &mut self,
999        ty: &TypeRef,
1000        ast_node: &Node,
1001    ) -> InternalFunctionDefinition {
1002        let node = self.to_node(ast_node);
1003        let mut generator = ExpressionGenerator::new(
1004            &mut self.shared.state.types,
1005            &self.shared.state.associated_impls,
1006        );
1007        internal_generate_to_string_function_for_type(
1008            &mut generator,
1009            &mut self.shared.state.internal_function_id_allocator,
1010            &self.module_path,
1011            ty,
1012            &node,
1013            false,
1014        )
1015    }
1016
1017    fn generate_to_short_string_function_for_type(
1018        &mut self,
1019        ty: &TypeRef,
1020        ast_node: &Node,
1021    ) -> InternalFunctionDefinition {
1022        let node = self.to_node(ast_node);
1023        let mut generator = ExpressionGenerator::new(
1024            &mut self.shared.state.types,
1025            &self.shared.state.associated_impls,
1026        );
1027        internal_generate_to_short_string_function_for_type(
1028            &mut generator,
1029            &mut self.shared.state.internal_function_id_allocator,
1030            &self.module_path,
1031            ty,
1032            &node,
1033        )
1034    }
1035
1036    fn generate_to_pretty_string_function_for_type(
1037        &mut self,
1038        ty: &TypeRef,
1039        ast_node: &Node,
1040    ) -> InternalFunctionDefinition {
1041        let node = self.to_node(ast_node);
1042        let mut generator = ExpressionGenerator::new(
1043            &mut self.shared.state.types,
1044            &self.shared.state.associated_impls,
1045        );
1046        internal_generate_to_pretty_string_function_for_type(
1047            &mut generator,
1048            &mut self.shared.state.internal_function_id_allocator,
1049            &self.module_path,
1050            ty,
1051            &node,
1052        )
1053    }
1054}