1use std::collections::{HashMap, HashSet};
2use std::fmt::{Display, Formatter, Write};
3use proc_macro2::{Spacing, TokenTree};
4use quote::{quote, ToTokens};
5use syn::{Attribute, Ident, ItemUse, Path, Signature, Type};
6use crate::ast::{PathHolder, TypeHolder, TypePathHolder};
7use crate::composable::{GenericBoundsModel, GenericConversion, TraitModelPart1, TraitDecompositionPart1, TraitTypeModel};
8use crate::context::{GlobalContext, ScopeChain};
9use crate::conversion::{MixinKind, ObjectKind};
10use crate::tree::{ScopeTreeExportID, ScopeTreeExportItem, ScopeTreeItem};
11
12#[allow(unused)]
13pub fn format_imported_set(dict: &HashSet<ItemUse>) -> String {
14 let debug_imports = dict.iter().map(|i| {
15 i.to_token_stream()
16 }).collect::<Vec<_>>();
17 let all = quote!(#(#debug_imports,)*);
18 all.to_string()
19}
20
21#[allow(unused)]
22pub fn format_scope_refinement(dict: &Vec<(ScopeChain, HashMap<TypeHolder, ObjectKind>)>) -> String {
23 let mut iter = dict.iter()
24 .map(|(scope, types)|
25 format!("\t{}: \n\t\t{}", scope.self_path_holder_ref(), types.iter().map(scope_type_conversion_pair).collect::<Vec<_>>()
26 .join("\n\t")))
27 .collect::<Vec<String>>();
28 iter.sort();
29 iter.join("\n")
30
31}
32
33#[allow(unused)]
34pub fn format_type_holders(dict: &HashSet<TypeHolder>) -> String {
35 dict.iter()
36 .map(|item| item.0.to_token_stream().to_string())
38 .collect::<Vec<_>>()
39 .join("\n\n")
40}
41#[allow(unused)]
42pub fn format_type_holders_vec(dict: &Vec<TypeHolder>) -> String {
43 dict.iter()
44 .map(|item| item.0.to_token_stream().to_string())
46 .collect::<Vec<_>>()
47 .join("\n\n")
48}
49#[allow(unused)]
50pub fn format_types(dict: &HashSet<Type>) -> String {
51 dict.iter()
52 .map(|item| item.to_token_stream().to_string())
54 .collect::<Vec<_>>()
55 .join("\n\n")
56}
57
58#[allow(unused)]
59pub fn format_generic_conversions(dict: &HashMap<GenericConversion, HashSet<Option<Attribute>>>) -> String {
60 dict.iter()
61 .map(|(item, attrs)| format!("{}: {}", format_unique_attrs(attrs), item.object.to_token_stream()))
62 .collect::<Vec<_>>()
63 .join("\n\t")
64}
65#[allow(unused)]
66pub fn format_mixin_kinds(dict: &HashMap<MixinKind, HashSet<Option<Attribute>>>) -> String {
67 dict.iter()
68 .map(|(item, attrs)| format!("{}:\t {}", item, format_unique_attrs(attrs)))
69 .collect::<Vec<_>>()
70 .join("\n\t")
71}
72#[allow(unused)]
73pub fn format_mixin_conversions(dict: &HashMap<GenericBoundsModel, HashSet<Option<Attribute>>>) -> String {
74 dict.iter()
75 .map(|(item, attrs)| format!("{}:\n\t {}", item, format_unique_attrs(attrs)))
76 .collect::<Vec<_>>()
77 .join("\n\t")
78}
79
80#[allow(unused)]
81pub fn format_unique_attrs(dict: &HashSet<Option<Attribute>>) -> String {
82 dict.iter()
83 .map(|item| item.as_ref().map_or("[None]".to_string(), |a| a.to_token_stream().to_string()))
84 .collect::<Vec<_>>()
85 .join("\n\t")
86}
87
88pub fn format_attrs(dict: &Vec<Attribute>) -> String {
89 dict.iter()
90 .map(|item| item.to_token_stream().to_string())
91 .collect::<Vec<_>>()
92 .join("\n\t")
93}
94
95#[allow(unused)]
96pub fn format_imports(dict: &HashMap<ScopeChain, HashMap<PathHolder, Path>>) -> String {
97 let vec = scope_imports_dict(dict);
98 let expanded = quote!(#(#vec),*);
99 expanded.to_string()
100}
101
102#[allow(unused)]
103pub fn format_tree_exported_dict(dict: &HashMap<ScopeTreeExportID, ScopeTreeExportItem>) -> String {
104 dict.iter()
105 .map(|(ident, tree_item)| format!("{}: {}", ident, tree_item))
106 .collect::<Vec<_>>()
107 .join("\n\n")
108}
109
110#[allow(unused)]
111pub fn format_tree_item_dict(dict: &HashMap<ScopeTreeExportID, ScopeTreeItem>) -> String {
112 dict.iter()
113 .map(|(ident, tree_item)| format!("\t{}: {:?}", ident, tree_item))
114 .collect::<Vec<_>>()
115 .join("\n\n")
116}
117
118#[allow(unused)]
119pub fn scope_type_conversion_pair(dict: (&TypeHolder, &ObjectKind)) -> String {
120 format!("\t{}: {}", dict.0.to_token_stream(), dict.1)
121 }
123
124#[allow(unused)]
125pub fn refinement_pair(dict: (&TypeHolder, &Vec<ObjectKind>)) -> String {
126 format!("\t{}: \n\t\t{}", dict.0.to_token_stream(), dict.1.iter().map(|i| i.to_string()).collect::<Vec<_>>()
127 .join("\n\t"))
128 }
130#[allow(unused)]
138pub fn ident_type_conversion_pair(dict: (&Ident, &Type)) -> String {
139 format!("\t{}: {}", format_token_stream(dict.0), format_token_stream(dict.1))
140}
141
142#[allow(unused)]
143pub fn ident_signature_conversion_pair(dict: (&Ident, &Signature)) -> String {
144 format!("\t{}: {}", format_token_stream(dict.0), format_token_stream(dict.1))
145}
146
147#[allow(unused)]
148pub fn ident_trait_type_decomposition_conversion_pair(dict: (&Ident, &TraitTypeModel)) -> String {
149 format!("\t{}: {}", format_token_stream(dict.0), {
150 let TraitTypeModel { ident, trait_bounds, generics } = dict.1;
151 quote!(#ident: [bounds: #(#trait_bounds)*, generics: #generics])
152 })
153}
154fn format_ident_path_pair(pair: (&PathHolder, &Path)) -> String {
155 format!("\t{}: {}", format_token_stream(pair.0), format_token_stream(pair.1))
156}
157
158pub fn format_path_vec(vec: &Vec<Path>) -> String {
159 vec.iter().map(|p| p.to_token_stream().to_string()).collect::<Vec<_>>().join(",")
160}
161pub fn format_obj_vec(vec: &Vec<ObjectKind>) -> String {
162 vec.iter().map(|p| p.to_token_stream().to_string()).collect::<Vec<_>>().join(",")
163}
164
165#[allow(unused)]
166pub fn type_vec_path_conversion_pair(pair: (&Type, &Vec<Path>)) -> String {
167 format!("\t{}: [{}]", format_token_stream(pair.0), format_path_vec(pair.1))
168}
169#[allow(unused)]
170pub fn type_vec_obj_conversion_pair(pair: (&Type, &Vec<ObjectKind>)) -> String {
171 format!("\t{}: [{}]", format_token_stream(pair.0), format_obj_vec(pair.1))
172}
173#[allow(unused)]
174pub fn format_predicates_dict(vec: &HashMap<Type, Vec<Path>>) -> String {
175 vec.iter()
176 .map(type_vec_path_conversion_pair)
177 .collect::<Vec<_>>()
178 .join(",")
179}
180#[allow(unused)]
181pub fn format_predicates_obj_dict(vec: &HashMap<Type, Vec<ObjectKind>>) -> String {
182 vec.iter()
183 .map(type_vec_obj_conversion_pair)
184 .collect::<Vec<_>>()
185 .join(",")
186}
187
188#[allow(unused)]
189fn format_generic_bounds_pair(pair: (&TypePathHolder, &Vec<Path>)) -> String {
190 format!("\t{}: [{}]", format_token_stream(pair.0), format_path_vec(pair.1))
191}
192
193fn format_ident_trait_pair(pair: (&Ident, &TraitModelPart1)) -> String {
194 let implementors = &pair.1.implementors;
195 format!("\t{}: {}: [{}]", format_token_stream(pair.0), "...", quote!(#(#implementors),*))
196}
197
198#[allow(unused)]
199pub fn format_types_dict(dict: &HashMap<TypeHolder, ObjectKind>) -> String {
200 types_dict(dict)
201 .join("\n")
202}
203#[allow(unused)]
204pub fn format_types_to_refine(dict: &HashMap<TypeHolder, Vec<ObjectKind>>) -> String {
205 let mut iter = dict.iter()
206 .map(refinement_pair)
207 .collect::<Vec<String>>();
208 iter.sort();
209 iter.join("\n")
210}
211
212#[allow(unused)]
213pub fn format_ident_types_dict(dict: &HashMap<Ident, Type>) -> String {
214 ident_types_dict(dict)
215 .join("\n")
216}
217
218#[allow(unused)]
225pub fn format_used_traits(dict: &HashMap<ScopeChain, HashMap<Ident, TraitModelPart1>>) -> String {
226 scope_traits_dict(dict).join("\n")
227}
228
229pub fn format_token_stream<TT: ToTokens>(token_stream: TT) -> String {
234 let token_stream = token_stream.into_token_stream();
236 let mut formatted_string = String::new();
237 let mut space_needed = false;
238 let mut inside_angle_brackets = 0;
239 let mut inside_round_brackets = 0;
240 let mut last_token_was_ampersand = false;
242 let mut last_token_was_comma = false;
243 for token in token_stream {
246 if last_token_was_comma {
247 formatted_string.push(' ');
248 }
249 last_token_was_comma = false;
250 match token {
251 TokenTree::Ident(ident) => {
252 if last_token_was_ampersand && (ident == "mut" || ident.to_string().starts_with('\'')) {
254 formatted_string.pop(); } else if space_needed {
256 formatted_string.push(' ');
257 }
258 formatted_string.push_str(&ident.to_string());
259 space_needed = true;
260 last_token_was_ampersand = false;
261 }
262 TokenTree::Punct(punct) => {
263 match punct.as_char() {
264 ';' => {
265 formatted_string.push(';');
266 space_needed = true;
267 }
268 ':' => {
269 formatted_string.push(':');
270 space_needed = false;
271 }
272 '(' => {
273 inside_round_brackets += 1;
274 formatted_string.push('(');
275 space_needed = false;
276 }
277 ')' => {
278 inside_round_brackets -= 1;
279 formatted_string.push(')');
280 space_needed = true;
281 }
282 '<' => {
283 inside_angle_brackets += 1;
284 formatted_string.push('<');
285 space_needed = false;
286 }
287 '>' => {
288 inside_angle_brackets -= 1;
289 formatted_string.push('>');
290 space_needed = true;
291 }
292 ',' => {
303 formatted_string.push(',');
304 last_token_was_comma = true;
305 space_needed = true; }
307 '&' => {
308 formatted_string.push('&');
309 last_token_was_ampersand = true;
310 space_needed = false;
311 }
312 _ => {
313 if space_needed {
314 formatted_string.push(' ');
315 }
316 formatted_string.push(punct.as_char());
317 space_needed = punct.spacing() == Spacing::Alone;
318 }
319 }
320 }
321 TokenTree::Literal(literal) => {
322 if space_needed {
323 formatted_string.push(' ');
324 }
325 formatted_string.push_str(&literal.to_string());
326 space_needed = true;
327 last_token_was_ampersand = false;
328 }
329 TokenTree::Group(group) => {
330 if space_needed && (inside_angle_brackets == 0 || inside_round_brackets == 0) {
331 formatted_string.push(' ');
332 }
333 formatted_string.push_str(&format_token_stream(group.stream()));
334 space_needed = true;
335 last_token_was_ampersand = false;
336 }
337 }
338 }
339
340 formatted_string
341}
342
343
344
345pub fn imports_dict(dict: &HashMap<PathHolder, Path>) -> Vec<String> {
348 dict.iter()
349 .map(format_ident_path_pair)
350 .collect()
351}
352
353#[allow(unused)]
354pub fn generic_bounds_dict(dict: &HashMap<TypePathHolder, Vec<Path>>) -> Vec<String> {
355 dict.iter()
356 .map(format_generic_bounds_pair)
357 .collect()
358}
359
360pub fn types_dict(dict: &HashMap<TypeHolder, ObjectKind>) -> Vec<String> {
361 let mut iter = dict.iter()
362 .map(scope_type_conversion_pair)
363 .collect::<Vec<String>>();
364 iter.sort();
365 iter
366}
367fn ident_signatures_dict(dict: &HashMap<Ident, Signature>) -> Vec<String> {
368 let mut iter = dict.iter()
369 .map(ident_signature_conversion_pair)
370 .collect::<Vec<String>>();
371 iter.sort();
372 iter
373}
374
375
376fn ident_trait_type_decomposition_dict(dict: &HashMap<Ident, TraitTypeModel>) -> Vec<String> {
377 let mut iter = dict.iter()
378 .map(ident_trait_type_decomposition_conversion_pair)
379 .collect::<Vec<String>>();
380 iter.sort();
381 iter
382}
383
384fn ident_types_dict(dict: &HashMap<Ident, Type>) -> Vec<String> {
385 let mut iter = dict.iter()
386 .map(ident_type_conversion_pair)
387 .collect::<Vec<String>>();
388 iter.sort();
389 iter
390}
391
392fn traits_dict(dict: &HashMap<Ident, TraitModelPart1>) -> Vec<String> {
393 let mut iter = dict.iter()
394 .map(format_ident_trait_pair)
395 .collect::<Vec<String>>();
396 iter.sort();
397 iter
398}
399
400
401fn nested_scope_dict<K, K2, V2, F: Fn(&K, &HashMap<K2, V2>) -> String>(dict: &HashMap<K, HashMap<K2, V2>>, mapper: F) -> Vec<String> {
402 let mut iter = dict.iter()
403 .map(|(key, value)| mapper(key, value))
404 .collect::<Vec<String>>();
405 iter.sort();
406 iter
407}
408
409fn format_scope_dict<K2, V2, F: Fn(&HashMap<K2, V2>) -> Vec<String>>(dict: &HashMap<ScopeChain, HashMap<K2, V2>>, mapper: F) -> Vec<String> {
410 nested_scope_dict(dict, |scope, sub_dict|
411 format!("\t{}:\n\t\t{}", scope.fmt_short(), mapper(sub_dict).join("\n\t\t")))
412}
413
414pub fn scope_imports_dict(dict: &HashMap<ScopeChain, HashMap<PathHolder, Path>>) -> Vec<String> {
415 format_scope_dict(dict, imports_dict)
416}
417
418#[allow(unused)]
419pub fn scope_generics_dict(dict: &HashMap<ScopeChain, HashMap<TypePathHolder, Vec<Path>>>) -> Vec<String> {
420 format_scope_dict(dict, generic_bounds_dict)
421}
422
423
424fn scope_traits_dict(dict: &HashMap<ScopeChain, HashMap<Ident, TraitModelPart1>>) -> Vec<String> {
425 format_scope_dict(dict, traits_dict)
426}
427
428
429
430fn traits_impl_dict(dict: &HashMap<ScopeChain, Vec<PathHolder>>) -> Vec<String> {
431 let mut iter = dict.iter()
434 .filter_map(|(key, value)| {
435 let scopes = quote!(#(#value),*);
436 if value.is_empty() {
437 None
438 } else {
439 Some(format!("\t{}:\n\t\t{}", format_token_stream(key), format_token_stream(&scopes)))
440 }
441 })
442 .collect::<Vec<String>>();
443 iter.sort();
444 iter
445}
446
447fn format_complex_obj(vec: Vec<Vec<String>>) -> String {
448 vec.into_iter()
449 .flatten()
450 .collect::<Vec<String>>()
451 .join("\n\t")
452}
453
454pub fn format_global_context(context: &GlobalContext) -> String {
455 format_complex_obj(vec![
456 vec!["-- types:".to_string(), context.scope_register.to_string()],
457 vec!["-- traits:".to_string()], scope_traits_dict(&context.traits.inner),
458 vec!["-- traits_impl:".to_string()], traits_impl_dict(&context.traits.used_traits_dictionary),
459 vec!["-- custom:".to_string(), context.custom.to_string()],
460 vec!["-- imports:".to_string()], scope_imports_dict(&context.imports.inner),
461 vec!["-- generics:".to_string()], scope_generics_dict(&context.generics.inner),
462 ])
463}
464
465#[allow(unused)]
466pub fn format_trait_decomposition_part1(dict: &TraitDecompositionPart1) -> String {
467 format_complex_obj(vec![
468 vec!["\n-- ident:".to_string()], vec![format_token_stream(&dict.ident)],
469 vec!["-- consts:".to_string()], ident_types_dict(&dict.consts),
470 vec!["-- methods:".to_string()], ident_signatures_dict(&dict.methods),
471 vec!["-- types:".to_string()], ident_trait_type_decomposition_dict(&dict.types),
472 ])
473}
474
475#[allow(dead_code)]
491pub enum Emoji {
492 Branch,
493 Question,
494 Local,
495 Nothing,
496 Ok,
497 Error,
498 Plus,
499 Node,
500 Folder,
501 File
502}
503
504impl Display for Emoji {
505 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
506 f.write_char(
507 match self {
508 Emoji::Question => '\u{2753}',
509 Emoji::Branch => '\u{1D30E}',
510 Emoji::Local => '\u{1F501}',
511 Emoji::Ok => '\u{2705}',
512 Emoji::Error => '\u{274C}',
513 Emoji::Nothing => '\u{1F502}',
514 Emoji::Plus => '\u{271A}',
515 Emoji::Node => '\u{1F491}',
516 Emoji::Folder => '\u{1f4c1}',
517 Emoji::File => '\u{1f4c4}'
518 })
519 }
520}
521
522#[macro_export]
523macro_rules! nprint {
524 ($counter:expr, $emoji:expr, $($arg:tt)*) => {
525 };
531}
532
533#[macro_export]
534macro_rules! print_phase {
535 ($label:expr, $($arg:tt)*) => {
536 println!("\n########################################################################################################################");
537 println!("# {}", $label);
538 println!("########################################################################################################################");
539 println!("{}", format!($($arg)*));
540 println!("########################################################################################################################\n");
541 }
542}
543