1#![recursion_limit = "128"]
2
3extern crate quote;
4extern crate syn;
5#[macro_use]
6extern crate synstructure;
7extern crate proc_macro2;
8
9use synstructure::{BindStyle, Structure};
10
11decl_derive!([BoundTerm] => bound_term_derive);
12
13fn bound_term_derive(mut s: Structure) -> proc_macro2::TokenStream {
14 s.bind_with(|_| BindStyle::Ref);
15 let term_eq_body = {
16 let body = s.variants().iter().fold(quote!(), |acc, v| {
17 let mut lhs = v.clone();
19 let mut rhs = v.clone();
20 lhs.binding_name(|_, i| {
21 syn::Ident::new(
22 &format!("__binding_lhs_{}", i),
23 proc_macro2::Span::call_site(),
24 )
25 });
26 rhs.binding_name(|_, i| {
27 syn::Ident::new(
28 &format!("__binding_rhs_{}", i),
29 proc_macro2::Span::call_site(),
30 )
31 });
32
33 let lhs_pat = lhs.pat();
34 let rhs_pat = rhs.pat();
35
36 let arm_body = <_>::zip(lhs.bindings().iter(), rhs.bindings()).fold(
38 quote!(true),
39 |acc, (lhs, rhs)| {
40 quote! { #acc && moniker::BoundTerm::<String>::term_eq(#lhs, #rhs) }
41 },
42 );
43
44 quote! { #acc (&#lhs_pat, &#rhs_pat) => #arm_body, }
45 });
46
47 match s.variants().len() {
49 0 | 1 => body,
50 _ => quote! { #body (_, _) => false },
51 }
52 };
53
54 s.bind_with(|_| BindStyle::RefMut);
55 let close_term_body = s.each(|bi| {
56 quote!{ moniker::BoundTerm::<String>::close_term(#bi, __state, __on_free); }
57 });
58 let open_term_body = s.each(|bi| {
59 quote!{ moniker::BoundTerm::<String>::open_term(#bi, __state, __on_bound); }
60 });
61
62 s.bind_with(|_| BindStyle::Ref);
63 let visit_vars_body = s.each(|bi| {
64 quote!{ moniker::BoundTerm::<String>::visit_vars(#bi, __on_var); }
65 });
66 s.bind_with(|_| BindStyle::RefMut);
67 let visit_mut_vars_body = s.each(|bi| {
68 quote!{ moniker::BoundTerm::<String>::visit_mut_vars(#bi, __on_var); }
69 });
70
71 s.gen_impl(quote! {
72 extern crate moniker;
73
74 gen impl moniker::BoundTerm<String> for @Self {
75 fn term_eq(&self, other: &Self) -> bool {
76 match (self, other) { #term_eq_body }
77 }
78
79 fn close_term(
80 &mut self,
81 __state: moniker::ScopeState,
82 __on_free: &impl moniker::OnFreeFn<String>,
83 ) {
84 match *self { #close_term_body }
85 }
86
87 fn open_term(
88 &mut self,
89 __state: moniker::ScopeState,
90 __on_bound: &impl moniker::OnBoundFn<String>,
91 ) {
92 match *self { #open_term_body }
93 }
94
95 fn visit_vars(&self, __on_var: &mut impl FnMut(&moniker::Var<String>)) {
96 match *self { #visit_vars_body }
97 }
98
99 fn visit_mut_vars(&mut self, __on_var: &mut impl FnMut(&mut moniker::Var<String>)) {
100 match *self { #visit_mut_vars_body }
101 }
102 }
103 })
104}
105
106decl_derive!([BoundPattern] => bound_pattern_derive);
107
108fn bound_pattern_derive(mut s: Structure) -> proc_macro2::TokenStream {
109 s.bind_with(|_| BindStyle::Ref);
110 let pattern_eq_body = {
111 let body = s.variants().iter().fold(quote!(), |acc, v| {
112 let mut lhs = v.clone();
114 let mut rhs = v.clone();
115 lhs.binding_name(|_, i| {
116 syn::Ident::new(
117 &format!("__binding_lhs_{}", i),
118 proc_macro2::Span::call_site(),
119 )
120 });
121 rhs.binding_name(|_, i| {
122 syn::Ident::new(
123 &format!("__binding_rhs_{}", i),
124 proc_macro2::Span::call_site(),
125 )
126 });
127
128 let lhs_pat = lhs.pat();
129 let rhs_pat = rhs.pat();
130
131 let arm_body = <_>::zip(lhs.bindings().iter(), rhs.bindings()).fold(
133 quote!(true),
134 |acc, (lhs, rhs)| {
135 quote! { #acc && moniker::BoundPattern::<String>::pattern_eq(#lhs, #rhs) }
136 },
137 );
138
139 quote! { #acc (&#lhs_pat, &#rhs_pat) => #arm_body, }
140 });
141
142 match s.variants().len() {
144 0 | 1 => body,
145 _ => quote! { #body (_, _) => false },
146 }
147 };
148
149 s.bind_with(|_| BindStyle::RefMut);
150 let close_pattern_body = s.each(|bi| {
151 quote!{ moniker::BoundPattern::<String>::close_pattern(#bi, __state, __on_free); }
152 });
153 let open_pattern_body = s.each(|bi| {
154 quote!{ moniker::BoundPattern::<String>::open_pattern(#bi, __state, __on_bound); }
155 });
156
157 s.bind_with(|_| BindStyle::Ref);
158 let visit_vars_body = s.each(|bi| {
159 quote!{ moniker::BoundPattern::<String>::visit_vars(#bi, __on_var); }
160 });
161 s.bind_with(|_| BindStyle::RefMut);
162 let visit_mut_vars_body = s.each(|bi| {
163 quote!{ moniker::BoundPattern::<String>::visit_mut_vars(#bi, __on_var); }
164 });
165
166 s.bind_with(|_| BindStyle::Ref);
167 let visit_binders_body = s.each(|bi| {
168 quote!{ moniker::BoundPattern::<String>::visit_binders(#bi, __on_binder); }
169 });
170 s.bind_with(|_| BindStyle::RefMut);
171 let visit_mut_binders_body = s.each(|bi| {
172 quote!{ moniker::BoundPattern::<String>::visit_mut_binders(#bi, __on_binder); }
173 });
174
175 s.gen_impl(quote! {
176 extern crate moniker;
177
178 gen impl moniker::BoundPattern<String> for @Self {
179 fn pattern_eq(&self, other: &Self) -> bool {
180 match (self, other) { #pattern_eq_body }
181 }
182
183 fn close_pattern(
184 &mut self,
185 __state: moniker::ScopeState,
186 __on_free: &impl moniker::OnFreeFn<String>,
187 ) {
188 match *self { #close_pattern_body }
189 }
190
191 fn open_pattern(
192 &mut self,
193 __state: moniker::ScopeState,
194 __on_bound: &impl moniker::OnBoundFn<String>,
195 ) {
196 match *self { #open_pattern_body }
197 }
198
199 fn visit_vars(&self, __on_var: &mut impl FnMut(&moniker::Var<String>)) {
200 match *self { #visit_vars_body }
201 }
202
203 fn visit_mut_vars(
204 &mut self,
205 __on_var: &mut impl FnMut(&mut moniker::Var<String>),
206 ) {
207 match *self { #visit_mut_vars_body }
208 }
209
210 fn visit_binders(&self, __on_binder: &mut impl FnMut(&moniker::Binder<String>)) {
211 match *self { #visit_binders_body }
212 }
213
214 fn visit_mut_binders(
215 &mut self,
216 __on_binder: &mut impl FnMut(&mut moniker::Binder<String>),
217 ) {
218 match *self { #visit_mut_binders_body }
219 }
220 }
221 })
222}