@@ -20,9 +20,11 @@ use parse::token;
20
20
use parse:: token:: { InternedString , intern, str_to_ident} ;
21
21
use util:: small_vector:: SmallVector ;
22
22
use ext:: mtwt;
23
+ use fold:: Folder ;
23
24
24
25
use std:: collections:: HashMap ;
25
26
use std:: gc:: { Gc , GC } ;
27
+ use std:: rc:: Rc ;
26
28
27
29
// new-style macro! tt code:
28
30
//
@@ -104,9 +106,9 @@ pub type IdentMacroExpanderFn =
104
106
/// just into the compiler's internal macro table, for `make_def`).
105
107
pub trait MacResult {
106
108
/// Define a new macro.
107
- // this particular flavor should go away; the idea that a macro might
108
- // expand into either a macro definition or an expression, depending
109
- // on what the context wants, is kind of silly.
109
+ // this should go away; the idea that a macro might expand into
110
+ // either a macro definition or an expression, depending on what
111
+ // the context wants, is kind of silly.
110
112
fn make_def ( & self ) -> Option < MacroDef > {
111
113
None
112
114
}
@@ -314,7 +316,7 @@ impl BlockInfo {
314
316
315
317
/// The base map of methods for expanding syntax extension
316
318
/// AST nodes into full ASTs
317
- pub fn syntax_expander_table ( ) -> SyntaxEnv {
319
+ fn initial_syntax_expander_table ( ) -> SyntaxEnv {
318
320
// utility function to simplify creating NormalTT syntax extensions
319
321
fn builtin_normal_expander ( f : MacroExpanderFn ) -> SyntaxExtension {
320
322
NormalTT ( box BasicMacroExpander {
@@ -431,7 +433,9 @@ pub struct ExtCtxt<'a> {
431
433
432
434
pub mod_path : Vec < ast:: Ident > ,
433
435
pub trace_mac : bool ,
434
- pub exported_macros : Vec < Gc < ast:: Item > >
436
+ pub exported_macros : Vec < Gc < ast:: Item > > ,
437
+
438
+ pub syntax_env : SyntaxEnv ,
435
439
}
436
440
437
441
impl < ' a > ExtCtxt < ' a > {
@@ -445,22 +449,18 @@ impl<'a> ExtCtxt<'a> {
445
449
ecfg : ecfg,
446
450
trace_mac : false ,
447
451
exported_macros : Vec :: new ( ) ,
452
+ syntax_env : initial_syntax_expander_table ( ) ,
448
453
}
449
454
}
450
455
451
- pub fn expand_expr ( & mut self , mut e : Gc < ast:: Expr > ) -> Gc < ast:: Expr > {
452
- loop {
453
- match e. node {
454
- ast:: ExprMac ( ..) => {
455
- let mut expander = expand:: MacroExpander {
456
- extsbox : syntax_expander_table ( ) ,
457
- cx : self ,
458
- } ;
459
- e = expand:: expand_expr ( e, & mut expander) ;
460
- }
461
- _ => return e
462
- }
463
- }
456
+ #[ deprecated = "Replaced with `expander().fold_expr()`" ]
457
+ pub fn expand_expr ( & mut self , e : Gc < ast:: Expr > ) -> Gc < ast:: Expr > {
458
+ self . expander ( ) . fold_expr ( e)
459
+ }
460
+
461
+ /// Returns a `Folder` for deeply expanding all macros in a AST node.
462
+ pub fn expander < ' b > ( & ' b mut self ) -> expand:: MacroExpander < ' b , ' a > {
463
+ expand:: MacroExpander { cx : self }
464
464
}
465
465
466
466
pub fn new_parser_from_tts ( & self , tts : & [ ast:: TokenTree ] )
@@ -570,7 +570,7 @@ impl<'a> ExtCtxt<'a> {
570
570
pub fn expr_to_string ( cx : & mut ExtCtxt , expr : Gc < ast:: Expr > , err_msg : & str )
571
571
-> Option < ( InternedString , ast:: StrStyle ) > {
572
572
// we want to be able to handle e.g. concat("foo", "bar")
573
- let expr = cx. expand_expr ( expr) ;
573
+ let expr = cx. expander ( ) . fold_expr ( expr) ;
574
574
match expr. node {
575
575
ast:: ExprLit ( l) => match l. node {
576
576
ast:: LitStr ( ref s, style) => return Some ( ( ( * s) . clone ( ) , style) ) ,
@@ -627,7 +627,7 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
627
627
let mut p = cx. new_parser_from_tts ( tts) ;
628
628
let mut es = Vec :: new ( ) ;
629
629
while p. token != token:: EOF {
630
- es. push ( cx. expand_expr ( p. parse_expr ( ) ) ) ;
630
+ es. push ( cx. expander ( ) . fold_expr ( p. parse_expr ( ) ) ) ;
631
631
if p. eat ( & token:: COMMA ) {
632
632
continue ;
633
633
}
@@ -642,10 +642,13 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
642
642
/// In order to have some notion of scoping for macros,
643
643
/// we want to implement the notion of a transformation
644
644
/// environment.
645
-
645
+ ///
646
646
/// This environment maps Names to SyntaxExtensions.
647
+ pub struct SyntaxEnv {
648
+ chain : Vec < MapChainFrame > ,
649
+ }
647
650
648
- //impl question: how to implement it? Initially, the
651
+ // impl question: how to implement it? Initially, the
649
652
// env will contain only macros, so it might be painful
650
653
// to add an empty frame for every context. Let's just
651
654
// get it working, first....
@@ -657,15 +660,11 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
657
660
658
661
struct MapChainFrame {
659
662
info : BlockInfo ,
660
- map : HashMap < Name , SyntaxExtension > ,
661
- }
662
-
663
- pub struct SyntaxEnv {
664
- chain : Vec < MapChainFrame > ,
663
+ map : HashMap < Name , Rc < SyntaxExtension > > ,
665
664
}
666
665
667
666
impl SyntaxEnv {
668
- pub fn new ( ) -> SyntaxEnv {
667
+ fn new ( ) -> SyntaxEnv {
669
668
let mut map = SyntaxEnv { chain : Vec :: new ( ) } ;
670
669
map. push_frame ( ) ;
671
670
map
@@ -692,18 +691,18 @@ impl SyntaxEnv {
692
691
unreachable ! ( )
693
692
}
694
693
695
- pub fn find < ' a > ( & ' a self , k : & Name ) -> Option < & ' a SyntaxExtension > {
694
+ pub fn find ( & self , k : & Name ) -> Option < Rc < SyntaxExtension > > {
696
695
for frame in self . chain . iter ( ) . rev ( ) {
697
696
match frame. map . find ( k) {
698
- Some ( v) => return Some ( v) ,
697
+ Some ( v) => return Some ( v. clone ( ) ) ,
699
698
None => { }
700
699
}
701
700
}
702
701
None
703
702
}
704
703
705
704
pub fn insert ( & mut self , k : Name , v : SyntaxExtension ) {
706
- self . find_escape_frame ( ) . map . insert ( k, v ) ;
705
+ self . find_escape_frame ( ) . map . insert ( k, Rc :: new ( v ) ) ;
707
706
}
708
707
709
708
pub fn info < ' a > ( & ' a mut self ) -> & ' a mut BlockInfo {
0 commit comments