1use crate::to_string::{
6 internal_generate_to_pretty_string_function_for_type, internal_generate_to_pretty_string_parameterless_function_for_type,
7 internal_generate_to_short_string_function_for_type,
8 internal_generate_to_string_function_for_type,
9 ExpressionGenerator,
10};
11use crate::types::TypeAnalyzeContext;
12use crate::Analyzer;
13use seq_map::SeqMap;
14use std::rc::Rc;
15use swamp_ast::Node;
16use swamp_attributes::Attributes;
17use swamp_modules::symtbl::AliasType;
18use swamp_semantic::err::ErrorKind;
19use swamp_semantic::{
20 ExternalFunctionDefinition, ExternalFunctionId, Function, InternalFunctionDefinition,
21 InternalFunctionId, LocalIdentifier, UseItem,
22};
23use swamp_symbol::{Symbol, SymbolKind, TopLevelSymbolId};
24use swamp_types::prelude::*;
25use tracing::debug;
26
27impl Analyzer<'_> {
28 fn general_import(
29 &mut self,
30 path: &[String],
31 import_items: &swamp_ast::ImportItems,
32 node: &swamp_ast::Node,
33 ) {
34 let found_module = if let Some(module) = self.shared.get_module(path) {
35 module.clone()
36 } else {
37 self.add_err(ErrorKind::UnknownModule, node);
38 return;
39 };
40
41 let name_node = self.to_node(node);
42
43 match import_items {
44 swamp_ast::ImportItems::Nothing => {
45 let last_name = path.last().unwrap();
46 if self
47 .shared
48 .lookup_table
49 .get_module_link(last_name)
50 .is_none()
51 {
52 match self
53 .shared
54 .lookup_table
55 .add_module_link(last_name, &name_node, found_module.clone())
56 {
57 Ok(_x) => {}
58 Err(err) => {
59 self.add_err(ErrorKind::SemanticError(err), node);
60 }
61 }
62 }
63 }
64 swamp_ast::ImportItems::Items(items) => {
65 for ast_items in items {
66 match ast_items {
67 swamp_ast::ImportItem::Identifier(node) => {
68 let ident_resolved_node = self.to_node(&node.0);
69 let ident = UseItem::Identifier(ident_resolved_node.clone());
70 let ident_text =
71 self.get_text_resolved(&ident_resolved_node).to_string();
72 if let Some(found_symbol) =
73 found_module.definition_table.get_symbol(&ident_text)
74 {
75 if let Err(sem_err) = self
76 .shared
77 .lookup_table
78 .add_symbol(&ident_text, found_symbol.clone())
79 {
80 self.add_err(ErrorKind::SemanticError(sem_err), &node.0);
81 return;
82 }
83 } else {
84 return self.add_err_resolved(
85 ErrorKind::UnknownTypeReference,
86 &ident_resolved_node,
87 );
88 }
89 ident
90 }
91 swamp_ast::ImportItem::Type(node) => {
92 let ident_resolved_node = self.to_node(&node.0);
93 let ident_text =
94 self.get_text_resolved(&ident_resolved_node).to_string();
95 if let Some(found_symbol) =
96 found_module.definition_table.get_symbol(&ident_text)
97 {
98 if let Err(sem_err) = self
99 .shared
100 .lookup_table
101 .add_symbol(&ident_text, found_symbol.clone())
102 {
103 self.add_err(ErrorKind::SemanticError(sem_err), &node.0);
104 return;
105 }
106 } else {
107 return self.add_err_resolved(
108 ErrorKind::UnknownTypeReference,
109 &ident_resolved_node,
110 );
111 }
112 UseItem::TypeIdentifier(self.to_node(&node.0))
113 }
114 };
115 }
116 }
117 swamp_ast::ImportItems::All => {
118 if let Err(sem_err) = self
119 .shared
120 .lookup_table
121 .extend_from(&found_module.definition_table)
122 {
123 self.add_err(ErrorKind::SemanticError(sem_err), node);
124 }
125 }
126 }
127 }
128
129 fn analyze_mod_definition(&mut self, mod_definition: &swamp_ast::Mod) {
130 let mut path = Vec::new();
131 for ast_node in &mod_definition.module_path.0 {
132 path.push(self.get_text(ast_node).to_string());
133 }
134
135 let mut nodes_copy = path.clone();
136 nodes_copy.insert(0, "crate".to_string());
137
138 self.general_import(
139 &nodes_copy,
140 &mod_definition.items,
141 &mod_definition.module_path.0[0],
142 );
143 }
144
145 fn analyze_use_definition(&mut self, use_definition: &swamp_ast::Use) {
146 let mut nodes = Vec::new();
147 for ast_node in &use_definition.module_path.0 {
148 nodes.push(self.to_node(ast_node));
149 }
150
151 let path: Vec<String> = nodes
152 .iter()
153 .map(|node| {
154 let text = self.get_text_resolved(node);
155 text.to_string()
156 })
157 .collect();
158
159 self.general_import(
160 &path,
161 &use_definition.items,
162 &use_definition.module_path.0[0],
163 );
164 }
165
166 fn analyze_enum_type_definition(
167 &mut self,
168 enum_type_name: &swamp_ast::LocalTypeIdentifierWithOptionalTypeVariables,
169 ast_variants: &[swamp_ast::EnumVariantType],
170 ) {
171 let mut resolved_variants = SeqMap::new();
172
173 let name_node = self.to_node(&enum_type_name.name);
174
175 let symbol_id = self.shared.state.symbol_id_allocator.alloc_top_level();
176 self.shared.state.symbols.insert_top(symbol_id, Symbol {
177 id: symbol_id.into(),
178 kind: SymbolKind::Enum,
179 source_map_node: name_node.clone(),
180 name: name_node.clone(),
181 });
182
183 let mut new_enum_type = EnumType {
184 symbol_id,
185 name: name_node,
186 assigned_name: self.get_text(&enum_type_name.name).to_string(),
187 module_path: vec![],
188 variants: SeqMap::default(),
189 instantiated_type_parameters: Vec::default(),
190 };
191
192 for (container_index_usize, ast_variant_type) in ast_variants.iter().enumerate() {
193 let variant_name_node = match ast_variant_type {
194 swamp_ast::EnumVariantType::Simple(name) => name,
195 swamp_ast::EnumVariantType::Direct(name, _) => name,
196 swamp_ast::EnumVariantType::Tuple(name, _) => name,
197 swamp_ast::EnumVariantType::Struct(name, _) => name,
198 };
199
200 let name_node_for_variant = self.to_node(variant_name_node);
201
202 let variant_symbol_id = self.shared.state.symbol_id_allocator.alloc_top_level();
203 self.shared.state.symbols.insert_top(variant_symbol_id, Symbol {
204 id: variant_symbol_id.into(),
205 kind: SymbolKind::EnumVariant,
206 source_map_node: name_node_for_variant.clone(),
207 name: name_node_for_variant.clone(),
208 });
209
210 let common = EnumVariantCommon {
211 symbol_id: variant_symbol_id,
212 name: name_node_for_variant,
213 assigned_name: self.get_text(variant_name_node).to_string(),
214 container_index: container_index_usize as u8,
215 };
216
217 let payload_type = match ast_variant_type {
218 swamp_ast::EnumVariantType::Simple(_variant_name_node) => self.types().unit(),
219 swamp_ast::EnumVariantType::Direct(_variant_name_node, direct_type) => {
220 let analyzed_type =
221 self.analyze_type(direct_type, &TypeAnalyzeContext::default());
222 match &*analyzed_type.kind {
224 TypeKind::Tuple(elements) if elements.len() == 1 => elements[0].clone(),
225 _ => analyzed_type,
226 }
227 }
228 swamp_ast::EnumVariantType::Tuple(_variant_name_node, types) => {
229 let mut vec = Vec::new();
230 for tuple_type in types {
231 let resolved_type =
232 self.analyze_type(tuple_type, &TypeAnalyzeContext::default());
233 vec.push(resolved_type);
234 }
235
236 if vec.len() == 1 {
238 vec.into_iter().next().unwrap()
239 } else {
240 self.types().tuple(vec)
241 }
242 }
243 swamp_ast::EnumVariantType::Struct(_variant_name_node, ast_struct_fields) => {
244 let mut fields = SeqMap::new();
245
246 for field_with_type in &ast_struct_fields.fields {
247 let resolved_type = self.analyze_type(
248 &field_with_type.field_type,
249 &TypeAnalyzeContext::default(),
250 );
251 let field_name_str =
252 self.get_text(&field_with_type.field_name.0).to_string();
253
254 let name_node = self.to_node(&field_with_type.field_name.0);
255
256 let symbol_id = self.shared.state.symbol_id_allocator.alloc_top_level();
257 self.shared.state.symbols.insert_top(symbol_id, Symbol {
258 id: symbol_id.into(),
259 kind: SymbolKind::EnumPayloadStructField,
260 source_map_node: name_node.clone(),
261 name: name_node.clone(),
262 });
263
264 let resolved_field = StructTypeField {
265 symbol_id,
266 identifier: Some(name_node),
267 field_type: resolved_type,
268 };
269
270 if let Err(_seq_map_err) = fields.insert(field_name_str, resolved_field) {
271 return self.add_err(
272 ErrorKind::DuplicateFieldName,
273 &field_with_type.field_name.0,
274 );
275 }
276 }
277
278 let anonymous_struct_type = AnonymousStructType {
279 field_name_sorted_fields: fields,
280 };
281
282 self.types().anonymous_struct(anonymous_struct_type)
283 }
284 };
285
286 let enum_variant_type = swamp_types::prelude::EnumVariantType {
287 common,
288 payload_type,
289 };
290
291 let variant_name_str = self.get_text(variant_name_node).to_string();
292
293 if let Err(_seq_map_err) = resolved_variants.insert(variant_name_str, enum_variant_type)
294 {
295 return self.add_err(ErrorKind::DuplicateFieldName, variant_name_node);
296 }
297 }
298
299 new_enum_type.variants = resolved_variants;
300
301 let enum_type_ref = self.shared.state.types.enum_type(new_enum_type);
302
303 if let Err(sem_err) = self
304 .shared
305 .definition_table
306 .add_named_type(enum_type_ref.clone())
307 {
308 return self.add_err(ErrorKind::SemanticError(sem_err), &enum_type_name.name);
309 }
310
311 if let Err(sem_err) = self
312 .shared
313 .lookup_table
314 .add_named_type(enum_type_ref.clone())
315 {
316 return self.add_err(ErrorKind::SemanticError(sem_err), &enum_type_name.name);
317 }
318
319 self.add_default_functions(&enum_type_ref, &enum_type_name.name);
320 }
321
322 pub fn analyze_alias_type_definition(&mut self, ast_alias: &swamp_ast::AliasType) -> AliasType {
325 let resolved_type =
326 self.analyze_type(&ast_alias.referenced_type, &TypeAnalyzeContext::default());
327
328 self.ensure_default_functions_for_type(&resolved_type, &ast_alias.identifier.0);
330
331 let alias_name_str = self.get_text(&ast_alias.identifier.0).to_string();
332 let name_node = self.to_node(&ast_alias.identifier.0);
333 let symbol_id = self.shared.state.symbol_id_allocator.alloc_top_level();
334 self.shared.state.symbols.insert_top(symbol_id, Symbol {
335 id: symbol_id.into(),
336 kind: SymbolKind::Alias,
337 source_map_node: name_node.clone(),
338 name: name_node.clone(),
339 });
340 let resolved_alias = AliasType {
341 symbol_id,
342 name: name_node,
343 ty: resolved_type,
344 assigned_name: alias_name_str,
345 };
346
347 let resolved_alias_ref = match self.shared.definition_table.add_alias(resolved_alias) {
348 Ok(re) => re,
349
350 Err(err) => {
351 self.add_err(ErrorKind::SemanticError(err), &ast_alias.identifier.0);
352 AliasType {
353 symbol_id: TopLevelSymbolId::new_illegal(),
354 name: source_map_node::Node::default(),
355 assigned_name: "err".to_string(),
356 ty: self.types().unit(),
357 }
358 }
359 };
360
361 if let Err(sem_err) = self
362 .shared
363 .lookup_table
364 .add_alias_link(resolved_alias_ref.clone())
365 {
366 self.add_err(ErrorKind::SemanticError(sem_err), &ast_alias.identifier.0);
367 AliasType {
368 symbol_id: TopLevelSymbolId::new_illegal(),
369 name: source_map_node::Node::default(),
370 assigned_name: "err".to_string(),
371 ty: self.types().unit(),
372 }
373 } else {
374 resolved_alias_ref
375 }
376 }
377
378 pub fn analyze_anonymous_struct_type(
381 &mut self,
382 ast_struct: &swamp_ast::AnonymousStructType,
383 ctx: &TypeAnalyzeContext,
384 ) -> AnonymousStructType {
385 let resolved_fields = self.analyze_anonymous_struct_type_fields(&ast_struct.fields, ctx);
386
387 AnonymousStructType::new_and_sort_fields(&resolved_fields)
388 }
389
390 pub fn analyze_anonymous_struct_type_fields(
393 &mut self,
394 ast_struct_fields: &[swamp_ast::StructTypeField],
395 ctx: &TypeAnalyzeContext,
396 ) -> SeqMap<String, StructTypeField> {
397 let mut resolved_fields = SeqMap::new();
398
399 for field_name_and_type in ast_struct_fields {
400 let resolved_type = self.analyze_type(&field_name_and_type.field_type, ctx);
401 let name_string = self.get_text(&field_name_and_type.field_name.0).to_string();
402
403 if !resolved_type.can_be_stored_in_transient_field() {
404 self.add_err(ErrorKind::NeedStorage, &field_name_and_type.field_name.0);
405 return resolved_fields;
406 }
407
408 if !resolved_type.can_be_stored_in_field() {
409 self.add_hint(ErrorKind::NeedStorage, &field_name_and_type.field_name.0);
410 }
411 let name_node = self.to_node(&field_name_and_type.field_name.0);
412
413 let symbol_id = self.shared.state.symbol_id_allocator.alloc_top_level();
414 self.shared.state.symbols.insert_top(symbol_id, Symbol {
415 id: symbol_id.into(),
416 kind: SymbolKind::NamedStructField,
417 source_map_node: name_node.clone(),
418 name: name_node.clone(),
419 });
420
421 let field_type = StructTypeField {
422 symbol_id,
423 identifier: Some(name_node),
424 field_type: resolved_type,
425 };
426
427 if let Err(_seq_map_err) = resolved_fields.insert(name_string, field_type) {
428 self.add_err(
429 ErrorKind::DuplicateFieldName,
430 &field_name_and_type.field_name.0,
431 );
432 }
433 }
434
435 resolved_fields
436 }
437
438 pub fn analyze_named_struct_type_definition(
441 &mut self,
442 ast_struct_def: &swamp_ast::NamedStructDef,
443 ) {
444 let struct_name_str = self.get_text(&ast_struct_def.identifier.name).to_string();
445
446 let fields = self.analyze_anonymous_struct_type_fields(
447 &ast_struct_def.struct_type.fields,
448 &TypeAnalyzeContext::default(),
449 );
450
451 let analyzed_anonymous_struct = AnonymousStructType::new(fields);
452
453 let anon_struct_type_ref = self
454 .shared
455 .state
456 .types
457 .anonymous_struct(analyzed_anonymous_struct);
458
459 let name_node = self.to_node(&ast_struct_def.identifier.name);
460
461 let symbol_id = self.shared.state.symbol_id_allocator.alloc_top_level();
462 self.shared.state.symbols.insert_top(symbol_id, Symbol {
463 id: symbol_id.into(),
464 kind: SymbolKind::NamedStruct,
465 source_map_node: name_node.clone(),
466 name: name_node.clone(),
467 });
468
469
470 let named_struct_type = NamedStructType {
471 symbol_id,
472 name: name_node,
473 anon_struct_type: anon_struct_type_ref,
474 assigned_name: struct_name_str,
475 module_path: self.shared.definition_table.module_path(),
476 };
477
478 let named_struct_type_ref = self.shared.state.types.named_struct(named_struct_type);
479
480 match self
481 .shared
482 .definition_table
483 .add_named_type(named_struct_type_ref.clone())
484 {
485 Ok(()) => {}
486 Err(sem_err) => {
487 return self.add_err(
488 ErrorKind::SemanticError(sem_err),
489 &ast_struct_def.identifier.name,
490 );
491 }
492 }
493
494 match self
495 .shared
496 .lookup_table
497 .add_named_type(named_struct_type_ref.clone())
498 {
499 Ok(()) => {}
500 Err(sem_err) => {
501 return self.add_err(
502 ErrorKind::SemanticError(sem_err),
503 &ast_struct_def.identifier.name,
504 );
505 }
506 }
507
508 self.add_default_functions(&named_struct_type_ref, &ast_struct_def.identifier.name);
509 }
510
511 #[allow(clippy::too_many_lines)]
512 pub(crate) fn analyze_function_definition(
513 &mut self,
514 function: &swamp_ast::Function,
515 attributes: &Attributes,
516 ) -> Option<Function> {
517 let func = match &function {
518 swamp_ast::Function::Internal(function_data) => {
519 let parameters = self.analyze_parameters(&function_data.declaration.params);
520 let return_type = if let Some(found) = &function_data.declaration.return_type {
521 let analyzed_return_type =
522 self.analyze_type(found, &TypeAnalyzeContext::default());
523 if !analyzed_return_type.allowed_as_return_type() {
524 self.add_err(
525 ErrorKind::NotAllowedAsReturnType(analyzed_return_type),
526 function.node(),
527 );
528 return None;
529 }
530 analyzed_return_type
531 } else {
532 self.shared.state.types.unit()
533 };
534
535 for param in ¶meters {
536 let param_type = ¶m.resolved_type;
537 let actual_type = param_type.clone();
538 self.create_parameter_resolved(
539 ¶m.node.as_ref().unwrap().name,
540 param.node.as_ref().unwrap().is_mutable.as_ref(),
541 &actual_type,
542 );
543 }
544 let function_name = self
545 .get_text(&function_data.declaration.name)
546 .trim()
547 .to_string();
548
549 let name_node = self.to_node(&function_data.declaration.name);
550 let statements =
551 self.analyze_function_body_expression(&function_data.body, &return_type);
552
553 let symbol_id = self.shared.state.symbol_id_allocator.alloc_top_level();
554 self.shared.state.symbols.insert_top(symbol_id, Symbol {
555 id: symbol_id.into(),
556 kind: SymbolKind::Function,
557 source_map_node: name_node.clone(),
558 name: name_node.clone(),
559 });
560 let internal = InternalFunctionDefinition {
561 symbol_id,
562 signature: Signature {
563 parameters,
564 return_type,
565 },
566 body: statements,
567 name: LocalIdentifier(name_node),
568 assigned_name: self.get_text(&function_data.declaration.name).to_string(),
569 associated_with_type: None,
570 defined_in_module_path: self.module_path.clone(),
571 function_variables: self.scope.total_scopes.clone(),
572 program_unique_id: self.shared.state.allocate_internal_function_id(),
573 attributes: attributes.clone(),
574 };
575
576 let function_ref = match self
577 .shared
578 .definition_table
579 .add_internal_function(&function_name, internal)
580 {
581 Ok(func_def) => func_def,
582 Err(sem_err) => {
583 self.add_err(
584 ErrorKind::SemanticError(sem_err),
585 &function_data.declaration.name,
586 );
587 return None;
588 }
589 };
590
591 match self
592 .shared
593 .lookup_table
594 .add_internal_function_link(&function_name, function_ref.clone())
595 {
596 Ok(()) => {}
597 Err(sem_err) => {
598 self.add_err(
599 ErrorKind::SemanticError(sem_err),
600 &function_data.declaration.name,
601 );
602 return None;
603 }
604 }
605
606 Function::Internal(function_ref)
607 }
608 swamp_ast::Function::External(int_node, ast_signature) => {
609 let parameters = self.analyze_parameters(&ast_signature.params);
610 let external_return_type = if let Some(found) = &ast_signature.return_type {
611 self.analyze_type(found, &TypeAnalyzeContext::default())
612 } else {
613 self.shared.state.types.unit()
614 };
615
616 let return_type = external_return_type;
617
618 let int_string = self.get_text(int_node);
619 let external_function_id_int = Self::str_to_int(int_string).unwrap() as u32;
620
621 let external_function_id = external_function_id_int as ExternalFunctionId;
622
623 let external = ExternalFunctionDefinition {
624 assigned_name: self.get_text(&ast_signature.name).to_string(),
625 signature: Signature {
626 parameters,
627 return_type,
628 },
629 name: self.to_node(&ast_signature.name),
630 id: external_function_id,
631 };
632
633 let function_ref = match self
634 .shared
635 .definition_table
636 .add_external_function_declaration(external)
637 {
638 Ok(func_ref) => func_ref,
639 Err(sem_err) => {
640 self.add_err(ErrorKind::SemanticError(sem_err), &ast_signature.name);
641 return None;
642 }
643 };
644
645 if let Err(sem_err) = self
646 .shared
647 .lookup_table
648 .add_external_function_declaration_link(function_ref.clone())
649 {
650 self.add_err(ErrorKind::SemanticError(sem_err), &ast_signature.name);
651 return None;
652 }
653
654 Function::External(function_ref)
655 }
656 };
657
658 Some(func)
659 }
660
661 pub fn debug_definition(&self, definition: &swamp_ast::Definition) {
662 let (line, col) = self
663 .shared
664 .source_map
665 .get_span_location_utf8(self.shared.file_id, definition.node.span.offset as usize);
666 let source_line = self
667 .shared
668 .source_map
669 .get_source_line(self.shared.file_id, line)
670 .unwrap();
671 debug!(?line, ?col, ?source_line);
672 }
673
674 pub fn analyze_definition(&mut self, ast_def: &swamp_ast::Definition) {
677 let analyzed_attributes = self.analyze_attributes(&ast_def.attributes);
680
681 match &ast_def.kind {
682 swamp_ast::DefinitionKind::NamedStructDef(ast_struct) => {
683 self.analyze_named_struct_type_definition(ast_struct);
684 }
685 swamp_ast::DefinitionKind::AliasDef(alias_def) => {
686 self.analyze_alias_type_definition(alias_def);
687 }
688 swamp_ast::DefinitionKind::EnumDef(identifier, variants) => {
689 self.analyze_enum_type_definition(identifier, variants);
690 }
691 swamp_ast::DefinitionKind::FunctionDef(function) => {
692 let _resolved_return_type = self.analyze_return_type(function);
693 self.start_function(function.node());
694 self.analyze_function_definition(function, &analyzed_attributes);
695 self.stop_function();
696 }
697 swamp_ast::DefinitionKind::ImplDef(type_identifier, functions) => {
698 self.analyze_impl_definition(type_identifier, functions);
699 }
700 swamp_ast::DefinitionKind::Mod(mod_info) => self.analyze_mod_definition(mod_info),
701 swamp_ast::DefinitionKind::Use(use_info) => self.analyze_use_definition(use_info),
702 swamp_ast::DefinitionKind::Constant(const_info) => {
703 self.analyze_constant_definition(const_info);
704 }
705 }
706 }
707
708 fn analyze_impl_definition(
709 &mut self,
710 attached_to_type: &swamp_ast::LocalTypeIdentifierWithOptionalTypeVariables,
711 functions: &[swamp_ast::Function],
712 ) {
713 let converted_type_variables_to_ast_types = attached_to_type
714 .type_variables
715 .iter()
716 .map(|x| {
717 swamp_ast::GenericParameter::Type(swamp_ast::Type::Named(
718 swamp_ast::QualifiedTypeIdentifier {
719 name: swamp_ast::LocalTypeIdentifier(x.0.clone()),
720 module_path: None,
721 generic_params: vec![],
722 },
723 ))
724 })
725 .collect();
726
727 let qualified = swamp_ast::QualifiedTypeIdentifier {
728 name: swamp_ast::LocalTypeIdentifier(attached_to_type.name.clone()),
729 module_path: None,
730 generic_params: converted_type_variables_to_ast_types,
731 };
732
733 let maybe_type_to_attach_to = Some(self.analyze_named_type(&qualified));
734 if let Some(type_to_attach_to) = maybe_type_to_attach_to {
735 let function_refs: Vec<&swamp_ast::Function> = functions.iter().collect();
736 self.analyze_impl_functions(&type_to_attach_to, &function_refs);
737 } else {
738 self.add_err(
739 ErrorKind::CanNotAttachFunctionsToType,
740 &attached_to_type.name,
741 );
742 }
743 }
744
745 pub fn analyze_impl_functions(
748 &mut self,
749 attach_to_type: &TypeRef,
750 functions: &[&swamp_ast::Function],
751 ) {
752 if !self
753 .shared
754 .state
755 .associated_impls
756 .is_prepared(attach_to_type)
757 {
758 self.shared.state.associated_impls.prepare(attach_to_type);
759 }
760
761 for function in functions {
762
763 let function_name = match function {
764 swamp_ast::Function::Internal(function_with_body) => {
765 &function_with_body.declaration
766 }
767 swamp_ast::Function::External(_, external_declaration) => external_declaration,
768 };
769 self.start_function(&function_name.name);
770
771 let function_name_str = self.get_text(&function_name.name).to_string();
772
773 let existing_function_id = if matches!(
774 function_name_str.as_str(),
775 "string"
776 | "short_string"
777 | "pretty_string"
778 | "pretty_string_with_indent"
779 | "default"
780 ) {
781 self.shared
782 .state
783 .associated_impls
784 .get_internal_member_function(attach_to_type, &function_name_str)
785 .map(|existing_fn| existing_fn.program_unique_id)
786 } else {
787 None
788 };
789
790 let resolved_function =
791 self.analyze_impl_func(function, attach_to_type, existing_function_id);
792
793 let resolved_function_ref = Rc::new(resolved_function);
794
795 self.stop_function();
796
797 let is_built_in = matches!(
798 function_name_str.as_str(),
799 "string"
800 | "short_string"
801 | "pretty_string"
802 | "pretty_string_with_indent"
803 | "default"
804 );
805 if is_built_in {
806 self.shared
807 .state
808 .associated_impls
809 .remove_internal_function_if_exists(attach_to_type, &function_name_str);
810 }
811
812 if let Err(sem_err) = self.shared.state.associated_impls.add_member_function(
813 attach_to_type,
814 &function_name_str,
815 resolved_function_ref,
816 ) {
817 return self.add_err(ErrorKind::SemanticError(sem_err), &function_name.name);
818 }
819 }
820 }
821
822 #[allow(clippy::too_many_lines)]
823 fn analyze_impl_func(
824 &mut self,
825 function: &swamp_ast::Function,
826 self_type: &TypeRef,
827 existing_function_id: Option<InternalFunctionId>,
828 ) -> Function {
829 match function {
830 swamp_ast::Function::Internal(function_data) => {
831 let mut parameters = Vec::new();
832
833 if let Some(found_self) = &function_data.declaration.self_parameter {
834 let actual_self_type = self_type.clone();
835 parameters.push(TypeForParameter {
836 name: self.get_text(&found_self.self_node).to_string(),
837 resolved_type: actual_self_type,
838 is_mutable: found_self.is_mutable.is_some(),
839 node: Option::from(ParameterNode {
840 name: self.to_node(&found_self.self_node),
841 is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
842 }),
843 });
844 }
845
846 for param in &function_data.declaration.params {
847 let resolved_type =
848 self.analyze_type(¶m.param_type, &TypeAnalyzeContext::default());
849
850 let resolved_param = TypeForParameter {
851 name: self.get_text(¶m.variable.name).to_string(),
852 resolved_type,
853 is_mutable: param.variable.is_mutable.is_some(),
854 node: Option::from(ParameterNode {
855 name: self.to_node(¶m.variable.name),
856 is_mutable: self
857 .to_node_option(Option::from(¶m.variable.is_mutable)),
858 }),
859 };
860
861 parameters.push(resolved_param);
862 }
863
864 let return_type =
865 if let Some(ast_return_type) = &function_data.declaration.return_type {
866 self.analyze_type(ast_return_type, &TypeAnalyzeContext::default())
867 } else {
868 self.shared.state.types.unit()
869 };
870
871 for param in ¶meters {
872 self.create_parameter_resolved(
873 ¶m.node.as_ref().unwrap().name,
874 param.node.as_ref().unwrap().is_mutable.as_ref(),
875 ¶m.resolved_type.clone(),
876 );
877 }
878
879 let statements =
880 self.analyze_function_body_expression(&function_data.body, &return_type);
881
882 let attributes = self.analyze_attributes(&function_data.attributes);
883
884 let symbol_id = self.shared.state.symbol_id_allocator.alloc_top_level();
885
886 let name_node = self.to_node(&function_data.declaration.name);
887 self.shared.state.symbols.insert_top(symbol_id, Symbol {
888 id: symbol_id.into(),
889 kind: SymbolKind::MemberFunction,
890 source_map_node: name_node.clone(),
891 name: name_node.clone(),
892 });
893
894 let internal = InternalFunctionDefinition {
895 symbol_id,
896 signature: Signature {
897 parameters,
898 return_type,
899 },
900 body: statements,
901 name: LocalIdentifier(name_node),
902 assigned_name: self.get_text(&function_data.declaration.name).to_string(),
903 defined_in_module_path: self.module_path.clone(),
904 associated_with_type: Some(self_type.clone()),
905 function_variables: self.scope.total_scopes.clone(),
906 program_unique_id: existing_function_id
907 .unwrap_or_else(|| self.shared.state.allocate_internal_function_id()),
908 attributes,
909 };
910
911 let internal_ref = Rc::new(internal);
912
913 Function::Internal(internal_ref)
914 }
915
916 swamp_ast::Function::External(int_node, signature) => {
917 let mut parameters = Vec::new();
918
919 if let Some(found_self) = &signature.self_parameter {
920 let param = TypeForParameter {
921 name: self.get_text(&found_self.self_node).to_string(),
922 resolved_type: self_type.clone(),
923 is_mutable: found_self.is_mutable.is_some(),
924 node: Option::from(ParameterNode {
925 name: self.to_node(&found_self.self_node),
926 is_mutable: self.to_node_option(Option::from(&found_self.is_mutable)),
927 }),
928 };
929
930 parameters.push(param);
931 }
932
933 for param in &signature.params {
934 let resolved_type =
935 self.analyze_type(¶m.param_type, &TypeAnalyzeContext::default());
936
937 parameters.push(TypeForParameter {
938 name: self.get_text(¶m.variable.name).to_string(),
939 resolved_type,
940 is_mutable: param.variable.is_mutable.is_some(),
941 node: Option::from(ParameterNode {
942 name: self.to_node(¶m.variable.name),
943 is_mutable: self
944 .to_node_option(Option::from(¶m.variable.is_mutable)),
945 }),
946 });
947 }
948
949 let return_type = self.analyze_maybe_type(Option::from(&signature.return_type));
950
951 let int_string = self.get_text(int_node);
952 let external_function_id_int = Self::str_to_int(int_string).unwrap() as u32;
953
954 let external_function_id = external_function_id_int as ExternalFunctionId;
955
956 let external = ExternalFunctionDefinition {
957 assigned_name: self.get_text(&signature.name).to_string(),
958 name: self.to_node(&signature.name),
959 signature: Signature {
960 parameters,
961 return_type,
962 },
963 id: external_function_id,
964 };
965
966 let external_ref = Rc::new(external);
967
968 Function::External(external_ref)
969 }
970 }
971 }
972
973 pub fn on_type_encountered(&mut self, ty: &TypeRef, node: &swamp_ast::Node) {
975 if self.needs_any_string_functions(ty) {
977 if !self.shared.state.associated_impls.is_prepared(ty)
979 || self
980 .shared
981 .state
982 .associated_impls
983 .get_internal_member_function(ty, "string")
984 .is_none()
985 {
986 self.add_default_functions(ty, node);
987 }
988 }
989 }
990
991 fn needs_any_string_functions(&self, ty: &TypeRef) -> bool {
993 let should_not_have_string_functions = matches!(
998 &*ty.kind,
999 TypeKind::Any
1000 | TypeKind::Byte
1001 | TypeKind::Codepoint
1002 | TypeKind::Int
1003 | TypeKind::Float
1004 | TypeKind::Bool
1005 | TypeKind::Range(_)
1006 | TypeKind::String(..)
1007 | TypeKind::Function(_)
1008 );
1009
1010 if should_not_have_string_functions {
1011 return false;
1012 }
1013
1014 if !self.shared.state.associated_impls.is_prepared(ty) {
1016 return true;
1017 }
1018
1019 let has_to_string = self
1020 .shared
1021 .state
1022 .associated_impls
1023 .get_internal_member_function(ty, "string")
1024 .is_some();
1025
1026 let has_to_short_string = self
1027 .shared
1028 .state
1029 .associated_impls
1030 .get_internal_member_function(ty, "short_string")
1031 .is_some();
1032
1033 let has_to_pretty_string = self
1034 .shared
1035 .state
1036 .associated_impls
1037 .get_internal_member_function(ty, "pretty_string")
1038 .is_some();
1039
1040 let has_to_pretty_string_with_indent = self
1041 .shared
1042 .state
1043 .associated_impls
1044 .get_internal_member_function(ty, "pretty_string_with_indent")
1045 .is_some();
1046
1047 !has_to_string
1048 || !has_to_short_string
1049 || !has_to_pretty_string
1050 || !has_to_pretty_string_with_indent
1051 }
1052
1053 pub fn add_default_functions(&mut self, type_to_attach_to: &TypeRef, node: &swamp_ast::Node) {
1054 if let TypeKind::Enum(enum_type) = &*type_to_attach_to.kind {
1055 for (_, variant) in &enum_type.variants {
1056 if !matches!(&*variant.payload_type.kind, TypeKind::Unit)
1057 && !TypeRef::ptr_eq(&variant.payload_type, type_to_attach_to)
1058 {
1059 let needs_string_functions =
1060 self.needs_any_string_functions(&variant.payload_type);
1061
1062 if needs_string_functions {
1063 self.add_default_functions(&variant.payload_type, node);
1064 }
1065 }
1066 }
1067 }
1068
1069 match &*type_to_attach_to.kind {
1071 TypeKind::Tuple(tuple_types) => {
1072 for element_type in tuple_types {
1073 if self.needs_any_string_functions(element_type) {
1074 self.add_default_functions(element_type, node);
1075 }
1076 }
1077 }
1078 TypeKind::Optional(inner_type) => {
1079 if self.needs_any_string_functions(inner_type) {
1080 self.add_default_functions(inner_type, node);
1081 }
1082 }
1083 TypeKind::FixedCapacityAndLengthArray(element_type, _)
1084 | TypeKind::SliceView(element_type)
1085 | TypeKind::DynamicLengthVecView(element_type)
1086 | TypeKind::VecStorage(element_type, _)
1087 | TypeKind::StackView(element_type)
1088 | TypeKind::QueueView(element_type)
1089 | TypeKind::StackStorage(element_type, _)
1090 | TypeKind::QueueStorage(element_type, _)
1091 | TypeKind::SparseView(element_type)
1092 | TypeKind::SparseStorage(element_type, _)
1093 | TypeKind::GridView(element_type)
1094 | TypeKind::GridStorage(element_type, _, _) => {
1095 if self.needs_any_string_functions(element_type) {
1096 self.add_default_functions(element_type, node);
1097 }
1098 }
1099 TypeKind::MapStorage(key_type, value_type, _)
1100 | TypeKind::DynamicLengthMapView(key_type, value_type) => {
1101 if self.needs_any_string_functions(key_type) {
1102 self.add_default_functions(key_type, node);
1103 }
1104 if self.needs_any_string_functions(value_type) {
1105 self.add_default_functions(value_type, node);
1106 }
1107 }
1108 _ => {}
1109 }
1110
1111 let underlying = type_to_attach_to;
1112
1113 if self.needs_any_string_functions(underlying) {
1114 if !self
1115 .shared
1116 .state
1117 .associated_impls
1118 .is_prepared(type_to_attach_to)
1119 {
1120 self.shared
1121 .state
1122 .associated_impls
1123 .prepare(type_to_attach_to);
1124 }
1125
1126 if self
1127 .shared
1128 .state
1129 .associated_impls
1130 .get_internal_member_function(underlying, "string")
1131 .is_none()
1132 {
1133 let to_string_function =
1134 self.generate_to_string_function_for_type(type_to_attach_to, node);
1135 self.shared
1136 .state
1137 .associated_impls
1138 .add_internal_function(type_to_attach_to, to_string_function)
1139 .unwrap();
1140 }
1141
1142 if self
1143 .shared
1144 .state
1145 .associated_impls
1146 .get_internal_member_function(underlying, "short_string")
1147 .is_none()
1148 {
1149 let to_short_string_function =
1150 self.generate_to_short_string_function_for_type(type_to_attach_to, node);
1151 self.shared
1152 .state
1153 .associated_impls
1154 .add_internal_function(type_to_attach_to, to_short_string_function)
1155 .unwrap();
1156 }
1157
1158 if self
1159 .shared
1160 .state
1161 .associated_impls
1162 .get_internal_member_function(underlying, "pretty_string")
1163 .is_none()
1164 {
1165 let to_pretty_string_function = self
1166 .generate_to_pretty_string_parameterless_function_for_type(
1167 type_to_attach_to,
1168 node,
1169 );
1170 self.shared
1171 .state
1172 .associated_impls
1173 .add_internal_function(type_to_attach_to, to_pretty_string_function)
1174 .unwrap();
1175 }
1176
1177 if self
1178 .shared
1179 .state
1180 .associated_impls
1181 .get_internal_member_function(underlying, "pretty_string_with_indent")
1182 .is_none()
1183 {
1184 let to_pretty_string_with_indent_function =
1185 self.generate_to_pretty_string_function_for_type(type_to_attach_to, node);
1186 self.shared
1187 .state
1188 .associated_impls
1189 .add_internal_function(type_to_attach_to, to_pretty_string_with_indent_function)
1190 .unwrap();
1191 }
1192 }
1193 }
1194
1195 pub fn ensure_default_functions_for_type(&mut self, ty: &TypeRef, node: &swamp_ast::Node) {
1198 if self.needs_any_string_functions(ty) {
1199 self.add_default_functions(ty, node);
1200 }
1201 }
1202
1203 fn generate_to_string_function_for_type(
1204 &mut self,
1205 ty: &TypeRef,
1206 ast_node: &Node,
1207 ) -> InternalFunctionDefinition {
1208 let node = self.to_node(ast_node);
1209 let mut generator = ExpressionGenerator::new(
1210 &mut self.shared.state.types,
1211 &self.shared.state.associated_impls,
1212 );
1213 internal_generate_to_string_function_for_type(
1214 &mut generator,
1215 &mut self.shared.state.internal_function_id_allocator,
1216 &mut self.shared.state.symbol_id_allocator,
1217 &mut self.shared.state.symbols,
1218 &self.module_path,
1219 ty,
1220 &node,
1221 false,
1222 )
1223 }
1224
1225 fn generate_to_short_string_function_for_type(
1226 &mut self,
1227 ty: &TypeRef,
1228 ast_node: &Node,
1229 ) -> InternalFunctionDefinition {
1230 let node = self.to_node(ast_node);
1231 let mut generator = ExpressionGenerator::new(
1232 &mut self.shared.state.types,
1233 &self.shared.state.associated_impls,
1234 );
1235 internal_generate_to_short_string_function_for_type(
1236 &mut generator,
1237 &mut self.shared.state.internal_function_id_allocator,
1238 &mut self.shared.state.symbol_id_allocator,
1239 &mut self.shared.state.symbols,
1240 &self.module_path,
1241 ty,
1242 &node,
1243 )
1244 }
1245
1246 fn generate_to_pretty_string_function_for_type(
1247 &mut self,
1248 ty: &TypeRef,
1249 ast_node: &Node,
1250 ) -> InternalFunctionDefinition {
1251 let node = self.to_node(ast_node);
1252 let mut generator = ExpressionGenerator::new(
1253 &mut self.shared.state.types,
1254 &self.shared.state.associated_impls,
1255 );
1256 internal_generate_to_pretty_string_function_for_type(
1257 &mut generator,
1258 &mut self.shared.state.internal_function_id_allocator,
1259 &mut self.shared.state.symbol_id_allocator,
1260 &mut self.shared.state.symbols,
1261 &self.module_path,
1262 ty,
1263 &node,
1264 )
1265 }
1266
1267 fn generate_to_pretty_string_parameterless_function_for_type(
1268 &mut self,
1269 ty: &TypeRef,
1270 ast_node: &Node,
1271 ) -> InternalFunctionDefinition {
1272 let node = self.to_node(ast_node);
1273 let mut generator = ExpressionGenerator::new(
1274 &mut self.shared.state.types,
1275 &self.shared.state.associated_impls,
1276 );
1277 internal_generate_to_pretty_string_parameterless_function_for_type(
1278 &mut generator,
1279 &mut self.shared.state.internal_function_id_allocator,
1280 &mut self.shared.state.symbol_id_allocator,
1281 &mut self.shared.state.symbols,
1282 &self.module_path,
1283 ty,
1284 &node,
1285 )
1286 }
1287}