macroscope_utils/
lib.rs

1mod macros;
2
3pub mod tools {
4    pub use {::proc_macro2, ::proc_macro_crate, ::quote, ::syn};
5}
6
7use proc_macro2::Span;
8use proc_macro_crate::{crate_name, FoundCrate};
9use quote::quote;
10use syn::{Ident, LitStr};
11
12pub fn quote_crate(found: FoundCrate) -> proc_macro2::TokenStream {
13    match found {
14        FoundCrate::Itself => quote! { crate },
15        FoundCrate::Name(name) => {
16            let ident = Ident::new(&name, Span::call_site());
17            quote! { #ident }
18        }
19    }
20}
21
22pub fn find_macroscope() -> proc_macro2::TokenStream {
23    quote_crate(crate_name("macroscope").unwrap())
24}
25
26pub fn find_crate(first: LitStr /*, rest: impl Iterator<Item = LitStr> */) -> FoundCrate {
27    match crate_name(&first.value()) {
28        Ok(c) => return c,
29        Err(err) => panic!("{}", err),
30    }
31
32    // let result = find(
33    //     vec![first],
34    //     rest,
35    //     |accum: &mut Vec<LitStr>, lit, is_last| match crate_name(&lit.value()) {
36    //         Ok(name) => MapResult::Found(name),
37    //         Err(error) => {
38    //             if !is_last {
39    //                 accum.push(lit.clone());
40    //             }
41    //             MapResult::Failure(error)
42    //         }
43    //     },
44    // );
45
46    // match result {
47    //     FindResult::Failure { error, accumulated } => {
48    //         if accumulated.is_empty() {
49    //             panic!("{}", error);
50    //         } else {
51    //             panic!(
52    //                 "{}\nAlso tried: {}",
53    //                 error,
54    //                 itertools::join(accumulated.iter().map(|lit| lit.value()), ", ")
55    //             );
56    //         }
57    //     }
58    //     FindResult::Found(found) => found,
59    // }
60}
61
62#[allow(unused)]
63enum FindResult<T, E, A> {
64    Found(T),
65    Failure { error: E, accumulated: A },
66}
67
68#[allow(unused)]
69enum MapResult<T, E> {
70    Found(T),
71    Failure(E),
72}
73
74#[allow(unused)]
75fn find<T, U, A, E>(
76    initial: A,
77    iterator: impl Iterator<Item = T>,
78    mapper: impl Fn(&mut A, &T, bool) -> MapResult<U, E>,
79) -> FindResult<U, E, A> {
80    let mut iter = iterator.peekable();
81    let mut accum = initial;
82
83    while let Some(item) = iter.next() {
84        match mapper(&mut accum, &item, iter.peek().is_none()) {
85            MapResult::Found(found) => return FindResult::Found(found),
86            MapResult::Failure(error) if iter.peek().is_none() => {
87                return FindResult::Failure {
88                    error,
89                    accumulated: accum,
90                }
91            }
92            MapResult::Failure(_) => continue,
93        };
94    }
95
96    unreachable!("loop should reach iter.peek() == None at some point")
97}