Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Expand
quote!
to allow for using all tokens and literals
To celebrate this, we now have a `stringy_math!` macro which is used in documentation of the upcoming macro feature.
- Loading branch information
Showing
32 changed files
with
1,213 additions
and
377 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Macros | ||
|
||
Rune has (experimental) support for macros. These are functions which expand | ||
into code, and can be used by library writers to "extend the compiler". | ||
|
||
For now, the following type of macros are support: | ||
* Function-like macros expanding to items (functions, type declarations, ..). | ||
* Function-like macros expanding to expression (statements, blocks, async blocks, ..). | ||
|
||
Macros can currently only be defined natively. This is to get around the rather | ||
tricky issue that the code of a macro has to be available and runnable during | ||
compilation. Native modules have a benefit here, because they have to be defined | ||
at a time when they are available to the compiler. | ||
|
||
It also means we can re-use all the compiler infrastructure for Rune as a | ||
library for macro authors. Which is really nice. | ||
|
||
## Writing a native macro | ||
|
||
The following is the definition of the `stringy_math!` macro. Which is a macro | ||
that can be invoked on expressions. | ||
|
||
```rust,noplaypen | ||
{{#include ../../crates/rune-macros/src/stringy_math_macro.rs}} | ||
``` | ||
|
||
A macro is added to a [`Module`] using the [`Module::macro_`] function. | ||
|
||
```rust,noplaypen | ||
pub fn module() -> Result<runestick::Module, runestick::ContextError> { | ||
let mut module = runestick::Module::new(&["std", "experiments"]); | ||
module.macro_(&["stringy_math"], stringy_math_macro::stringy_math)?; | ||
Ok(module) | ||
} | ||
``` | ||
|
||
With this module installed, we can now take `stringy_math!` for a spin. | ||
|
||
```rune | ||
{{#include ../../scripts/book/macros/stringy_math.rn}} | ||
``` | ||
|
||
```text | ||
$> cargo run -- scripts/book/macros/stringy_math.rn -O macros=true --experimental | ||
200 | ||
== () (2.9737ms) | ||
``` | ||
|
||
Until macros are considered somewhat stable, they will be hidden behind the `-O | ||
macros=true` compiler option. This can be set programmatically in | ||
[`Options::macros`]. `--experimental` is an option to Rune CLI which adds the | ||
`std::experimental` module, which contains weird and experimental things like | ||
`stringy_math!`. | ||
|
||
[`Module`]: https://docs.rs/runestick/0/runestick/module/struct.Module.html | ||
[`Module::macro_`]: https://docs.rs/runestick/0/runestick/module/struct.Module.html#method.macro_ | ||
[`Options::macros`]: https://docs.rs/rune/0/rune/struct.Options.html#method.macros |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use rune::ast; | ||
use rune::Resolve as _; | ||
use rune::{quote, MacroContext, Parser, TokenStream}; | ||
|
||
/// Implementation for the `stringy_math!` macro. | ||
pub(crate) fn stringy_math( | ||
ctx: &mut MacroContext, | ||
stream: &TokenStream, | ||
) -> runestick::Result<TokenStream> { | ||
let mut parser = Parser::from_token_stream(stream); | ||
|
||
let mut output = quote!(ctx => 0); | ||
|
||
while !parser.is_eof()? { | ||
let op = parser.parse::<ast::Ident>()?.macro_resolve(ctx)?; | ||
|
||
match op.as_ref() { | ||
"add" => { | ||
let op = parser.parse::<ast::Expr>()?; | ||
output = quote!(ctx => (#output) + #op); | ||
} | ||
"sub" => { | ||
let op = parser.parse::<ast::Expr>()?; | ||
output = quote!(ctx => (#output) - #op); | ||
} | ||
"div" => { | ||
let op = parser.parse::<ast::Expr>()?; | ||
output = quote!(ctx => (#output) / #op); | ||
} | ||
"mul" => { | ||
let op = parser.parse::<ast::Expr>()?; | ||
output = quote!(ctx => (#output) * #op); | ||
} | ||
other => { | ||
return Err(runestick::Error::msg(format!( | ||
"unsupported operation `{}`", | ||
other | ||
))); | ||
} | ||
} | ||
} | ||
|
||
parser.parse_eof()?; | ||
Ok(output) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.