diff options
| author | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-08-29 05:32:41 +0000 |
|---|---|---|
| committer | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-09-05 04:53:33 +0000 |
| commit | c07ff8d26a6d5c8728419ae4e870b3a65940efbc (patch) | |
| tree | c9e3784d05eafca8cff84c6ebbd6615d933fb9b7 /src/libsyntax | |
| parent | 7a3ae576fa729e0465719f97aa7bb80c9721b446 (diff) | |
| download | rust-c07ff8d26a6d5c8728419ae4e870b3a65940efbc.tar.gz rust-c07ff8d26a6d5c8728419ae4e870b3a65940efbc.zip | |
Add module `ext::placeholders` with `placeholder()` and `PlaceholderExpander`.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 48 | ||||
| -rw-r--r-- | src/libsyntax/ext/placeholders.rs | 172 | ||||
| -rw-r--r-- | src/libsyntax/lib.rs | 1 |
3 files changed, 182 insertions, 39 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 17b2b2d25b9..c5fc149bb7e 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -12,8 +12,9 @@ use ast::{Block, Crate, Ident, Mac_, PatKind}; use ast::{MacStmtStyle, StmtKind, ItemKind}; use ast; use ext::hygiene::Mark; +use ext::placeholders; use attr::{self, HasAttrs}; -use codemap::{dummy_spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; +use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; use syntax_pos::{self, Span, ExpnId}; use config::StripUnconfigured; use ext::base::*; @@ -35,8 +36,8 @@ macro_rules! expansions { $(.$fold:ident)* $(lift .$fold_elt:ident)*, $(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => { #[derive(Copy, Clone)] - enum ExpansionKind { OptExpr, $( $kind, )* } - enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* } + pub enum ExpansionKind { OptExpr, $( $kind, )* } + pub enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* } impl ExpansionKind { fn name(self) -> &'static str { @@ -55,20 +56,20 @@ macro_rules! expansions { } impl Expansion { - fn make_opt_expr(self) -> Option<P<ast::Expr>> { + pub fn make_opt_expr(self) -> Option<P<ast::Expr>> { match self { Expansion::OptExpr(expr) => expr, _ => panic!("Expansion::make_* called on the wrong kind of expansion"), } } - $( fn $make(self) -> $ty { + $( pub fn $make(self) -> $ty { match self { Expansion::$kind(ast) => ast, _ => panic!("Expansion::make_* called on the wrong kind of expansion"), } } )* - fn fold_with<F: Folder>(self, folder: &mut F) -> Self { + pub fn fold_with<F: Folder>(self, folder: &mut F) -> Self { use self::Expansion::*; match self { OptExpr(expr) => OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))), @@ -434,9 +435,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // If keep_macs is true, expands to a MacEager::items instead. if self.keep_macs { - Some(reconstruct_macro_rules(&def, &path)) + Some(placeholders::reconstructed_macro_rules(&def, &path)) } else { - Some(macro_scope_placeholder()) + Some(placeholders::macro_scope_placeholder()) } } @@ -650,37 +651,6 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { } } -fn macro_scope_placeholder() -> Expansion { - Expansion::Items(SmallVector::one(P(ast::Item { - ident: keywords::Invalid.ident(), - attrs: Vec::new(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::Mac(dummy_spanned(ast::Mac_ { - path: ast::Path { span: syntax_pos::DUMMY_SP, global: false, segments: Vec::new() }, - tts: Vec::new(), - })), - vis: ast::Visibility::Inherited, - span: syntax_pos::DUMMY_SP, - }))) -} - -fn reconstruct_macro_rules(def: &ast::MacroDef, path: &ast::Path) -> Expansion { - Expansion::Items(SmallVector::one(P(ast::Item { - ident: def.ident, - attrs: def.attrs.clone(), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::Mac(ast::Mac { - span: def.span, - node: ast::Mac_ { - path: path.clone(), - tts: def.body.clone(), - } - }), - vis: ast::Visibility::Inherited, - span: def.span, - }))) -} - pub struct ExpansionConfig<'feat> { pub crate_name: String, pub features: Option<&'feat Features>, diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs new file mode 100644 index 00000000000..f1665bdde75 --- /dev/null +++ b/src/libsyntax/ext/placeholders.rs @@ -0,0 +1,172 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ast; +use codemap::{DUMMY_SP, dummy_spanned}; +use ext::expand::{Expansion, ExpansionKind}; +use fold::*; +use parse::token::keywords; +use ptr::P; +use util::small_vector::SmallVector; + +use std::collections::HashMap; + +pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion { + fn mac_placeholder() -> ast::Mac { + dummy_spanned(ast::Mac_ { + path: ast::Path { span: DUMMY_SP, global: false, segments: Vec::new() }, + tts: Vec::new(), + }) + } + + let ident = keywords::Invalid.ident(); + let attrs = Vec::new(); + let vis = ast::Visibility::Inherited; + let span = DUMMY_SP; + let expr_placeholder = || P(ast::Expr { + id: id, span: span, + attrs: ast::ThinVec::new(), + node: ast::ExprKind::Mac(mac_placeholder()), + }); + + match kind { + ExpansionKind::Expr => Expansion::Expr(expr_placeholder()), + ExpansionKind::OptExpr => Expansion::OptExpr(Some(expr_placeholder())), + ExpansionKind::Items => Expansion::Items(SmallVector::one(P(ast::Item { + id: id, span: span, ident: ident, vis: vis, attrs: attrs, + node: ast::ItemKind::Mac(mac_placeholder()), + }))), + ExpansionKind::TraitItems => Expansion::TraitItems(SmallVector::one(ast::TraitItem { + id: id, span: span, ident: ident, attrs: attrs, + node: ast::TraitItemKind::Macro(mac_placeholder()), + })), + ExpansionKind::ImplItems => Expansion::ImplItems(SmallVector::one(ast::ImplItem { + id: id, span: span, ident: ident, vis: vis, attrs: attrs, + node: ast::ImplItemKind::Macro(mac_placeholder()), + defaultness: ast::Defaultness::Final, + })), + ExpansionKind::Pat => Expansion::Pat(P(ast::Pat { + id: id, span: span, node: ast::PatKind::Mac(mac_placeholder()), + })), + ExpansionKind::Ty => Expansion::Ty(P(ast::Ty { + id: id, span: span, node: ast::TyKind::Mac(mac_placeholder()), + })), + ExpansionKind::Stmts => Expansion::Stmts(SmallVector::one({ + let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::ThinVec::new())); + ast::Stmt { id: id, span: span, node: ast::StmtKind::Mac(mac) } + })), + } +} + +pub fn macro_scope_placeholder() -> Expansion { + placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID) +} + +pub struct PlaceholderExpander { + expansions: HashMap<ast::NodeId, Expansion>, +} + +impl PlaceholderExpander { + pub fn new(expansions: HashMap<ast::NodeId, Expansion>) -> Self { + PlaceholderExpander { + expansions: expansions, + } + } + + pub fn remove(&mut self, id: ast::NodeId) -> Expansion { + let expansion = self.expansions.remove(&id).unwrap(); + expansion.fold_with(self) + } +} + +impl Folder for PlaceholderExpander { + fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> { + match item.node { + // Scope placeholder + ast::ItemKind::Mac(_) if item.id == ast::DUMMY_NODE_ID => SmallVector::one(item), + ast::ItemKind::Mac(_) => self.remove(item.id).make_items(), + _ => noop_fold_item(item, self), + } + } + + fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> { + match item.node { + ast::TraitItemKind::Macro(_) => self.remove(item.id).make_trait_items(), + _ => noop_fold_trait_item(item, self), + } + } + + fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVector<ast::ImplItem> { + match item.node { + ast::ImplItemKind::Macro(_) => self.remove(item.id).make_impl_items(), + _ => noop_fold_impl_item(item, self), + } + } + + fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> { + match expr.node { + ast::ExprKind::Mac(_) => self.remove(expr.id).make_expr(), + _ => expr.map(|expr| noop_fold_expr(expr, self)), + } + } + + fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> { + match expr.node { + ast::ExprKind::Mac(_) => self.remove(expr.id).make_opt_expr(), + _ => noop_fold_opt_expr(expr, self), + } + } + + fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> { + let (style, mut expansion) = match stmt.node { + ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()), + _ => return noop_fold_stmt(stmt, self), + }; + + if style == ast::MacStmtStyle::Semicolon { + if let Some(stmt) = expansion.pop() { + expansion.push(stmt.add_trailing_semicolon()); + } + } + + expansion + } + + fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> { + match pat.node { + ast::PatKind::Mac(_) => self.remove(pat.id).make_pat(), + _ => noop_fold_pat(pat, self), + } + } + + fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> { + match ty.node { + ast::TyKind::Mac(_) => self.remove(ty.id).make_ty(), + _ => noop_fold_ty(ty, self), + } + } +} + +pub fn reconstructed_macro_rules(def: &ast::MacroDef, path: &ast::Path) -> Expansion { + Expansion::Items(SmallVector::one(P(ast::Item { + ident: def.ident, + attrs: def.attrs.clone(), + id: ast::DUMMY_NODE_ID, + node: ast::ItemKind::Mac(ast::Mac { + span: def.span, + node: ast::Mac_ { + path: path.clone(), + tts: def.body.clone(), + } + }), + vis: ast::Visibility::Inherited, + span: def.span, + }))) +} diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 65bc9f34c90..42201231247 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -126,6 +126,7 @@ pub mod ext { pub mod base; pub mod build; pub mod expand; + pub mod placeholders; pub mod hygiene; pub mod proc_macro_shim; pub mod quote; |
