Expand description
The macro system of Rune.
Macros are registered with Module::macro_ and are function-like items that are expanded at compile time.
Macros take token streams as arguments and are responsible for translating them into another token stream that will be embedded into the source location where the macro was invoked.
The attribute macros rune::macro_
for function macros (some_macro!( ... )
) and
rune::attribute_macro
for attribute macros (#[some_macro ...]
).
use rune::{T, Context, Diagnostics, Module, Vm};
use rune::ast;
use rune::compile;
use rune::macros::{quote, MacroContext, TokenStream, ToTokens};
use rune::parse::Parser;
use rune::termcolor::{ColorChoice, StandardStream};
use rune::alloc::String;
use std::sync::Arc;
#[rune::macro_]
fn concat_idents(cx: &mut MacroContext<'_, '_, '_>, input: &TokenStream) -> compile::Result<TokenStream> {
let mut output = String::new();
let mut p = Parser::from_token_stream(input, cx.input_span());
let ident = p.parse::<ast::Ident>()?;
output.try_push_str(cx.resolve(ident)?)?;
while p.parse::<Option<T![,]>>()?.is_some() {
if p.is_eof()? {
break;
}
let ident = p.parse::<ast::Ident>()?;
output.try_push_str(cx.resolve(ident)?)?;
}
p.eof()?;
let output = cx.ident(&output)?;
Ok(quote!(#output).into_token_stream(cx)?)
}
#[rune::attribute_macro]
fn rename(cx: &mut MacroContext<'_, '_, '_>, input: &TokenStream, item: &TokenStream) -> compile::Result<TokenStream> {
let mut parser = Parser::from_token_stream(item, cx.macro_span());
let mut fun: ast::ItemFn = parser.parse_all()?;
let mut parser = Parser::from_token_stream(input, cx.input_span());
fun.name = parser.parse_all::<ast::EqValue<_>>()?.value;
let mut tokens = TokenStream::new();
fun.to_tokens(cx, &mut tokens);
Ok(tokens)
}
let mut m = Module::new();
m.macro_meta(concat_idents)?;
m.macro_meta(rename)?;
let mut context = Context::new();
context.install(m)?;
let runtime = Arc::new(context.runtime()?);
let mut sources = rune::sources! {
entry => {
#[rename = foobar]
fn renamed() {
42
}
pub fn main() {
let foobar = foobar();
concat_idents!(foo, bar)
}
}
};
let mut diagnostics = Diagnostics::new();
let result = rune::prepare(&mut sources)
.with_context(&context)
.with_diagnostics(&mut diagnostics)
.build();
if !diagnostics.is_empty() {
let mut writer = StandardStream::stderr(ColorChoice::Always);
diagnostics.emit(&mut writer, &sources)?;
}
let unit = result?;
let unit = Arc::new(unit);
let mut vm = Vm::new(runtime, unit);
let value = vm.call(["main"], ())?;
let value: u32 = rune::from_value(value)?;
assert_eq!(value, 42);
Macros§
- Macro helper function for quoting the token stream as macro output.
Structs§
- A format specification: A format string followed by arguments to be formatted in accordance with that string.
- Context for a running macro.
- A synthetic identifier which can be used to reference something in storage.
- A token stream.
- A token stream iterator.
Enums§
- The kind of a synthetic token.
Traits§
- Helper trait used for things that can be converted into tokens.
- Trait for things that can be turned into tokens.
Functions§
- Construct a token stream from a function.
- Construct an empty macro context which can be used for testing.