1212
1313use hir;
1414
15+ use std:: collections:: HashMap ;
16+
1517use syntax:: ast:: * ;
1618use syntax:: ptr:: P ;
1719use syntax:: codemap:: { respan, Spanned , Span } ;
1820use syntax:: owned_slice:: OwnedSlice ;
1921use syntax:: parse:: token:: { self , str_to_ident} ;
2022use syntax:: std_inject;
2123
22- pub struct LoweringContext < ' a , ' hir > {
23- // TODO
24- foo : & ' hir i32 ,
25- id_assigner : & ' a NodeIdAssigner ,
24+ use std:: cell:: { Cell , RefCell } ;
25+
26+ pub struct LoweringContext < ' a > {
2627 crate_root : Option < & ' static str > ,
28+ id_cache : RefCell < HashMap < NodeId , NodeId > > ,
29+ id_assigner : & ' a NodeIdAssigner ,
30+ cached_id : Cell < u32 > ,
2731}
2832
29- impl < ' a , ' hir > LoweringContext < ' a , ' hir > {
30- pub fn new ( foo : & ' hir i32 , id_assigner : & ' a NodeIdAssigner , c : & Crate ) -> LoweringContext < ' a , ' hir > {
33+ impl < ' a , ' hir > LoweringContext < ' a > {
34+ pub fn new ( id_assigner : & ' a NodeIdAssigner , c : & Crate ) -> LoweringContext < ' a > {
3135 let crate_root = if std_inject:: no_core ( c) {
3236 None
3337 } else if std_inject:: no_std ( c) {
@@ -37,14 +41,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
3741 } ;
3842
3943 LoweringContext {
40- foo : foo,
41- id_assigner : id_assigner,
4244 crate_root : crate_root,
45+ id_cache : RefCell :: new ( HashMap :: new ( ) ) ,
46+ id_assigner : id_assigner,
47+ cached_id : Cell :: new ( 0 ) ,
4348 }
4449 }
4550
4651 fn next_id ( & self ) -> NodeId {
47- self . id_assigner . next_node_id ( )
52+ let cached = self . cached_id . get ( ) ;
53+ if cached == 0 {
54+ return self . id_assigner . next_node_id ( )
55+ }
56+
57+ self . cached_id . set ( cached + 1 ) ;
58+ cached
4859 }
4960}
5061
@@ -745,6 +756,49 @@ pub fn lower_pat(_lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
745756 } )
746757}
747758
759+ // RAII utility for setting and unsetting the cached id.
760+ struct CachedIdSetter < ' a > {
761+ reset : bool ,
762+ lctx : & ' a LoweringContext < ' a > ,
763+ }
764+
765+ impl < ' a > CachedIdSetter < ' a > {
766+ fn new ( lctx : & ' a LoweringContext , expr_id : NodeId ) -> CachedIdSetter < ' a > {
767+ let id_cache: & mut HashMap < _ , _ > = & mut lctx. id_cache . borrow_mut ( ) ;
768+
769+ if id_cache. contains_key ( & expr_id) {
770+ let cached_id = lctx. cached_id . get ( ) ;
771+ if cached_id == 0 {
772+ // We're entering a node where we need to track ids, but are not
773+ // yet tracking.
774+ lctx. cached_id . set ( id_cache[ & expr_id] ) ;
775+ } else {
776+ // We're already tracking - check that the tracked id is the same
777+ // as the expected id.
778+ assert ! ( cached_id == id_cache[ & expr_id] , "id mismatch" ) ;
779+ }
780+ } else {
781+ id_cache. insert ( expr_id, lctx. id_assigner . peek_node_id ( ) ) ;
782+ }
783+
784+ CachedIdSetter {
785+ // Only reset the id if it was previously 0, i.e., was not cached.
786+ // If it was cached, we are in a nested node, but our id count will
787+ // still count towards the parent's count.
788+ reset : lctx. cached_id . get ( ) == 0 ,
789+ lctx : lctx,
790+ }
791+ }
792+ }
793+
794+ impl < ' a > Drop for CachedIdSetter < ' a > {
795+ fn drop ( & mut self ) {
796+ if self . reset {
797+ self . lctx . cached_id . set ( 0 ) ;
798+ }
799+ }
800+ }
801+
748802pub fn lower_expr ( lctx : & LoweringContext , e : & Expr ) -> P < hir:: Expr > {
749803 P ( hir:: Expr {
750804 id : e. id ,
@@ -780,9 +834,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
780834 // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
781835 // InPlace::finalize(place)
782836 // })
783-
784- // TODO
785- println ! ( "{}" , lctx. foo) ;
837+ let _old_cached = CachedIdSetter :: new ( lctx, e. id ) ;
786838
787839 let placer_expr = lower_expr ( lctx, placer) ;
788840 let value_expr = lower_expr ( lctx, value_expr) ;
@@ -903,6 +955,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
903955 // might be `if let`.
904956 ExprIf ( ref cond, ref blk, ref else_opt) => {
905957 let else_opt = else_opt. as_ref ( ) . map ( |els| match els. node {
958+ let _old_cached = CachedIdSetter :: new ( lctx, e. id ) ;
906959 ExprIfLet ( ..) => {
907960 // wrap the if-let expr in a block
908961 let span = els. span ;
@@ -1019,6 +1072,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
10191072 // [_ if <else_opt_if_cond> => <else_opt_if_body>,]
10201073 // _ => [<else_opt> | ()]
10211074 // }
1075+
1076+ let _old_cached = CachedIdSetter :: new ( lctx, e. id ) ;
10221077
10231078 // `<pat> => <body>`
10241079 let pat_arm = {
@@ -1098,6 +1153,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
10981153 // }
10991154 // }
11001155
1156+ let _old_cached = CachedIdSetter :: new ( lctx, e. id ) ;
1157+
11011158 // `<pat> => <body>`
11021159 let pat_arm = {
11031160 let body_expr = expr_block ( lctx, lower_block ( lctx, body) ) ;
@@ -1141,6 +1198,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
11411198 // result
11421199 // }
11431200
1201+ let _old_cached = CachedIdSetter :: new ( lctx, e. id ) ;
1202+
11441203 // expand <head>
11451204 let head = lower_expr ( lctx, head) ;
11461205
0 commit comments