rune/macros/mod.rs
1//! The macro system of Rune.
2//!
3//! Macros are registered with [Module::macro_][crate::Module::macro_] and are
4//! function-like items that are expanded at compile time.
5//!
6//! Macros take token streams as arguments and are responsible for translating
7//! them into another token stream that will be embedded into the source location
8//! where the macro was invoked.
9//!
10//! The attribute macros [`rune::macro_`](crate::macro_) for function macros (`some_macro!( ... )`) and
11//! [`rune::attribute_macro`](crate::attribute_macro) for attribute macros (`#[some_macro ...]`).
12//!
13//! ```
14//! use rune::{T, Context, Diagnostics, Module, Vm};
15//! use rune::ast;
16//! use rune::compile;
17//! use rune::macros::{quote, MacroContext, TokenStream, ToTokens};
18//! use rune::parse::Parser;
19//! use rune::termcolor::{ColorChoice, StandardStream};
20//! use rune::alloc::String;
21//! use rune::sync::Arc;
22//!
23//! #[rune::macro_]
24//! fn concat_idents(cx: &mut MacroContext<'_, '_, '_>, input: &TokenStream) -> compile::Result<TokenStream> {
25//! let mut output = String::new();
26//!
27//! let mut p = Parser::from_token_stream(input, cx.input_span());
28//!
29//! let ident = p.parse::<ast::Ident>()?;
30//! output.try_push_str(cx.resolve(ident)?)?;
31//!
32//! while p.parse::<Option<T![,]>>()?.is_some() {
33//! if p.is_eof()? {
34//! break;
35//! }
36//!
37//! let ident = p.parse::<ast::Ident>()?;
38//! output.try_push_str(cx.resolve(ident)?)?;
39//! }
40//!
41//! p.eof()?;
42//!
43//! let output = cx.ident(&output)?;
44//! Ok(quote!(#output).into_token_stream(cx)?)
45//! }
46//!
47//! #[rune::attribute_macro]
48//! fn rename(cx: &mut MacroContext<'_, '_, '_>, input: &TokenStream, item: &TokenStream) -> compile::Result<TokenStream> {
49//! let mut parser = Parser::from_token_stream(item, cx.macro_span());
50//! let mut fun: ast::ItemFn = parser.parse_all()?;
51//!
52//! let mut parser = Parser::from_token_stream(input, cx.input_span());
53//! fun.name = parser.parse_all::<ast::EqValue<_>>()?.value;
54//!
55//! let mut tokens = TokenStream::new();
56//! fun.to_tokens(cx, &mut tokens);
57//! Ok(tokens)
58//! }
59//!
60//! let mut m = Module::new();
61//! m.macro_meta(concat_idents)?;
62//! m.macro_meta(rename)?;
63//!
64//! let mut context = Context::new();
65//! context.install(m)?;
66//!
67//! let runtime = Arc::try_new(context.runtime()?)?;
68//!
69//! let mut sources = rune::sources! {
70//! entry => {
71//! #[rename = foobar]
72//! fn renamed() {
73//! 42
74//! }
75//!
76//! pub fn main() {
77//! let foobar = foobar();
78//! concat_idents!(foo, bar)
79//! }
80//! }
81//! };
82//!
83//! let mut diagnostics = Diagnostics::new();
84//!
85//! let result = rune::prepare(&mut sources)
86//! .with_context(&context)
87//! .with_diagnostics(&mut diagnostics)
88//! .build();
89//!
90//! if !diagnostics.is_empty() {
91//! let mut writer = StandardStream::stderr(ColorChoice::Always);
92//! diagnostics.emit(&mut writer, &sources)?;
93//! }
94//!
95//! let unit = result?;
96//! let unit = Arc::try_new(unit)?;
97//!
98//! let mut vm = Vm::new(runtime, unit);
99//! let value = vm.call(["main"], ())?;
100//! let value: u32 = rune::from_value(value)?;
101//!
102//! assert_eq!(value, 42);
103//! # Ok::<_, rune::support::Error>(())
104//! ```
105
106mod format_args;
107#[doc(inline)]
108pub use self::format_args::FormatArgs;
109
110mod into_lit;
111#[doc(inline)]
112pub use self::into_lit::IntoLit;
113
114mod macro_compiler;
115#[doc(inline)]
116pub(crate) use self::macro_compiler::MacroCompiler;
117
118mod macro_context;
119#[cfg(feature = "std")]
120#[doc(inline)]
121pub use self::macro_context::test;
122#[doc(inline)]
123pub use self::macro_context::MacroContext;
124
125mod quote_fn;
126#[doc(inline)]
127pub use self::quote_fn::{quote_fn, Quote};
128
129mod storage;
130pub(crate) use self::storage::Storage;
131#[doc(inline)]
132pub use self::storage::{SyntheticId, SyntheticKind};
133
134mod token_stream;
135#[doc(inline)]
136pub use self::token_stream::{ToTokens, TokenStream, TokenStreamIter};
137
138/// Macro helper function for quoting the token stream as macro output.
139///
140/// Is capable of quoting everything in Rune, except for the following:
141/// * Labels, which must be created using `Label::new`.
142/// * Dynamic quoted strings and other literals, which must be created using
143/// `Lit::new`.
144///
145/// ```
146/// use rune::macros::quote;
147///
148/// quote!(hello self);
149/// ```
150///
151/// # Interpolating values
152///
153/// Values are interpolated with `#value`, or `#(value + 1)` for expressions.
154///
155/// # Iterators
156///
157/// Anything that can be used as an iterator can be iterated over with
158/// `#(iter)*`. A token can also be used to join inbetween each iteration, like
159/// `#(iter),*`.
160pub use rune_macros::quote;
161
162/// Helper derive to implement [`ToTokens`].
163pub use rune_macros::ToTokens;