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