@@ -20,9 +20,11 @@ use parse::token;
2020use parse:: token:: { InternedString , intern, str_to_ident} ;
2121use util:: small_vector:: SmallVector ;
2222use ext:: mtwt;
23+ use fold:: Folder ;
2324
2425use std:: collections:: HashMap ;
2526use std:: gc:: { Gc , GC } ;
27+ use std:: rc:: Rc ;
2628
2729// new-style macro! tt code:
2830//
@@ -104,9 +106,9 @@ pub type IdentMacroExpanderFn =
104106/// just into the compiler's internal macro table, for `make_def`).
105107pub trait MacResult {
106108 /// 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.
110112 fn make_def ( & self ) -> Option < MacroDef > {
111113 None
112114 }
@@ -314,7 +316,7 @@ impl BlockInfo {
314316
315317/// The base map of methods for expanding syntax extension
316318/// AST nodes into full ASTs
317- pub fn syntax_expander_table ( ) -> SyntaxEnv {
319+ fn initial_syntax_expander_table ( ) -> SyntaxEnv {
318320 // utility function to simplify creating NormalTT syntax extensions
319321 fn builtin_normal_expander ( f : MacroExpanderFn ) -> SyntaxExtension {
320322 NormalTT ( box BasicMacroExpander {
@@ -431,7 +433,9 @@ pub struct ExtCtxt<'a> {
431433
432434 pub mod_path : Vec < ast:: Ident > ,
433435 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 ,
435439}
436440
437441impl < ' a > ExtCtxt < ' a > {
@@ -445,22 +449,18 @@ impl<'a> ExtCtxt<'a> {
445449 ecfg : ecfg,
446450 trace_mac : false ,
447451 exported_macros : Vec :: new ( ) ,
452+ syntax_env : initial_syntax_expander_table ( ) ,
448453 }
449454 }
450455
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 }
464464 }
465465
466466 pub fn new_parser_from_tts ( & self , tts : & [ ast:: TokenTree ] )
@@ -570,7 +570,7 @@ impl<'a> ExtCtxt<'a> {
570570pub fn expr_to_string ( cx : & mut ExtCtxt , expr : Gc < ast:: Expr > , err_msg : & str )
571571 -> Option < ( InternedString , ast:: StrStyle ) > {
572572 // 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) ;
574574 match expr. node {
575575 ast:: ExprLit ( l) => match l. node {
576576 ast:: LitStr ( ref s, style) => return Some ( ( ( * s) . clone ( ) , style) ) ,
@@ -627,7 +627,7 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
627627 let mut p = cx. new_parser_from_tts ( tts) ;
628628 let mut es = Vec :: new ( ) ;
629629 while p. token != token:: EOF {
630- es. push ( cx. expand_expr ( p. parse_expr ( ) ) ) ;
630+ es. push ( cx. expander ( ) . fold_expr ( p. parse_expr ( ) ) ) ;
631631 if p. eat ( & token:: COMMA ) {
632632 continue ;
633633 }
@@ -642,10 +642,13 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
642642/// In order to have some notion of scoping for macros,
643643/// we want to implement the notion of a transformation
644644/// environment.
645-
645+ ///
646646/// This environment maps Names to SyntaxExtensions.
647+ pub struct SyntaxEnv {
648+ chain : Vec < MapChainFrame > ,
649+ }
647650
648- //impl question: how to implement it? Initially, the
651+ // impl question: how to implement it? Initially, the
649652// env will contain only macros, so it might be painful
650653// to add an empty frame for every context. Let's just
651654// get it working, first....
@@ -657,15 +660,11 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
657660
658661struct MapChainFrame {
659662 info : BlockInfo ,
660- map : HashMap < Name , SyntaxExtension > ,
661- }
662-
663- pub struct SyntaxEnv {
664- chain : Vec < MapChainFrame > ,
663+ map : HashMap < Name , Rc < SyntaxExtension > > ,
665664}
666665
667666impl SyntaxEnv {
668- pub fn new ( ) -> SyntaxEnv {
667+ fn new ( ) -> SyntaxEnv {
669668 let mut map = SyntaxEnv { chain : Vec :: new ( ) } ;
670669 map. push_frame ( ) ;
671670 map
@@ -692,18 +691,18 @@ impl SyntaxEnv {
692691 unreachable ! ( )
693692 }
694693
695- pub fn find < ' a > ( & ' a self , k : & Name ) -> Option < & ' a SyntaxExtension > {
694+ pub fn find ( & self , k : & Name ) -> Option < Rc < SyntaxExtension > > {
696695 for frame in self . chain . iter ( ) . rev ( ) {
697696 match frame. map . find ( k) {
698- Some ( v) => return Some ( v) ,
697+ Some ( v) => return Some ( v. clone ( ) ) ,
699698 None => { }
700699 }
701700 }
702701 None
703702 }
704703
705704 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 ) ) ;
707706 }
708707
709708 pub fn info < ' a > ( & ' a mut self ) -> & ' a mut BlockInfo {
0 commit comments