1use std::collections::{HashMap, HashSet};
2use std::fmt::{Display, Formatter, Write};
3use indexmap::IndexMap;
4use proc_macro2::{Spacing, TokenTree};
5use quote::{quote, ToTokens};
6use syn::{Attribute, Ident, ItemUse, Path, Signature, Type};
7use crate::composable::{GenericBoundsModel, TraitModelPart1, TraitDecompositionPart1, TraitTypeModel};
8use crate::context::{GlobalContext, ScopeChain, TypeChain};
9use crate::kind::{MixinKind, ObjectKind};
10use crate::tree::{ScopeTreeID, 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: &[(ScopeChain, IndexMap<Type, ObjectKind>)]) -> String {
23 let mut iter = dict.iter()
24 .map(|(scope, types)|
25 format!("\t{}: \n\t\t{}", format_token_stream(scope.self_path_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_types(dict: &HashSet<Type>) -> String {
35 dict.iter()
36 .map(|item| item.to_token_stream().to_string())
38 .collect::<Vec<_>>()
39 .join("\n\n")
40}
41
42#[allow(unused)]
43pub fn format_mixin_kinds(dict: &IndexMap<MixinKind, HashSet<Option<Attribute>>>) -> String {
44 dict.iter()
45 .map(|(item, attrs)| format!("{}:\t {}", item, format_unique_attrs(attrs)))
46 .collect::<Vec<_>>()
47 .join("\n\t")
48}
49#[allow(unused)]
50pub fn format_mixin_conversions(dict: &IndexMap<GenericBoundsModel, HashSet<Option<Attribute>>>) -> String {
51 dict.iter()
52 .map(|(item, attrs)| format!("{}:\n\t {}", item, format_unique_attrs(attrs)))
53 .collect::<Vec<_>>()
54 .join("\n\t")
55}
56
57#[allow(unused)]
58pub fn format_unique_attrs(dict: &HashSet<Option<Attribute>>) -> String {
59 dict.iter()
60 .map(|item| item.as_ref().map_or("[None]".to_string(), |a| a.to_token_stream().to_string()))
61 .collect::<Vec<_>>()
62 .join("\n\t")
63}
64
65pub fn format_attrs(dict: &[Attribute]) -> String {
66 dict.iter()
67 .map(|item| item.to_token_stream().to_string())
68 .collect::<Vec<_>>()
69 .join("\n\t")
70}
71
72#[allow(unused)]
73pub fn format_imports(dict: &IndexMap<ScopeChain, IndexMap<Path, Path>>) -> String {
74 let vec = scope_imports_dict(dict);
75 let expanded = quote!(#(#vec),*);
76 expanded.to_string()
77}
78
79#[allow(unused)]
80pub fn format_tree_exported_dict(dict: &IndexMap<ScopeTreeID, ScopeTreeExportItem>) -> String {
81 dict.iter()
82 .map(|(ident, tree_item)| format!("{}: {}", ident, tree_item))
83 .collect::<Vec<_>>()
84 .join("\n\n")
85}
86
87#[allow(unused)]
88pub fn format_tree_item_dict(dict: &IndexMap<ScopeTreeID, ScopeTreeItem>) -> String {
89 dict.iter()
90 .map(|(ident, tree_item)| format!("\t{}: {:?}", ident, tree_item))
91 .collect::<Vec<_>>()
92 .join("\n\n")
93}
94
95#[allow(unused)]
96pub fn scope_type_conversion_pair(dict: (&Type, &ObjectKind)) -> String {
97 format!("\t{}: {}", dict.0.to_token_stream(), dict.1)
98 }
100
101#[allow(unused)]
102pub fn refinement_pair(dict: (&Type, &Vec<ObjectKind>)) -> String {
103 format!("\t{}: \n\t\t{}", dict.0.to_token_stream(), dict.1.iter().map(|i| i.to_string()).collect::<Vec<_>>()
104 .join("\n\t"))
105 }
107#[allow(unused)]
115pub fn ident_type_conversion_pair(dict: (&Ident, &Type)) -> String {
116 format!("\t{}: {}", format_token_stream(dict.0), format_token_stream(dict.1))
117}
118
119#[allow(unused)]
120pub fn ident_signature_conversion_pair(dict: (&Ident, &Signature)) -> String {
121 format!("\t{}: {}", format_token_stream(dict.0), format_token_stream(dict.1))
122}
123
124#[allow(unused)]
125pub fn ident_trait_type_decomposition_conversion_pair(dict: (&Ident, &TraitTypeModel)) -> String {
126 format!("\t{}: {}", format_token_stream(dict.0), {
127 let TraitTypeModel { ident, trait_bounds } = dict.1;
128 quote!(#ident: [bounds: #(#trait_bounds)*])
129 })
130}
131fn format_ident_path_pair(pair: (&Path, &Path)) -> String {
132 format!("\t{}: {}", format_token_stream(pair.0), format_token_stream(pair.1))
133}
134
135pub fn format_path_vec(vec: &[Path]) -> String {
136 vec.iter().map(|p| p.to_token_stream().to_string()).collect::<Vec<_>>().join(",")
137}
138pub fn format_obj_vec(vec: &[ObjectKind]) -> String {
139 vec.iter().map(|p| p.to_token_stream().to_string()).collect::<Vec<_>>().join(",")
140}
141
142#[allow(unused)]
143pub fn type_vec_path_conversion_pair(pair: (&Type, &Vec<Path>)) -> String {
144 format!("\t{}: [{}]", format_token_stream(pair.0), format_path_vec(pair.1))
145}
146#[allow(unused)]
147pub fn type_vec_obj_conversion_pair(pair: (&Type, &Vec<ObjectKind>)) -> String {
148 format!("\t{}: [{}]", format_token_stream(pair.0), format_obj_vec(pair.1))
149}
150#[allow(unused)]
151pub fn format_predicates_dict(vec: &HashMap<Type, Vec<Path>>) -> String {
152 vec.iter()
153 .map(type_vec_path_conversion_pair)
154 .collect::<Vec<_>>()
155 .join(",")
156}
157#[allow(unused)]
158pub fn format_predicates_obj_dict(vec: &IndexMap<Type, Vec<ObjectKind>>) -> String {
159 vec.iter()
160 .map(type_vec_obj_conversion_pair)
161 .collect::<Vec<_>>()
162 .join(",")
163}
164
165#[allow(unused)]
166fn format_generic_bounds_pair(pair: (&Type, &Vec<Path>)) -> String {
167 format!("\t{}: [{}]", format_token_stream(pair.0), format_path_vec(pair.1))
168}
169
170fn format_ident_trait_pair(pair: (&Ident, &TraitModelPart1)) -> String {
171 let implementors = &pair.1.implementors;
172 format!("\t{}: {}: [{}]", format_token_stream(pair.0), "...", quote!(#(#implementors),*))
173}
174
175#[allow(unused)]
176pub fn format_types_dict(dict: &IndexMap<Type, ObjectKind>) -> String {
177 types_dict(dict)
178 .join("\n")
179}
180#[allow(unused)]
181pub fn format_types_to_refine(dict: &IndexMap<Type, Vec<ObjectKind>>) -> String {
182 let mut iter = dict.iter()
183 .map(refinement_pair)
184 .collect::<Vec<String>>();
185 iter.sort();
186 iter.join("\n")
187}
188
189#[allow(unused)]
190pub fn format_ident_types_dict(dict: &IndexMap<Ident, Type>) -> String {
191 ident_types_dict(dict)
192 .join("\n")
193}
194
195#[allow(unused)]
196pub fn format_scope_types_dict(dict: &HashMap<ScopeChain, TypeChain>) -> String {
197 dict.iter().map(|(scope, tc)| {
198 format!("{}: \n\t{}", scope.fmt_short(), format_types_dict(&tc.inner))
199 }).collect::<Vec<_>>()
200 .join("\n")
201}
202#[allow(unused)]
204pub fn format_used_traits(dict: &IndexMap<ScopeChain, IndexMap<Ident, TraitModelPart1>>) -> String {
205 scope_traits_dict(dict).join("\n")
206}
207
208pub fn format_token_stream<TT: ToTokens>(token_stream: TT) -> String {
213 let token_stream = token_stream.into_token_stream();
214 let mut formatted_string = String::new();
215 let mut space_needed = false;
216 let mut inside_angle_brackets = 0;
217 let mut inside_round_brackets = 0;
218 let mut last_token_was_ampersand = false;
220 let mut last_token_was_comma = false;
221 for token in token_stream {
224 if last_token_was_comma {
225 formatted_string.push(' ');
226 }
227 last_token_was_comma = false;
228 match token {
229 TokenTree::Ident(ident) => {
230 if last_token_was_ampersand && (ident == "mut" || ident.to_string().starts_with('\'')) {
232 formatted_string.pop(); } else if space_needed {
234 formatted_string.push(' ');
235 }
236 formatted_string.push_str(&ident.to_string());
237 space_needed = true;
238 last_token_was_ampersand = false;
239 }
240 TokenTree::Punct(punct) => {
241 match punct.as_char() {
242 ';' => {
243 formatted_string.push(';');
244 space_needed = true;
245 }
246 ':' => {
247 formatted_string.push(':');
248 space_needed = false;
249 }
250 '(' => {
251 inside_round_brackets += 1;
252 formatted_string.push('(');
253 space_needed = false;
254 }
255 ')' => {
256 inside_round_brackets -= 1;
257 formatted_string.push(')');
258 space_needed = true;
259 }
260 '<' => {
261 inside_angle_brackets += 1;
262 formatted_string.push('<');
263 space_needed = false;
264 }
265 '>' => {
266 inside_angle_brackets -= 1;
267 formatted_string.push('>');
268 space_needed = true;
269 }
270 ',' => {
271 formatted_string.push(',');
272 last_token_was_comma = true;
273 space_needed = true; }
275 '&' => {
276 formatted_string.push('&');
277 last_token_was_ampersand = true;
278 space_needed = false;
279 }
280 _ => {
281 if space_needed {
282 formatted_string.push(' ');
283 }
284 formatted_string.push(punct.as_char());
285 space_needed = punct.spacing() == Spacing::Alone;
286 }
287 }
288 }
289 TokenTree::Literal(literal) => {
290 if space_needed {
291 formatted_string.push(' ');
292 }
293 formatted_string.push_str(&literal.to_string());
294 space_needed = true;
295 last_token_was_ampersand = false;
296 }
297 TokenTree::Group(group) => {
298 if space_needed && (inside_angle_brackets == 0 || inside_round_brackets == 0) {
299 formatted_string.push(' ');
300 }
301 formatted_string.push_str(&format_token_stream(group.stream()));
302 space_needed = true;
303 last_token_was_ampersand = false;
304 }
305 }
306 }
307
308 formatted_string
309}
310
311pub fn imports_dict(dict: &IndexMap<Path, Path>) -> Vec<String> {
312 dict.iter()
313 .map(format_ident_path_pair)
314 .collect()
315}
316
317#[allow(unused)]
318pub fn generic_bounds_dict(dict: &IndexMap<Type, Vec<Path>>) -> Vec<String> {
319 dict.iter()
320 .map(format_generic_bounds_pair)
321 .collect()
322}
323#[allow(unused)]
324pub fn format_generic_scope_chain(dict: &IndexMap<ObjectKind, Vec<ObjectKind>>) -> String {
325 dict.iter()
326 .map(|(bounded_ty, bounds)| format!("{}: {}", bounded_ty.to_token_stream(), format_obj_vec(bounds)))
327 .collect::<Vec<_>>()
328 .join(", ")
329}
330
331pub fn types_dict(dict: &IndexMap<Type, ObjectKind>) -> Vec<String> {
332 let mut iter = dict.iter()
333 .map(scope_type_conversion_pair)
334 .collect::<Vec<String>>();
335 iter.sort();
336 iter
337}
338fn ident_signatures_dict(dict: &IndexMap<Ident, Signature>) -> Vec<String> {
339 let mut iter = dict.iter()
340 .map(ident_signature_conversion_pair)
341 .collect::<Vec<String>>();
342 iter.sort();
343 iter
344}
345
346
347fn ident_trait_type_decomposition_dict(dict: &IndexMap<Ident, TraitTypeModel>) -> Vec<String> {
348 let mut iter = dict.iter()
349 .map(ident_trait_type_decomposition_conversion_pair)
350 .collect::<Vec<String>>();
351 iter.sort();
352 iter
353}
354
355fn ident_types_dict(dict: &IndexMap<Ident, Type>) -> Vec<String> {
356 let mut iter = dict.iter()
357 .map(ident_type_conversion_pair)
358 .collect::<Vec<String>>();
359 iter.sort();
360 iter
361}
362
363fn traits_dict(dict: &IndexMap<Ident, TraitModelPart1>) -> Vec<String> {
364 let mut iter = dict.iter()
365 .map(format_ident_trait_pair)
366 .collect::<Vec<String>>();
367 iter.sort();
368 iter
369}
370
371
372fn nested_scope_dict<K, K2, V2, F: Fn(&K, &IndexMap<K2, V2>) -> String>(dict: &IndexMap<K, IndexMap<K2, V2>>, mapper: F) -> Vec<String> {
373 let mut iter = dict.iter()
374 .map(|(key, value)| mapper(key, value))
375 .collect::<Vec<String>>();
376 iter.sort();
377 iter
378}
379
380fn format_scope_dict<K2, V2, F: Fn(&IndexMap<K2, V2>) -> Vec<String>>(dict: &IndexMap<ScopeChain, IndexMap<K2, V2>>, mapper: F) -> Vec<String> {
381 nested_scope_dict(dict, |scope, sub_dict|
382 format!("\t{}:\n\t\t{}", scope.fmt_short(), mapper(sub_dict).join("\n\t\t")))
383}
384
385pub fn scope_imports_dict(dict: &IndexMap<ScopeChain, IndexMap<Path, Path>>) -> Vec<String> {
386 format_scope_dict(dict, imports_dict)
387}
388
389#[allow(unused)]
390pub fn scope_generics_dict(dict: &IndexMap<ScopeChain, IndexMap<Type, Vec<Path>>>) -> Vec<String> {
391 format_scope_dict(dict, generic_bounds_dict)
392}
393
394
395fn scope_traits_dict(dict: &IndexMap<ScopeChain, IndexMap<Ident, TraitModelPart1>>) -> Vec<String> {
396 format_scope_dict(dict, traits_dict)
397}
398
399
400
401fn traits_impl_dict(dict: &HashMap<ScopeChain, Vec<Path>>) -> Vec<String> {
402 let mut iter = dict.iter()
403 .filter_map(|(key, value)| {
404 let scopes = quote!(#(#value),*);
405 (!value.is_empty()).then(|| format!("\t{}:\n\t\t{}", format_token_stream(key), format_token_stream(&scopes)))
406 })
407 .collect::<Vec<String>>();
408 iter.sort();
409 iter
410}
411
412fn format_complex_obj(vec: Vec<Vec<String>>) -> String {
413 vec.into_iter()
414 .flatten()
415 .collect::<Vec<String>>()
416 .join("\n\t")
417}
418
419pub fn format_global_context(context: &GlobalContext) -> String {
420 format_complex_obj(vec![
421 vec!["-- types:".to_string(), context.scope_register.to_string()],
422 vec!["-- traits:".to_string()], scope_traits_dict(&context.traits.inner),
423 vec!["-- traits_impl:".to_string()], traits_impl_dict(&context.traits.used_traits_dictionary),
424 vec!["-- custom:".to_string(), context.custom.to_string()],
425 vec!["-- imports:".to_string()], scope_imports_dict(&context.imports.inner),
426 vec!["-- generics:".to_string()], scope_generics_dict(&context.generics.inner),
427 ])
428}
429
430#[allow(unused)]
431pub fn format_trait_decomposition_part1(dict: &TraitDecompositionPart1) -> String {
432 format_complex_obj(vec![
433 vec!["\n-- ident:".to_string()], vec![format_token_stream(&dict.ident)],
434 vec!["-- consts:".to_string()], ident_types_dict(&dict.consts),
435 vec!["-- methods:".to_string()], ident_signatures_dict(&dict.methods),
436 vec!["-- types:".to_string()], ident_trait_type_decomposition_dict(&dict.types),
437 ])
438}
439
440#[allow(dead_code)]
441pub enum Emoji {
442 Branch,
443 Question,
444 Local,
445 Nothing,
446 Ok,
447 Error,
448 Plus,
449 Node,
450 Folder,
451 File
452}
453
454impl Display for Emoji {
455 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
456 f.write_char(
457 match self {
458 Emoji::Question => '\u{2753}',
459 Emoji::Branch => '\u{1D30E}',
460 Emoji::Local => '\u{1F501}',
461 Emoji::Ok => '\u{2705}',
462 Emoji::Error => '\u{274C}',
463 Emoji::Nothing => '\u{1F502}',
464 Emoji::Plus => '\u{271A}',
465 Emoji::Node => '\u{1F491}',
466 Emoji::Folder => '\u{1f4c1}',
467 Emoji::File => '\u{1f4c4}'
468 })
469 }
470}
471
472#[macro_export]
473macro_rules! nprint {
474 ($counter:expr, $emoji:expr, $($arg:tt)*) => {
475 };
481}
482
483#[macro_export]
484macro_rules! print_phase {
485 ($label:expr, $($arg:tt)*) => {
486 println!("\n########################################################################################################################");
487 println!("# {}", $label);
488 println!("########################################################################################################################");
489 println!("{}", format!($($arg)*));
490 println!("########################################################################################################################\n");
491 }
492}
493