1#![recursion_limit = "128"]
2
3extern crate proc_macro;
4
5use crate::proc_macro::TokenStream;
6use quote::quote;
7use syn::Data::{Enum, Struct};
8use syn::{self, DeriveInput};
9
10#[proc_macro_derive(Node)]
11pub fn node_derive(input: TokenStream) -> TokenStream {
12 let ast = syn::parse(input).unwrap();
13 impl_node(&ast)
14}
15
16fn impl_node(ast: &DeriveInput) -> TokenStream {
17 let name = &ast.ident;
18
19 let next = match ast.data {
20 Enum(ref data) => {
21 let mut items = quote! {};
22 for v in &data.variants {
23 let ident = &v.ident;
24 let item = quote! {
25 #name::#ident(x) => { x.into() },
26 };
27 items = quote! {
28 #items
29 #item
30 };
31 }
32
33 quote! {
34 match self {
35 #items
36 }
37 }
38 }
39 Struct(_) => {
40 quote! {
41 (&(self.nodes)).into()
42 }
43 }
44 _ => {
45 quote! {
46 vec![].into()
47 }
48 }
49 };
50
51 let gen = quote! {
52 impl<'a> Node<'a> for #name {
53 fn next(&'a self) -> RefNodes<'a> {
54 #next
55 }
56 }
57
58 impl<'a> From<&'a #name> for RefNodes<'a> {
59 fn from(x: &'a #name) -> Self {
60 vec![RefNode::#name(x)].into()
61 }
62 }
63
64 impl From<#name> for AnyNode {
65 fn from(x: #name) -> Self {
66 AnyNode::#name(x)
67 }
68 }
69
70 impl<'a> From<&'a #name> for RefNode<'a> {
71 fn from(x: &'a #name) -> Self {
72 RefNode::#name(x)
73 }
74 }
75
76 impl core::convert::TryFrom<#name> for Locate {
77 type Error = ();
78 fn try_from(x: #name) -> Result<Self, Self::Error> {
79 Self::try_from(&x)
80 }
81 }
82
83 impl<'a> core::convert::TryFrom<&'a #name> for Locate {
84 type Error = ();
85 fn try_from(x: &'a #name) -> Result<Self, Self::Error> {
86 let mut locate: Option<Locate> = None;
87 for x in x {
88 match x {
89 RefNode::Locate(x) => if let Some(loc) = locate {
90 assert_eq!(x.offset, loc.offset + loc.len);
91 locate = Some(Locate { offset: loc.offset, line: loc.line, len: loc.len + x.len });
92 } else {
93 locate = Some(*x);
94 },
95 _ => (),
96 }
97 }
98 locate.ok_or(())
99 }
100 }
101
102 impl<'a> IntoIterator for &'a #name {
103 type Item = RefNode<'a>;
104 type IntoIter = Iter<'a>;
105
106 fn into_iter(self) -> Self::IntoIter {
107 let mut nodes: RefNodes = self.into();
108 nodes.0.reverse();
109 Iter { next: nodes }
110 }
111 }
112 };
113 gen.into()
114}
115
116#[proc_macro_derive(AnyNode)]
117pub fn any_node_derive(input: TokenStream) -> TokenStream {
118 let ast = syn::parse(input).unwrap();
119 impl_any_node(&ast)
120}
121
122fn impl_any_node(ast: &DeriveInput) -> TokenStream {
123 let data = &match ast.data {
124 Enum(ref data) => data,
125 _ => unreachable!(),
126 };
127
128 let mut try_froms = quote! {};
129 let mut from_items = quote! {};
130 for v in &data.variants {
131 let ident = &v.ident;
132
133 try_froms = quote! {
134 #try_froms
135 impl TryFrom<AnyNode> for #ident {
136 type Error = ();
137 fn try_from(x: AnyNode) -> Result<Self, Self::Error> {
138 match x {
139 AnyNode::#ident(x) => Ok(x),
140 _ => Err(()),
141 }
142 }
143 }
144 };
145
146 from_items = quote! {
147 #from_items
148 AnyNode::#ident(x) => RefNode::#ident(&x),
149 };
150 }
151
152 let gen = quote! {
153 #try_froms
154
155 impl<'a> From<&'a AnyNode> for RefNode<'a> {
156 fn from(x: &'a AnyNode) -> Self {
157 match x {
158 #from_items
159 }
160 }
161 }
162 };
163 gen.into()
164}
165
166#[proc_macro_derive(RefNode)]
167pub fn ref_node_derive(input: TokenStream) -> TokenStream {
168 let ast = syn::parse(input).unwrap();
169 impl_ref_node(&ast)
170}
171
172fn impl_ref_node(ast: &DeriveInput) -> TokenStream {
173 let data = &match ast.data {
174 Enum(ref data) => data,
175 _ => unreachable!(),
176 };
177
178 let mut next_items = quote! {};
179 let mut into_iter_items = quote! {};
180 for v in &data.variants {
181 let ident = &v.ident;
182 next_items = quote! {
183 #next_items
184 RefNode::#ident(x) => x.next(),
185 };
186 into_iter_items = quote! {
187 #into_iter_items
188 RefNode::#ident(x) => x.into_iter(),
189 };
190 }
191
192 let name = &ast.ident;
193 let gen = quote! {
194 impl<'a> #name<'a> {
195 fn next(&self) -> RefNodes<'a> {
196 match self {
197 #next_items
198 }
199 }
200 }
201
202 impl<'a> IntoIterator for #name<'a> {
203 type Item = RefNode<'a>;
204 type IntoIter = Iter<'a>;
205
206 fn into_iter(self) -> Self::IntoIter {
207 match self {
208 #into_iter_items
209 }
210 }
211 }
212 };
213 gen.into()
214}