rune_macros/
lib.rs
1#![allow(clippy::manual_map)]
26#![allow(clippy::too_many_arguments)]
27
28mod any;
29mod const_value;
30mod context;
31mod from_value;
32mod function;
33mod hash;
34mod inst_display;
35mod item;
36mod macro_;
37mod module;
38mod opaque;
39mod parse;
40mod path_in;
41mod quote;
42mod spanned;
43mod to_tokens;
44mod to_value;
45
46use self::context::{Context, Tokens};
47
48use ::quote::format_ident;
49use proc_macro2::TokenStream;
50use syn::{Generics, Path};
51
52const RUNE: &str = "rune";
53
54#[proc_macro]
55pub fn quote(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
56 let input = proc_macro2::TokenStream::from(input);
57 let parser = crate::quote::Quote::new();
58
59 let output = match parser.parse(input) {
60 Ok(output) => output,
61 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
62 };
63
64 output.into()
65}
66
67#[proc_macro_attribute]
68pub fn function(
69 attrs: proc_macro::TokenStream,
70 item: proc_macro::TokenStream,
71) -> proc_macro::TokenStream {
72 let attrs = syn::parse_macro_input!(attrs with crate::function::FunctionAttrs::parse);
73 let function = syn::parse_macro_input!(item with crate::function::Function::parse);
74
75 let output = match function.expand(attrs) {
76 Ok(output) => output,
77 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
78 };
79
80 output.into()
81}
82
83#[proc_macro_attribute]
84pub fn macro_(
85 attrs: proc_macro::TokenStream,
86 item: proc_macro::TokenStream,
87) -> proc_macro::TokenStream {
88 let attrs = syn::parse_macro_input!(attrs with crate::macro_::Config::parse);
89 let macro_ = syn::parse_macro_input!(item with crate::macro_::Macro::parse);
90
91 let output = match macro_.expand(attrs, format_ident!("function")) {
92 Ok(output) => output,
93 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
94 };
95
96 output.into()
97}
98
99#[proc_macro_attribute]
100pub fn module(
101 attrs: proc_macro::TokenStream,
102 item: proc_macro::TokenStream,
103) -> proc_macro::TokenStream {
104 let attrs = syn::parse_macro_input!(attrs with crate::module::ModuleAttrs::parse);
105 let module = syn::parse_macro_input!(item with crate::module::Module::parse);
106
107 let output = match module.expand(attrs) {
108 Ok(output) => output,
109 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
110 };
111
112 output.into()
113}
114
115#[proc_macro_attribute]
116pub fn attribute_macro(
117 attrs: proc_macro::TokenStream,
118 item: proc_macro::TokenStream,
119) -> proc_macro::TokenStream {
120 let attrs = syn::parse_macro_input!(attrs with crate::macro_::Config::parse);
121 let macro_ = syn::parse_macro_input!(item with crate::macro_::Macro::parse);
122
123 let output = match macro_.expand(attrs, format_ident!("attribute")) {
124 Ok(output) => output,
125 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
126 };
127
128 output.into()
129}
130
131#[proc_macro_derive(ToTokens, attributes(rune))]
132#[doc(hidden)]
133pub fn to_tokens(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
134 let derive = syn::parse_macro_input!(input as to_tokens::Derive);
135 Context::build(|cx| derive.expand(cx)).into()
136}
137
138#[proc_macro_derive(Parse, attributes(rune))]
139#[doc(hidden)]
140pub fn parse(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
141 let derive = syn::parse_macro_input!(input as parse::Derive);
142 Context::build(|cx| derive.expand(cx)).into()
143}
144
145#[proc_macro_derive(Spanned, attributes(rune))]
146#[doc(hidden)]
147pub fn spanned(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
148 let derive = syn::parse_macro_input!(input as spanned::Derive);
149 Context::build(|cx| derive.expand(cx, false)).into()
150}
151
152#[proc_macro_derive(OptionSpanned, attributes(rune))]
153#[doc(hidden)]
154pub fn option_spanned(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
155 let derive = syn::parse_macro_input!(input as spanned::Derive);
156 Context::build(|cx| derive.expand(cx, true)).into()
157}
158
159#[proc_macro_derive(Opaque, attributes(rune))]
160#[doc(hidden)]
161pub fn opaque(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
162 let derive = syn::parse_macro_input!(input as opaque::Derive);
163 Context::build(|cx| derive.expand(cx)).into()
164}
165
166#[proc_macro_derive(FromValue, attributes(rune))]
167pub fn from_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
168 let input = syn::parse_macro_input!(input as syn::DeriveInput);
169 Context::build(|cx| from_value::expand(cx, &input)).into()
170}
171
172#[proc_macro_derive(ToValue, attributes(rune))]
173pub fn to_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
174 let input = syn::parse_macro_input!(input as syn::DeriveInput);
175 Context::build(|cx| to_value::expand(cx, &input)).into()
176}
177
178#[proc_macro_derive(Any, attributes(rune))]
179pub fn any(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
180 let derive = syn::parse_macro_input!(input as any::Derive);
181
182 let stream = Context::build(|cx| {
183 let attr = cx.type_attrs(&derive.input.attrs);
184 let tokens = cx.tokens_with_module(attr.module.as_ref());
185 Ok(derive.into_any_builder(cx, &attr, &tokens)?.expand())
186 });
187
188 stream.into()
189}
190
191#[proc_macro_derive(ToConstValue, attributes(const_value))]
192pub fn const_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
193 let derive = syn::parse_macro_input!(input as const_value::Derive);
194 Context::build(|cx| Ok(derive.into_builder(cx)?.expand())).into()
195}
196
197#[proc_macro]
207pub fn hash(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
208 let args = syn::parse_macro_input!(input as self::hash::Arguments);
209
210 let stream = Context::build(|cx| {
211 let Tokens { hash, .. } = cx.tokens_with_module(None);
212 let value = args.build_type_hash(cx)?.into_inner();
213 Ok(::quote::quote!(#hash(#value)))
214 });
215
216 stream.into()
217}
218
219#[doc(hidden)]
220#[proc_macro]
221pub fn hash_in(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
222 let path_in::PathIn { in_crate, item, .. } =
223 syn::parse_macro_input!(input as path_in::PathIn<self::hash::Arguments>);
224
225 let stream = Context::build(|cx| {
226 let value = item.build_type_hash(cx)?.into_inner();
227 Ok(::quote::quote!(#in_crate::Hash(#value)))
228 });
229
230 stream.into()
231}
232
233#[proc_macro]
251pub fn item(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
252 let path = syn::parse_macro_input!(input as syn::Path);
253
254 let stream = match self::item::build_item(&path) {
255 Ok(hash) => {
256 ::quote::quote!(unsafe { rune::Item::from_bytes(&#hash) })
257 }
258 Err(error) => to_compile_errors([error]),
259 };
260
261 stream.into()
262}
263
264#[proc_macro]
265#[doc(hidden)]
266pub fn item_in(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
267 let path_in::PathIn { in_crate, item, .. } = syn::parse_macro_input!(input as path_in::PathIn);
268
269 let stream = match self::item::build_item(&item) {
270 Ok(hash) => {
271 ::quote::quote!(unsafe { #in_crate::Item::from_bytes(&#hash) })
272 }
273 Err(error) => to_compile_errors([error]),
274 };
275
276 stream.into()
277}
278
279#[proc_macro]
283#[doc(hidden)]
284pub fn binding(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
285 let derive = syn::parse_macro_input!(input as any::InternalCall);
286
287 let stream = Context::build_with_crate(|cx| {
288 let mut stream = TokenStream::default();
289 let attr = context::TypeAttr::default();
290 let tokens = cx.tokens_with_module(None);
291
292 for builder in derive.into_any_builders(cx, &attr, &tokens) {
293 stream.extend(builder.expand());
294 }
295
296 Ok(stream)
297 });
298
299 stream.into()
300}
301
302#[proc_macro_attribute]
304#[doc(hidden)]
305pub fn stable(
306 _attr: proc_macro::TokenStream,
307 item: proc_macro::TokenStream,
308) -> proc_macro::TokenStream {
309 item
310}
311
312#[proc_macro_attribute]
314#[doc(hidden)]
315pub fn unstable(
316 _attr: proc_macro::TokenStream,
317 item: proc_macro::TokenStream,
318) -> proc_macro::TokenStream {
319 item
320}
321
322#[proc_macro_derive(InstDisplay, attributes(inst_display))]
323#[doc(hidden)]
324pub fn inst_display(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
325 let derive = syn::parse_macro_input!(input as inst_display::Derive);
326 derive.expand().unwrap_or_else(to_compile_errors).into()
327}
328
329fn add_trait_bounds(generics: &mut Generics, path: &Path) {
331 for ty in &mut generics.type_params_mut() {
332 ty.bounds.push(syn::TypeParamBound::Trait(syn::TraitBound {
333 paren_token: None,
334 modifier: syn::TraitBoundModifier::None,
335 lifetimes: None,
336 path: path.clone(),
337 }));
338 }
339}
340
341fn to_compile_errors<I>(errors: I) -> proc_macro2::TokenStream
342where
343 I: IntoIterator<Item = syn::Error>,
344{
345 let compile_errors = errors.into_iter().map(syn::Error::into_compile_error);
346 ::quote::quote!(#(#compile_errors)*)
347}