]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs
Rollup merge of #48753 - tbu-:pr_hashmap_isize, r=BurntSushi
[rust.git] / src / test / run-pass-fulldeps / auxiliary / procedural_mbe_matching.rs
1 // Copyright 2015 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
11 // force-host
12
13 #![crate_type="dylib"]
14 #![feature(plugin_registrar, quote, rustc_private)]
15
16 extern crate syntax;
17 extern crate syntax_pos;
18 extern crate rustc;
19 extern crate rustc_plugin;
20
21 use syntax::feature_gate::Features;
22 use syntax::parse::token::{NtExpr, NtPat};
23 use syntax::ast::{Ident, Pat};
24 use syntax::tokenstream::{TokenTree};
25 use syntax::ext::base::{ExtCtxt, MacResult, MacEager};
26 use syntax::ext::build::AstBuilder;
27 use syntax::ext::tt::quoted;
28 use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
29 use syntax::ext::tt::macro_parser::{Success, Failure, Error};
30 use syntax::ext::tt::macro_parser::parse_failure_msg;
31 use syntax::ptr::P;
32 use syntax_pos::Span;
33 use rustc_plugin::Registry;
34
35 use std::cell::RefCell;
36
37 fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree])
38         -> Box<MacResult + 'static> {
39
40     let mbe_matcher = quote_tokens!(cx, $$matched:expr, $$($$pat:pat)|+);
41     let mbe_matcher = quoted::parse(mbe_matcher.into_iter().collect(),
42                                     true,
43                                     cx.parse_sess,
44                                     &Features::new(),
45                                     &[]);
46     let map = match TokenTree::parse(cx, &mbe_matcher, args.iter().cloned().collect()) {
47         Success(map) => map,
48         Failure(_, tok) => {
49             panic!("expected Success, but got Failure: {}", parse_failure_msg(tok));
50         }
51         Error(_, s) => {
52             panic!("expected Success, but got Error: {}", s);
53         }
54     };
55
56     let matched_nt = match *map[&Ident::from_str("matched")] {
57         MatchedNonterminal(ref nt) => nt.clone(),
58         _ => unreachable!(),
59     };
60
61     let mac_expr = match (&*matched_nt, &*map[&Ident::from_str("pat")]) {
62         (&NtExpr(ref matched_expr), &MatchedSeq(ref pats, seq_sp)) => {
63             let pats: Vec<P<Pat>> = pats.iter().map(|pat_nt| {
64                 match *pat_nt {
65                     MatchedNonterminal(ref nt) => match **nt {
66                         NtPat(ref pat) => pat.clone(),
67                         _ => unreachable!(),
68                     },
69                     _ => unreachable!(),
70                 }
71             }).collect();
72             let arm = cx.arm(seq_sp, pats, cx.expr_bool(seq_sp, true));
73
74             quote_expr!(cx,
75                 match $matched_expr {
76                     $arm
77                     _ => false
78                 }
79             )
80         }
81         _ => unreachable!()
82     };
83
84     MacEager::expr(mac_expr)
85 }
86
87 #[plugin_registrar]
88 pub fn plugin_registrar(reg: &mut Registry) {
89     reg.register_macro("matches", expand_mbe_matches);
90 }