@@ -19,10 +19,10 @@ use token::*;
19
19
*
20
20
* Quasiquoting works via token trees.
21
21
*
22
- * This is registered as a set of expression syntax extension called quote! that lifts
23
- * its argument token-tree to an AST representing the construction of the same
24
- * token tree, with ast::tt_nonterminal nodes interpreted as antiquotes
25
- * (splices).
22
+ * This is registered as a set of expression syntax extension called quote!
23
+ * that lifts its argument token-tree to an AST representing the
24
+ * construction of the same token tree, with ast::tt_nonterminal nodes
25
+ * interpreted as antiquotes (splices).
26
26
*
27
27
*/
28
28
@@ -32,6 +32,176 @@ pub mod rt {
32
32
pub use parse:: new_parser_from_tts;
33
33
pub use codemap:: BytePos ;
34
34
pub use codemap:: span;
35
+
36
+ use print:: pprust;
37
+ use pprust:: { item_to_str, ty_to_str} ;
38
+
39
+ trait ToTokens {
40
+ pub fn to_tokens ( _cx : ext_ctxt ) -> ~[ token_tree ] ;
41
+ }
42
+
43
+ impl ~[ token_tree ] : ToTokens {
44
+ pub fn to_tokens ( _cx : ext_ctxt ) -> ~[ token_tree ] {
45
+ copy self
46
+ }
47
+ }
48
+
49
+ /* Should be (when bugs in default methods are fixed):
50
+
51
+ trait ToSource : ToTokens {
52
+ // Takes a thing and generates a string containing rust code for it.
53
+ pub fn to_source(cx: ext_ctxt) -> ~str;
54
+
55
+ // If you can make source, you can definitely make tokens.
56
+ pub fn to_tokens(cx: ext_ctxt) -> ~[token_tree] {
57
+ cx.parse_tts(self.to_source(cx))
58
+ }
59
+ }
60
+
61
+ */
62
+
63
+ trait ToSource {
64
+ // Takes a thing and generates a string containing rust code for it.
65
+ pub fn to_source ( cx : ext_ctxt ) -> ~str ;
66
+ }
67
+
68
+ impl ast:: ident : ToSource {
69
+ fn to_source ( cx : ext_ctxt ) -> ~str {
70
+ copy * cx. parse_sess ( ) . interner . get ( self )
71
+ }
72
+ }
73
+
74
+ impl @ast:: item : ToSource {
75
+ fn to_source ( cx : ext_ctxt ) -> ~str {
76
+ item_to_str ( self , cx. parse_sess ( ) . interner )
77
+ }
78
+ }
79
+
80
+ impl ~[ @ast:: item ] : ToSource {
81
+ fn to_source ( cx : ext_ctxt ) -> ~str {
82
+ str:: connect ( self . map ( |i| i. to_source ( cx) ) , ~"\n \n ")
83
+ }
84
+ }
85
+
86
+ impl @ast:: Ty : ToSource {
87
+ fn to_source ( cx : ext_ctxt ) -> ~str {
88
+ ty_to_str ( self , cx. parse_sess ( ) . interner )
89
+ }
90
+ }
91
+
92
+ impl ~[ @ast:: Ty ] : ToSource {
93
+ fn to_source ( cx : ext_ctxt ) -> ~str {
94
+ str:: connect ( self . map ( |i| i. to_source ( cx) ) , ~", ")
95
+ }
96
+ }
97
+
98
+ impl ~[ast::ty_param]: ToSource {
99
+ fn to_source(cx: ext_ctxt) -> ~str {
100
+ pprust::typarams_to_str(self, cx.parse_sess().interner)
101
+ }
102
+ }
103
+
104
+ impl @ast::expr: ToSource {
105
+ fn to_source(cx: ext_ctxt) -> ~str {
106
+ pprust::expr_to_str(self, cx.parse_sess().interner)
107
+ }
108
+ }
109
+
110
+ // Alas ... we write these out instead. All redundant.
111
+
112
+ impl ast::ident: ToTokens {
113
+ fn to_tokens(cx: ext_ctxt) -> ~[token_tree] {
114
+ cx.parse_tts(self.to_source(cx))
115
+ }
116
+ }
117
+
118
+ impl @ast::item: ToTokens {
119
+ fn to_tokens(cx: ext_ctxt) -> ~[token_tree] {
120
+ cx.parse_tts(self.to_source(cx))
121
+ }
122
+ }
123
+
124
+ impl ~[@ast::item]: ToTokens {
125
+ fn to_tokens(cx: ext_ctxt) -> ~[token_tree] {
126
+ cx.parse_tts(self.to_source(cx))
127
+ }
128
+ }
129
+
130
+ impl @ast::Ty: ToTokens {
131
+ fn to_tokens(cx: ext_ctxt) -> ~[token_tree] {
132
+ cx.parse_tts(self.to_source(cx))
133
+ }
134
+ }
135
+
136
+ impl ~[@ast::Ty]: ToTokens {
137
+ fn to_tokens(cx: ext_ctxt) -> ~[token_tree] {
138
+ cx.parse_tts(self.to_source(cx))
139
+ }
140
+ }
141
+
142
+ impl ~[ast::ty_param]: ToTokens {
143
+ fn to_tokens(cx: ext_ctxt) -> ~[token_tree] {
144
+ cx.parse_tts(self.to_source(cx))
145
+ }
146
+ }
147
+
148
+ impl @ast::expr: ToTokens {
149
+ fn to_tokens(cx: ext_ctxt) -> ~[token_tree] {
150
+ cx.parse_tts(self.to_source(cx))
151
+ }
152
+ }
153
+
154
+ trait ExtParseUtils {
155
+ fn parse_item(s: ~str) -> @ast::item;
156
+ fn parse_expr(s: ~str) -> @ast::expr;
157
+ fn parse_stmt(s: ~str) -> @ast::stmt;
158
+ fn parse_tts(s: ~str) -> ~[ast::token_tree];
159
+ }
160
+
161
+ impl ext_ctxt: ExtParseUtils {
162
+
163
+ fn parse_item(s: ~str) -> @ast::item {
164
+ let res = parse::parse_item_from_source_str(
165
+ ~" <quote expansion>",
166
+ @(copy s),
167
+ self.cfg(),
168
+ ~[],
169
+ self.parse_sess());
170
+ match res {
171
+ Some(ast) => ast,
172
+ None => {
173
+ error!("Parse error with ```\n %s\n ```" , s) ;
174
+ fail
175
+ }
176
+ }
177
+ }
178
+
179
+ fn parse_stmt ( s : ~str ) -> @ast:: stmt {
180
+ parse:: parse_stmt_from_source_str (
181
+ ~"<quote expansion>",
182
+ @(copy s),
183
+ self.cfg(),
184
+ ~[],
185
+ self.parse_sess())
186
+ }
187
+
188
+ fn parse_expr(s: ~str) -> @ast::expr {
189
+ parse::parse_expr_from_source_str(
190
+ ~" <quote expansion>",
191
+ @(copy s),
192
+ self.cfg(),
193
+ self.parse_sess())
194
+ }
195
+
196
+ fn parse_tts(s: ~str) -> ~[ast::token_tree] {
197
+ parse::parse_tts_from_source_str(
198
+ ~" <quote expansion>",
199
+ @(copy s),
200
+ self.cfg(),
201
+ self.parse_sess())
202
+ }
203
+ }
204
+
35
205
}
36
206
37
207
pub fn expand_quote_tokens(cx: ext_ctxt,
@@ -288,14 +458,27 @@ fn mk_tt(cx: ext_ctxt, sp: span, tt: &ast::token_tree)
288
458
ast:: tt_seq( * ) => fail ~"tt_seq in quote!",
289
459
290
460
ast::tt_nonterminal(sp, ident) => {
461
+
462
+ // tt.push_all_move($ident.to_tokens(ext_cx))
463
+
464
+ let e_to_toks =
465
+ build::mk_call_(cx, sp,
466
+ build::mk_access
467
+ (cx, sp,
468
+ ~[ident],
469
+ id_ext(cx, ~" to_tokens") ) ,
470
+ ~[ build:: mk_path( cx, sp,
471
+ ids_ext( cx, ~[ ~"ext_cx"] ) ) ] ) ;
472
+
291
473
let e_push =
292
474
build:: mk_call_( cx, sp,
293
475
build:: mk_access
294
476
( cx, sp,
295
477
ids_ext( cx, ~[ ~"tt"] ) ,
296
478
id_ext( cx, ~"push_all_move") ) ,
297
- ~[ build:: mk_path( cx, sp, ~[ ident] ) ] ) ;
298
- ~[ build:: mk_stmt( cx, sp, e_push) ]
479
+ ~[ e_to_toks] ) ;
480
+
481
+ ~[ build:: mk_stmt( cx, sp, e_push) ]
299
482
}
300
483
}
301
484
}
@@ -367,7 +550,7 @@ fn expand_tts(cx: ext_ctxt,
367
550
let stmt_let_sp = build:: mk_local( cx, sp, false ,
368
551
id_ext( cx, ~"sp") ,
369
552
e_sp) ;
370
-
553
+
371
554
let stmt_let_tt = build:: mk_local( cx, sp, true ,
372
555
id_ext( cx, ~"tt") ,
373
556
build:: mk_uniq_vec_e( cx, sp, ~[ ] ) ) ;
0 commit comments