1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 use codemap
::{DUMMY_SP, dummy_spanned}
;
13 use ext
::base
::ExtCtxt
;
14 use ext
::expand
::{Expansion, ExpansionKind}
;
15 use ext
::hygiene
::Mark
;
16 use tokenstream
::TokenStream
;
20 use util
::move_map
::MoveMap
;
21 use util
::small_vector
::SmallVector
;
23 use std
::collections
::HashMap
;
25 pub fn placeholder(kind
: ExpansionKind
, id
: ast
::NodeId
) -> Expansion
{
26 fn mac_placeholder() -> ast
::Mac
{
27 dummy_spanned(ast
::Mac_
{
28 path
: ast
::Path { span: DUMMY_SP, segments: Vec::new() }
,
29 tts
: TokenStream
::empty().into(),
33 let ident
= keywords
::Invalid
.ident();
34 let attrs
= Vec
::new();
35 let vis
= ast
::Visibility
::Inherited
;
37 let expr_placeholder
= || P(ast
::Expr
{
39 attrs
: ast
::ThinVec
::new(),
40 node
: ast
::ExprKind
::Mac(mac_placeholder()),
44 ExpansionKind
::Expr
=> Expansion
::Expr(expr_placeholder()),
45 ExpansionKind
::OptExpr
=> Expansion
::OptExpr(Some(expr_placeholder())),
46 ExpansionKind
::Items
=> Expansion
::Items(SmallVector
::one(P(ast
::Item
{
47 id
: id
, span
: span
, ident
: ident
, vis
: vis
, attrs
: attrs
,
48 node
: ast
::ItemKind
::Mac(mac_placeholder()),
50 ExpansionKind
::TraitItems
=> Expansion
::TraitItems(SmallVector
::one(ast
::TraitItem
{
51 id
: id
, span
: span
, ident
: ident
, attrs
: attrs
,
52 node
: ast
::TraitItemKind
::Macro(mac_placeholder()),
54 ExpansionKind
::ImplItems
=> Expansion
::ImplItems(SmallVector
::one(ast
::ImplItem
{
55 id
: id
, span
: span
, ident
: ident
, vis
: vis
, attrs
: attrs
,
56 node
: ast
::ImplItemKind
::Macro(mac_placeholder()),
57 defaultness
: ast
::Defaultness
::Final
,
59 ExpansionKind
::Pat
=> Expansion
::Pat(P(ast
::Pat
{
60 id
: id
, span
: span
, node
: ast
::PatKind
::Mac(mac_placeholder()),
62 ExpansionKind
::Ty
=> Expansion
::Ty(P(ast
::Ty
{
63 id
: id
, span
: span
, node
: ast
::TyKind
::Mac(mac_placeholder()),
65 ExpansionKind
::Stmts
=> Expansion
::Stmts(SmallVector
::one({
66 let mac
= P((mac_placeholder(), ast
::MacStmtStyle
::Braces
, ast
::ThinVec
::new()));
67 ast
::Stmt { id: id, span: span, node: ast::StmtKind::Mac(mac) }
72 pub struct PlaceholderExpander
<'a
, 'b
: 'a
> {
73 expansions
: HashMap
<ast
::NodeId
, Expansion
>,
74 cx
: &'a
mut ExtCtxt
<'b
>,
78 impl<'a
, 'b
> PlaceholderExpander
<'a
, 'b
> {
79 pub fn new(cx
: &'a
mut ExtCtxt
<'b
>, monotonic
: bool
) -> Self {
82 expansions
: HashMap
::new(),
87 pub fn add(&mut self, id
: ast
::NodeId
, expansion
: Expansion
, derives
: Vec
<Mark
>) {
88 let mut expansion
= expansion
.fold_with(self);
89 if let Expansion
::Items(mut items
) = expansion
{
90 for derive
in derives
{
91 match self.remove(derive
.as_placeholder_id()) {
92 Expansion
::Items(derived_items
) => items
.extend(derived_items
),
96 expansion
= Expansion
::Items(items
);
98 self.expansions
.insert(id
, expansion
);
101 fn remove(&mut self, id
: ast
::NodeId
) -> Expansion
{
102 self.expansions
.remove(&id
).unwrap()
106 impl<'a
, 'b
> Folder
for PlaceholderExpander
<'a
, 'b
> {
107 fn fold_item(&mut self, item
: P
<ast
::Item
>) -> SmallVector
<P
<ast
::Item
>> {
109 ast
::ItemKind
::Mac(_
) => return self.remove(item
.id
).make_items(),
110 ast
::ItemKind
::MacroDef(_
) => return SmallVector
::one(item
),
114 noop_fold_item(item
, self)
117 fn fold_trait_item(&mut self, item
: ast
::TraitItem
) -> SmallVector
<ast
::TraitItem
> {
119 ast
::TraitItemKind
::Macro(_
) => self.remove(item
.id
).make_trait_items(),
120 _
=> noop_fold_trait_item(item
, self),
124 fn fold_impl_item(&mut self, item
: ast
::ImplItem
) -> SmallVector
<ast
::ImplItem
> {
126 ast
::ImplItemKind
::Macro(_
) => self.remove(item
.id
).make_impl_items(),
127 _
=> noop_fold_impl_item(item
, self),
131 fn fold_expr(&mut self, expr
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
133 ast
::ExprKind
::Mac(_
) => self.remove(expr
.id
).make_expr(),
134 _
=> expr
.map(|expr
| noop_fold_expr(expr
, self)),
138 fn fold_opt_expr(&mut self, expr
: P
<ast
::Expr
>) -> Option
<P
<ast
::Expr
>> {
140 ast
::ExprKind
::Mac(_
) => self.remove(expr
.id
).make_opt_expr(),
141 _
=> noop_fold_opt_expr(expr
, self),
145 fn fold_stmt(&mut self, stmt
: ast
::Stmt
) -> SmallVector
<ast
::Stmt
> {
146 let (style
, mut expansion
) = match stmt
.node
{
147 ast
::StmtKind
::Mac(mac
) => (mac
.1, self.remove(stmt
.id
).make_stmts()),
148 _
=> return noop_fold_stmt(stmt
, self),
151 if style
== ast
::MacStmtStyle
::Semicolon
{
152 if let Some(stmt
) = expansion
.pop() {
153 expansion
.push(stmt
.add_trailing_semicolon());
160 fn fold_pat(&mut self, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
162 ast
::PatKind
::Mac(_
) => self.remove(pat
.id
).make_pat(),
163 _
=> noop_fold_pat(pat
, self),
167 fn fold_ty(&mut self, ty
: P
<ast
::Ty
>) -> P
<ast
::Ty
> {
169 ast
::TyKind
::Mac(_
) => self.remove(ty
.id
).make_ty(),
170 _
=> noop_fold_ty(ty
, self),
174 fn fold_block(&mut self, block
: P
<ast
::Block
>) -> P
<ast
::Block
> {
175 noop_fold_block(block
, self).map(|mut block
| {
176 let mut remaining_stmts
= block
.stmts
.len();
178 block
.stmts
= block
.stmts
.move_flat_map(|mut stmt
| {
179 remaining_stmts
-= 1;
182 // Avoid wasting a node id on a trailing expression statement,
183 // which shares a HIR node with the expression itself.
184 ast
::StmtKind
::Expr(ref expr
) if remaining_stmts
== 0 => stmt
.id
= expr
.id
,
186 _
if self.monotonic
=> {
187 assert_eq
!(stmt
.id
, ast
::DUMMY_NODE_ID
);
188 stmt
.id
= self.cx
.resolver
.next_node_id();
201 fn fold_mod(&mut self, module
: ast
::Mod
) -> ast
::Mod
{
202 let mut module
= noop_fold_mod(module
, self);
203 module
.items
= module
.items
.move_flat_map(|item
| match item
.node
{
204 ast
::ItemKind
::Mac(_
) if !self.cx
.ecfg
.keep_macs
=> None
, // remove macro definitions
210 fn fold_mac(&mut self, mac
: ast
::Mac
) -> ast
::Mac
{