Skip to main content

kons_macros/
lib.rs

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}