1use crate::ast::{
2 EnumDef, EnumVariant, FieldOwnership, FunctionDef, FunctionParam, ImplBlock, Span, StructDef,
3 StructField, TraitBound, TraitDef, TraitMethod, Type, TypeKind, Visibility,
4};
5use crate::typechecker::{FunctionSignature, TypeChecker};
6use crate::vm::VM;
7use crate::Result;
8use hashbrown::HashMap;
9use std::collections::BTreeMap;
10
11#[derive(Clone, Default)]
13pub struct ExternRegistry {
14 structs: Vec<StructDef>,
15 enums: Vec<EnumDef>,
16 traits: Vec<TraitDef>,
17 impls: Vec<ImplBlock>,
18 functions: Vec<FunctionDef>,
19 constants: Vec<(String, Type)>,
20}
21
22impl ExternRegistry {
23 pub fn new() -> Self {
24 Self::default()
25 }
26
27 pub fn add_struct(&mut self, def: StructDef) -> &mut Self {
28 self.structs.push(def);
29 self
30 }
31
32 pub fn add_enum(&mut self, def: EnumDef) -> &mut Self {
33 self.enums.push(def);
34 self
35 }
36
37 pub fn add_trait(&mut self, def: TraitDef) -> &mut Self {
38 self.traits.push(def);
39 self
40 }
41
42 pub fn add_impl(&mut self, impl_block: ImplBlock) -> &mut Self {
43 self.impls.push(impl_block);
44 self
45 }
46
47 pub fn add_function(&mut self, func: FunctionDef) -> &mut Self {
48 self.functions.push(func);
49 self
50 }
51
52 pub fn add_const(&mut self, name: impl Into<String>, ty: Type) -> &mut Self {
53 self.constants.push((name.into(), ty));
54 self
55 }
56
57 pub fn extend(&mut self, other: &ExternRegistry) {
58 self.structs.extend(other.structs.iter().cloned());
59 self.enums.extend(other.enums.iter().cloned());
60 self.traits.extend(other.traits.iter().cloned());
61 self.impls.extend(other.impls.iter().cloned());
62 self.functions.extend(other.functions.iter().cloned());
63 self.constants.extend(other.constants.iter().cloned());
64 }
65
66 pub fn register_with_typechecker(&self, checker: &mut TypeChecker) -> Result<()> {
67 for def in &self.structs {
68 checker.register_external_struct(def.clone())?;
69 }
70 for def in &self.enums {
71 checker.register_external_enum(def.clone())?;
72 }
73 for def in &self.traits {
74 checker.register_external_trait(def.clone())?;
75 }
76 for func in &self.functions {
77 checker.register_external_function(function_signature_for(func))?;
78 }
79 for impl_block in &self.impls {
80 checker.register_external_impl(impl_block.clone())?;
81 }
82 for (name, ty) in &self.constants {
83 checker.register_external_constant(name.clone(), ty.clone())?;
84 }
85 Ok(())
86 }
87
88 pub fn register_with_vm(&self, vm: &mut VM) {
89 self.register_struct_layouts(vm);
90 self.register_type_stubs(vm);
91 }
92
93 pub fn register_struct_layouts(&self, vm: &mut VM) {
94 let prefix = vm.export_prefix();
95 let mut struct_map: HashMap<String, StructDef> = HashMap::new();
96 for def in &self.structs {
97 let canonical = canonicalize_struct(def, prefix.as_deref());
98 struct_map.insert(canonical.name.clone(), canonical);
99 }
100 if !struct_map.is_empty() {
101 vm.register_structs(&struct_map);
102 }
103 }
104
105 pub fn register_type_stubs(&self, vm: &mut VM) {
106 if self.structs.is_empty()
107 && self.enums.is_empty()
108 && self.traits.is_empty()
109 && self.impls.is_empty()
110 && self.constants.is_empty()
111 {
112 return;
113 }
114 let prefix = vm.export_prefix();
115 vm.register_type_stubs(self.module_stubs_with_prefix(prefix.as_deref()));
116 }
117
118 pub fn module_stubs(&self) -> Vec<ModuleStub> {
119 self.module_stubs_with_prefix(None)
120 }
121
122 fn module_stubs_with_prefix(&self, prefix: Option<&str>) -> Vec<ModuleStub> {
123 let mut modules: BTreeMap<String, ModuleStub> = BTreeMap::new();
124 for def in &self.structs {
125 let canonical = canonicalize_struct(def, prefix);
126 if let Some((module, name)) = module_and_name(&canonical.name) {
127 let entry = modules.entry(module.clone()).or_insert_with(|| ModuleStub {
128 module,
129 ..ModuleStub::default()
130 });
131 entry.struct_defs.push(format_struct_def(name, &canonical));
132 }
133 }
134 for def in &self.enums {
135 let canonical = canonicalize_enum(def, prefix);
136 if let Some((module, name)) = module_and_name(&canonical.name) {
137 let entry = modules.entry(module.clone()).or_insert_with(|| ModuleStub {
138 module,
139 ..ModuleStub::default()
140 });
141 entry.enum_defs.push(format_enum_def(name, &canonical));
142 }
143 }
144 for def in &self.traits {
145 let canonical = canonicalize_trait(def, prefix);
146 if let Some((module, name)) = module_and_name(&canonical.name) {
147 let entry = modules.entry(module.clone()).or_insert_with(|| ModuleStub {
148 module,
149 ..ModuleStub::default()
150 });
151 entry.trait_defs.push(format_trait_def(name, &canonical));
152 }
153 }
154 for (name, ty) in &self.constants {
155 let canonical_name = canonicalize_simple_name(name, prefix);
156 if let Some((module, short)) = module_and_name(&canonical_name) {
157 let entry = modules.entry(module.clone()).or_insert_with(|| ModuleStub {
158 module,
159 ..ModuleStub::default()
160 });
161 entry
162 .const_defs
163 .push(format_const_def(short, &canonicalize_type(ty, prefix)));
164 }
165 }
166 for def in &self.impls {
167 let canonical = canonicalize_impl(def, prefix);
168 if let Some(module) = impl_module(&canonical) {
169 modules.entry(module.clone()).or_insert_with(|| ModuleStub {
170 module,
171 ..ModuleStub::default()
172 });
173 }
174 }
175 modules.into_values().collect()
176 }
177
178 pub fn structs(&self) -> impl Iterator<Item = &StructDef> {
179 self.structs.iter()
180 }
181
182 pub fn enums(&self) -> impl Iterator<Item = &EnumDef> {
183 self.enums.iter()
184 }
185}
186
187#[derive(Clone, Debug, Default)]
188pub struct ModuleStub {
189 pub module: String,
190 pub struct_defs: Vec<String>,
191 pub enum_defs: Vec<String>,
192 pub trait_defs: Vec<String>,
193 pub const_defs: Vec<String>,
194}
195
196impl ModuleStub {
197 pub fn is_empty(&self) -> bool {
198 self.struct_defs.is_empty()
199 && self.enum_defs.is_empty()
200 && self.trait_defs.is_empty()
201 && self.const_defs.is_empty()
202 }
203}
204
205#[derive(Clone)]
206pub struct StructBuilder {
207 def: StructDef,
208}
209
210impl StructBuilder {
211 pub fn new(name: impl Into<String>) -> Self {
212 StructBuilder {
213 def: StructDef {
214 name: name.into(),
215 type_params: Vec::new(),
216 trait_bounds: Vec::new(),
217 fields: Vec::new(),
218 visibility: Visibility::Public,
219 },
220 }
221 }
222
223 pub fn visibility(mut self, visibility: Visibility) -> Self {
224 self.def.visibility = visibility;
225 self
226 }
227
228 pub fn type_param(mut self, name: impl Into<String>) -> Self {
229 self.def.type_params.push(name.into());
230 self
231 }
232
233 pub fn trait_bound(mut self, bound: TraitBound) -> Self {
234 self.def.trait_bounds.push(bound);
235 self
236 }
237
238 pub fn field(mut self, field: StructField) -> Self {
239 self.def.fields.push(field);
240 self
241 }
242
243 pub fn finish(self) -> StructDef {
244 self.def
245 }
246}
247
248#[derive(Clone)]
249pub struct EnumBuilder {
250 def: EnumDef,
251}
252
253impl EnumBuilder {
254 pub fn new(name: impl Into<String>) -> Self {
255 EnumBuilder {
256 def: EnumDef {
257 name: name.into(),
258 type_params: Vec::new(),
259 trait_bounds: Vec::new(),
260 variants: Vec::new(),
261 visibility: Visibility::Public,
262 },
263 }
264 }
265
266 pub fn visibility(mut self, visibility: Visibility) -> Self {
267 self.def.visibility = visibility;
268 self
269 }
270
271 pub fn type_param(mut self, name: impl Into<String>) -> Self {
272 self.def.type_params.push(name.into());
273 self
274 }
275
276 pub fn trait_bound(mut self, bound: TraitBound) -> Self {
277 self.def.trait_bounds.push(bound);
278 self
279 }
280
281 pub fn variant(mut self, variant: EnumVariant) -> Self {
282 self.def.variants.push(variant);
283 self
284 }
285
286 pub fn finish(self) -> EnumDef {
287 self.def
288 }
289}
290
291#[derive(Clone)]
292pub struct TraitBuilder {
293 def: TraitDef,
294}
295
296impl TraitBuilder {
297 pub fn new(name: impl Into<String>) -> Self {
298 TraitBuilder {
299 def: TraitDef {
300 name: name.into(),
301 type_params: Vec::new(),
302 methods: Vec::new(),
303 visibility: Visibility::Public,
304 },
305 }
306 }
307
308 pub fn visibility(mut self, visibility: Visibility) -> Self {
309 self.def.visibility = visibility;
310 self
311 }
312
313 pub fn type_param(mut self, name: impl Into<String>) -> Self {
314 self.def.type_params.push(name.into());
315 self
316 }
317
318 pub fn method(mut self, method: TraitMethod) -> Self {
319 self.def.methods.push(method);
320 self
321 }
322
323 pub fn finish(self) -> TraitDef {
324 self.def
325 }
326}
327
328#[derive(Clone)]
329pub struct ImplBuilder {
330 block: ImplBlock,
331}
332
333impl ImplBuilder {
334 pub fn new(target_type: Type) -> Self {
335 ImplBuilder {
336 block: ImplBlock {
337 type_params: Vec::new(),
338 trait_name: None,
339 target_type,
340 methods: Vec::new(),
341 where_clause: Vec::new(),
342 },
343 }
344 }
345
346 pub fn for_trait(mut self, trait_name: impl Into<String>) -> Self {
347 self.block.trait_name = Some(trait_name.into());
348 self
349 }
350
351 pub fn type_param(mut self, name: impl Into<String>) -> Self {
352 self.block.type_params.push(name.into());
353 self
354 }
355
356 pub fn where_bound(mut self, bound: TraitBound) -> Self {
357 self.block.where_clause.push(bound);
358 self
359 }
360
361 pub fn method(mut self, method: FunctionDef) -> Self {
362 self.block.methods.push(method);
363 self
364 }
365
366 pub fn finish(self) -> ImplBlock {
367 self.block
368 }
369}
370
371#[derive(Clone)]
372pub struct TraitMethodBuilder {
373 method: TraitMethod,
374}
375
376impl TraitMethodBuilder {
377 pub fn new(name: impl Into<String>) -> Self {
378 TraitMethodBuilder {
379 method: TraitMethod {
380 name: name.into(),
381 type_params: Vec::new(),
382 params: Vec::new(),
383 return_type: None,
384 default_impl: None,
385 },
386 }
387 }
388
389 pub fn type_param(mut self, name: impl Into<String>) -> Self {
390 self.method.type_params.push(name.into());
391 self
392 }
393
394 pub fn param(mut self, param: FunctionParam) -> Self {
395 self.method.params.push(param);
396 self
397 }
398
399 pub fn return_type(mut self, ty: Type) -> Self {
400 self.method.return_type = Some(ty);
401 self
402 }
403
404 pub fn finish(self) -> TraitMethod {
405 self.method
406 }
407}
408
409#[derive(Clone)]
410pub struct FunctionBuilder {
411 function: FunctionDef,
412}
413
414impl FunctionBuilder {
415 pub fn new(name: impl Into<String>) -> Self {
416 let name = name.into();
417 FunctionBuilder {
418 function: FunctionDef {
419 name,
420 type_params: Vec::new(),
421 trait_bounds: Vec::new(),
422 params: Vec::new(),
423 return_type: None,
424 body: Vec::new(),
425 is_method: false,
426 visibility: Visibility::Public,
427 },
428 }
429 }
430
431 pub fn visibility(mut self, visibility: Visibility) -> Self {
432 self.function.visibility = visibility;
433 self
434 }
435
436 pub fn type_param(mut self, name: impl Into<String>) -> Self {
437 self.function.type_params.push(name.into());
438 self
439 }
440
441 pub fn trait_bound(mut self, bound: TraitBound) -> Self {
442 self.function.trait_bounds.push(bound);
443 self
444 }
445
446 pub fn param(mut self, param: FunctionParam) -> Self {
447 if param.is_self {
448 self.function.is_method = true;
449 }
450 self.function.params.push(param);
451 self
452 }
453
454 pub fn return_type(mut self, ty: Type) -> Self {
455 self.function.return_type = Some(ty);
456 self
457 }
458
459 pub fn finish(self) -> FunctionDef {
460 self.function
461 }
462}
463
464pub fn struct_field_decl(name: impl Into<String>, ty: Type) -> StructField {
465 StructField {
466 name: name.into(),
467 ty,
468 visibility: Visibility::Public,
469 ownership: FieldOwnership::Strong,
470 weak_target: None,
471 }
472}
473
474pub fn weak_struct_field_decl(name: impl Into<String>, ty: Type) -> StructField {
475 let span = ty.span;
476 let option = Type::new(TypeKind::Option(Box::new(ty.clone())), span);
477 StructField {
478 name: name.into(),
479 ty: option,
480 visibility: Visibility::Public,
481 ownership: FieldOwnership::Weak,
482 weak_target: Some(ty),
483 }
484}
485
486pub fn private_struct_field_decl(name: impl Into<String>, ty: Type) -> StructField {
487 StructField {
488 name: name.into(),
489 ty,
490 visibility: Visibility::Private,
491 ownership: FieldOwnership::Strong,
492 weak_target: None,
493 }
494}
495
496pub fn enum_variant(name: impl Into<String>) -> EnumVariant {
497 EnumVariant {
498 name: name.into(),
499 fields: None,
500 }
501}
502
503pub fn enum_variant_with(
504 name: impl Into<String>,
505 fields: impl IntoIterator<Item = Type>,
506) -> EnumVariant {
507 EnumVariant {
508 name: name.into(),
509 fields: Some(fields.into_iter().collect()),
510 }
511}
512
513pub fn trait_bound(
514 param: impl Into<String>,
515 traits: impl IntoIterator<Item = String>,
516) -> TraitBound {
517 TraitBound {
518 type_param: param.into(),
519 traits: traits.into_iter().collect(),
520 }
521}
522
523pub fn function_param(name: impl Into<String>, ty: Type) -> FunctionParam {
524 FunctionParam {
525 name: name.into(),
526 ty,
527 is_self: false,
528 }
529}
530
531pub fn self_param(ty: Option<Type>) -> FunctionParam {
532 FunctionParam {
533 name: "self".to_string(),
534 ty: ty.unwrap_or_else(|| Type::new(TypeKind::Infer, Span::dummy())),
535 is_self: true,
536 }
537}
538
539pub fn type_named(name: impl Into<String>) -> Type {
540 Type::new(TypeKind::Named(name.into()), Span::dummy())
541}
542
543pub fn type_unit() -> Type {
544 Type::new(TypeKind::Unit, Span::dummy())
545}
546
547pub fn type_unknown() -> Type {
548 Type::new(TypeKind::Unknown, Span::dummy())
549}
550
551fn function_signature_for(func: &FunctionDef) -> (String, FunctionSignature) {
552 let params: Vec<Type> = func.params.iter().map(|p| p.ty.clone()).collect();
553 let return_type = func
554 .return_type
555 .clone()
556 .unwrap_or_else(|| Type::new(TypeKind::Unit, Span::dummy()));
557 (
558 func.name.clone(),
559 FunctionSignature {
560 params,
561 return_type,
562 is_method: func.is_method,
563 },
564 )
565}
566
567fn module_and_name(name: &str) -> Option<(String, String)> {
568 if let Some((module, rest)) = name.rsplit_once("::") {
569 return Some((module.replace("::", "."), rest.to_string()));
570 }
571 if let Some((module, rest)) = name.rsplit_once('.') {
572 return Some((module.to_string(), rest.to_string()));
573 }
574 None
575}
576
577fn impl_module(impl_block: &ImplBlock) -> Option<String> {
578 match &impl_block.target_type.kind {
579 TypeKind::Named(name) => module_and_name(name).map(|(module, _)| module),
580 TypeKind::GenericInstance { name, .. } => module_and_name(name).map(|(module, _)| module),
581 _ => None,
582 }
583}
584
585fn format_struct_def(name: String, def: &StructDef) -> String {
586 let mut out = String::new();
587 if matches!(def.visibility, Visibility::Public) {
588 out.push_str("pub ");
589 }
590 out.push_str("struct ");
591 out.push_str(&name);
592 if !def.type_params.is_empty() {
593 out.push('<');
594 out.push_str(&def.type_params.join(", "));
595 out.push('>');
596 }
597 out.push('\n');
598 for field in &def.fields {
599 out.push_str(" ");
600 if matches!(field.visibility, Visibility::Public) {
601 out.push_str("pub ");
602 }
603 out.push_str(&field.name);
604 out.push_str(": ");
605 match field.ownership {
606 FieldOwnership::Weak => {
607 out.push_str("ref ");
608 if let Some(target) = &field.weak_target {
609 out.push_str(&format_type(target));
610 } else {
611 out.push_str(&format_type(&field.ty));
612 }
613 }
614 FieldOwnership::Strong => {
615 out.push_str(&format_type(&field.ty));
616 }
617 }
618 out.push('\n');
619 }
620 out.push_str("end\n");
621 out
622}
623
624fn format_enum_def(name: String, def: &EnumDef) -> String {
625 let mut out = String::new();
626 if matches!(def.visibility, Visibility::Public) {
627 out.push_str("pub ");
628 }
629 out.push_str("enum ");
630 out.push_str(&name);
631 if !def.type_params.is_empty() {
632 out.push('<');
633 out.push_str(&def.type_params.join(", "));
634 out.push('>');
635 }
636 out.push('\n');
637 for variant in &def.variants {
638 out.push_str(" ");
639 out.push_str(&variant.name);
640 if let Some(fields) = &variant.fields {
641 let parts: Vec<String> = fields.iter().map(format_type).collect();
642 out.push('(');
643 out.push_str(&parts.join(", "));
644 out.push(')');
645 }
646 out.push('\n');
647 }
648 out.push_str("end\n");
649 out
650}
651
652fn format_trait_def(name: String, def: &TraitDef) -> String {
653 let mut out = String::new();
654 if matches!(def.visibility, Visibility::Public) {
655 out.push_str("pub ");
656 }
657 out.push_str("trait ");
658 out.push_str(&name);
659 if !def.type_params.is_empty() {
660 out.push('<');
661 out.push_str(&def.type_params.join(", "));
662 out.push('>');
663 }
664 out.push('\n');
665 for method in &def.methods {
666 out.push_str(" ");
667 out.push_str(&format_trait_method(method));
668 out.push('\n');
669 }
670 out.push_str("end\n");
671 out
672}
673
674fn format_const_def(name: String, ty: &Type) -> String {
675 let mut out = String::new();
676 out.push_str("pub const ");
677 out.push_str(&name);
678 out.push_str(": ");
679 out.push_str(&format_type(ty));
680 out.push('\n');
681 out
682}
683
684fn format_trait_method(method: &TraitMethod) -> String {
685 let mut out = String::new();
686 out.push_str("function ");
687 out.push_str(&method.name);
688 if !method.type_params.is_empty() {
689 out.push('<');
690 out.push_str(&method.type_params.join(", "));
691 out.push('>');
692 }
693 out.push('(');
694 out.push_str(
695 &method
696 .params
697 .iter()
698 .map(format_param_signature)
699 .collect::<Vec<_>>()
700 .join(", "),
701 );
702 out.push(')');
703 if let Some(ret) = &method.return_type {
704 if !matches!(ret.kind, TypeKind::Unit) {
705 out.push_str(": ");
706 out.push_str(&format_type(ret));
707 }
708 }
709 out
710}
711
712fn format_param_signature(param: &FunctionParam) -> String {
713 if param.is_self {
714 return "self".to_string();
715 }
716 if matches!(param.ty.kind, TypeKind::Infer) {
717 param.name.clone()
718 } else {
719 format!("{}: {}", param.name, format_type(¶m.ty))
720 }
721}
722
723fn format_type(ty: &Type) -> String {
724 match &ty.kind {
725 TypeKind::Named(name) => {
726 let (_, simple) =
727 module_and_name(name).unwrap_or_else(|| (String::new(), name.clone()));
728 if simple.is_empty() {
729 name.clone()
730 } else {
731 simple
732 }
733 }
734 TypeKind::GenericInstance { name, type_args } => {
735 let (_, simple) =
736 module_and_name(name).unwrap_or_else(|| (String::new(), name.clone()));
737 let args = type_args
738 .iter()
739 .map(format_type)
740 .collect::<Vec<_>>()
741 .join(", ");
742 format!("{}<{}>", simple, args)
743 }
744 _ => format!("{}", ty),
745 }
746}
747
748fn canonicalize_struct(def: &StructDef, prefix: Option<&str>) -> StructDef {
749 let mut cloned = def.clone();
750 cloned.name = canonicalize_simple_name(&cloned.name, prefix);
751 for field in &mut cloned.fields {
752 field.ty = canonicalize_type(&field.ty, prefix);
753 if let Some(target) = &field.weak_target {
754 field.weak_target = Some(canonicalize_type(target, prefix));
755 }
756 }
757 cloned
758}
759
760fn canonicalize_enum(def: &EnumDef, prefix: Option<&str>) -> EnumDef {
761 let mut cloned = def.clone();
762 cloned.name = canonicalize_simple_name(&cloned.name, prefix);
763 for variant in &mut cloned.variants {
764 if let Some(fields) = &mut variant.fields {
765 for field in fields {
766 *field = canonicalize_type(field, prefix);
767 }
768 }
769 }
770 cloned
771}
772
773fn canonicalize_trait(def: &TraitDef, prefix: Option<&str>) -> TraitDef {
774 let mut cloned = def.clone();
775 cloned.name = canonicalize_simple_name(&cloned.name, prefix);
776 for method in &mut cloned.methods {
777 for param in &mut method.params {
778 param.ty = canonicalize_type(¶m.ty, prefix);
779 }
780 if let Some(ret) = method.return_type.clone() {
781 method.return_type = Some(canonicalize_type(&ret, prefix));
782 }
783 }
784 cloned
785}
786
787fn canonicalize_impl(def: &ImplBlock, prefix: Option<&str>) -> ImplBlock {
788 let mut cloned = def.clone();
789 cloned.target_type = canonicalize_type(&cloned.target_type, prefix);
790 let struct_name = match &cloned.target_type.kind {
791 TypeKind::Named(name) => name.clone(),
792 TypeKind::GenericInstance { name, .. } => name.clone(),
793 _ => cloned.target_type.to_string(),
794 };
795 if let Some(trait_name) = &cloned.trait_name {
796 cloned.trait_name = Some(canonicalize_simple_name(trait_name, prefix));
797 }
798 for method in &mut cloned.methods {
799 for param in &mut method.params {
800 param.ty = canonicalize_type(¶m.ty, prefix);
801 }
802 if let Some(ret) = method.return_type.clone() {
803 method.return_type = Some(canonicalize_type(&ret, prefix));
804 }
805 if let Some((_, rest)) = method.name.split_once(':') {
806 method.name = format!("{}:{}", struct_name, rest);
807 } else if let Some((_, rest)) = method.name.split_once('.') {
808 method.name = format!("{}.{}", struct_name, rest);
809 } else {
810 method.name = format!("{}:{}", struct_name, method.name);
811 }
812 #[cfg(debug_assertions)]
813 eprintln!("canonicalized method name -> {}", method.name);
814 }
815 cloned
816}
817
818fn canonicalize_type(ty: &Type, prefix: Option<&str>) -> Type {
819 use TypeKind as TK;
820 let mut canonical = ty.clone();
821 canonical.kind = match &ty.kind {
822 TK::Named(name) => TK::Named(canonicalize_simple_name(name, prefix)),
823 TK::GenericInstance { name, type_args } => TK::GenericInstance {
824 name: canonicalize_simple_name(name, prefix),
825 type_args: type_args
826 .iter()
827 .map(|arg| canonicalize_type(arg, prefix))
828 .collect(),
829 },
830 TK::Array(inner) => TK::Array(Box::new(canonicalize_type(inner, prefix))),
831 TK::Option(inner) => TK::Option(Box::new(canonicalize_type(inner, prefix))),
832 TK::Result(ok, err) => TK::Result(
833 Box::new(canonicalize_type(ok, prefix)),
834 Box::new(canonicalize_type(err, prefix)),
835 ),
836 TK::Ref(inner) => TK::Ref(Box::new(canonicalize_type(inner, prefix))),
837 TK::MutRef(inner) => TK::MutRef(Box::new(canonicalize_type(inner, prefix))),
838 TK::Map(key, value) => TK::Map(
839 Box::new(canonicalize_type(key, prefix)),
840 Box::new(canonicalize_type(value, prefix)),
841 ),
842 TK::Tuple(elements) => TK::Tuple(
843 elements
844 .iter()
845 .map(|element| canonicalize_type(element, prefix))
846 .collect(),
847 ),
848 TK::Union(types) => TK::Union(
849 types
850 .iter()
851 .map(|variant| canonicalize_type(variant, prefix))
852 .collect(),
853 ),
854 other => other.clone(),
855 };
856 canonical
857}
858
859fn canonicalize_simple_name(name: &str, prefix: Option<&str>) -> String {
860 if name.is_empty() {
861 return name.to_string();
862 }
863 if is_qualified_name(name) {
864 return name.replace("::", ".");
865 }
866 if let Some(prefix) = prefix {
867 if prefix.is_empty() {
868 return name.to_string();
869 }
870 return format!("{}.{}", prefix, name);
871 }
872 name.to_string()
873}
874
875fn is_qualified_name(name: &str) -> bool {
876 name.contains('.') || name.contains("::")
877}