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::Tuple(name, _) => name,
181                swamp_ast::EnumVariantType::Struct(name, _) => name,
182            };
183
184            let common = EnumVariantCommon {
185                name: self.to_node(variant_name_node),
186                assigned_name: self.get_text(variant_name_node).to_string(),
187                container_index: container_index_usize as u8,
188            };
189
190            let payload_type = match ast_variant_type {
191                swamp_ast::EnumVariantType::Simple(_variant_name_node) => self.types().unit(),
192                swamp_ast::EnumVariantType::Tuple(_variant_name_node, types) => {
193                    let mut vec = Vec::new();
194                    for tuple_type in types {
195                        let resolved_type = self.analyze_type(tuple_type);
196                        vec.push(resolved_type);
197                    }
198
199                    self.types().tuple(vec)
200                }
201                swamp_ast::EnumVariantType::Struct(_variant_name_node, ast_struct_fields) => {
202                    let mut fields = SeqMap::new();
203
204                    for field_with_type in &ast_struct_fields.fields {
205                        // TODO: Check the index
206                        let resolved_type = self.analyze_type(&field_with_type.field_type);
207                        let field_name_str =
208                            self.get_text(&field_with_type.field_name.0).to_string();
209
210                        let resolved_field = StructTypeField {
211                            identifier: Some(self.to_node(&field_with_type.field_name.0)),
212                            field_type: resolved_type,
213                        };
214
215                        if let Err(seq_map_err) = fields.insert(field_name_str, resolved_field) {
216                            return self.add_err(
217                                ErrorKind::DuplicateFieldName,
218                                &field_with_type.field_name.0,
219                            );
220                        }
221                    }
222
223                    let anonymous_struct_type = AnonymousStructType {
224                        field_name_sorted_fields: fields,
225                    };
226
227                    self.types().anonymous_struct(anonymous_struct_type)
228                }
229            };
230
231            let enum_variant_type = swamp_types::prelude::EnumVariantType {
232                common,
233                payload_type,
234            };
235
236            let variant_name_str = self.get_text(variant_name_node).to_string();
237
238            if let Err(_seq_map_err) = resolved_variants.insert(variant_name_str, enum_variant_type)
239            {
240                return self.add_err(ErrorKind::DuplicateFieldName, variant_name_node);
241            }
242        }
243
244        new_enum_type.variants = resolved_variants;
245
246        let enum_type_ref = self.shared.state.types.enum_type(new_enum_type);
247
248        if let Err(sem_err) = self
249            .shared
250            .definition_table
251            .add_named_type(enum_type_ref.clone())
252        {
253            return self.add_err(ErrorKind::SemanticError(sem_err), &enum_type_name.name);
254        }
255
256        if let Err(sem_err) = self
257            .shared
258            .lookup_table
259            .add_named_type(enum_type_ref.clone())
260        {
261            return self.add_err(ErrorKind::SemanticError(sem_err), &enum_type_name.name);
262        }
263
264        self.add_default_functions(&enum_type_ref, &enum_type_name.name);
265    }
266
267    /// # Errors
268    ///
269    pub fn analyze_alias_type_definition(&mut self, ast_alias: &swamp_ast::AliasType) -> AliasType {
270        let resolved_type = self.analyze_type(&ast_alias.referenced_type);
271
272        let alias_name_str = self.get_text(&ast_alias.identifier.0).to_string();
273        let resolved_alias = AliasType {
274            name: None,
275            ty: resolved_type,
276            assigned_name: alias_name_str,
277        };
278
279        let resolved_alias_ref = match self.shared.definition_table.add_alias(resolved_alias) {
280            Ok(re) => re,
281
282            Err(err) => {
283                self.add_err(ErrorKind::SemanticError(err), &ast_alias.identifier.0);
284                AliasType {
285                    name: None,
286                    assigned_name: "err".to_string(),
287                    ty: self.types().unit(),
288                }
289            }
290        };
291
292        if let Err(sem_err) = self
293            .shared
294            .lookup_table
295            .add_alias_link(resolved_alias_ref.clone())
296        {
297            self.add_err(ErrorKind::SemanticError(sem_err), &ast_alias.identifier.0);
298            AliasType {
299                name: None,
300                assigned_name: "err".to_string(),
301                ty: self.types().unit(),
302            }
303        } else {
304            resolved_alias_ref
305        }
306    }
307
308    /// # Errors
309    ///
310    pub fn analyze_anonymous_struct_type(
311        &mut self,
312        ast_struct: &swamp_ast::AnonymousStructType,
313    ) -> AnonymousStructType {
314        let resolved_fields = self.analyze_anonymous_struct_type_fields(&ast_struct.fields);
315
316        AnonymousStructType::new_and_sort_fields(&resolved_fields)
317    }
318
319    /// # Errors
320    ///
321    pub fn analyze_anonymous_struct_type_fields(
322        &mut self,
323        ast_struct_fields: &[swamp_ast::StructTypeField],
324    ) -> SeqMap<String, StructTypeField> {
325        let mut resolved_fields = SeqMap::new();
326
327        for field_name_and_type in ast_struct_fields {
328            let resolved_type = self.analyze_type(&field_name_and_type.field_type);
329            let name_string = self.get_text(&field_name_and_type.field_name.0).to_string();
330
331            let field_type = StructTypeField {
332                identifier: Some(self.to_node(&field_name_and_type.field_name.0)),
333                field_type: resolved_type,
334            };
335
336            if let Err(_seq_map_err) = resolved_fields.insert(name_string, field_type) {
337                self.add_err(
338                    ErrorKind::DuplicateFieldName,
339                    &field_name_and_type.field_name.0,
340                );
341            }
342        }
343
344        resolved_fields
345    }
346
347    /// # Errors
348    ///
349    pub fn analyze_named_struct_type_definition(
350        &mut self,
351        ast_struct_def: &swamp_ast::NamedStructDef,
352    ) {
353        let struct_name_str = self.get_text(&ast_struct_def.identifier.name).to_string();
354
355        let fields = 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        // Create a TypeRef for the anonymous struct to enable deduplication
360        let anon_struct_type_ref = self
361            .shared
362            .state
363            .types
364            .anonymous_struct(analyzed_anonymous_struct);
365
366        let named_struct_type = NamedStructType {
367            name: self.to_node(&ast_struct_def.identifier.name),
368            anon_struct_type: anon_struct_type_ref,
369            assigned_name: struct_name_str,
370            module_path: self.shared.definition_table.module_path(),
371            instantiated_type_parameters: Vec::default(),
372        };
373
374        let named_struct_type_ref = self.shared.state.types.named_struct(named_struct_type);
375
376        match self
377            .shared
378            .definition_table
379            .add_named_type(named_struct_type_ref.clone())
380        {
381            Ok(()) => {}
382            Err(sem_err) => {
383                return self.add_err(
384                    ErrorKind::SemanticError(sem_err),
385                    &ast_struct_def.identifier.name,
386                );
387            }
388        }
389
390        match self
391            .shared
392            .lookup_table
393            .add_named_type(named_struct_type_ref.clone())
394        {
395            Ok(()) => {}
396            Err(sem_err) => {
397                return self.add_err(
398                    ErrorKind::SemanticError(sem_err),
399                    &ast_struct_def.identifier.name,
400                );
401            }
402        }
403
404        self.add_default_functions(&named_struct_type_ref, &ast_struct_def.identifier.name);
405    }
406
407    #[allow(clippy::too_many_lines)]
408    pub(crate) fn analyze_function_definition(
409        &mut self,
410        function: &swamp_ast::Function,
411        attributes: &Attributes,
412    ) -> Option<Function> {
413        let func = match &function {
414            swamp_ast::Function::Internal(function_data) => {
415                let parameters = self.analyze_parameters(&function_data.declaration.params);
416                let return_type = if let Some(found) = &function_data.declaration.return_type {
417                    let analyzed_return_type = self.analyze_type(found);
418                    if !analyzed_return_type.allowed_as_return_type() {
419                        self.add_err(
420                            ErrorKind::NotAllowedAsReturnType(analyzed_return_type),
421                            function.node(),
422                        );
423                        return None;
424                    }
425                    analyzed_return_type
426                } else {
427                    self.shared.state.types.unit()
428                };
429
430                // Set up scope for function body
431                for param in &parameters {
432                    let param_type = &param.resolved_type;
433                    let actual_type = param_type.clone();
434                    self.create_parameter_resolved(
435                        &param.node.as_ref().unwrap().name,
436                        param.node.as_ref().unwrap().is_mutable.as_ref(),
437                        &actual_type,
438                    );
439                }
440                let function_name = self
441                    .get_text(&function_data.declaration.name)
442                    .trim()
443                    .to_string();
444                let statements =
445                    self.analyze_function_body_expression(&function_data.body, &return_type);
446
447                let internal = InternalFunctionDefinition {
448                    signature: Signature {
449                        parameters,
450                        return_type,
451                    },
452                    body: statements,
453                    name: LocalIdentifier(self.to_node(&function_data.declaration.name)),
454                    assigned_name: self.get_text(&function_data.declaration.name).to_string(),
455                    associated_with_type: None,
456                    defined_in_module_path: self.module_path.clone(),
457                    function_variables: self.scope.total_scopes.clone(),
458                    program_unique_id: self.shared.state.allocate_internal_function_id(),
459                    attributes: attributes.clone(),
460                };
461
462                let function_ref = match self
463                    .shared
464                    .definition_table
465                    .add_internal_function(&function_name, internal)
466                {
467                    Ok(func_def) => func_def,
468                    Err(sem_err) => {
469                        self.add_err(
470                            ErrorKind::SemanticError(sem_err),
471                            &function_data.declaration.name,
472                        );
473                        return None;
474                    }
475                };
476
477                match self
478                    .shared
479                    .lookup_table
480                    .add_internal_function_link(&function_name, function_ref.clone())
481                {
482                    Ok(()) => {}
483                    Err(sem_err) => {
484                        self.add_err(
485                            ErrorKind::SemanticError(sem_err),
486                            &function_data.declaration.name,
487                        );
488                        return None;
489                    }
490                }
491
492                Function::Internal(function_ref)
493            }
494            swamp_ast::Function::External(int_node, ast_signature) => {
495                let parameters = self.analyze_parameters(&ast_signature.params);
496                let external_return_type = if let Some(found) = &ast_signature.return_type {
497                    self.analyze_type(found)
498                } else {
499                    self.shared.state.types.unit()
500                };
501
502                let return_type = external_return_type;
503
504                let int_string = self.get_text(int_node);
505                let external_function_id_int = Self::str_to_int(int_string).unwrap() as u32;
506
507                let external_function_id = external_function_id_int as ExternalFunctionId; //self.shared.state.allocate_external_function_id();
508
509                let external = ExternalFunctionDefinition {
510                    assigned_name: self.get_text(&ast_signature.name).to_string(),
511                    signature: Signature {
512                        parameters,
513                        return_type,
514                    },
515                    name: Some(self.to_node(&ast_signature.name)),
516                    id: external_function_id,
517                };
518
519                let function_ref = match self
520                    .shared
521                    .definition_table
522                    .add_external_function_declaration(external)
523                {
524                    Ok(func_ref) => func_ref,
525                    Err(sem_err) => {
526                        self.add_err(ErrorKind::SemanticError(sem_err), &ast_signature.name);
527                        return None;
528                    }
529                };
530
531                if let Err(sem_err) = self
532                    .shared
533                    .lookup_table
534                    .add_external_function_declaration_link(function_ref.clone())
535                {
536                    self.add_err(ErrorKind::SemanticError(sem_err), &ast_signature.name);
537                    return None;
538                }
539
540                Function::External(function_ref)
541            }
542        };
543
544        Some(func)
545    }
546
547    pub fn debug_definition(&self, definition: &swamp_ast::Definition) {
548        let (line, col) = self
549            .shared
550            .source_map
551            .get_span_location_utf8(self.shared.file_id, definition.node.span.offset as usize);
552        let source_line = self
553            .shared
554            .source_map
555            .get_source_line(self.shared.file_id, line)
556            .unwrap();
557        debug!(?line, ?col, ?source_line);
558    }
559
560    /// # Errors
561    ///
562    pub fn analyze_definition(&mut self, ast_def: &swamp_ast::Definition) {
563        //self.debug_definition(ast_def);
564
565        let analyzed_attributes = self.analyze_attributes(&ast_def.attributes);
566
567        match &ast_def.kind {
568            swamp_ast::DefinitionKind::NamedStructDef(ast_struct) => {
569                self.analyze_named_struct_type_definition(ast_struct);
570            }
571            swamp_ast::DefinitionKind::AliasDef(alias_def) => {
572                self.analyze_alias_type_definition(alias_def);
573            }
574            swamp_ast::DefinitionKind::EnumDef(identifier, variants) => {
575                self.analyze_enum_type_definition(identifier, variants);
576            }
577            swamp_ast::DefinitionKind::FunctionDef(function) => {
578                let _resolved_return_type = self.analyze_return_type(function);
579                self.start_function();
580                self.analyze_function_definition(function, &analyzed_attributes);
581                self.stop_function();
582            }
583            swamp_ast::DefinitionKind::ImplDef(type_identifier, functions) => {
584                self.analyze_impl_definition(type_identifier, functions);
585            }
586            swamp_ast::DefinitionKind::Mod(mod_info) => self.analyze_mod_definition(mod_info),
587            swamp_ast::DefinitionKind::Use(use_info) => self.analyze_use_definition(use_info),
588            swamp_ast::DefinitionKind::Constant(const_info) => {
589                self.analyze_constant_definition(const_info);
590            }
591        }
592    }
593
594    fn analyze_impl_definition(
595        &mut self,
596        attached_to_type: &swamp_ast::LocalTypeIdentifierWithOptionalTypeVariables,
597        functions: &[swamp_ast::Function],
598    ) {
599        let type_name_text = self.get_text(&attached_to_type.name).to_string();
600
601        let converted_type_variables_to_ast_types = attached_to_type
602            .type_variables
603            .iter()
604            .map(|x| {
605                swamp_ast::GenericParameter::Type(swamp_ast::Type::Named(
606                    swamp_ast::QualifiedTypeIdentifier {
607                        name: swamp_ast::LocalTypeIdentifier(x.0.clone()),
608                        module_path: None,
609                        generic_params: vec![],
610                    },
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 maybe_type_to_attach_to = Some(self.analyze_named_type(&qualified));
622        if let Some(type_to_attach_to) = maybe_type_to_attach_to {
623            let function_refs: Vec<&swamp_ast::Function> = functions.iter().collect();
624            self.analyze_impl_functions(&type_to_attach_to, &function_refs);
625        } else {
626            self.add_err(
627                ErrorKind::CanNotAttachFunctionsToType,
628                &attached_to_type.name,
629            );
630        }
631    }
632
633    /// # Errors
634    ///
635    pub fn analyze_impl_functions(
636        &mut self,
637        attach_to_type: &TypeRef, // Needed for self
638        functions: &[&swamp_ast::Function],
639    ) {
640        if !self
641            .shared
642            .state
643            .associated_impls
644            .is_prepared(attach_to_type)
645        {
646            self.shared.state.associated_impls.prepare(attach_to_type);
647        }
648
649        for function in functions {
650            self.start_function();
651
652            let function_name = match function {
653                swamp_ast::Function::Internal(function_with_body) => {
654                    &function_with_body.declaration
655                }
656                swamp_ast::Function::External(_, external_declaration) => external_declaration,
657            };
658
659            let function_name_str = self.get_text(&function_name.name).to_string();
660            //            info!(function_name_str, "impl function");
661
662            // Check if this is a built-in function and if there's already an existing function to reuse its ID
663            let existing_function_id = if matches!(
664                function_name_str.as_str(),
665                "to_string" | "to_short_string" | "to_pretty_string" | "default"
666            ) {
667                self.shared
668                    .state
669                    .associated_impls
670                    .get_internal_member_function(attach_to_type, &function_name_str)
671                    .map(|existing_fn| existing_fn.program_unique_id)
672            } else {
673                None
674            };
675
676            let resolved_function =
677                self.analyze_impl_func(function, attach_to_type, existing_function_id);
678
679            let resolved_function_ref = Rc::new(resolved_function);
680
681            self.stop_function();
682
683            let is_built_in = matches!(
684                function_name_str.as_str(),
685                "to_string" | "to_short_string" | "to_pretty_string" | "default"
686            );
687            if is_built_in {
688                // For built-in functions, we reuse the existing function ID to preserve references
689                // The function replacement happens in add_member_function below
690                self.shared
691                    .state
692                    .associated_impls
693                    .remove_internal_function_if_exists(attach_to_type, &function_name_str);
694            }
695
696            if let Err(sem_err) = self.shared.state.associated_impls.add_member_function(
697                attach_to_type,
698                &function_name_str,
699                resolved_function_ref,
700            ) {
701                return self.add_err(ErrorKind::SemanticError(sem_err), &function_name.name);
702            }
703        }
704    }
705
706    #[allow(clippy::too_many_lines)]
707    fn analyze_impl_func(
708        &mut self,
709        function: &swamp_ast::Function,
710        self_type: &TypeRef,
711        existing_function_id: Option<InternalFunctionId>,
712    ) -> Function {
713        match function {
714            swamp_ast::Function::Internal(function_data) => {
715                let mut parameters = Vec::new();
716
717                if let Some(found_self) = &function_data.declaration.self_parameter {
718                    let actual_self_type = self_type.clone();
719                    parameters.push(TypeForParameter {
720                        name: self.get_text(&found_self.self_node).to_string(),
721                        resolved_type: actual_self_type,
722                        is_mutable: found_self.is_mutable.is_some(),
723                        node: Option::from(ParameterNode {
724                            name: self.to_node(&found_self.self_node),
725                            is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
726                        }),
727                    });
728                }
729
730                for param in &function_data.declaration.params {
731                    let resolved_type = self.analyze_type(&param.param_type);
732
733                    let resolved_param = TypeForParameter {
734                        name: self.get_text(&param.variable.name).to_string(),
735                        resolved_type,
736                        is_mutable: param.variable.is_mutable.is_some(),
737                        node: Option::from(ParameterNode {
738                            name: self.to_node(&param.variable.name),
739                            is_mutable: self
740                                .to_node_option(Option::from(&param.variable.is_mutable)),
741                        }),
742                    };
743                    // TODO: Add back concrete type checking when public method is available
744
745                    parameters.push(resolved_param);
746                }
747
748                let return_type =
749                    if let Some(ast_return_type) = &function_data.declaration.return_type {
750                        self.analyze_type(ast_return_type)
751                    } else {
752                        self.shared.state.types.unit()
753                    };
754
755                for param in &parameters {
756                    self.create_parameter_resolved(
757                        &param.node.as_ref().unwrap().name,
758                        param.node.as_ref().unwrap().is_mutable.as_ref(),
759                        &param.resolved_type.clone(),
760                    );
761                }
762
763                let statements =
764                    self.analyze_function_body_expression(&function_data.body, &return_type);
765
766                let attributes = self.analyze_attributes(&function_data.attributes);
767
768                let internal = InternalFunctionDefinition {
769                    signature: Signature {
770                        parameters,
771                        return_type,
772                    },
773                    body: statements,
774                    name: LocalIdentifier(self.to_node(&function_data.declaration.name)),
775                    assigned_name: self.get_text(&function_data.declaration.name).to_string(),
776                    defined_in_module_path: self.module_path.clone(),
777                    associated_with_type: Some(self_type.clone()),
778                    //variable_scopes: self.scope.clone(),
779                    function_variables: self.scope.total_scopes.clone(),
780                    program_unique_id: existing_function_id
781                        .unwrap_or_else(|| self.shared.state.allocate_internal_function_id()),
782                    attributes,
783                };
784
785                let internal_ref = Rc::new(internal);
786
787                Function::Internal(internal_ref)
788            }
789
790            swamp_ast::Function::External(int_node, signature) => {
791                let mut parameters = Vec::new();
792
793                if let Some(found_self) = &signature.self_parameter {
794                    let param = TypeForParameter {
795                        name: self.get_text(&found_self.self_node).to_string(),
796                        resolved_type: self_type.clone(),
797                        is_mutable: found_self.is_mutable.is_some(),
798                        node: Option::from(ParameterNode {
799                            name: self.to_node(&found_self.self_node),
800                            is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
801                        }),
802                    };
803
804                    parameters.push(param);
805                }
806
807                // Handle parameters, including self if present
808                for param in &signature.params {
809                    let resolved_type = self.analyze_type(&param.param_type);
810
811                    parameters.push(TypeForParameter {
812                        name: self.get_text(&param.variable.name).to_string(),
813                        resolved_type,
814                        is_mutable: param.variable.is_mutable.is_some(),
815                        node: Option::from(ParameterNode {
816                            name: self.to_node(&param.variable.name),
817                            is_mutable: self
818                                .to_node_option(Option::from(&param.variable.is_mutable)),
819                        }),
820                    });
821                }
822
823                let return_type = self.analyze_maybe_type(Option::from(&signature.return_type));
824
825                let int_string = self.get_text(int_node);
826                let external_function_id_int = Self::str_to_int(int_string).unwrap() as u32;
827
828                let external_function_id = external_function_id_int as ExternalFunctionId; //self.shared.state.allocate_external_function_id();
829
830                let external = ExternalFunctionDefinition {
831                    assigned_name: self.get_text(&signature.name).to_string(),
832                    name: Some(self.to_node(&signature.name)),
833                    signature: Signature {
834                        parameters,
835                        return_type,
836                    },
837                    id: external_function_id,
838                };
839
840                let external_ref = Rc::new(external);
841
842                Function::External(external_ref)
843            }
844        }
845    }
846
847    // Helper method to check if a type needs any string functions
848    fn needs_any_string_functions(&self, ty: &TypeRef) -> bool {
849        // Check if the type should have string functions
850        let should_have_string_functions = matches!(
851            &*ty.kind,
852            TypeKind::Enum(_)
853                | TypeKind::NamedStruct(_)
854                | TypeKind::AnonymousStruct(_)
855                | TypeKind::Tuple(_)
856                | TypeKind::FixedCapacityAndLengthArray(_, _)
857                | TypeKind::SliceView(_)
858                | TypeKind::DynamicLengthVecView(_)
859                | TypeKind::VecStorage(_, _)
860                | TypeKind::StackView(_)
861                | TypeKind::QueueView(_)
862                | TypeKind::StackStorage(_, _)
863                | TypeKind::QueueStorage(_, _)
864                | TypeKind::SparseView(_)
865                | TypeKind::SparseStorage(_, _)
866                | TypeKind::GridView(_)
867                | TypeKind::GridStorage(_, _, _)
868                | TypeKind::MapStorage(_, _, _)
869                | TypeKind::DynamicLengthMapView(_, _)
870                | TypeKind::Optional(_)
871        );
872
873        if !should_have_string_functions {
874            return false;
875        }
876
877        // Prepare the type if needed
878        if !self.shared.state.associated_impls.is_prepared(ty) {
879            return true; // Not prepared, so it needs functions
880        }
881
882        // Check if any of the string functions are missing
883        let has_to_string = self
884            .shared
885            .state
886            .associated_impls
887            .get_internal_member_function(ty, "to_string")
888            .is_some();
889
890        let has_to_short_string = self
891            .shared
892            .state
893            .associated_impls
894            .get_internal_member_function(ty, "to_short_string")
895            .is_some();
896
897        let has_to_pretty_string = self
898            .shared
899            .state
900            .associated_impls
901            .get_internal_member_function(ty, "to_pretty_string")
902            .is_some();
903
904        !has_to_string || !has_to_short_string || !has_to_pretty_string
905    }
906
907    pub fn add_default_functions(&mut self, type_to_attach_to: &TypeRef, node: &swamp_ast::Node) {
908        // For enum types, ensure variant payload types have string functions first
909        if let TypeKind::Enum(enum_type) = &*type_to_attach_to.kind {
910            for (_, variant) in &enum_type.variants {
911                // Only process non-Unit payload types that aren't the enum itself (recursive enum)
912                if !matches!(&*variant.payload_type.kind, TypeKind::Unit)
913                    && !TypeRef::ptr_eq(&variant.payload_type, type_to_attach_to)
914                {
915                    // Check if the payload type needs any string functions
916                    let needs_string_functions =
917                        self.needs_any_string_functions(&variant.payload_type);
918
919                    if needs_string_functions {
920                        self.add_default_functions(&variant.payload_type, node);
921                    }
922                }
923            }
924        }
925
926        let underlying = type_to_attach_to;
927
928        // Check if this type needs any string functions
929        if self.needs_any_string_functions(underlying) {
930            // Make sure the type is prepared for adding functions
931            if !self
932                .shared
933                .state
934                .associated_impls
935                .is_prepared(type_to_attach_to)
936            {
937                self.shared
938                    .state
939                    .associated_impls
940                    .prepare(type_to_attach_to);
941            }
942
943            // Check if to_string exists and generate it if needed
944            if self
945                .shared
946                .state
947                .associated_impls
948                .get_internal_member_function(underlying, "to_string")
949                .is_none()
950            {
951                let to_string_function =
952                    self.generate_to_string_function_for_type(type_to_attach_to, node);
953                self.shared
954                    .state
955                    .associated_impls
956                    .add_internal_function(type_to_attach_to, to_string_function)
957                    .unwrap();
958            }
959
960            // Check if to_short_string exists and generate it if needed
961            if self
962                .shared
963                .state
964                .associated_impls
965                .get_internal_member_function(underlying, "to_short_string")
966                .is_none()
967            {
968                let to_short_string_function =
969                    self.generate_to_short_string_function_for_type(type_to_attach_to, node);
970                self.shared
971                    .state
972                    .associated_impls
973                    .add_internal_function(type_to_attach_to, to_short_string_function)
974                    .unwrap();
975            }
976
977            // Check if to_pretty_string exists and generate it if needed
978            if self
979                .shared
980                .state
981                .associated_impls
982                .get_internal_member_function(underlying, "to_pretty_string")
983                .is_none()
984            {
985                let to_pretty_string_function =
986                    self.generate_to_pretty_string_function_for_type(type_to_attach_to, node);
987                self.shared
988                    .state
989                    .associated_impls
990                    .add_internal_function(type_to_attach_to, to_pretty_string_function)
991                    .unwrap();
992            }
993        }
994    }
995
996    fn generate_to_string_function_for_type(
997        &mut self,
998        ty: &TypeRef,
999        ast_node: &Node,
1000    ) -> InternalFunctionDefinition {
1001        let node = self.to_node(ast_node);
1002        let mut generator = ExpressionGenerator::new(
1003            &mut self.shared.state.types,
1004            &self.shared.state.associated_impls,
1005        );
1006        internal_generate_to_string_function_for_type(
1007            &mut generator,
1008            &mut self.shared.state.internal_function_id_allocator,
1009            &self.module_path,
1010            ty,
1011            &node,
1012            false, // is_short_string = false for regular to_string
1013        )
1014    }
1015
1016    fn generate_to_short_string_function_for_type(
1017        &mut self,
1018        ty: &TypeRef,
1019        ast_node: &Node,
1020    ) -> InternalFunctionDefinition {
1021        let node = self.to_node(ast_node);
1022        let mut generator = ExpressionGenerator::new(
1023            &mut self.shared.state.types,
1024            &self.shared.state.associated_impls,
1025        );
1026        internal_generate_to_short_string_function_for_type(
1027            &mut generator,
1028            &mut self.shared.state.internal_function_id_allocator,
1029            &self.module_path,
1030            ty,
1031            &node,
1032        )
1033    }
1034
1035    fn generate_to_pretty_string_function_for_type(
1036        &mut self,
1037        ty: &TypeRef,
1038        ast_node: &Node,
1039    ) -> InternalFunctionDefinition {
1040        let node = self.to_node(ast_node);
1041        let mut generator = ExpressionGenerator::new(
1042            &mut self.shared.state.types,
1043            &self.shared.state.associated_impls,
1044        );
1045        internal_generate_to_pretty_string_function_for_type(
1046            &mut generator,
1047            &mut self.shared.state.internal_function_id_allocator,
1048            &self.module_path,
1049            ty,
1050            &node,
1051        )
1052    }
1053}