expansion: Improve searchability for AstFragments
methods
This commit is contained in:
parent
a12726460e
commit
399da7bc35
2 changed files with 65 additions and 48 deletions
|
@ -41,22 +41,33 @@ use std::rc::Rc;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
macro_rules! ast_fragments {
|
macro_rules! ast_fragments {
|
||||||
($($kind:ident: $ty:ty [$($vec:ident, $ty_elt:ty)*], $kind_name:expr, .$make:ident,
|
(
|
||||||
$(.$fold:ident)* $(lift .$fold_elt:ident)*,
|
$($Kind:ident($AstTy:ty) {
|
||||||
$(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => {
|
$kind_name:expr;
|
||||||
|
$(one fn $fold_ast:ident; fn $visit_ast:ident;)?
|
||||||
|
$(many fn $fold_ast_elt:ident; fn $visit_ast_elt:ident;)?
|
||||||
|
fn $make_ast:ident;
|
||||||
|
})*
|
||||||
|
) => {
|
||||||
/// A fragment of AST that can be produced by a single macro expansion.
|
/// A fragment of AST that can be produced by a single macro expansion.
|
||||||
/// Can also serve as an input and intermediate result for macro expansion operations.
|
/// Can also serve as an input and intermediate result for macro expansion operations.
|
||||||
pub enum AstFragment { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }
|
pub enum AstFragment {
|
||||||
|
OptExpr(Option<P<ast::Expr>>),
|
||||||
|
$($Kind($AstTy),)*
|
||||||
|
}
|
||||||
|
|
||||||
/// "Discriminant" of an AST fragment.
|
/// "Discriminant" of an AST fragment.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum AstFragmentKind { OptExpr, $( $kind, )* }
|
pub enum AstFragmentKind {
|
||||||
|
OptExpr,
|
||||||
|
$($Kind,)*
|
||||||
|
}
|
||||||
|
|
||||||
impl AstFragmentKind {
|
impl AstFragmentKind {
|
||||||
pub fn name(self) -> &'static str {
|
pub fn name(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
AstFragmentKind::OptExpr => "expression",
|
AstFragmentKind::OptExpr => "expression",
|
||||||
$( AstFragmentKind::$kind => $kind_name, )*
|
$(AstFragmentKind::$Kind => $kind_name,)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +75,7 @@ macro_rules! ast_fragments {
|
||||||
match self {
|
match self {
|
||||||
AstFragmentKind::OptExpr =>
|
AstFragmentKind::OptExpr =>
|
||||||
result.make_expr().map(Some).map(AstFragment::OptExpr),
|
result.make_expr().map(Some).map(AstFragment::OptExpr),
|
||||||
$( AstFragmentKind::$kind => result.$make().map(AstFragment::$kind), )*
|
$(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,21 +87,24 @@ macro_rules! ast_fragments {
|
||||||
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
|
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$( pub fn $make(self) -> $ty {
|
|
||||||
|
$(pub fn $make_ast(self) -> $AstTy {
|
||||||
match self {
|
match self {
|
||||||
AstFragment::$kind(ast) => ast,
|
AstFragment::$Kind(ast) => ast,
|
||||||
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
|
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
|
||||||
}
|
}
|
||||||
} )*
|
})*
|
||||||
|
|
||||||
pub fn fold_with<F: Folder>(self, folder: &mut F) -> Self {
|
pub fn fold_with<F: Folder>(self, folder: &mut F) -> Self {
|
||||||
use self::AstFragment::*;
|
|
||||||
match self {
|
match self {
|
||||||
OptExpr(expr) => OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
|
AstFragment::OptExpr(expr) =>
|
||||||
$($( $kind(ast) => $kind(folder.$fold(ast)), )*)*
|
AstFragment::OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
|
||||||
$($( $kind(ast) => {
|
$($(AstFragment::$Kind(ast) =>
|
||||||
$kind(ast.into_iter().flat_map(|ast| folder.$fold_elt(ast)).collect())
|
AstFragment::$Kind(folder.$fold_ast(ast)),)?)*
|
||||||
}, )*)*
|
$($(AstFragment::$Kind(ast) =>
|
||||||
|
AstFragment::$Kind(ast.into_iter()
|
||||||
|
.flat_map(|ast| folder.$fold_ast_elt(ast))
|
||||||
|
.collect()),)?)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,48 +112,50 @@ macro_rules! ast_fragments {
|
||||||
match *self {
|
match *self {
|
||||||
AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
|
AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
|
||||||
AstFragment::OptExpr(None) => {}
|
AstFragment::OptExpr(None) => {}
|
||||||
$($( AstFragment::$kind(ref ast) => visitor.$visit(ast), )*)*
|
$($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
|
||||||
$($( AstFragment::$kind(ref ast) => for ast in &ast[..] {
|
$($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
|
||||||
visitor.$visit_elt(ast);
|
visitor.$visit_ast_elt(ast_elt);
|
||||||
}, )*)*
|
})?)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
|
impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
|
||||||
fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
||||||
self.expand(AstFragment::OptExpr(Some(expr))).make_opt_expr()
|
self.expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr()
|
||||||
}
|
}
|
||||||
$($(fn $fold(&mut self, node: $ty) -> $ty {
|
$($(fn $fold_ast(&mut self, ast: $AstTy) -> $AstTy {
|
||||||
self.expand(AstFragment::$kind(node)).$make()
|
self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()
|
||||||
})*)*
|
})?)*
|
||||||
$($(fn $fold_elt(&mut self, node: $ty_elt) -> $ty {
|
$($(fn $fold_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy {
|
||||||
self.expand(AstFragment::$kind(SmallVector::one(node))).$make()
|
self.expand_fragment(AstFragment::$Kind(SmallVector::one(ast_elt))).$make_ast()
|
||||||
})*)*
|
})?)*
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
|
impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
|
||||||
$(fn $make(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>) -> Option<$ty> {
|
$(fn $make_ast(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>)
|
||||||
Some(self.make(AstFragmentKind::$kind).$make())
|
-> Option<$AstTy> {
|
||||||
|
Some(self.make(AstFragmentKind::$Kind).$make_ast())
|
||||||
})*
|
})*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_fragments! {
|
ast_fragments! {
|
||||||
Expr: P<ast::Expr> [], "expression", .make_expr, .fold_expr, .visit_expr;
|
Expr(P<ast::Expr>) { "expression"; one fn fold_expr; fn visit_expr; fn make_expr; }
|
||||||
Pat: P<ast::Pat> [], "pattern", .make_pat, .fold_pat, .visit_pat;
|
Pat(P<ast::Pat>) { "pattern"; one fn fold_pat; fn visit_pat; fn make_pat; }
|
||||||
Ty: P<ast::Ty> [], "type", .make_ty, .fold_ty, .visit_ty;
|
Ty(P<ast::Ty>) { "type"; one fn fold_ty; fn visit_ty; fn make_ty; }
|
||||||
Stmts: SmallVector<ast::Stmt> [SmallVector, ast::Stmt],
|
Stmts(SmallVector<ast::Stmt>) { "statement"; many fn fold_stmt; fn visit_stmt; fn make_stmts; }
|
||||||
"statement", .make_stmts, lift .fold_stmt, lift .visit_stmt;
|
Items(SmallVector<P<ast::Item>>) { "item"; many fn fold_item; fn visit_item; fn make_items; }
|
||||||
Items: SmallVector<P<ast::Item>> [SmallVector, P<ast::Item>],
|
TraitItems(SmallVector<ast::TraitItem>) {
|
||||||
"item", .make_items, lift .fold_item, lift .visit_item;
|
"trait item"; many fn fold_trait_item; fn visit_trait_item; fn make_trait_items;
|
||||||
TraitItems: SmallVector<ast::TraitItem> [SmallVector, ast::TraitItem],
|
}
|
||||||
"trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item;
|
ImplItems(SmallVector<ast::ImplItem>) {
|
||||||
ImplItems: SmallVector<ast::ImplItem> [SmallVector, ast::ImplItem],
|
"impl item"; many fn fold_impl_item; fn visit_impl_item; fn make_impl_items;
|
||||||
"impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item;
|
}
|
||||||
ForeignItems: SmallVector<ast::ForeignItem> [SmallVector, ast::ForeignItem],
|
ForeignItems(SmallVector<ast::ForeignItem>) {
|
||||||
"foreign item", .make_foreign_items, lift .fold_foreign_item, lift .visit_foreign_item;
|
"foreign item"; many fn fold_foreign_item; fn visit_foreign_item; fn make_foreign_items;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AstFragmentKind {
|
impl AstFragmentKind {
|
||||||
|
@ -261,7 +277,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
tokens: None,
|
tokens: None,
|
||||||
})));
|
})));
|
||||||
|
|
||||||
match self.expand(krate_item).make_items().pop().map(P::into_inner) {
|
match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
|
||||||
Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
|
Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
|
||||||
krate.attrs = attrs;
|
krate.attrs = attrs;
|
||||||
krate.module = module;
|
krate.module = module;
|
||||||
|
@ -281,7 +297,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fully expand all macro invocations in this AST fragment.
|
// Fully expand all macro invocations in this AST fragment.
|
||||||
fn expand(&mut self, input_fragment: AstFragment) -> AstFragment {
|
fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
|
||||||
let orig_expansion_data = self.cx.current_expansion.clone();
|
let orig_expansion_data = self.cx.current_expansion.clone();
|
||||||
self.cx.current_expansion.depth = 0;
|
self.cx.current_expansion.depth = 0;
|
||||||
|
|
||||||
|
|
|
@ -19,13 +19,14 @@
|
||||||
html_root_url = "https://doc.rust-lang.org/nightly/",
|
html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||||
test(attr(deny(warnings))))]
|
test(attr(deny(warnings))))]
|
||||||
|
|
||||||
#![feature(unicode_internals)]
|
#![feature(const_atomic_usize_new)]
|
||||||
|
#![feature(crate_visibility_modifier)]
|
||||||
|
#![feature(macro_at_most_once_rep)]
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
#![feature(rustc_diagnostic_macros)]
|
#![feature(rustc_diagnostic_macros)]
|
||||||
#![feature(slice_sort_by_cached_key)]
|
#![feature(slice_sort_by_cached_key)]
|
||||||
#![feature(const_atomic_usize_new)]
|
|
||||||
#![feature(rustc_attrs)]
|
|
||||||
#![feature(str_escape)]
|
#![feature(str_escape)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(unicode_internals)]
|
||||||
|
|
||||||
#![recursion_limit="256"]
|
#![recursion_limit="256"]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue