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.
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.
11 pub use self::SyntaxExtension
::*;
16 use codemap
::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION, CompilerExpansion}
;
19 use ext
::tt
::macro_rules
;
23 use parse
::token
::{InternedString, intern, str_to_ident}
;
25 use util
::small_vector
::SmallVector
;
29 use std
::collections
::HashMap
;
31 use std
::default::Default
;
33 #[unstable(feature = "rustc_private")]
34 #[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
35 pub trait ItemDecorator
{
39 meta_item
: &ast
::MetaItem
,
41 push
: &mut FnMut(P
<ast
::Item
>));
45 #[unstable(feature = "rustc_private")]
46 #[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
47 impl<F
> ItemDecorator
for F
48 where F
: Fn(&mut ExtCtxt
, Span
, &ast
::MetaItem
, &ast
::Item
, &mut FnMut(P
<ast
::Item
>))
53 meta_item
: &ast
::MetaItem
,
55 push
: &mut FnMut(P
<ast
::Item
>)) {
56 (*self)(ecx
, sp
, meta_item
, item
, push
)
60 #[unstable(feature = "rustc_private")]
61 #[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")]
62 pub trait ItemModifier
{
66 meta_item
: &ast
::MetaItem
,
72 #[unstable(feature = "rustc_private")]
73 #[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")]
74 impl<F
> ItemModifier
for F
75 where F
: Fn(&mut ExtCtxt
, Span
, &ast
::MetaItem
, P
<ast
::Item
>) -> P
<ast
::Item
>
81 meta_item
: &ast
::MetaItem
,
84 (*self)(ecx
, span
, meta_item
, item
)
88 #[derive(Debug,Clone)]
89 pub enum Annotatable
{
91 TraitItem(P
<ast
::TraitItem
>),
92 ImplItem(P
<ast
::ImplItem
>),
96 pub fn attrs(&self) -> &[ast
::Attribute
] {
98 Annotatable
::Item(ref i
) => &i
.attrs
,
99 Annotatable
::TraitItem(ref ti
) => &ti
.attrs
,
100 Annotatable
::ImplItem(ref ii
) => &ii
.attrs
,
104 pub fn fold_attrs(self, attrs
: Vec
<ast
::Attribute
>) -> Annotatable
{
106 Annotatable
::Item(i
) => Annotatable
::Item(i
.map(|i
| ast
::Item
{
110 Annotatable
::TraitItem(i
) => Annotatable
::TraitItem(i
.map(|ti
| {
111 ast
::TraitItem { attrs: attrs, ..ti }
113 Annotatable
::ImplItem(i
) => Annotatable
::ImplItem(i
.map(|ii
| {
114 ast
::ImplItem { attrs: attrs, ..ii }
119 pub fn expect_item(self) -> P
<ast
::Item
> {
121 Annotatable
::Item(i
) => i
,
122 _
=> panic
!("expected Item")
126 pub fn map_item_or
<F
, G
>(self, mut f
: F
, mut or
: G
) -> Annotatable
127 where F
: FnMut(P
<ast
::Item
>) -> P
<ast
::Item
>,
128 G
: FnMut(Annotatable
) -> Annotatable
131 Annotatable
::Item(i
) => Annotatable
::Item(f(i
)),
136 pub fn expect_trait_item(self) -> P
<ast
::TraitItem
> {
138 Annotatable
::TraitItem(i
) => i
,
139 _
=> panic
!("expected Item")
143 pub fn expect_impl_item(self) -> P
<ast
::ImplItem
> {
145 Annotatable
::ImplItem(i
) => i
,
146 _
=> panic
!("expected Item")
151 // A more flexible ItemDecorator.
152 pub trait MultiItemDecorator
{
156 meta_item
: &ast
::MetaItem
,
158 push
: &mut FnMut(Annotatable
));
161 impl<F
> MultiItemDecorator
for F
162 where F
: Fn(&mut ExtCtxt
, Span
, &ast
::MetaItem
, Annotatable
, &mut FnMut(Annotatable
))
167 meta_item
: &ast
::MetaItem
,
169 push
: &mut FnMut(Annotatable
)) {
170 (*self)(ecx
, sp
, meta_item
, item
, push
)
174 // A more flexible ItemModifier (ItemModifier should go away, eventually, FIXME).
175 // meta_item is the annotation, item is the item being modified, parent_item
176 // is the impl or trait item is declared in if item is part of such a thing.
177 // FIXME Decorators should follow the same pattern too.
178 pub trait MultiItemModifier
{
182 meta_item
: &ast
::MetaItem
,
187 impl<F
> MultiItemModifier
for F
188 where F
: Fn(&mut ExtCtxt
,
191 Annotatable
) -> Annotatable
196 meta_item
: &ast
::MetaItem
,
199 (*self)(ecx
, span
, meta_item
, item
)
203 /// Represents a thing that maps token trees to Macro Results
204 pub trait TTMacroExpander
{
205 fn expand
<'cx
>(&self,
206 ecx
: &'cx
mut ExtCtxt
,
208 token_tree
: &[ast
::TokenTree
])
209 -> Box
<MacResult
+'cx
>;
212 pub type MacroExpanderFn
=
213 for<'cx
> fn(&'cx
mut ExtCtxt
, Span
, &[ast
::TokenTree
]) -> Box
<MacResult
+'cx
>;
215 impl<F
> TTMacroExpander
for F
216 where F
: for<'cx
> Fn(&'cx
mut ExtCtxt
, Span
, &[ast
::TokenTree
]) -> Box
<MacResult
+'cx
>
218 fn expand
<'cx
>(&self,
219 ecx
: &'cx
mut ExtCtxt
,
221 token_tree
: &[ast
::TokenTree
])
222 -> Box
<MacResult
+'cx
> {
223 (*self)(ecx
, span
, token_tree
)
227 pub trait IdentMacroExpander
{
228 fn expand
<'cx
>(&self,
229 cx
: &'cx
mut ExtCtxt
,
232 token_tree
: Vec
<ast
::TokenTree
> )
233 -> Box
<MacResult
+'cx
>;
236 pub type IdentMacroExpanderFn
=
237 for<'cx
> fn(&'cx
mut ExtCtxt
, Span
, ast
::Ident
, Vec
<ast
::TokenTree
>) -> Box
<MacResult
+'cx
>;
239 impl<F
> IdentMacroExpander
for F
240 where F
: for<'cx
> Fn(&'cx
mut ExtCtxt
, Span
, ast
::Ident
,
241 Vec
<ast
::TokenTree
>) -> Box
<MacResult
+'cx
>
243 fn expand
<'cx
>(&self,
244 cx
: &'cx
mut ExtCtxt
,
247 token_tree
: Vec
<ast
::TokenTree
> )
248 -> Box
<MacResult
+'cx
>
250 (*self)(cx
, sp
, ident
, token_tree
)
254 // Use a macro because forwarding to a simple function has type system issues
255 macro_rules
! make_stmts_default
{
257 $me
.make_expr().map(|e
| {
258 SmallVector
::one(P(codemap
::respan(
259 e
.span
, ast
::StmtExpr(e
, ast
::DUMMY_NODE_ID
))))
264 /// The result of a macro expansion. The return values of the various
265 /// methods are spliced into the AST at the callsite of the macro.
266 pub trait MacResult
{
267 /// Create an expression.
268 fn make_expr(self: Box
<Self>) -> Option
<P
<ast
::Expr
>> {
271 /// Create zero or more items.
272 fn make_items(self: Box
<Self>) -> Option
<SmallVector
<P
<ast
::Item
>>> {
276 /// Create zero or more impl items.
277 fn make_impl_items(self: Box
<Self>) -> Option
<SmallVector
<P
<ast
::ImplItem
>>> {
281 /// Create a pattern.
282 fn make_pat(self: Box
<Self>) -> Option
<P
<ast
::Pat
>> {
286 /// Create zero or more statements.
288 /// By default this attempts to create an expression statement,
289 /// returning None if that fails.
290 fn make_stmts(self: Box
<Self>) -> Option
<SmallVector
<P
<ast
::Stmt
>>> {
291 make_stmts_default
!(self)
295 macro_rules
! make_MacEager
{
296 ( $
( $fld
:ident
: $t
:ty
, )* ) => {
297 /// `MacResult` implementation for the common case where you've already
298 /// built each form of AST that you might return.
300 pub struct MacEager
{
302 pub $fld
: Option
<$t
>,
308 pub fn $
fld(v
: $t
) -> Box
<MacResult
> {
322 items
: SmallVector
<P
<ast
::Item
>>,
323 impl_items
: SmallVector
<P
<ast
::ImplItem
>>,
324 stmts
: SmallVector
<P
<ast
::Stmt
>>,
327 impl MacResult
for MacEager
{
328 fn make_expr(self: Box
<Self>) -> Option
<P
<ast
::Expr
>> {
332 fn make_items(self: Box
<Self>) -> Option
<SmallVector
<P
<ast
::Item
>>> {
336 fn make_impl_items(self: Box
<Self>) -> Option
<SmallVector
<P
<ast
::ImplItem
>>> {
340 fn make_stmts(self: Box
<Self>) -> Option
<SmallVector
<P
<ast
::Stmt
>>> {
341 match self.stmts
.as_ref().map_or(0, |s
| s
.len()) {
342 0 => make_stmts_default
!(self),
347 fn make_pat(self: Box
<Self>) -> Option
<P
<ast
::Pat
>> {
348 if let Some(p
) = self.pat
{
351 if let Some(e
) = self.expr
{
352 if let ast
::ExprLit(_
) = e
.node
{
353 return Some(P(ast
::Pat
{
354 id
: ast
::DUMMY_NODE_ID
,
356 node
: ast
::PatLit(e
),
364 /// Fill-in macro expansion result, to allow compilation to continue
365 /// after hitting errors.
366 #[derive(Copy, Clone)]
367 pub struct DummyResult
{
373 /// Create a default MacResult that can be anything.
375 /// Use this as a return value after hitting any errors and
376 /// calling `span_err`.
377 pub fn any(sp
: Span
) -> Box
<MacResult
+'
static> {
378 Box
::new(DummyResult { expr_only: false, span: sp }
)
381 /// Create a default MacResult that can only be an expression.
383 /// Use this for macros that must expand to an expression, so even
384 /// if an error is encountered internally, the user will receive
385 /// an error that they also used it in the wrong place.
386 pub fn expr(sp
: Span
) -> Box
<MacResult
+'
static> {
387 Box
::new(DummyResult { expr_only: true, span: sp }
)
390 /// A plain dummy expression.
391 pub fn raw_expr(sp
: Span
) -> P
<ast
::Expr
> {
393 id
: ast
::DUMMY_NODE_ID
,
394 node
: ast
::ExprLit(P(codemap
::respan(sp
, ast
::LitBool(false)))),
399 /// A plain dummy pattern.
400 pub fn raw_pat(sp
: Span
) -> ast
::Pat
{
402 id
: ast
::DUMMY_NODE_ID
,
403 node
: ast
::PatWild(ast
::PatWildSingle
),
410 impl MacResult
for DummyResult
{
411 fn make_expr(self: Box
<DummyResult
>) -> Option
<P
<ast
::Expr
>> {
412 Some(DummyResult
::raw_expr(self.span
))
414 fn make_pat(self: Box
<DummyResult
>) -> Option
<P
<ast
::Pat
>> {
415 Some(P(DummyResult
::raw_pat(self.span
)))
417 fn make_items(self: Box
<DummyResult
>) -> Option
<SmallVector
<P
<ast
::Item
>>> {
418 // this code needs a comment... why not always just return the Some() ?
422 Some(SmallVector
::zero())
425 fn make_impl_items(self: Box
<DummyResult
>) -> Option
<SmallVector
<P
<ast
::ImplItem
>>> {
429 Some(SmallVector
::zero())
432 fn make_stmts(self: Box
<DummyResult
>) -> Option
<SmallVector
<P
<ast
::Stmt
>>> {
433 Some(SmallVector
::one(P(
434 codemap
::respan(self.span
,
435 ast
::StmtExpr(DummyResult
::raw_expr(self.span
),
436 ast
::DUMMY_NODE_ID
)))))
440 /// An enum representing the different kinds of syntax extensions.
441 pub enum SyntaxExtension
{
442 /// A syntax extension that is attached to an item and creates new items
444 #[unstable(feature = "rustc_private")]
445 #[deprecated(since = "1.0.0", reason = "replaced by MultiDecorator")]
447 Decorator(Box
<ItemDecorator
+ '
static>),
449 /// A syntax extension that is attached to an item and creates new items
452 /// `#[derive(...)]` is a `MultiItemDecorator`.
453 MultiDecorator(Box
<MultiItemDecorator
+ '
static>),
455 /// A syntax extension that is attached to an item and modifies it
457 #[unstable(feature = "rustc_private")]
458 #[deprecated(since = "1.0.0", reason = "replaced by MultiModifier")]
460 Modifier(Box
<ItemModifier
+ '
static>),
462 /// A syntax extension that is attached to an item and modifies it
463 /// in-place. More flexible version than Modifier.
464 MultiModifier(Box
<MultiItemModifier
+ '
static>),
466 /// A normal, function-like syntax extension.
468 /// `bytes!` is a `NormalTT`.
470 /// The `bool` dictates whether the contents of the macro can
471 /// directly use `#[unstable]` things (true == yes).
472 NormalTT(Box
<TTMacroExpander
+ '
static>, Option
<Span
>, bool
),
474 /// A function-like syntax extension that has an extra ident before
477 IdentTT(Box
<IdentMacroExpander
+ '
static>, Option
<Span
>, bool
),
479 /// Represents `macro_rules!` itself.
483 pub type NamedSyntaxExtension
= (Name
, SyntaxExtension
);
485 pub struct BlockInfo
{
486 /// Should macros escape from this scope?
487 pub macros_escape
: bool
,
488 /// What are the pending renames?
489 pub pending_renames
: mtwt
::RenameList
,
493 pub fn new() -> BlockInfo
{
495 macros_escape
: false,
496 pending_renames
: Vec
::new(),
501 /// The base map of methods for expanding syntax extension
502 /// AST nodes into full ASTs
503 fn initial_syntax_expander_table
<'feat
>(ecfg
: &expand
::ExpansionConfig
<'feat
>)
505 // utility function to simplify creating NormalTT syntax extensions
506 fn builtin_normal_expander(f
: MacroExpanderFn
) -> SyntaxExtension
{
507 NormalTT(Box
::new(f
), None
, false)
510 let mut syntax_expanders
= SyntaxEnv
::new();
511 syntax_expanders
.insert(intern("macro_rules"), MacroRulesTT
);
512 syntax_expanders
.insert(intern("format_args"),
513 // format_args uses `unstable` things internally.
514 NormalTT(Box
::new(ext
::format
::expand_format_args
), None
, true));
515 syntax_expanders
.insert(intern("env"),
516 builtin_normal_expander(
517 ext
::env
::expand_env
));
518 syntax_expanders
.insert(intern("option_env"),
519 builtin_normal_expander(
520 ext
::env
::expand_option_env
));
521 syntax_expanders
.insert(intern("concat_idents"),
522 builtin_normal_expander(
523 ext
::concat_idents
::expand_syntax_ext
));
524 syntax_expanders
.insert(intern("concat"),
525 builtin_normal_expander(
526 ext
::concat
::expand_syntax_ext
));
527 syntax_expanders
.insert(intern("log_syntax"),
528 builtin_normal_expander(
529 ext
::log_syntax
::expand_syntax_ext
));
531 ext
::deriving
::register_all(&mut syntax_expanders
);
533 if ecfg
.enable_quotes() {
534 // Quasi-quoting expanders
535 syntax_expanders
.insert(intern("quote_tokens"),
536 builtin_normal_expander(
537 ext
::quote
::expand_quote_tokens
));
538 syntax_expanders
.insert(intern("quote_expr"),
539 builtin_normal_expander(
540 ext
::quote
::expand_quote_expr
));
541 syntax_expanders
.insert(intern("quote_ty"),
542 builtin_normal_expander(
543 ext
::quote
::expand_quote_ty
));
544 syntax_expanders
.insert(intern("quote_item"),
545 builtin_normal_expander(
546 ext
::quote
::expand_quote_item
));
547 syntax_expanders
.insert(intern("quote_pat"),
548 builtin_normal_expander(
549 ext
::quote
::expand_quote_pat
));
550 syntax_expanders
.insert(intern("quote_arm"),
551 builtin_normal_expander(
552 ext
::quote
::expand_quote_arm
));
553 syntax_expanders
.insert(intern("quote_stmt"),
554 builtin_normal_expander(
555 ext
::quote
::expand_quote_stmt
));
556 syntax_expanders
.insert(intern("quote_matcher"),
557 builtin_normal_expander(
558 ext
::quote
::expand_quote_matcher
));
559 syntax_expanders
.insert(intern("quote_attr"),
560 builtin_normal_expander(
561 ext
::quote
::expand_quote_attr
));
564 syntax_expanders
.insert(intern("line"),
565 builtin_normal_expander(
566 ext
::source_util
::expand_line
));
567 syntax_expanders
.insert(intern("column"),
568 builtin_normal_expander(
569 ext
::source_util
::expand_column
));
570 syntax_expanders
.insert(intern("file"),
571 builtin_normal_expander(
572 ext
::source_util
::expand_file
));
573 syntax_expanders
.insert(intern("stringify"),
574 builtin_normal_expander(
575 ext
::source_util
::expand_stringify
));
576 syntax_expanders
.insert(intern("include"),
577 builtin_normal_expander(
578 ext
::source_util
::expand_include
));
579 syntax_expanders
.insert(intern("include_str"),
580 builtin_normal_expander(
581 ext
::source_util
::expand_include_str
));
582 syntax_expanders
.insert(intern("include_bytes"),
583 builtin_normal_expander(
584 ext
::source_util
::expand_include_bytes
));
585 syntax_expanders
.insert(intern("module_path"),
586 builtin_normal_expander(
587 ext
::source_util
::expand_mod
));
588 syntax_expanders
.insert(intern("asm"),
589 builtin_normal_expander(
590 ext
::asm
::expand_asm
));
591 syntax_expanders
.insert(intern("cfg"),
592 builtin_normal_expander(
593 ext
::cfg
::expand_cfg
));
594 syntax_expanders
.insert(intern("trace_macros"),
595 builtin_normal_expander(
596 ext
::trace_macros
::expand_trace_macros
));
600 /// One of these is made during expansion and incrementally updated as we go;
601 /// when a macro expansion occurs, the resulting nodes have the backtrace()
602 /// -> expn_info of their expansion context stored into their span.
603 pub struct ExtCtxt
<'a
> {
604 pub parse_sess
: &'a parse
::ParseSess
,
605 pub cfg
: ast
::CrateConfig
,
606 pub backtrace
: ExpnId
,
607 pub ecfg
: expand
::ExpansionConfig
<'a
>,
610 pub mod_path
: Vec
<ast
::Ident
> ,
611 pub exported_macros
: Vec
<ast
::MacroDef
>,
613 pub syntax_env
: SyntaxEnv
,
614 pub recursion_count
: usize,
617 impl<'a
> ExtCtxt
<'a
> {
618 pub fn new(parse_sess
: &'a parse
::ParseSess
, cfg
: ast
::CrateConfig
,
619 ecfg
: expand
::ExpansionConfig
<'a
>) -> ExtCtxt
<'a
> {
620 let env
= initial_syntax_expander_table(&ecfg
);
622 parse_sess
: parse_sess
,
624 backtrace
: NO_EXPANSION
,
625 mod_path
: Vec
::new(),
628 exported_macros
: Vec
::new(),
634 #[unstable(feature = "rustc_private")]
635 #[deprecated(since = "1.0.0",
636 reason
= "Replaced with `expander().fold_expr()`")]
637 pub fn expand_expr(&mut self, e
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
638 self.expander().fold_expr(e
)
641 /// Returns a `Folder` for deeply expanding all macros in a AST node.
642 pub fn expander
<'b
>(&'b
mut self) -> expand
::MacroExpander
<'b
, 'a
> {
643 expand
::MacroExpander
::new(self)
646 pub fn new_parser_from_tts(&self, tts
: &[ast
::TokenTree
])
647 -> parser
::Parser
<'a
> {
648 parse
::tts_to_parser(self.parse_sess
, tts
.to_vec(), self.cfg())
651 pub fn codemap(&self) -> &'a CodeMap { &self.parse_sess.span_diagnostic.cm }
652 pub fn parse_sess(&self) -> &'a parse
::ParseSess { self.parse_sess }
653 pub fn cfg(&self) -> ast
::CrateConfig { self.cfg.clone() }
654 pub fn call_site(&self) -> Span
{
655 self.codemap().with_expn_info(self.backtrace
, |ei
| match ei
{
656 Some(expn_info
) => expn_info
.call_site
,
657 None
=> self.bug("missing top span")
660 pub fn backtrace(&self) -> ExpnId { self.backtrace }
662 /// Original span that caused the current exapnsion to happen.
663 pub fn original_span(&self) -> Span
{
664 let mut expn_id
= self.backtrace
;
665 let mut call_site
= None
;
667 match self.codemap().with_expn_info(expn_id
, |ei
| ei
.map(|ei
| ei
.call_site
)) {
670 call_site
= Some(cs
);
671 expn_id
= cs
.expn_id
;
675 call_site
.expect("missing expansion backtrace")
678 /// Returns span for the macro which originally caused the current expansion to happen.
680 /// Stops backtracing at include! boundary.
681 pub fn expansion_cause(&self) -> Span
{
682 let mut expn_id
= self.backtrace
;
683 let mut last_macro
= None
;
685 if self.codemap().with_expn_info(expn_id
, |info
| {
686 info
.map_or(None
, |i
| {
687 if i
.callee
.name
== "include" {
688 // Stop going up the backtrace once include! is encountered
691 expn_id
= i
.call_site
.expn_id
;
692 if i
.callee
.format
!= CompilerExpansion
{
693 last_macro
= Some(i
.call_site
)
701 last_macro
.expect("missing expansion backtrace")
704 pub fn mod_push(&mut self, i
: ast
::Ident
) { self.mod_path.push(i); }
705 pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
706 pub fn mod_path(&self) -> Vec
<ast
::Ident
> {
707 let mut v
= Vec
::new();
708 v
.push(token
::str_to_ident(&self.ecfg
.crate_name
));
709 v
.extend(self.mod_path
.iter().cloned());
712 pub fn bt_push(&mut self, ei
: ExpnInfo
) {
713 self.recursion_count
+= 1;
714 if self.recursion_count
> self.ecfg
.recursion_limit
{
715 panic
!(self.span_fatal(ei
.call_site
,
716 &format
!("recursion limit reached while expanding the macro `{}`",
720 let mut call_site
= ei
.call_site
;
721 call_site
.expn_id
= self.backtrace
;
722 self.backtrace
= self.codemap().record_expansion(ExpnInfo
{
723 call_site
: call_site
,
727 pub fn bt_pop(&mut self) {
728 match self.backtrace
{
729 NO_EXPANSION
=> self.bug("tried to pop without a push"),
731 self.recursion_count
-= 1;
732 self.backtrace
= self.codemap().with_expn_info(expn_id
, |expn_info
| {
733 expn_info
.map_or(NO_EXPANSION
, |ei
| ei
.call_site
.expn_id
)
739 pub fn insert_macro(&mut self, def
: ast
::MacroDef
) {
741 self.exported_macros
.push(def
.clone());
744 let ext
= macro_rules
::compile(self, &def
);
745 self.syntax_env
.insert(def
.ident
.name
, ext
);
749 /// Emit `msg` attached to `sp`, and stop compilation immediately.
751 /// `span_err` should be strongly preferred where-ever possible:
752 /// this should *only* be used when
753 /// - continuing has a high risk of flow-on errors (e.g. errors in
754 /// declaring a macro would cause all uses of that macro to
755 /// complain about "undefined macro"), or
756 /// - there is literally nothing else that can be done (however,
757 /// in most cases one can construct a dummy expression/item to
758 /// substitute; we never hit resolve/type-checking so the dummy
759 /// value doesn't have to match anything)
760 pub fn span_fatal(&self, sp
: Span
, msg
: &str) -> ! {
761 panic
!(self.parse_sess
.span_diagnostic
.span_fatal(sp
, msg
));
764 /// Emit `msg` attached to `sp`, without immediately stopping
767 /// Compilation will be stopped in the near future (at the end of
768 /// the macro expansion phase).
769 pub fn span_err(&self, sp
: Span
, msg
: &str) {
770 self.parse_sess
.span_diagnostic
.span_err(sp
, msg
);
772 pub fn span_warn(&self, sp
: Span
, msg
: &str) {
773 self.parse_sess
.span_diagnostic
.span_warn(sp
, msg
);
775 pub fn span_unimpl(&self, sp
: Span
, msg
: &str) -> ! {
776 self.parse_sess
.span_diagnostic
.span_unimpl(sp
, msg
);
778 pub fn span_bug(&self, sp
: Span
, msg
: &str) -> ! {
779 self.parse_sess
.span_diagnostic
.span_bug(sp
, msg
);
781 pub fn span_note(&self, sp
: Span
, msg
: &str) {
782 self.parse_sess
.span_diagnostic
.span_note(sp
, msg
);
784 pub fn span_help(&self, sp
: Span
, msg
: &str) {
785 self.parse_sess
.span_diagnostic
.span_help(sp
, msg
);
787 pub fn fileline_help(&self, sp
: Span
, msg
: &str) {
788 self.parse_sess
.span_diagnostic
.fileline_help(sp
, msg
);
790 pub fn bug(&self, msg
: &str) -> ! {
791 self.parse_sess
.span_diagnostic
.handler().bug(msg
);
793 pub fn trace_macros(&self) -> bool
{
796 pub fn set_trace_macros(&mut self, x
: bool
) {
797 self.ecfg
.trace_mac
= x
799 pub fn ident_of(&self, st
: &str) -> ast
::Ident
{
802 pub fn ident_of_std(&self, st
: &str) -> ast
::Ident
{
803 self.ident_of(if self.use_std { "std" }
else { st }
)
805 pub fn name_of(&self, st
: &str) -> ast
::Name
{
810 /// Extract a string literal from the macro expanded version of `expr`,
811 /// emitting `err_msg` if `expr` is not a string literal. This does not stop
812 /// compilation on error, merely emits a non-fatal error and returns None.
813 pub fn expr_to_string(cx
: &mut ExtCtxt
, expr
: P
<ast
::Expr
>, err_msg
: &str)
814 -> Option
<(InternedString
, ast
::StrStyle
)> {
815 // we want to be able to handle e.g. concat("foo", "bar")
816 let expr
= cx
.expander().fold_expr(expr
);
818 ast
::ExprLit(ref l
) => match l
.node
{
819 ast
::LitStr(ref s
, style
) => return Some(((*s
).clone(), style
)),
820 _
=> cx
.span_err(l
.span
, err_msg
)
822 _
=> cx
.span_err(expr
.span
, err_msg
)
827 /// Non-fatally assert that `tts` is empty. Note that this function
828 /// returns even when `tts` is non-empty, macros that *need* to stop
829 /// compilation should call
830 /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
831 /// done as rarely as possible).
832 pub fn check_zero_tts(cx
: &ExtCtxt
,
834 tts
: &[ast
::TokenTree
],
837 cx
.span_err(sp
, &format
!("{} takes no arguments", name
));
841 /// Extract the string literal from the first token of `tts`. If this
842 /// is not a string literal, emit an error and return None.
843 pub fn get_single_str_from_tts(cx
: &mut ExtCtxt
,
845 tts
: &[ast
::TokenTree
],
848 let mut p
= cx
.new_parser_from_tts(tts
);
849 if p
.token
== token
::Eof
{
850 cx
.span_err(sp
, &format
!("{} takes 1 argument", name
));
853 let ret
= cx
.expander().fold_expr(p
.parse_expr());
854 if p
.token
!= token
::Eof
{
855 cx
.span_err(sp
, &format
!("{} takes 1 argument", name
));
857 expr_to_string(cx
, ret
, "argument must be a string literal").map(|(s
, _
)| {
862 /// Extract comma-separated expressions from `tts`. If there is a
863 /// parsing error, emit a non-fatal error and return None.
864 pub fn get_exprs_from_tts(cx
: &mut ExtCtxt
,
866 tts
: &[ast
::TokenTree
]) -> Option
<Vec
<P
<ast
::Expr
>>> {
867 let mut p
= cx
.new_parser_from_tts(tts
);
868 let mut es
= Vec
::new();
869 while p
.token
!= token
::Eof
{
870 es
.push(cx
.expander().fold_expr(p
.parse_expr()));
871 if panictry
!(p
.eat(&token
::Comma
)){
874 if p
.token
!= token
::Eof
{
875 cx
.span_err(sp
, "expected token: `,`");
882 /// In order to have some notion of scoping for macros,
883 /// we want to implement the notion of a transformation
886 /// This environment maps Names to SyntaxExtensions.
887 pub struct SyntaxEnv
{
888 chain
: Vec
<MapChainFrame
> ,
891 // impl question: how to implement it? Initially, the
892 // env will contain only macros, so it might be painful
893 // to add an empty frame for every context. Let's just
894 // get it working, first....
896 // NB! the mutability of the underlying maps means that
897 // if expansion is out-of-order, a deeper scope may be
898 // able to refer to a macro that was added to an enclosing
899 // scope lexically later than the deeper scope.
901 struct MapChainFrame
{
903 map
: HashMap
<Name
, Rc
<SyntaxExtension
>>,
907 fn new() -> SyntaxEnv
{
908 let mut map
= SyntaxEnv { chain: Vec::new() }
;
913 pub fn push_frame(&mut self) {
914 self.chain
.push(MapChainFrame
{
915 info
: BlockInfo
::new(),
920 pub fn pop_frame(&mut self) {
921 assert
!(self.chain
.len() > 1, "too many pops on MapChain!");
925 fn find_escape_frame
<'a
>(&'a
mut self) -> &'a
mut MapChainFrame
{
926 for (i
, frame
) in self.chain
.iter_mut().enumerate().rev() {
927 if !frame
.info
.macros_escape
|| i
== 0 {
934 pub fn find(&self, k
: &Name
) -> Option
<Rc
<SyntaxExtension
>> {
935 for frame
in self.chain
.iter().rev() {
936 match frame
.map
.get(k
) {
937 Some(v
) => return Some(v
.clone()),
944 pub fn insert(&mut self, k
: Name
, v
: SyntaxExtension
) {
945 self.find_escape_frame().map
.insert(k
, Rc
::new(v
));
948 pub fn info
<'a
>(&'a
mut self) -> &'a
mut BlockInfo
{
949 let last_chain_index
= self.chain
.len() - 1;
950 &mut self.chain
[last_chain_index
].info