(index<- ) ./libsyntax/ext/base.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Fri May 9 13:02:28 2014
1 // Copyright 2012-2014 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 use ast;
12 use ast::Name;
13 use codemap;
14 use codemap::{CodeMap, Span, ExpnInfo};
15 use ext;
16 use ext::expand;
17 use parse;
18 use parse::token;
19 use parse::token::{InternedString, intern, str_to_ident};
20 use util::small_vector::SmallVector;
21
22 use collections::HashMap;
23
24 // new-style macro! tt code:
25 //
26 // MacResult, NormalTT, IdentTT
27 //
28 // also note that ast::Mac used to have a bunch of extraneous cases and
29 // is now probably a redundant AST node, can be merged with
30 // ast::MacInvocTT.
31
32 pub struct MacroDef {
33 pub name: StrBuf,
34 pub ext: SyntaxExtension
35 }
36
37 pub type ItemDecorator =
38 fn(&mut ExtCtxt, Span, @ast::MetaItem, @ast::Item, |@ast::Item|);
39
40 pub type ItemModifier =
41 fn(&mut ExtCtxt, Span, @ast::MetaItem, @ast::Item) -> @ast::Item;
42
43 pub struct BasicMacroExpander {
44 pub expander: MacroExpanderFn,
45 pub span: Option<Span>
46 }
47
48 pub trait MacroExpander {
49 fn expand(&self,
50 ecx: &mut ExtCtxt,
51 span: Span,
52 token_tree: &[ast::TokenTree])
53 -> Box<MacResult>;
54 }
55
56 pub type MacroExpanderFn =
57 fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
58 -> Box<MacResult>;
59
60 impl MacroExpander for BasicMacroExpander {
61 fn expand(&self,
62 ecx: &mut ExtCtxt,
63 span: Span,
64 token_tree: &[ast::TokenTree])
65 -> Box<MacResult> {
66 (self.expander)(ecx, span, token_tree)
67 }
68 }
69
70 pub struct BasicIdentMacroExpander {
71 pub expander: IdentMacroExpanderFn,
72 pub span: Option<Span>
73 }
74
75 pub trait IdentMacroExpander {
76 fn expand(&self,
77 cx: &mut ExtCtxt,
78 sp: Span,
79 ident: ast::Ident,
80 token_tree: Vec<ast::TokenTree> )
81 -> Box<MacResult>;
82 }
83
84 impl IdentMacroExpander for BasicIdentMacroExpander {
85 fn expand(&self,
86 cx: &mut ExtCtxt,
87 sp: Span,
88 ident: ast::Ident,
89 token_tree: Vec<ast::TokenTree> )
90 -> Box<MacResult> {
91 (self.expander)(cx, sp, ident, token_tree)
92 }
93 }
94
95 pub type IdentMacroExpanderFn =
96 fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult>;
97
98 pub type MacroCrateRegistrationFun =
99 fn(|ast::Name, SyntaxExtension|);
100
101 /// The result of a macro expansion. The return values of the various
102 /// methods are spliced into the AST at the callsite of the macro (or
103 /// just into the compiler's internal macro table, for `make_def`).
104 pub trait MacResult {
105 /// Define a new macro.
106 fn make_def(&self) -> Option<MacroDef> {
107 None
108 }
109 /// Create an expression.
110 fn make_expr(&self) -> Option<@ast::Expr> {
111 None
112 }
113 /// Create zero or more items.
114 fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
115 None
116 }
117
118 /// Create a statement.
119 ///
120 /// By default this attempts to create an expression statement,
121 /// returning None if that fails.
122 fn make_stmt(&self) -> Option<@ast::Stmt> {
123 self.make_expr()
124 .map(|e| @codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID)))
125 }
126 }
127
128 /// A convenience type for macros that return a single expression.
129 pub struct MacExpr {
130 e: @ast::Expr
131 }
132 impl MacExpr {
133 pub fn new(e: @ast::Expr) -> Box<MacResult> {
134 box MacExpr { e: e } as Box<MacResult>
135 }
136 }
137 impl MacResult for MacExpr {
138 fn make_expr(&self) -> Option<@ast::Expr> {
139 Some(self.e)
140 }
141 }
142 /// A convenience type for macros that return a single item.
143 pub struct MacItem {
144 i: @ast::Item
145 }
146 impl MacItem {
147 pub fn new(i: @ast::Item) -> Box<MacResult> {
148 box MacItem { i: i } as Box<MacResult>
149 }
150 }
151 impl MacResult for MacItem {
152 fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
153 Some(SmallVector::one(self.i))
154 }
155 fn make_stmt(&self) -> Option<@ast::Stmt> {
156 Some(@codemap::respan(
157 self.i.span,
158 ast::StmtDecl(
159 @codemap::respan(self.i.span, ast::DeclItem(self.i)),
160 ast::DUMMY_NODE_ID)))
161 }
162 }
163
164 /// Fill-in macro expansion result, to allow compilation to continue
165 /// after hitting errors.
166 pub struct DummyResult {
167 expr_only: bool,
168 span: Span
169 }
170
171 impl DummyResult {
172 /// Create a default MacResult that can be anything.
173 ///
174 /// Use this as a return value after hitting any errors and
175 /// calling `span_err`.
176 pub fn any(sp: Span) -> Box<MacResult> {
177 box DummyResult { expr_only: false, span: sp } as Box<MacResult>
178 }
179
180 /// Create a default MacResult that can only be an expression.
181 ///
182 /// Use this for macros that must expand to an expression, so even
183 /// if an error is encountered internally, the user will recieve
184 /// an error that they also used it in the wrong place.
185 pub fn expr(sp: Span) -> Box<MacResult> {
186 box DummyResult { expr_only: true, span: sp } as Box<MacResult>
187 }
188
189 /// A plain dummy expression.
190 pub fn raw_expr(sp: Span) -> @ast::Expr {
191 @ast::Expr {
192 id: ast::DUMMY_NODE_ID,
193 node: ast::ExprLit(@codemap::respan(sp, ast::LitNil)),
194 span: sp,
195 }
196 }
197 }
198
199 impl MacResult for DummyResult {
200 fn make_expr(&self) -> Option<@ast::Expr> {
201 Some(DummyResult::raw_expr(self.span))
202 }
203 fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
204 if self.expr_only {
205 None
206 } else {
207 Some(SmallVector::zero())
208 }
209 }
210 fn make_stmt(&self) -> Option<@ast::Stmt> {
211 Some(@codemap::respan(self.span,
212 ast::StmtExpr(DummyResult::raw_expr(self.span),
213 ast::DUMMY_NODE_ID)))
214 }
215 }
216
217 /// An enum representing the different kinds of syntax extensions.
218 pub enum SyntaxExtension {
219 /// A syntax extension that is attached to an item and creates new items
220 /// based upon it.
221 ///
222 /// `#[deriving(...)]` is an `ItemDecorator`.
223 ItemDecorator(ItemDecorator),
224
225 /// A syntax extension that is attached to an item and modifies it
226 /// in-place.
227 ItemModifier(ItemModifier),
228
229 /// A normal, function-like syntax extension.
230 ///
231 /// `bytes!` is a `NormalTT`.
232 NormalTT(Box<MacroExpander:'static>, Option<Span>),
233
234 /// A function-like syntax extension that has an extra ident before
235 /// the block.
236 ///
237 /// `macro_rules!` is an `IdentTT`.
238 IdentTT(Box<IdentMacroExpander:'static>, Option<Span>),
239 }
240
241 pub struct BlockInfo {
242 // should macros escape from this scope?
243 pub macros_escape: bool,
244 // what are the pending renames?
245 pub pending_renames: RenameList,
246 }
247
248 impl BlockInfo {
249 pub fn new() -> BlockInfo {
250 BlockInfo {
251 macros_escape: false,
252 pending_renames: Vec::new(),
253 }
254 }
255 }
256
257 // a list of ident->name renamings
258 pub type RenameList = Vec<(ast::Ident, Name)>;
259
260 // The base map of methods for expanding syntax extension
261 // AST nodes into full ASTs
262 pub fn syntax_expander_table() -> SyntaxEnv {
263 // utility function to simplify creating NormalTT syntax extensions
264 fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
265 NormalTT(box BasicMacroExpander {
266 expander: f,
267 span: None,
268 },
269 None)
270 }
271
272 let mut syntax_expanders = SyntaxEnv::new();
273 syntax_expanders.insert(intern("macro_rules"),
274 IdentTT(box BasicIdentMacroExpander {
275 expander: ext::tt::macro_rules::add_new_extension,
276 span: None,
277 },
278 None));
279 syntax_expanders.insert(intern("fmt"),
280 builtin_normal_expander(
281 ext::fmt::expand_syntax_ext));
282 syntax_expanders.insert(intern("format_args"),
283 builtin_normal_expander(
284 ext::format::expand_args));
285 syntax_expanders.insert(intern("env"),
286 builtin_normal_expander(
287 ext::env::expand_env));
288 syntax_expanders.insert(intern("option_env"),
289 builtin_normal_expander(
290 ext::env::expand_option_env));
291 syntax_expanders.insert(intern("bytes"),
292 builtin_normal_expander(
293 ext::bytes::expand_syntax_ext));
294 syntax_expanders.insert(intern("concat_idents"),
295 builtin_normal_expander(
296 ext::concat_idents::expand_syntax_ext));
297 syntax_expanders.insert(intern("concat"),
298 builtin_normal_expander(
299 ext::concat::expand_syntax_ext));
300 syntax_expanders.insert(intern("log_syntax"),
301 builtin_normal_expander(
302 ext::log_syntax::expand_syntax_ext));
303 syntax_expanders.insert(intern("deriving"),
304 ItemDecorator(ext::deriving::expand_meta_deriving));
305
306 // Quasi-quoting expanders
307 syntax_expanders.insert(intern("quote_tokens"),
308 builtin_normal_expander(
309 ext::quote::expand_quote_tokens));
310 syntax_expanders.insert(intern("quote_expr"),
311 builtin_normal_expander(
312 ext::quote::expand_quote_expr));
313 syntax_expanders.insert(intern("quote_ty"),
314 builtin_normal_expander(
315 ext::quote::expand_quote_ty));
316 syntax_expanders.insert(intern("quote_item"),
317 builtin_normal_expander(
318 ext::quote::expand_quote_item));
319 syntax_expanders.insert(intern("quote_pat"),
320 builtin_normal_expander(
321 ext::quote::expand_quote_pat));
322 syntax_expanders.insert(intern("quote_stmt"),
323 builtin_normal_expander(
324 ext::quote::expand_quote_stmt));
325
326 syntax_expanders.insert(intern("line"),
327 builtin_normal_expander(
328 ext::source_util::expand_line));
329 syntax_expanders.insert(intern("col"),
330 builtin_normal_expander(
331 ext::source_util::expand_col));
332 syntax_expanders.insert(intern("file"),
333 builtin_normal_expander(
334 ext::source_util::expand_file));
335 syntax_expanders.insert(intern("stringify"),
336 builtin_normal_expander(
337 ext::source_util::expand_stringify));
338 syntax_expanders.insert(intern("include"),
339 builtin_normal_expander(
340 ext::source_util::expand_include));
341 syntax_expanders.insert(intern("include_str"),
342 builtin_normal_expander(
343 ext::source_util::expand_include_str));
344 syntax_expanders.insert(intern("include_bin"),
345 builtin_normal_expander(
346 ext::source_util::expand_include_bin));
347 syntax_expanders.insert(intern("module_path"),
348 builtin_normal_expander(
349 ext::source_util::expand_mod));
350 syntax_expanders.insert(intern("asm"),
351 builtin_normal_expander(
352 ext::asm::expand_asm));
353 syntax_expanders.insert(intern("cfg"),
354 builtin_normal_expander(
355 ext::cfg::expand_cfg));
356 syntax_expanders.insert(intern("trace_macros"),
357 builtin_normal_expander(
358 ext::trace_macros::expand_trace_macros));
359 syntax_expanders
360 }
361
362 pub struct MacroCrate {
363 pub lib: Option<Path>,
364 pub macros: Vec<StrBuf>,
365 pub registrar_symbol: Option<StrBuf>,
366 }
367
368 pub trait CrateLoader {
369 fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate;
370 }
371
372 // One of these is made during expansion and incrementally updated as we go;
373 // when a macro expansion occurs, the resulting nodes have the backtrace()
374 // -> expn_info of their expansion context stored into their span.
375 pub struct ExtCtxt<'a> {
376 pub parse_sess: &'a parse::ParseSess,
377 pub cfg: ast::CrateConfig,
378 pub backtrace: Option<@ExpnInfo>,
379 pub ecfg: expand::ExpansionConfig<'a>,
380
381 pub mod_path: Vec<ast::Ident> ,
382 pub trace_mac: bool,
383 }
384
385 impl<'a> ExtCtxt<'a> {
386 pub fn new<'a>(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
387 ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> {
388 ExtCtxt {
389 parse_sess: parse_sess,
390 cfg: cfg,
391 backtrace: None,
392 mod_path: Vec::new(),
393 ecfg: ecfg,
394 trace_mac: false
395 }
396 }
397
398 pub fn expand_expr(&mut self, mut e: @ast::Expr) -> @ast::Expr {
399 loop {
400 match e.node {
401 ast::ExprMac(..) => {
402 let mut expander = expand::MacroExpander {
403 extsbox: syntax_expander_table(),
404 cx: self,
405 };
406 e = expand::expand_expr(e, &mut expander);
407 }
408 _ => return e
409 }
410 }
411 }
412
413 pub fn codemap(&self) -> &'a CodeMap { &self.parse_sess.span_diagnostic.cm }
414 pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
415 pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() }
416 pub fn call_site(&self) -> Span {
417 match self.backtrace {
418 Some(expn_info) => expn_info.call_site,
419 None => self.bug("missing top span")
420 }
421 }
422 pub fn print_backtrace(&self) { }
423 pub fn backtrace(&self) -> Option<@ExpnInfo> { self.backtrace }
424 pub fn mod_push(&mut self, i: ast::Ident) { self.mod_path.push(i); }
425 pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
426 pub fn mod_path(&self) -> Vec<ast::Ident> {
427 let mut v = Vec::new();
428 v.push(token::str_to_ident(self.ecfg.crate_id.name.as_slice()));
429 v.extend(self.mod_path.iter().map(|a| *a));
430 return v;
431 }
432 pub fn bt_push(&mut self, ei: codemap::ExpnInfo) {
433 match ei {
434 ExpnInfo {call_site: cs, callee: ref callee} => {
435 self.backtrace =
436 Some(@ExpnInfo {
437 call_site: Span {lo: cs.lo, hi: cs.hi,
438 expn_info: self.backtrace},
439 callee: (*callee).clone()
440 });
441 }
442 }
443 }
444 pub fn bt_pop(&mut self) {
445 match self.backtrace {
446 Some(expn_info) => self.backtrace = expn_info.call_site.expn_info,
447 _ => self.bug("tried to pop without a push")
448 }
449 }
450 /// Emit `msg` attached to `sp`, and stop compilation immediately.
451 ///
452 /// `span_err` should be strongly prefered where-ever possible:
453 /// this should *only* be used when
454 /// - continuing has a high risk of flow-on errors (e.g. errors in
455 /// declaring a macro would cause all uses of that macro to
456 /// complain about "undefined macro"), or
457 /// - there is literally nothing else that can be done (however,
458 /// in most cases one can construct a dummy expression/item to
459 /// substitute; we never hit resolve/type-checking so the dummy
460 /// value doesn't have to match anything)
461 pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
462 self.print_backtrace();
463 self.parse_sess.span_diagnostic.span_fatal(sp, msg);
464 }
465
466 /// Emit `msg` attached to `sp`, without immediately stopping
467 /// compilation.
468 ///
469 /// Compilation will be stopped in the near future (at the end of
470 /// the macro expansion phase).
471 pub fn span_err(&self, sp: Span, msg: &str) {
472 self.print_backtrace();
473 self.parse_sess.span_diagnostic.span_err(sp, msg);
474 }
475 pub fn span_warn(&self, sp: Span, msg: &str) {
476 self.print_backtrace();
477 self.parse_sess.span_diagnostic.span_warn(sp, msg);
478 }
479 pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
480 self.print_backtrace();
481 self.parse_sess.span_diagnostic.span_unimpl(sp, msg);
482 }
483 pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
484 self.print_backtrace();
485 self.parse_sess.span_diagnostic.span_bug(sp, msg);
486 }
487 pub fn span_note(&self, sp: Span, msg: &str) {
488 self.print_backtrace();
489 self.parse_sess.span_diagnostic.span_note(sp, msg);
490 }
491 pub fn bug(&self, msg: &str) -> ! {
492 self.print_backtrace();
493 self.parse_sess.span_diagnostic.handler().bug(msg);
494 }
495 pub fn trace_macros(&self) -> bool {
496 self.trace_mac
497 }
498 pub fn set_trace_macros(&mut self, x: bool) {
499 self.trace_mac = x
500 }
501 pub fn ident_of(&self, st: &str) -> ast::Ident {
502 str_to_ident(st)
503 }
504 }
505
506 /// Extract a string literal from the macro expanded version of `expr`,
507 /// emitting `err_msg` if `expr` is not a string literal. This does not stop
508 /// compilation on error, merely emits a non-fatal error and returns None.
509 pub fn expr_to_str(cx: &mut ExtCtxt, expr: @ast::Expr, err_msg: &str)
510 -> Option<(InternedString, ast::StrStyle)> {
511 // we want to be able to handle e.g. concat("foo", "bar")
512 let expr = cx.expand_expr(expr);
513 match expr.node {
514 ast::ExprLit(l) => match l.node {
515 ast::LitStr(ref s, style) => return Some(((*s).clone(), style)),
516 _ => cx.span_err(l.span, err_msg)
517 },
518 _ => cx.span_err(expr.span, err_msg)
519 }
520 None
521 }
522
523 /// Non-fatally assert that `tts` is empty. Note that this function
524 /// returns even when `tts` is non-empty, macros that *need* to stop
525 /// compilation should call
526 /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
527 /// done as rarely as possible).
528 pub fn check_zero_tts(cx: &ExtCtxt,
529 sp: Span,
530 tts: &[ast::TokenTree],
531 name: &str) {
532 if tts.len() != 0 {
533 cx.span_err(sp, format!("{} takes no arguments", name));
534 }
535 }
536
537 /// Extract the string literal from the first token of `tts`. If this
538 /// is not a string literal, emit an error and return None.
539 pub fn get_single_str_from_tts(cx: &ExtCtxt,
540 sp: Span,
541 tts: &[ast::TokenTree],
542 name: &str)
543 -> Option<StrBuf> {
544 if tts.len() != 1 {
545 cx.span_err(sp, format!("{} takes 1 argument.", name));
546 } else {
547 match tts[0] {
548 ast::TTTok(_, token::LIT_STR(ident))
549 | ast::TTTok(_, token::LIT_STR_RAW(ident, _)) => {
550 return Some(token::get_ident(ident).get().to_strbuf())
551 }
552 _ => cx.span_err(sp, format!("{} requires a string.", name)),
553 }
554 }
555 None
556 }
557
558 /// Extract comma-separated expressions from `tts`. If there is a
559 /// parsing error, emit a non-fatal error and return None.
560 pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
561 sp: Span,
562 tts: &[ast::TokenTree]) -> Option<Vec<@ast::Expr> > {
563 let mut p = parse::new_parser_from_tts(cx.parse_sess(),
564 cx.cfg(),
565 tts.iter()
566 .map(|x| (*x).clone())
567 .collect());
568 let mut es = Vec::new();
569 while p.token != token::EOF {
570 if es.len() != 0 && !p.eat(&token::COMMA) {
571 cx.span_err(sp, "expected token: `,`");
572 return None;
573 }
574 es.push(cx.expand_expr(p.parse_expr()));
575 }
576 Some(es)
577 }
578
579 // in order to have some notion of scoping for macros,
580 // we want to implement the notion of a transformation
581 // environment.
582
583 // This environment maps Names to SyntaxExtensions.
584
585 //impl question: how to implement it? Initially, the
586 // env will contain only macros, so it might be painful
587 // to add an empty frame for every context. Let's just
588 // get it working, first....
589
590 // NB! the mutability of the underlying maps means that
591 // if expansion is out-of-order, a deeper scope may be
592 // able to refer to a macro that was added to an enclosing
593 // scope lexically later than the deeper scope.
594
595 struct MapChainFrame {
596 info: BlockInfo,
597 map: HashMap<Name, SyntaxExtension>,
598 }
599
600 // Only generic to make it easy to test
601 pub struct SyntaxEnv {
602 chain: Vec<MapChainFrame> ,
603 }
604
605 impl SyntaxEnv {
606 pub fn new() -> SyntaxEnv {
607 let mut map = SyntaxEnv { chain: Vec::new() };
608 map.push_frame();
609 map
610 }
611
612 pub fn push_frame(&mut self) {
613 self.chain.push(MapChainFrame {
614 info: BlockInfo::new(),
615 map: HashMap::new(),
616 });
617 }
618
619 pub fn pop_frame(&mut self) {
620 assert!(self.chain.len() > 1, "too many pops on MapChain!");
621 self.chain.pop();
622 }
623
624 fn find_escape_frame<'a>(&'a mut self) -> &'a mut MapChainFrame {
625 for (i, frame) in self.chain.mut_iter().enumerate().rev() {
626 if !frame.info.macros_escape || i == 0 {
627 return frame
628 }
629 }
630 unreachable!()
631 }
632
633 pub fn find<'a>(&'a self, k: &Name) -> Option<&'a SyntaxExtension> {
634 for frame in self.chain.iter().rev() {
635 match frame.map.find(k) {
636 Some(v) => return Some(v),
637 None => {}
638 }
639 }
640 None
641 }
642
643 pub fn insert(&mut self, k: Name, v: SyntaxExtension) {
644 self.find_escape_frame().map.insert(k, v);
645 }
646
647 pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo {
648 let last_chain_index = self.chain.len() - 1;
649 &mut self.chain.get_mut(last_chain_index).info
650 }
651 }
libsyntax/ext/base.rs:31:1-31:1 -struct- definition:
pub struct MacroDef {
pub name: StrBuf,
pub ext: SyntaxExtension
references:- 5libsyntax/ext/tt/macro_rules.rs:
248: box MacroRulesDefiner {
249: def: RefCell::new(Some(MacroDef {
250: name: token::get_ident(name).to_str().to_strbuf(),
libsyntax/ext/base.rs:
105: /// Define a new macro.
106: fn make_def(&self) -> Option<MacroDef> {
107: None
libsyntax/ext/tt/macro_rules.rs:
108: struct MacroRulesDefiner {
109: def: RefCell<Option<MacroDef>>
110: }
111: impl MacResult for MacroRulesDefiner {
112: fn make_def(&self) -> Option<MacroDef> {
113: Some(self.def.borrow_mut().take().expect("MacroRulesDefiner expanded twice"))
libsyntax/ext/expand.rs:
432: let items = match expanded.make_def() {
433: Some(MacroDef { name, ext }) => {
434: // yikes... no idea how to apply the mark to this. I'm afraid
libsyntax/ext/base.rs:538:60-538:60 -fn- definition:
/// is not a string literal, emit an error and return None.
pub fn get_single_str_from_tts(cx: &ExtCtxt,
sp: Span,
references:- 4libsyntax/ext/source_util.rs:
104: -> Box<base::MacResult> {
105: let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
106: Some(f) => f,
--
135: -> Box<base::MacResult> {
136: let file = match get_single_str_from_tts(cx, sp, tts, "include_bin!") {
137: Some(f) => f,
libsyntax/ext/env.rs:
27: -> Box<base::MacResult> {
28: let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
29: None => return DummyResult::expr(sp),
libsyntax/ext/base.rs:217:67-217:67 -enum- definition:
/// An enum representing the different kinds of syntax extensions.
pub enum SyntaxExtension {
/// A syntax extension that is attached to an item and creates new items
references:- 698: pub type MacroCrateRegistrationFun =
99: fn(|ast::Name, SyntaxExtension|);
--
633: pub fn find<'a>(&'a self, k: &Name) -> Option<&'a SyntaxExtension> {
634: for frame in self.chain.iter().rev() {
--
643: pub fn insert(&mut self, k: Name, v: SyntaxExtension) {
644: self.find_escape_frame().map.insert(k, v);
libsyntax/ext/base.rs:240:1-240:1 -struct- definition:
pub struct BlockInfo {
// should macros escape from this scope?
pub macros_escape: bool,
references:- 5249: pub fn new() -> BlockInfo {
250: BlockInfo {
251: macros_escape: false,
--
647: pub fn info<'a>(&'a mut self) -> &'a mut BlockInfo {
648: let last_chain_index = self.chain.len() - 1;
libsyntax/ext/base.rs:594:1-594:1 -struct- definition:
struct MapChainFrame {
info: BlockInfo,
map: HashMap<Name, SyntaxExtension>,
references:- 3612: pub fn push_frame(&mut self) {
613: self.chain.push(MapChainFrame {
614: info: BlockInfo::new(),
--
624: fn find_escape_frame<'a>(&'a mut self) -> &'a mut MapChainFrame {
625: for (i, frame) in self.chain.mut_iter().enumerate().rev() {
libsyntax/ext/base.rs:600:40-600:40 -struct- definition:
// Only generic to make it easy to test
pub struct SyntaxEnv {
chain: Vec<MapChainFrame> ,
references:- 5606: pub fn new() -> SyntaxEnv {
607: let mut map = SyntaxEnv { chain: Vec::new() };
608: map.push_frame();
libsyntax/ext/expand.rs:
834: pub struct MacroExpander<'a, 'b> {
835: pub extsbox: SyntaxEnv,
836: pub cx: &'a mut ExtCtxt<'b>,
libsyntax/ext/base.rs:74:1-74:1 -trait- definition:
pub trait IdentMacroExpander {
fn expand(&self,
cx: &mut ExtCtxt,
references:- 284: impl IdentMacroExpander for BasicIdentMacroExpander {
85: fn expand(&self,
--
237: /// `macro_rules!` is an `IdentTT`.
238: IdentTT(Box<IdentMacroExpander:'static>, Option<Span>),
239: }
libsyntax/ext/base.rs:142:61-142:61 -struct- definition:
/// A convenience type for macros that return a single item.
pub struct MacItem {
i: @ast::Item
references:- 3150: }
151: impl MacResult for MacItem {
152: fn make_items(&self) -> Option<SmallVector<@ast::Item>> {
libsyntax/ext/base.rs:47:1-47:1 -trait- definition:
pub trait MacroExpander {
fn expand(&self,
ecx: &mut ExtCtxt,
references:- 360: impl MacroExpander for BasicMacroExpander {
61: fn expand(&self,
libsyntax/ext/tt/macro_rules.rs:
93: impl MacroExpander for MacroRulesMacroExpander {
94: fn expand(&self,
libsyntax/ext/base.rs:
231: /// `bytes!` is a `NormalTT`.
232: NormalTT(Box<MacroExpander:'static>, Option<Span>),
libsyntax/ext/base.rs:361:1-361:1 -struct- definition:
pub struct MacroCrate {
pub lib: Option<Path>,
pub macros: Vec<StrBuf>,
references:- 2368: pub trait CrateLoader {
369: fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate;
370: }
libsyntax/ext/expand.rs:
487: fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
488: let MacroCrate { lib, macros, registrar_symbol } =
489: fld.cx.ecfg.loader.load_crate(krate);
libsyntax/ext/base.rs:261:28-261:28 -fn- definition:
// AST nodes into full ASTs
pub fn syntax_expander_table() -> SyntaxEnv {
// utility function to simplify creating NormalTT syntax extensions
references:- 2libsyntax/ext/expand.rs:
875: let mut expander = MacroExpander {
876: extsbox: syntax_expander_table(),
877: cx: &mut cx,
libsyntax/ext/base.rs:
402: let mut expander = expand::MacroExpander {
403: extsbox: syntax_expander_table(),
404: cx: self,
libsyntax/ext/base.rs:42:1-42:1 -struct- definition:
pub struct BasicMacroExpander {
pub expander: MacroExpanderFn,
pub span: Option<Span>
references:- 2264: fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
265: NormalTT(box BasicMacroExpander {
266: expander: f,
libsyntax/ext/base.rs:128:67-128:67 -struct- definition:
/// A convenience type for macros that return a single expression.
pub struct MacExpr {
e: @ast::Expr
references:- 3136: }
137: impl MacResult for MacExpr {
138: fn make_expr(&self) -> Option<@ast::Expr> {
libsyntax/ext/base.rs:559:59-559:59 -fn- definition:
/// parsing error, emit a non-fatal error and return None.
pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
sp: Span,
references:- 3libsyntax/ext/env.rs:
63: -> Box<base::MacResult> {
64: let exprs = match get_exprs_from_tts(cx, sp, tts) {
65: Some(ref exprs) if exprs.len() == 0 => {
libsyntax/ext/bytes.rs:
22: // Gather all argument expressions
23: let exprs = match get_exprs_from_tts(cx, sp, tts) {
24: None => return DummyResult::expr(sp),
libsyntax/ext/concat.rs:
22: -> Box<base::MacResult> {
23: let es = match base::get_exprs_from_tts(cx, sp, tts) {
24: Some(e) => e,
libsyntax/ext/base.rs:55:1-55:1 -NK_AS_STR_TODO- definition:
pub type MacroExpanderFn =
fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
-> Box<MacResult>;
references:- 243: pub struct BasicMacroExpander {
44: pub expander: MacroExpanderFn,
45: pub span: Option<Span>
--
263: // utility function to simplify creating NormalTT syntax extensions
264: fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
265: NormalTT(box BasicMacroExpander {
libsyntax/ext/base.rs:165:26-165:26 -struct- definition:
/// after hitting errors.
pub struct DummyResult {
expr_only: bool,
references:- 4176: pub fn any(sp: Span) -> Box<MacResult> {
177: box DummyResult { expr_only: false, span: sp } as Box<MacResult>
178: }
--
185: pub fn expr(sp: Span) -> Box<MacResult> {
186: box DummyResult { expr_only: true, span: sp } as Box<MacResult>
187: }
--
199: impl MacResult for DummyResult {
200: fn make_expr(&self) -> Option<@ast::Expr> {
libsyntax/ext/base.rs:527:33-527:33 -fn- definition:
/// done as rarely as possible).
pub fn check_zero_tts(cx: &ExtCtxt,
sp: Span,
references:- 4libsyntax/ext/source_util.rs:
55: -> Box<base::MacResult> {
56: base::check_zero_tts(cx, sp, tts, "file!");
--
72: -> Box<base::MacResult> {
73: base::check_zero_tts(cx, sp, tts, "module_path!");
74: let string = cx.mod_path()
libsyntax/ext/base.rs:69:1-69:1 -struct- definition:
pub struct BasicIdentMacroExpander {
pub expander: IdentMacroExpanderFn,
pub span: Option<Span>
references:- 284: impl IdentMacroExpander for BasicIdentMacroExpander {
85: fn expand(&self,
--
273: syntax_expanders.insert(intern("macro_rules"),
274: IdentTT(box BasicIdentMacroExpander {
275: expander: ext::tt::macro_rules::add_new_extension,
libsyntax/ext/base.rs:264:4-264:4 -fn- definition:
fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
NormalTT(box BasicMacroExpander {
expander: f,
references:- 25297: syntax_expanders.insert(intern("concat"),
298: builtin_normal_expander(
299: ext::concat::expand_syntax_ext));
--
356: syntax_expanders.insert(intern("trace_macros"),
357: builtin_normal_expander(
358: ext::trace_macros::expand_trace_macros));
libsyntax/ext/base.rs:374:67-374:67 -struct- definition:
// -> expn_info of their expansion context stored into their span.
pub struct ExtCtxt<'a> {
pub parse_sess: &'a parse::ParseSess,
references:- 160libsyntax/ext/expand.rs:
libsyntax/ext/quote.rs:
libsyntax/ext/deriving/mod.rs:
libsyntax/ext/deriving/bounds.rs:
libsyntax/ext/deriving/clone.rs:
libsyntax/ext/deriving/encodable.rs:
libsyntax/ext/deriving/decodable.rs:
libsyntax/ext/deriving/hash.rs:
libsyntax/ext/deriving/rand.rs:
libsyntax/ext/deriving/show.rs:
libsyntax/ext/deriving/zero.rs:
libsyntax/ext/deriving/default.rs:
libsyntax/ext/deriving/primitive.rs:
libsyntax/ext/deriving/cmp/eq.rs:
libsyntax/ext/deriving/cmp/totaleq.rs:
libsyntax/ext/deriving/cmp/ord.rs:
libsyntax/ext/deriving/cmp/totalord.rs:
libsyntax/ext/deriving/generic.rs:
libsyntax/ext/deriving/ty.rs:
libsyntax/ext/build.rs:
libsyntax/ext/tt/macro_rules.rs:
libsyntax/ext/cfg.rs:
libsyntax/ext/fmt.rs:
libsyntax/ext/format.rs:
libsyntax/ext/env.rs:
libsyntax/ext/bytes.rs:
libsyntax/ext/concat.rs:
libsyntax/ext/concat_idents.rs:
libsyntax/ext/log_syntax.rs:
libsyntax/ext/source_util.rs:
libsyntax/ext/trace_macros.rs:
libsyntax/ext/asm.rs:
libsyntax/ext/base.rs:
libsyntax/ext/base.rs:103:68-103:68 -trait- definition:
/// just into the compiler's internal macro table, for `make_def`).
pub trait MacResult {
/// Define a new macro.
references:- 49libsyntax/ext/quote.rs:
libsyntax/ext/tt/macro_rules.rs:
libsyntax/ext/cfg.rs:
libsyntax/ext/fmt.rs:
libsyntax/ext/format.rs:
libsyntax/ext/env.rs:
libsyntax/ext/bytes.rs:
libsyntax/ext/concat.rs:
libsyntax/ext/concat_idents.rs:
libsyntax/ext/log_syntax.rs:
libsyntax/ext/source_util.rs:
libsyntax/ext/trace_macros.rs:
libsyntax/ext/asm.rs:
libsyntax/ext/source_util.rs:
libsyntax/ext/base.rs:508:75-508:75 -fn- definition:
/// compilation on error, merely emits a non-fatal error and returns None.
pub fn expr_to_str(cx: &mut ExtCtxt, expr: @ast::Expr, err_msg: &str)
-> Option<(InternedString, ast::StrStyle)> {
references:- 4libsyntax/ext/format.rs:
832: cx.fmtsp = efmt.span;
833: let fmt = match expr_to_str(cx.ecx,
834: efmt,
libsyntax/ext/env.rs:
73: let var = match expr_to_str(cx,
74: *exprs.get(0),
libsyntax/ext/asm.rs:
71: Asm => {
72: let (s, style) = match expr_to_str(cx, p.parse_expr(),
73: "inline assembly must be a string literal.") {
libsyntax/ext/env.rs:
85: 2 => {
86: match expr_to_str(cx, *exprs.get(1), "expected string literal") {
87: None => return DummyResult::expr(sp),
libsyntax/ext/base.rs:257:35-257:35 -NK_AS_STR_TODO- definition:
// a list of ident->name renamings
pub type RenameList = Vec<(ast::Ident, Name)>;
// The base map of methods for expanding syntax extension
references:- 3244: // what are the pending renames?
245: pub pending_renames: RenameList,
246: }
libsyntax/ext/expand.rs:
801: pub struct IdentRenamer<'a> {
802: renames: &'a mut RenameList,
803: }
--
818: // renames.
819: pub fn renames_to_fold<'a>(renames: &'a mut RenameList) -> IdentRenamer<'a> {
820: IdentRenamer {