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