]> git.lizzy.rs Git - rust.git/blob - src/libsyntax_ext/concat_idents.rs
9c49a59678fdbf434606aa99e41347db8e2c2d40
[rust.git] / src / libsyntax_ext / concat_idents.rs
1 use rustc_data_structures::thin_vec::ThinVec;
2
3 use syntax::ast;
4 use syntax::ext::base::*;
5 use syntax::ext::base;
6 use syntax::feature_gate;
7 use syntax::parse::token;
8 use syntax::ptr::P;
9 use syntax_pos::Span;
10 use syntax_pos::symbol::Symbol;
11 use syntax::tokenstream::TokenTree;
12
13 pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
14                               sp: Span,
15                               tts: &[TokenTree])
16                               -> Box<dyn base::MacResult + 'cx> {
17     if !cx.ecfg.enable_concat_idents() {
18         feature_gate::emit_feature_err(&cx.parse_sess,
19                                        "concat_idents",
20                                        sp,
21                                        feature_gate::GateIssue::Language,
22                                        feature_gate::EXPLAIN_CONCAT_IDENTS);
23     }
24
25     if tts.is_empty() {
26         cx.span_err(sp, "concat_idents! takes 1 or more arguments.");
27         return DummyResult::expr(sp);
28     }
29
30     let mut res_str = String::new();
31     for (i, e) in tts.iter().enumerate() {
32         if i & 1 == 1 {
33             match *e {
34                 TokenTree::Token(_, token::Comma) => {}
35                 _ => {
36                     cx.span_err(sp, "concat_idents! expecting comma.");
37                     return DummyResult::expr(sp);
38                 }
39             }
40         } else {
41             match *e {
42                 TokenTree::Token(_, token::Ident(ident, _)) =>
43                     res_str.push_str(&ident.as_str()),
44                 _ => {
45                     cx.span_err(sp, "concat_idents! requires ident args.");
46                     return DummyResult::expr(sp);
47                 }
48             }
49         }
50     }
51
52     let ident = ast::Ident::new(Symbol::intern(&res_str), sp.apply_mark(cx.current_expansion.mark));
53
54     struct ConcatIdentsResult { ident: ast::Ident }
55
56     impl base::MacResult for ConcatIdentsResult {
57         fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
58             Some(P(ast::Expr {
59                 id: ast::DUMMY_NODE_ID,
60                 node: ast::ExprKind::Path(None, ast::Path::from_ident(self.ident)),
61                 span: self.ident.span,
62                 attrs: ThinVec::new(),
63             }))
64         }
65
66         fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
67             Some(P(ast::Ty {
68                 id: ast::DUMMY_NODE_ID,
69                 node: ast::TyKind::Path(None, ast::Path::from_ident(self.ident)),
70                 span: self.ident.span,
71             }))
72         }
73     }
74
75     Box::new(ConcatIdentsResult { ident })
76 }