pub struct MacroContext<'a, 'b, 'arena> { /* private fields */ }Expand description
Context for a running macro.
Implementations§
Source§impl<'a, 'b, 'arena> MacroContext<'a, 'b, 'arena>
impl<'a, 'b, 'arena> MacroContext<'a, 'b, 'arena>
Sourcepub fn parser<'s>(
&self,
token_stream: &'s TokenStream,
span: Span,
) -> Parser<'s>
pub fn parser<'s>( &self, token_stream: &'s TokenStream, span: Span, ) -> Parser<'s>
Construct a parser over a token stream, bounded by the compiler options this macro is being expanded under.
The syntax tree this parser produces is walked by recursing over it, so
how deep it is allowed to get is bounded by the max-ast-depth option.
A parser built with Parser::from_token_stream instead uses that
option’s default, since it has no way of seeing what the compiler was
configured with.
A macro which only needs to know where each of its arguments ends does
not need a tree at all - see MacroContext::exprs, which splits an
input without either recursing over it or holding it to that bound.
span is the span to use if the stream is empty - typically
MacroContext::input_span.
§Examples
use rune::ast;
use rune::macros::{self, quote};
macros::test(|cx| {
let stream = quote!(1 + 2).into_token_stream(cx)?;
let mut p = cx.parser(&stream, cx.input_span());
let expr = p.parse_all::<ast::Expr>()?;
let value = cx.eval(&expr)?;
let integer = value.as_integer::<u32>().context("Expected integer")?;
assert_eq!(3, integer);
Ok(())
})?;Sourcepub fn exprs(&mut self, stream: &TokenStream) -> Result<Vec<TokenStream>>
pub fn exprs(&mut self, stream: &TokenStream) -> Result<Vec<TokenStream>>
Split a token stream into the comma separated expressions it is made of, each one being the tokens it was written as.
This is what a macro which takes a list of arguments uses to find where
each one ends. The split is done by the same parser the compiler uses,
which walks its input over an explicit stack, and each expression is
handed back as tokens rather than as a syntax tree - so a macro built
out of this neither recurses over its own input nor holds it to the
much smaller max-ast-depth which bounds MacroContext::parser.
What comes back is where each argument ends rather than what it means: the tokens are handed on as they were written, and whatever they turn out to say is reported where the macro puts them, since that is where they are lowered.
§Examples
use rune::macros::{self, quote};
macros::test(|cx| {
let stream = quote!("Hello {}", 1 + 2).into_token_stream(cx)?;
let exprs = cx.exprs(&stream)?;
assert_eq!(exprs.len(), 2);
let value = cx.eval_stream(&exprs[1])?;
assert_eq!(value.as_integer::<u32>()?, 3);
Ok(())
})?;Sourcepub fn eval_stream(&mut self, stream: &TokenStream) -> Result<Value>
pub fn eval_stream(&mut self, stream: &TokenStream) -> Result<Value>
Evaluate the tokens of an expression as a constant.
This is MacroContext::eval over the tokens an expression was
written as, which is what a macro that split its input with
MacroContext::exprs holds.
§Examples
use rune::macros::{self, quote};
macros::test(|cx| {
let stream = quote!(1 + 2).into_token_stream(cx)?;
let value = cx.eval_stream(&stream)?;
assert_eq!(value.as_integer::<u32>()?, 3);
Ok(())
})?;Sourcepub fn eval(&mut self, target: &Expr) -> Result<Value>
pub fn eval(&mut self, target: &Expr) -> Result<Value>
Evaluate the given target as a constant expression.
§Panics
This will panic if it’s called outside of a macro context.
§Examples
use rune::ast;
use rune::macros::{self, quote};
use rune::parse::{Parser};
macros::test(|cx| {
let stream = quote!(1 + 2).into_token_stream(cx)?;
let mut p = Parser::from_token_stream(&stream, cx.input_span());
let expr = p.parse_all::<ast::Expr>()?;
let value = cx.eval(&expr)?;
let integer = value.as_integer::<u32>().context("Expected integer")?;
assert_eq!(3, integer);
Ok(())
})?;Sourcepub fn lit<T>(&mut self, lit: T) -> Result<Lit>where
T: IntoLit,
pub fn lit<T>(&mut self, lit: T) -> Result<Lit>where
T: IntoLit,
Construct a new literal from within a macro context.
§Examples
use rune::ast;
use rune::macros;
macros::test(|cx| {
let lit = cx.lit("hello world")?;
assert!(matches!(lit, ast::Lit::Str(..)));
Ok(())
})?;Sourcepub fn ident(&mut self, ident: &str) -> Result<Ident>
pub fn ident(&mut self, ident: &str) -> Result<Ident>
Construct a new identifier from the given string from inside of a macro context.
§Examples
use rune::ast;
use rune::macros;
macros::test(|cx| {
let lit = cx.ident("foo")?;
assert!(matches!(lit, ast::Ident { .. }));
Ok(())
})?;Sourcepub fn label(&mut self, label: &str) -> Result<Label>
pub fn label(&mut self, label: &str) -> Result<Label>
Construct a new label from the given string. The string should be
specified without the leading ', so "foo" instead of "'foo".
This constructor does not panic when called outside of a macro context
but requires access to a span and storage.
§Examples
use rune::ast;
use rune::macros;
macros::test(|cx| {
let lit = cx.label("foo")?;
assert!(matches!(lit, ast::Label { .. }));
Ok(())
})?;Sourcepub fn stringify<T>(
&mut self,
tokens: &T,
) -> Result<Stringify<'_, 'a, 'b, 'arena>>where
T: ToTokens,
pub fn stringify<T>(
&mut self,
tokens: &T,
) -> Result<Stringify<'_, 'a, 'b, 'arena>>where
T: ToTokens,
Stringify the token stream.
Sourcepub fn resolve<'r, T>(&'r self, item: T) -> Result<T::Output>where
T: Resolve<'r>,
pub fn resolve<'r, T>(&'r self, item: T) -> Result<T::Output>where
T: Resolve<'r>,
Resolve the value of a token.
Sourcepub fn insert_source(&mut self, name: &str, source: &str) -> Result<SourceId>
pub fn insert_source(&mut self, name: &str, source: &str) -> Result<SourceId>
Insert the given source so that it has a SourceId that can be used in combination with parsing functions such as parse_source.
Sourcepub fn parse_source<T>(&self, id: SourceId) -> Result<T>where
T: Parse,
pub fn parse_source<T>(&self, id: SourceId) -> Result<T>where
T: Parse,
Parse the given input as the given type that implements Parse.
Sourcepub fn macro_span(&self) -> Span
pub fn macro_span(&self) -> Span
The span of the macro call including the name of the macro.
If the macro call was stringify!(a + b) this would refer to the whole
macro call.
Sourcepub fn input_span(&self) -> Span
pub fn input_span(&self) -> Span
The span of the macro stream (the argument).
If the macro call was stringify!(a + b) this would refer to a + b.