1use 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 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 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 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 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 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 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); 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 for param in ¶meters {
432 let param_type = ¶m.resolved_type;
433 let actual_type = param_type.clone();
434 self.create_parameter_resolved(
435 ¶m.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; 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 pub fn analyze_definition(&mut self, ast_def: &swamp_ast::Definition) {
563 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 pub fn analyze_impl_functions(
636 &mut self,
637 attach_to_type: &TypeRef, 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 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 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(¶m.param_type);
732
733 let resolved_param = TypeForParameter {
734 name: self.get_text(¶m.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(¶m.variable.name),
739 is_mutable: self
740 .to_node_option(Option::from(¶m.variable.is_mutable)),
741 }),
742 };
743 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 ¶meters {
756 self.create_parameter_resolved(
757 ¶m.node.as_ref().unwrap().name,
758 param.node.as_ref().unwrap().is_mutable.as_ref(),
759 ¶m.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 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 for param in &signature.params {
809 let resolved_type = self.analyze_type(¶m.param_type);
810
811 parameters.push(TypeForParameter {
812 name: self.get_text(¶m.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(¶m.variable.name),
817 is_mutable: self
818 .to_node_option(Option::from(¶m.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; 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 fn needs_any_string_functions(&self, ty: &TypeRef) -> bool {
849 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 if !self.shared.state.associated_impls.is_prepared(ty) {
879 return true; }
881
882 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 if let TypeKind::Enum(enum_type) = &*type_to_attach_to.kind {
910 for (_, variant) in &enum_type.variants {
911 if !matches!(&*variant.payload_type.kind, TypeKind::Unit)
913 && !TypeRef::ptr_eq(&variant.payload_type, type_to_attach_to)
914 {
915 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 if self.needs_any_string_functions(underlying) {
930 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 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 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 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, )
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}