]> git.proxmox.com Git - rustc.git/blame - src/libsyntax/ext/placeholders.rs
New upstream version 1.31.0~beta.4+dfsg1
[rustc.git] / src / libsyntax / ext / placeholders.rs
CommitLineData
9e0c209e
SL
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.
4//
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.
10
cc61c64b 11use ast::{self, NodeId};
b7449926 12use source_map::{DUMMY_SP, dummy_spanned};
9e0c209e 13use ext::base::ExtCtxt;
8faf50e0 14use ext::expand::{AstFragment, AstFragmentKind};
32a655c1 15use ext::hygiene::Mark;
8bb4bdeb 16use tokenstream::TokenStream;
9e0c209e 17use fold::*;
9e0c209e 18use ptr::P;
0bf4aa26 19use smallvec::SmallVec;
32a655c1 20use symbol::keywords;
b7449926 21use ThinVec;
9e0c209e 22use util::move_map::MoveMap;
9e0c209e 23
b7449926 24use rustc_data_structures::fx::FxHashMap;
9e0c209e 25
8faf50e0 26pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
9e0c209e
SL
27 fn mac_placeholder() -> ast::Mac {
28 dummy_spanned(ast::Mac_ {
32a655c1 29 path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
8bb4bdeb 30 tts: TokenStream::empty().into(),
94b46f34 31 delim: ast::MacDelimiter::Brace,
9e0c209e
SL
32 })
33 }
34
35 let ident = keywords::Invalid.ident();
36 let attrs = Vec::new();
abe05a73 37 let generics = ast::Generics::default();
0531ce1d 38 let vis = dummy_spanned(ast::VisibilityKind::Inherited);
9e0c209e
SL
39 let span = DUMMY_SP;
40 let expr_placeholder = || P(ast::Expr {
3b2f2976 41 id, span,
b7449926 42 attrs: ThinVec::new(),
9e0c209e
SL
43 node: ast::ExprKind::Mac(mac_placeholder()),
44 });
45
46 match kind {
8faf50e0
XL
47 AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
48 AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
b7449926 49 AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
3b2f2976 50 id, span, ident, vis, attrs,
9e0c209e 51 node: ast::ItemKind::Mac(mac_placeholder()),
3b2f2976 52 tokens: None,
b7449926
XL
53 })]),
54 AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
abe05a73 55 id, span, ident, attrs, generics,
9e0c209e 56 node: ast::TraitItemKind::Macro(mac_placeholder()),
3b2f2976 57 tokens: None,
b7449926
XL
58 }]),
59 AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem {
abe05a73 60 id, span, ident, vis, attrs, generics,
9e0c209e
SL
61 node: ast::ImplItemKind::Macro(mac_placeholder()),
62 defaultness: ast::Defaultness::Final,
3b2f2976 63 tokens: None,
b7449926 64 }]),
8faf50e0 65 AstFragmentKind::ForeignItems =>
b7449926 66 AstFragment::ForeignItems(smallvec![ast::ForeignItem {
8faf50e0
XL
67 id, span, ident, vis, attrs,
68 node: ast::ForeignItemKind::Macro(mac_placeholder()),
b7449926 69 }]),
8faf50e0 70 AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
3b2f2976 71 id, span, node: ast::PatKind::Mac(mac_placeholder()),
9e0c209e 72 })),
8faf50e0 73 AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
3b2f2976 74 id, span, node: ast::TyKind::Mac(mac_placeholder()),
9e0c209e 75 })),
b7449926
XL
76 AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
77 let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new()));
3b2f2976 78 ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) }
b7449926 79 }]),
9e0c209e
SL
80 }
81}
82
9e0c209e 83pub struct PlaceholderExpander<'a, 'b: 'a> {
b7449926 84 expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
9e0c209e
SL
85 cx: &'a mut ExtCtxt<'b>,
86 monotonic: bool,
87}
88
89impl<'a, 'b> PlaceholderExpander<'a, 'b> {
90 pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
91 PlaceholderExpander {
3b2f2976 92 cx,
b7449926 93 expanded_fragments: FxHashMap::default(),
3b2f2976 94 monotonic,
9e0c209e
SL
95 }
96 }
97
8faf50e0
XL
98 pub fn add(&mut self, id: ast::NodeId, fragment: AstFragment, derives: Vec<Mark>) {
99 let mut fragment = fragment.fold_with(self);
100 if let AstFragment::Items(mut items) = fragment {
8bb4bdeb 101 for derive in derives {
cc61c64b 102 match self.remove(NodeId::placeholder_from_mark(derive)) {
8faf50e0 103 AstFragment::Items(derived_items) => items.extend(derived_items),
8bb4bdeb
XL
104 _ => unreachable!(),
105 }
106 }
8faf50e0 107 fragment = AstFragment::Items(items);
8bb4bdeb 108 }
8faf50e0 109 self.expanded_fragments.insert(id, fragment);
9e0c209e
SL
110 }
111
8faf50e0
XL
112 fn remove(&mut self, id: ast::NodeId) -> AstFragment {
113 self.expanded_fragments.remove(&id).unwrap()
9e0c209e
SL
114 }
115}
116
117impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
0bf4aa26 118 fn fold_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
9e0c209e 119 match item.node {
32a655c1 120 ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
b7449926 121 ast::ItemKind::MacroDef(_) => return smallvec![item],
32a655c1 122 _ => {}
9e0c209e 123 }
32a655c1
SL
124
125 noop_fold_item(item, self)
9e0c209e
SL
126 }
127
0bf4aa26 128 fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
9e0c209e
SL
129 match item.node {
130 ast::TraitItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
131 _ => noop_fold_trait_item(item, self),
132 }
133 }
134
0bf4aa26 135 fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
9e0c209e
SL
136 match item.node {
137 ast::ImplItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
138 _ => noop_fold_impl_item(item, self),
139 }
140 }
141
0bf4aa26 142 fn fold_foreign_item(&mut self, item: ast::ForeignItem) -> SmallVec<[ast::ForeignItem; 1]> {
83c7162d
XL
143 match item.node {
144 ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(),
145 _ => noop_fold_foreign_item(item, self),
146 }
147 }
148
9e0c209e
SL
149 fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
150 match expr.node {
151 ast::ExprKind::Mac(_) => self.remove(expr.id).make_expr(),
152 _ => expr.map(|expr| noop_fold_expr(expr, self)),
153 }
154 }
155
156 fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
157 match expr.node {
158 ast::ExprKind::Mac(_) => self.remove(expr.id).make_opt_expr(),
159 _ => noop_fold_opt_expr(expr, self),
160 }
161 }
162
0bf4aa26 163 fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
8faf50e0 164 let (style, mut stmts) = match stmt.node {
9e0c209e
SL
165 ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
166 _ => return noop_fold_stmt(stmt, self),
167 };
168
169 if style == ast::MacStmtStyle::Semicolon {
8faf50e0
XL
170 if let Some(stmt) = stmts.pop() {
171 stmts.push(stmt.add_trailing_semicolon());
9e0c209e
SL
172 }
173 }
174
8faf50e0 175 stmts
9e0c209e
SL
176 }
177
178 fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
179 match pat.node {
180 ast::PatKind::Mac(_) => self.remove(pat.id).make_pat(),
181 _ => noop_fold_pat(pat, self),
182 }
183 }
184
185 fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {
186 match ty.node {
187 ast::TyKind::Mac(_) => self.remove(ty.id).make_ty(),
188 _ => noop_fold_ty(ty, self),
189 }
190 }
191
192 fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> {
193 noop_fold_block(block, self).map(|mut block| {
9e0c209e
SL
194 let mut remaining_stmts = block.stmts.len();
195
196 block.stmts = block.stmts.move_flat_map(|mut stmt| {
197 remaining_stmts -= 1;
198
cc61c64b
XL
199 if self.monotonic {
200 assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
201 stmt.id = self.cx.resolver.next_node_id();
9e0c209e
SL
202 }
203
9e0c209e
SL
204 Some(stmt)
205 });
206
207 block
208 })
209 }
210
211 fn fold_mod(&mut self, module: ast::Mod) -> ast::Mod {
212 let mut module = noop_fold_mod(module, self);
213 module.items = module.items.move_flat_map(|item| match item.node {
32a655c1 214 ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => None, // remove macro definitions
9e0c209e
SL
215 _ => Some(item),
216 });
217 module
218 }
9e0c209e 219
32a655c1
SL
220 fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
221 mac
222 }
9e0c209e 223}