1use proc_macro2 as p;
2
3pub(crate) const S: Punct = Punct::new("::");
4pub(crate) const MACROS: RuneModule = RuneModule("macros");
5pub(crate) const AST: RuneModule = RuneModule("ast");
6
7use crate::RUNE;
8pub(crate) trait ToTokens {
9 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span);
10}
11
12impl ToTokens for &'static str {
13 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span) {
14 stream.extend(Some(p::TokenTree::Ident(p::Ident::new(self, span))))
15 }
16}
17
18impl ToTokens for char {
19 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span) {
20 let mut p = p::Punct::new(self, p::Spacing::Alone);
21 p.set_span(span);
22 stream.extend(Some(p::TokenTree::Punct(p)));
23 }
24}
25
26impl ToTokens for p::Literal {
27 fn to_tokens(mut self, stream: &mut p::TokenStream, span: p::Span) {
28 self.set_span(span);
29 stream.extend(Some(p::TokenTree::Literal(self)));
30 }
31}
32
33macro_rules! impl_tuple {
34 () => {};
35
36 ($f_ident:ident $f_var:ident, $($ident:ident $var:ident),* $(,)?) => {
37 impl<$f_ident, $( $ident,)*> ToTokens for ($f_ident, $($ident,)*)
38 where
39 $f_ident: ToTokens,
40 $($ident: ToTokens,)*
41 {
42 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span) {
43 let ($f_var, $($var,)*) = self;
44 $f_var.to_tokens(stream, span);
45 $($var.to_tokens(stream, span);)*
46 }
47 }
48
49 impl_tuple!($($ident $var,)*);
50 }
51}
52
53impl ToTokens for () {
54 fn to_tokens(self, _: &mut p::TokenStream, _: p::Span) {}
55}
56
57impl_tuple!(A a, B b, C c, D d, E e, F f, G g, H h);
58
59impl ToTokens for p::Ident {
60 fn to_tokens(self, stream: &mut p::TokenStream, _: p::Span) {
61 stream.extend(std::iter::once(p::TokenTree::Ident(self)));
62 }
63}
64
65impl ToTokens for p::TokenStream {
66 fn to_tokens(self, stream: &mut p::TokenStream, _: p::Span) {
67 stream.extend(self);
68 }
69}
70
71#[derive(Debug, Clone, Copy)]
72pub(crate) struct RuneModule(&'static str);
73
74impl ToTokens for RuneModule {
75 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span) {
76 (RUNE, S, self.0).to_tokens(stream, span);
77 }
78}
79
80#[derive(Debug, Clone, Copy)]
81pub(crate) struct ToTokensFn;
82
83impl ToTokens for ToTokensFn {
84 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span) {
85 (MACROS, S, "ToTokens", S, "to_tokens").to_tokens(stream, span);
86 }
87}
88
89#[derive(Debug, Clone, Copy)]
90pub(crate) struct Kind(pub(crate) &'static str);
91
92impl ToTokens for Kind {
93 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span) {
94 (AST, S, "Kind", S, self.0).to_tokens(stream, span);
95 }
96}
97
98#[derive(Debug, Clone, Copy)]
99pub(crate) struct Delimiter(pub(crate) &'static str);
100
101impl Delimiter {
102 pub(crate) fn from_proc_macro(d: p::Delimiter) -> Option<Self> {
104 match d {
105 p::Delimiter::Parenthesis => Some(Delimiter("Parenthesis")),
106 p::Delimiter::Brace => Some(Delimiter("Brace")),
107 p::Delimiter::Bracket => Some(Delimiter("Bracket")),
108 p::Delimiter::None => None,
109 }
110 }
111}
112
113impl ToTokens for Delimiter {
114 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span) {
115 (AST, S, "Delimiter", S).to_tokens(stream, span);
116 self.0.to_tokens(stream, span);
117 }
118}
119
120#[derive(Clone, Copy)]
122pub(crate) struct Punct(&'static str, p::Spacing);
123
124impl Punct {
125 pub(crate) const fn new(s: &'static str) -> Punct {
126 Punct(s, p::Spacing::Alone)
127 }
128}
129
130impl ToTokens for Punct {
131 fn to_tokens(self, stream: &mut proc_macro2::TokenStream, span: p::Span) {
132 let mut it = self.0.chars();
133 let last = it.next_back();
134
135 for c in it {
136 let mut p = p::Punct::new(c, p::Spacing::Joint);
137 p.set_span(span);
138 stream.extend(Some(p::TokenTree::Punct(p)));
139 }
140
141 if let Some(c) = last {
142 let mut p = p::Punct::new(c, self.1);
143 p.set_span(span);
144 stream.extend(Some(p::TokenTree::Punct(p)));
145 }
146 }
147}
148
149#[derive(Debug, Clone)]
150pub(crate) struct Group<T>(p::Delimiter, T);
151
152pub(crate) fn p<T>(inner: T) -> Group<T> {
154 Group(p::Delimiter::Parenthesis, inner)
155}
156
157pub(crate) fn braced<T>(inner: T) -> Group<T> {
159 Group(p::Delimiter::Brace, inner)
160}
161
162impl<T> ToTokens for Group<T>
163where
164 T: ToTokens,
165{
166 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span) {
167 let mut inner = p::TokenStream::new();
168 self.1.to_tokens(&mut inner, span);
169
170 let mut group = p::Group::new(self.0, inner);
171 group.set_span(span);
172 stream.extend(Some(p::TokenTree::Group(group)));
173 }
174}
175
176pub(crate) struct NewIdent<'a>(pub(crate) &'static str, pub(crate) &'a str);
178
179impl ToTokens for NewIdent<'_> {
180 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span) {
181 (self.0, '.', "ident", p(p::Literal::string(self.1)), '?').to_tokens(stream, span);
182 }
183}
184
185pub(crate) struct NewLit(pub(crate) &'static str, pub(crate) p::Literal);
187
188impl ToTokens for NewLit {
189 fn to_tokens(self, stream: &mut p::TokenStream, span: p::Span) {
190 (self.0, '.', "lit", p(self.1), '?').to_tokens(stream, span);
191 }
192}