1use proc_macro::*;
2
3fn cat(stream: TokenStream, rest: impl IntoIterator<Item = TokenTree>) -> TokenStream {
4 let mut stream = stream;
5 stream.extend(rest);
6 stream
7}
8
9fn ident(ident: &str) -> TokenTree {
10 TokenTree::Ident(Ident::new(ident, Span::call_site()))
11}
12
13fn punct(c: char) -> TokenTree {
14 TokenTree::Punct(Punct::new(c, Spacing::Alone))
15}
16
17#[proc_macro]
18pub fn kons_impl(stream: TokenStream) -> TokenStream {
19 let mut stream = stream.into_iter();
20 let Some(TokenTree::Group(krate)) = stream.next() else { panic!() };
21 let krate = &krate.stream();
22
23 let Some(TokenTree::Group(nil)) = stream.next() else { panic!() };
24 let mut out = nil.stream();
25
26 let mut stream = Vec::from_iter(stream).into_iter();
27
28 while let Some(item) = stream.next_back() {
29 let TokenTree::Group(item) = item else { panic!() };
30 let mut item = item.stream();
31 let mut here = TokenStream::new();
32
33 loop {
34 let mut iter = item.into_iter();
35 let first = iter.next();
36 let second = iter.next();
37 match (first, second) {
38 (Some(TokenTree::Group(first)), None) if first.delimiter() == Delimiter::None => item = first.stream(),
39 (first, second) => {
40 here.extend([first, second].into_iter().flatten().chain(iter));
41 break;
42 },
43 }
44 }
45
46 out = cat(
47 krate.clone(),
48 [
49 ident("List"),
50 Group::new(
51 Delimiter::Brace,
52 TokenStream::from_iter(
53 TokenStream::new()
54 .into_iter()
55 .chain([ident("here"), punct(':')])
56 .chain(here)
57 .chain([punct(','), ident("there"), punct(':')])
58 .chain(out)
59 .chain([punct(',')]),
60 ),
61 )
62 .into(),
63 ],
64 );
65 }
66
67 out
68}