@@ -24,6 +24,7 @@ use parse::parser;
24
24
use parse:: token;
25
25
use parse:: token:: { InternedString , intern, str_to_ident} ;
26
26
use ptr:: P ;
27
+ use std_inject;
27
28
use util:: small_vector:: SmallVector ;
28
29
use util:: lev_distance:: find_best_match_for_name;
29
30
use fold:: Folder ;
@@ -463,19 +464,6 @@ pub enum SyntaxExtension {
463
464
464
465
pub type NamedSyntaxExtension = ( Name , SyntaxExtension ) ;
465
466
466
- pub struct BlockInfo {
467
- /// Should macros escape from this scope?
468
- pub macros_escape : bool ,
469
- }
470
-
471
- impl BlockInfo {
472
- pub fn new ( ) -> BlockInfo {
473
- BlockInfo {
474
- macros_escape : false ,
475
- }
476
- }
477
- }
478
-
479
467
/// The base map of methods for expanding syntax extension
480
468
/// AST nodes into full ASTs
481
469
fn initial_syntax_expander_table < ' feat > ( ecfg : & expand:: ExpansionConfig < ' feat > )
@@ -586,38 +574,29 @@ pub struct ExtCtxt<'a> {
586
574
pub crate_root : Option < & ' static str > ,
587
575
pub loader : & ' a mut MacroLoader ,
588
576
589
- pub mod_path : Vec < ast:: Ident > ,
590
577
pub exported_macros : Vec < ast:: MacroDef > ,
591
578
592
579
pub syntax_env : SyntaxEnv ,
593
580
pub derive_modes : HashMap < InternedString , Box < MultiItemModifier > > ,
594
581
pub recursion_count : usize ,
595
-
596
- pub directory : PathBuf ,
597
- pub in_block : bool ,
598
582
}
599
583
600
584
impl < ' a > ExtCtxt < ' a > {
601
585
pub fn new ( parse_sess : & ' a parse:: ParseSess , cfg : ast:: CrateConfig ,
602
586
ecfg : expand:: ExpansionConfig < ' a > ,
603
587
loader : & ' a mut MacroLoader )
604
588
-> ExtCtxt < ' a > {
605
- let env = initial_syntax_expander_table ( & ecfg) ;
606
589
ExtCtxt {
590
+ syntax_env : initial_syntax_expander_table ( & ecfg) ,
607
591
parse_sess : parse_sess,
608
592
cfg : cfg,
609
593
backtrace : NO_EXPANSION ,
610
- mod_path : Vec :: new ( ) ,
611
594
ecfg : ecfg,
612
595
crate_root : None ,
613
596
exported_macros : Vec :: new ( ) ,
614
597
loader : loader,
615
- syntax_env : env,
616
598
derive_modes : HashMap :: new ( ) ,
617
599
recursion_count : 0 ,
618
-
619
- directory : PathBuf :: new ( ) ,
620
- in_block : false ,
621
600
}
622
601
}
623
602
@@ -666,14 +645,6 @@ impl<'a> ExtCtxt<'a> {
666
645
last_macro. expect ( "missing expansion backtrace" )
667
646
}
668
647
669
- pub fn mod_push ( & mut self , i : ast:: Ident ) { self . mod_path . push ( i) ; }
670
- pub fn mod_pop ( & mut self ) { self . mod_path . pop ( ) . unwrap ( ) ; }
671
- pub fn mod_path ( & self ) -> Vec < ast:: Ident > {
672
- let mut v = Vec :: new ( ) ;
673
- v. push ( token:: str_to_ident ( & self . ecfg . crate_name ) ) ;
674
- v. extend ( self . mod_path . iter ( ) . cloned ( ) ) ;
675
- return v;
676
- }
677
648
pub fn bt_push ( & mut self , ei : ExpnInfo ) {
678
649
self . recursion_count += 1 ;
679
650
if self . recursion_count > self . ecfg . recursion_limit {
@@ -818,6 +789,30 @@ impl<'a> ExtCtxt<'a> {
818
789
}
819
790
}
820
791
}
792
+
793
+ pub fn initialize ( & mut self , user_exts : Vec < NamedSyntaxExtension > , krate : & ast:: Crate ) {
794
+ if std_inject:: no_core ( & krate) {
795
+ self . crate_root = None ;
796
+ } else if std_inject:: no_std ( & krate) {
797
+ self . crate_root = Some ( "core" ) ;
798
+ } else {
799
+ self . crate_root = Some ( "std" ) ;
800
+ }
801
+
802
+ // User extensions must be added before expander.load_macros is called,
803
+ // so that macros from external crates shadow user defined extensions.
804
+ for ( name, extension) in user_exts {
805
+ self . syntax_env . insert ( name, extension) ;
806
+ }
807
+
808
+ self . syntax_env . current_module = Module ( 0 ) ;
809
+ let mut paths = ModulePaths {
810
+ mod_path : vec ! [ token:: str_to_ident( & self . ecfg. crate_name) ] ,
811
+ directory : PathBuf :: from ( self . parse_sess . codemap ( ) . span_to_filename ( krate. span ) ) ,
812
+ } ;
813
+ paths. directory . pop ( ) ;
814
+ self . syntax_env . module_data [ 0 ] . paths = Rc :: new ( paths) ;
815
+ }
821
816
}
822
817
823
818
/// Extract a string literal from the macro expanded version of `expr`,
@@ -904,79 +899,103 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
904
899
///
905
900
/// This environment maps Names to SyntaxExtensions.
906
901
pub struct SyntaxEnv {
907
- chain : Vec < MapChainFrame > ,
902
+ module_data : Vec < ModuleData > ,
903
+ current_module : Module ,
904
+
908
905
/// All bang-style macro/extension names
909
906
/// encountered so far; to be used for diagnostics in resolve
910
907
pub names : HashSet < Name > ,
911
908
}
912
909
913
- // impl question: how to implement it? Initially, the
914
- // env will contain only macros, so it might be painful
915
- // to add an empty frame for every context. Let's just
916
- // get it working, first....
910
+ #[ derive( Copy , Clone , PartialEq , Eq ) ]
911
+ pub struct Module ( u32 ) ;
917
912
918
- // NB! the mutability of the underlying maps means that
919
- // if expansion is out-of-order, a deeper scope may be
920
- // able to refer to a macro that was added to an enclosing
921
- // scope lexically later than the deeper scope.
913
+ struct ModuleData {
914
+ parent : Module ,
915
+ paths : Rc < ModulePaths > ,
916
+ macros : HashMap < Name , Rc < SyntaxExtension > > ,
917
+ macros_escape : bool ,
918
+ in_block : bool ,
919
+ }
922
920
923
- struct MapChainFrame {
924
- info : BlockInfo ,
925
- map : HashMap < Name , Rc < SyntaxExtension > > ,
921
+ #[ derive( Clone ) ]
922
+ pub struct ModulePaths {
923
+ pub mod_path : Vec < ast:: Ident > ,
924
+ pub directory : PathBuf ,
926
925
}
927
926
928
927
impl SyntaxEnv {
929
928
fn new ( ) -> SyntaxEnv {
930
- let mut map = SyntaxEnv { chain : Vec :: new ( ) , names : HashSet :: new ( ) } ;
931
- map. push_frame ( ) ;
932
- map
929
+ let mut env = SyntaxEnv {
930
+ current_module : Module ( 0 ) ,
931
+ module_data : Vec :: new ( ) ,
932
+ names : HashSet :: new ( ) ,
933
+ } ;
934
+ let paths = Rc :: new ( ModulePaths { mod_path : Vec :: new ( ) , directory : PathBuf :: new ( ) } ) ;
935
+ env. add_module ( false , false , paths) ;
936
+ env
933
937
}
934
938
935
- pub fn push_frame ( & mut self ) {
936
- self . chain . push ( MapChainFrame {
937
- info : BlockInfo :: new ( ) ,
938
- map : HashMap :: new ( ) ,
939
- } ) ;
939
+ fn data ( & self , module : Module ) -> & ModuleData {
940
+ & self . module_data [ module. 0 as usize ]
940
941
}
941
942
942
- pub fn pop_frame ( & mut self ) {
943
- assert ! ( self . chain. len( ) > 1 , "too many pops on MapChain!" ) ;
944
- self . chain . pop ( ) ;
943
+ pub fn set_current_module ( & mut self , module : Module ) -> Module {
944
+ :: std:: mem:: replace ( & mut self . current_module , module)
945
945
}
946
946
947
- fn find_escape_frame ( & mut self ) -> & mut MapChainFrame {
948
- for ( i, frame) in self . chain . iter_mut ( ) . enumerate ( ) . rev ( ) {
949
- if !frame. info . macros_escape || i == 0 {
950
- return frame
951
- }
952
- }
953
- unreachable ! ( )
947
+ pub fn paths ( & self ) -> Rc < ModulePaths > {
948
+ self . data ( self . current_module ) . paths . clone ( )
949
+ }
950
+
951
+ pub fn in_block ( & self ) -> bool {
952
+ self . data ( self . current_module ) . in_block
954
953
}
955
954
956
- pub fn find ( & self , k : Name ) -> Option < Rc < SyntaxExtension > > {
957
- for frame in self . chain . iter ( ) . rev ( ) {
958
- if let Some ( v) = frame. map . get ( & k) {
959
- return Some ( v. clone ( ) ) ;
955
+ pub fn add_module ( & mut self , macros_escape : bool , in_block : bool , paths : Rc < ModulePaths > )
956
+ -> Module {
957
+ let data = ModuleData {
958
+ parent : self . current_module ,
959
+ paths : paths,
960
+ macros : HashMap :: new ( ) ,
961
+ macros_escape : macros_escape,
962
+ in_block : in_block,
963
+ } ;
964
+
965
+ self . module_data . push ( data) ;
966
+ Module ( self . module_data . len ( ) as u32 - 1 )
967
+ }
968
+
969
+ pub fn find ( & self , name : Name ) -> Option < Rc < SyntaxExtension > > {
970
+ let mut module = self . current_module ;
971
+ let mut module_data;
972
+ loop {
973
+ module_data = self . data ( module) ;
974
+ if let Some ( ext) = module_data. macros . get ( & name) {
975
+ return Some ( ext. clone ( ) ) ;
960
976
}
977
+ if module == module_data. parent {
978
+ return None ;
979
+ }
980
+ module = module_data. parent ;
961
981
}
962
- None
963
982
}
964
983
965
- pub fn insert ( & mut self , k : Name , v : SyntaxExtension ) {
966
- if let NormalTT ( ..) = v {
967
- self . names . insert ( k ) ;
984
+ pub fn insert ( & mut self , name : Name , ext : SyntaxExtension ) {
985
+ if let NormalTT ( ..) = ext {
986
+ self . names . insert ( name ) ;
968
987
}
969
- self . find_escape_frame ( ) . map . insert ( k, Rc :: new ( v) ) ;
970
- }
971
988
972
- pub fn info ( & mut self ) -> & mut BlockInfo {
973
- let last_chain_index = self . chain . len ( ) - 1 ;
974
- & mut self . chain [ last_chain_index] . info
989
+ let mut module = self . current_module ;
990
+ while self . data ( module) . macros_escape {
991
+ module = self . data ( module) . parent ;
992
+ }
993
+ self . module_data [ module. 0 as usize ] . macros . insert ( name, Rc :: new ( ext) ) ;
975
994
}
976
995
977
996
pub fn is_crate_root ( & mut self ) -> bool {
978
997
// The first frame is pushed in `SyntaxEnv::new()` and the second frame is
979
998
// pushed when folding the crate root pseudo-module (c.f. noop_fold_crate).
980
- self . chain . len ( ) <= 2
999
+ self . current_module . 0 <= 1
981
1000
}
982
1001
}
0 commit comments