Skip to content

Commit 5005be6

Browse files
committed
syntax: rename quote! to quote_tokens!, add quote_{expr,type,item,pat,stmt}!
r=brson, Close #3976.
1 parent 2bf6663 commit 5005be6

File tree

3 files changed

+141
-28
lines changed

3 files changed

+141
-28
lines changed

src/libsyntax/ext/base.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,21 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
9696
ext::log_syntax::expand_syntax_ext));
9797
syntax_expanders.insert(~"ast",
9898
builtin(ext::qquote::expand_ast));
99-
syntax_expanders.insert(~"quote",
100-
builtin_expr_tt(ext::quote::expand_quote));
99+
100+
// Quasi-quoting expanders
101+
syntax_expanders.insert(~"quote_tokens",
102+
builtin_expr_tt(ext::quote::expand_quote_tokens));
103+
syntax_expanders.insert(~"quote_expr",
104+
builtin_expr_tt(ext::quote::expand_quote_expr));
105+
syntax_expanders.insert(~"quote_type",
106+
builtin_expr_tt(ext::quote::expand_quote_type));
107+
syntax_expanders.insert(~"quote_item",
108+
builtin_expr_tt(ext::quote::expand_quote_item));
109+
syntax_expanders.insert(~"quote_pat",
110+
builtin_expr_tt(ext::quote::expand_quote_pat));
111+
syntax_expanders.insert(~"quote_stmt",
112+
builtin_expr_tt(ext::quote::expand_quote_stmt));
113+
101114
syntax_expanders.insert(~"line",
102115
builtin(ext::source_util::expand_line));
103116
syntax_expanders.insert(~"col",

src/libsyntax/ext/quote.rs

+107-26
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,54 @@ use token::*;
1616
*
1717
*/
1818

19-
pub fn expand_quote(cx: ext_ctxt,
20-
sp: span,
21-
tts: ~[ast::token_tree]) -> base::mac_result
22-
{
19+
pub mod rt {
20+
pub use ast::*;
21+
pub use parse::token::*;
22+
pub use parse::new_parser_from_tt;
23+
}
2324

24-
// NB: It appears that the main parser loses its mind if we consider
25-
// $foo as a tt_nonterminal during the main parse, so we have to re-parse
26-
// under quote_depth > 0. This is silly and should go away; the _guess_ is
27-
// it has to do with transition away from supporting old-style macros, so
28-
// try removing it when enough of them are gone.
29-
let p = parse::new_parser_from_tt(cx.parse_sess(), cx.cfg(), tts);
30-
p.quote_depth += 1u;
31-
let tq = dvec::DVec();
32-
while p.token != token::EOF {
33-
tq.push(p.parse_token_tree());
34-
}
35-
let tts = tq.get();
25+
pub fn expand_quote_tokens(cx: ext_ctxt,
26+
sp: span,
27+
tts: ~[ast::token_tree]) -> base::mac_result {
28+
base::mr_expr(expand_tt(cx, sp, tts))
29+
}
3630

37-
// We want to emit a block expression that does a sequence of 'use's to
38-
// import the AST and token constructors, followed by a tt expression.
39-
let uses = ~[ build::mk_glob_use(cx, sp, ids_ext(cx, ~[~"syntax",
40-
~"ast"])),
41-
build::mk_glob_use(cx, sp, ids_ext(cx, ~[~"syntax",
42-
~"parse",
43-
~"token"])) ];
44-
base::mr_expr(build::mk_block(cx, sp, uses, ~[],
45-
Some(mk_tt(cx, sp, &ast::tt_delim(tts)))))
31+
pub fn expand_quote_expr(cx: ext_ctxt,
32+
sp: span,
33+
tts: ~[ast::token_tree]) -> base::mac_result {
34+
base::mr_expr(expand_parse_call(cx, sp, ~"parse_expr", ~[], tts))
35+
}
36+
37+
pub fn expand_quote_item(cx: ext_ctxt,
38+
sp: span,
39+
tts: ~[ast::token_tree]) -> base::mac_result {
40+
let e_attrs = build::mk_uniq_vec_e(cx, sp, ~[]);
41+
base::mr_expr(expand_parse_call(cx, sp, ~"parse_item",
42+
~[e_attrs], tts))
43+
}
44+
45+
pub fn expand_quote_pat(cx: ext_ctxt,
46+
sp: span,
47+
tts: ~[ast::token_tree]) -> base::mac_result {
48+
let e_refutable = build::mk_lit(cx, sp, ast::lit_bool(true));
49+
base::mr_expr(expand_parse_call(cx, sp, ~"parse_pat",
50+
~[e_refutable], tts))
51+
}
52+
53+
pub fn expand_quote_type(cx: ext_ctxt,
54+
sp: span,
55+
tts: ~[ast::token_tree]) -> base::mac_result {
56+
let e_param_colons = build::mk_lit(cx, sp, ast::lit_bool(false));
57+
base::mr_expr(expand_parse_call(cx, sp, ~"parse_type",
58+
~[e_param_colons], tts))
59+
}
60+
61+
pub fn expand_quote_stmt(cx: ext_ctxt,
62+
sp: span,
63+
tts: ~[ast::token_tree]) -> base::mac_result {
64+
let e_attrs = build::mk_uniq_vec_e(cx, sp, ~[]);
65+
base::mr_expr(expand_parse_call(cx, sp, ~"parse_stmt",
66+
~[e_attrs], tts))
4667
}
4768

4869
fn ids_ext(cx: ext_ctxt, strs: ~[~str]) -> ~[ast::ident] {
@@ -304,4 +325,64 @@ fn mk_tt(cx: ext_ctxt, sp: span, tt: &ast::token_tree) -> @ast::expr {
304325
ast::tt_nonterminal(sp, ident) =>
305326
build::mk_copy(cx, sp, build::mk_path(cx, sp, ~[ident]))
306327
}
307-
}
328+
}
329+
330+
331+
fn expand_tt(cx: ext_ctxt,
332+
sp: span,
333+
tts: ~[ast::token_tree]) -> @ast::expr {
334+
// NB: It appears that the main parser loses its mind if we consider
335+
// $foo as a tt_nonterminal during the main parse, so we have to re-parse
336+
// under quote_depth > 0. This is silly and should go away; the _guess_ is
337+
// it has to do with transition away from supporting old-style macros, so
338+
// try removing it when enough of them are gone.
339+
let p = parse::new_parser_from_tt(cx.parse_sess(), cx.cfg(), tts);
340+
p.quote_depth += 1u;
341+
let tq = dvec::DVec();
342+
while p.token != token::EOF {
343+
tq.push(p.parse_token_tree());
344+
}
345+
let tts = tq.get();
346+
347+
// We want to emit a block expression that does a sequence of 'use's to
348+
// import the runtime module, followed by a tt expression.
349+
let uses = ~[ build::mk_glob_use(cx, sp, ids_ext(cx, ~[~"syntax",
350+
~"ext",
351+
~"quote",
352+
~"rt"])) ];
353+
build::mk_block(cx, sp, uses, ~[],
354+
Some(mk_tt(cx, sp, &ast::tt_delim(tts))))
355+
}
356+
357+
fn expand_parse_call(cx: ext_ctxt,
358+
sp: span,
359+
parse_method: ~str,
360+
arg_exprs: ~[@ast::expr],
361+
tts: ~[ast::token_tree]) -> @ast::expr {
362+
let tt_expr = expand_tt(cx, sp, tts);
363+
364+
let cfg_call = || build::mk_call_(
365+
cx, sp, build::mk_access(cx, sp, ids_ext(cx, ~[~"ext_cx"]),
366+
id_ext(cx, ~"cfg")), ~[]);
367+
368+
let parse_sess_call = || build::mk_call_(
369+
cx, sp, build::mk_access(cx, sp, ids_ext(cx, ~[~"ext_cx"]),
370+
id_ext(cx, ~"parse_sess")), ~[]);
371+
372+
let new_parser_call =
373+
build::mk_call(cx, sp,
374+
ids_ext(cx, ~[~"syntax",
375+
~"ext",
376+
~"quote",
377+
~"rt",
378+
~"new_parser_from_tt"]),
379+
~[parse_sess_call(),
380+
cfg_call(),
381+
build::mk_uniq_vec_e(cx, sp, ~[tt_expr])]);
382+
383+
build::mk_call_(cx, sp,
384+
build::mk_access_(cx, sp, new_parser_call,
385+
id_ext(cx, parse_method)),
386+
arg_exprs)
387+
}
388+
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
extern mod syntax;
2+
3+
use syntax::ext::base::ext_ctxt;
4+
5+
fn syntax_extension(ext_cx: @ext_ctxt) {
6+
let e_toks : syntax::ast::token_tree = quote_tokens!(1 + 2);
7+
let p_toks : syntax::ast::token_tree = quote_tokens!((x, 1 .. 4, *));
8+
9+
let _a: @syntax::ast::expr = quote_expr!(1 + 2);
10+
let _b: Option<@syntax::ast::item> = quote_item!( const foo : int = $e_toks; );
11+
let _c: @syntax::ast::pat = quote_pat!( (x, 1 .. 4, *) );
12+
let _d: @syntax::ast::stmt = quote_stmt!( let x = $e_toks; );
13+
let _e: @syntax::ast::expr = quote_expr!( match foo { $p_toks => 10 } );
14+
}
15+
16+
fn main() {
17+
let _x: syntax::ast::token_tree = quote_tokens!(a::Foo::foo());
18+
}
19+

0 commit comments

Comments
 (0)