@@ -15,6 +15,7 @@ use codemap::{span, spanned};
15
15
use parse:: token;
16
16
use visit;
17
17
use opt_vec;
18
+ use core:: hashmap:: HashMap ;
18
19
19
20
use core:: to_bytes;
20
21
@@ -577,22 +578,61 @@ pub enum Privacy {
577
578
// HYGIENE FUNCTIONS
578
579
579
580
/// Construct an identifier with the given repr and an empty context:
580
- pub fn mk_ident ( repr : uint ) -> ident { ident { repr : repr, ctxt : 0 } }
581
+ pub fn new_ident ( repr : uint ) -> ident { ident { repr : repr, ctxt : 0 } }
581
582
582
583
/// Extend a syntax context with a given mark
583
- pub fn mk_mark ( m : Mrk , ctxt : SyntaxContext , table : & mut SCTable )
584
+ pub fn new_mark ( m : Mrk , tail : SyntaxContext , table : & mut SCTable )
584
585
-> SyntaxContext {
585
- idx_push ( table, Mark ( m, ctxt) )
586
+ let key = ( tail, m) ;
587
+ // FIXME #5074 : can't use more natural style because we're missing
588
+ // flow-sensitivity. Results in two lookups on a hash table hit.
589
+ // also applies to new_rename, below.
590
+ // let try_lookup = table.mark_memo.find(&key);
591
+ match table. mark_memo . contains_key ( & key) {
592
+ false => {
593
+ let new_idx = idx_push ( & mut table. table , Mark ( m, tail) ) ;
594
+ table. mark_memo . insert ( key, new_idx) ;
595
+ new_idx
596
+ }
597
+ true => {
598
+ match table. mark_memo . find ( & key) {
599
+ None => fail ! ( ~"internal error: key disappeared 2013042901 "),
600
+ Some(idxptr) => {*idxptr}
601
+ }
602
+ }
603
+ }
586
604
}
587
605
588
606
/// Extend a syntax context with a given rename
589
- pub fn mk_rename ( id : ident , to : Name , tail : SyntaxContext , table : & mut SCTable )
607
+ pub fn new_rename (id:ident, to:Name, tail:SyntaxContext, table: &mut SCTable)
590
608
-> SyntaxContext {
591
- idx_push ( table, Rename ( id, to, tail) )
609
+ let key = (tail,id,to);
610
+ // FIXME #5074
611
+ //let try_lookup = table.rename_memo.find(&key);
612
+ match table.rename_memo.contains_key(&key) {
613
+ false => {
614
+ let new_idx = idx_push(&mut table.table,Rename(id,to,tail));
615
+ table.rename_memo.insert(key,new_idx);
616
+ new_idx
617
+ }
618
+ true => {
619
+ match table.rename_memo.find(&key) {
620
+ None => fail!(~" internal error: key disappeared 2013042902 "),
621
+ Some(idxptr) => {*idxptr}
622
+ }
623
+ }
624
+ }
592
625
}
593
626
594
627
/// Make a fresh syntax context table with EmptyCtxt in slot zero
595
- pub fn mk_sctable ( ) -> SCTable { ~[ EmptyCtxt ] }
628
+ /// and IllegalCtxt in slot one.
629
+ pub fn new_sctable() -> SCTable {
630
+ SCTable {
631
+ table: ~[EmptyCtxt,IllegalCtxt],
632
+ mark_memo: HashMap::new(),
633
+ rename_memo: HashMap::new()
634
+ }
635
+ }
596
636
597
637
/// Add a value to the end of a vec, return its index
598
638
fn idx_push<T>(vec: &mut ~[T], val: T) -> uint {
@@ -601,8 +641,8 @@ fn idx_push<T>(vec: &mut ~[T], val: T) -> uint {
601
641
}
602
642
603
643
/// Resolve a syntax object to a name, per MTWT.
604
- pub fn resolve ( id : ident , table : & SCTable ) -> Name {
605
- match table[ id. ctxt ] {
644
+ pub fn resolve (id : ident, table : &mut SCTable) -> Name {
645
+ match table.table [id.ctxt] {
606
646
EmptyCtxt => id.repr,
607
647
// ignore marks here:
608
648
Mark(_,subctxt) => resolve (ident{repr:id.repr, ctxt: subctxt},table),
@@ -619,6 +659,7 @@ pub fn resolve (id : ident, table : &SCTable) -> Name {
619
659
resolvedthis
620
660
}
621
661
}
662
+ IllegalCtxt() => fail!(~" expected resolvable context, got IllegalCtxt ")
622
663
}
623
664
}
624
665
@@ -629,7 +670,7 @@ pub fn marksof(ctxt: SyntaxContext, stopname: Name, table: &SCTable) -> ~[Mrk] {
629
670
let mut result = ~[];
630
671
let mut loopvar = ctxt;
631
672
loop {
632
- match table[ loopvar] {
673
+ match table.table [loopvar] {
633
674
EmptyCtxt => {return result;},
634
675
Mark(mark,tl) => {
635
676
xorPush(&mut result,mark);
@@ -644,6 +685,7 @@ pub fn marksof(ctxt: SyntaxContext, stopname: Name, table: &SCTable) -> ~[Mrk] {
644
685
loopvar = tl;
645
686
}
646
687
}
688
+ IllegalCtxt => fail!(~" expected resolvable context, got IllegalCtxt ")
647
689
}
648
690
}
649
691
}
@@ -713,15 +755,15 @@ mod test {
713
755
-> SyntaxContext {
714
756
tscs.foldr(tail, |tsc : &TestSC,tail : SyntaxContext|
715
757
{match *tsc {
716
- M ( mrk) => mk_mark ( mrk, tail, table) ,
717
- R ( ident, name) => mk_rename ( ident, name, tail, table) } } )
758
+ M(mrk) => new_mark (mrk,tail,table),
759
+ R(ident,name) => new_rename (ident,name,tail,table)}})
718
760
}
719
761
720
762
// gather a SyntaxContext back into a vector of TestSCs
721
763
fn refold_test_sc(mut sc: SyntaxContext, table : &SCTable) -> ~[TestSC] {
722
764
let mut result = ~[];
723
765
loop {
724
- match table[ sc] {
766
+ match table.table [sc] {
725
767
EmptyCtxt => {return result;},
726
768
Mark(mrk,tail) => {
727
769
result.push(M(mrk));
@@ -733,40 +775,41 @@ mod test {
733
775
sc = tail;
734
776
loop;
735
777
}
778
+ IllegalCtxt => fail!(" expected resolvable context, got IllegalCtxt ")
736
779
}
737
780
}
738
781
}
739
782
740
783
#[test] fn test_unfold_refold(){
741
- let mut t = mk_sctable ( ) ;
784
+ let mut t = new_sctable ();
742
785
743
786
let test_sc = ~[M(3),R(id(101,0),14),M(9)];
744
- assert_eq ! ( unfold_test_sc( copy test_sc, empty_ctxt, & mut t) , 3 ) ;
745
- assert_eq ! ( t[ 1 ] , Mark ( 9 , 0 ) ) ;
746
- assert_eq ! ( t[ 2 ] , Rename ( id( 101 , 0 ) , 14 , 1 ) ) ;
747
- assert_eq ! ( t[ 3 ] , Mark ( 3 , 2 ) ) ;
748
- assert_eq ! ( refold_test_sc( 3 , & t) , test_sc) ;
787
+ assert_eq!(unfold_test_sc(copy test_sc,empty_ctxt,&mut t),4 );
788
+ assert_eq!(t.table[2 ],Mark(9,0));
789
+ assert_eq!(t.table[3 ],Rename(id(101,0),14,2 ));
790
+ assert_eq!(t.table[4 ],Mark(3,3 ));
791
+ assert_eq!(refold_test_sc(4 ,&t),test_sc);
749
792
}
750
793
751
794
// extend a syntax context with a sequence of marks given
752
795
// in a vector. v[0] will be the outermost mark.
753
796
fn unfold_marks(mrks:~[Mrk],tail:SyntaxContext,table: &mut SCTable) -> SyntaxContext {
754
797
mrks.foldr(tail, |mrk:&Mrk,tail:SyntaxContext|
755
- { mk_mark ( * mrk, tail, table) } )
798
+ {new_mark (*mrk,tail,table)})
756
799
}
757
800
758
801
#[test] fn unfold_marks_test() {
759
- let mut t = ~ [ EmptyCtxt ] ;
802
+ let mut t = new_sctable() ;
760
803
761
- assert_eq ! ( unfold_marks( ~[ 3 , 7 ] , empty_ctxt, & mut t) , 2 ) ;
762
- assert_eq ! ( t[ 1 ] , Mark ( 7 , 0 ) ) ;
763
- assert_eq ! ( t[ 2 ] , Mark ( 3 , 1 ) ) ;
804
+ assert_eq!(unfold_marks(~[3,7],empty_ctxt,&mut t),3 );
805
+ assert_eq!(t.table[2 ],Mark(7,0));
806
+ assert_eq!(t.table[3 ],Mark(3,2 ));
764
807
}
765
808
766
809
#[test] fn test_marksof () {
767
810
let stopname = 242;
768
811
let name1 = 243;
769
- let mut t = mk_sctable ( ) ;
812
+ let mut t = new_sctable ();
770
813
assert_eq!(marksof (empty_ctxt,stopname,&t),~[]);
771
814
// FIXME #5074: ANF'd to dodge nested calls
772
815
{ let ans = unfold_marks(~[4,98],empty_ctxt,&mut t);
@@ -780,13 +823,13 @@ mod test {
780
823
// rename where stop doesn't match:
781
824
{ let chain = ~[M(9),
782
825
R(id(name1,
783
- mk_mark ( 4 , empty_ctxt, & mut t) ) ,
826
+ new_mark (4, empty_ctxt,&mut t)),
784
827
100101102),
785
828
M(14)];
786
829
let ans = unfold_test_sc(chain,empty_ctxt,&mut t);
787
830
assert_eq! (marksof (ans, stopname, &t), ~[9,14]);}
788
831
// rename where stop does match
789
- { let name1sc = mk_mark ( 4 , empty_ctxt, & mut t) ;
832
+ { let name1sc = new_mark (4, empty_ctxt, &mut t);
790
833
let chain = ~[M(9),
791
834
R(id(name1, name1sc),
792
835
stopname),
@@ -798,51 +841,60 @@ mod test {
798
841
799
842
#[test] fn resolve_tests () {
800
843
let a = 40;
801
- let mut t = mk_sctable ( ) ;
844
+ let mut t = new_sctable ();
802
845
// - ctxt is MT
803
- assert_eq ! ( resolve( id( a, empty_ctxt) , & t) , a) ;
846
+ assert_eq!(resolve(id(a,empty_ctxt),&mut t),a);
804
847
// - simple ignored marks
805
848
{ let sc = unfold_marks(~[1,2,3],empty_ctxt,&mut t);
806
- assert_eq ! ( resolve( id( a, sc) , & t) , a) ; }
849
+ assert_eq!(resolve(id(a,sc),&mut t),a);}
807
850
// - orthogonal rename where names don't match
808
851
{ let sc = unfold_test_sc(~[R(id(50,empty_ctxt),51),M(12)],empty_ctxt,&mut t);
809
- assert_eq ! ( resolve( id( a, sc) , & t) , a) ; }
852
+ assert_eq!(resolve(id(a,sc),&mut t),a);}
810
853
// - rename where names do match, but marks don't
811
- { let sc1 = mk_mark ( 1 , empty_ctxt, & mut t) ;
854
+ { let sc1 = new_mark (1,empty_ctxt,&mut t);
812
855
let sc = unfold_test_sc(~[R(id(a,sc1),50),
813
856
M(1),
814
857
M(2)],
815
858
empty_ctxt,&mut t);
816
- assert_eq ! ( resolve( id( a, sc) , & t) , a) ; }
859
+ assert_eq!(resolve(id(a,sc),&mut t), a);}
817
860
// - rename where names and marks match
818
861
{ let sc1 = unfold_test_sc(~[M(1),M(2)],empty_ctxt,&mut t);
819
862
let sc = unfold_test_sc(~[R(id(a,sc1),50),M(1),M(2)],empty_ctxt,&mut t);
820
- assert_eq ! ( resolve( id( a, sc) , & t) , 50 ) ; }
863
+ assert_eq!(resolve(id(a,sc),&mut t), 50); }
821
864
// - rename where names and marks match by literal sharing
822
865
{ let sc1 = unfold_test_sc(~[M(1),M(2)],empty_ctxt,&mut t);
823
866
let sc = unfold_test_sc(~[R(id(a,sc1),50)],sc1,&mut t);
824
- assert_eq ! ( resolve( id( a, sc) , & t) , 50 ) ; }
867
+ assert_eq!(resolve(id(a,sc),&mut t), 50); }
825
868
// - two renames of the same var.. can only happen if you use
826
869
// local-expand to prevent the inner binding from being renamed
827
870
// during the rename-pass caused by the first:
828
871
io::println(" about to run bad test") ;
829
872
{ let sc = unfold_test_sc( ~[ R ( id( a, empty_ctxt) , 50 ) ,
830
873
R ( id( a, empty_ctxt) , 51 ) ] ,
831
874
empty_ctxt, & mut t) ;
832
- assert_eq ! ( resolve( id( a, sc) , & t) , 51 ) ; }
875
+ assert_eq!( resolve( id( a, sc) , & mut t) , 51 ) ; }
833
876
// the simplest double-rename:
834
- { let a_to_a50 = mk_rename ( id ( a, empty_ctxt) , 50 , empty_ctxt, & mut t) ;
835
- let a50_to_a51 = mk_rename ( id ( a, a_to_a50) , 51 , a_to_a50, & mut t) ;
836
- assert_eq ! ( resolve( id( a, a50_to_a51) , & t) , 51 ) ;
877
+ { let a_to_a50 = new_rename ( id( a, empty_ctxt) , 50 , empty_ctxt, & mut t) ;
878
+ let a50_to_a51 = new_rename ( id( a, a_to_a50) , 51 , a_to_a50, & mut t) ;
879
+ assert_eq!( resolve( id( a, a50_to_a51) , & mut t) , 51 ) ;
837
880
// mark on the outside doesn't stop rename:
838
- let sc = mk_mark ( 9 , a50_to_a51, & mut t) ;
839
- assert_eq ! ( resolve( id( a, sc) , & t) , 51 ) ;
881
+ let sc = new_mark ( 9 , a50_to_a51, & mut t) ;
882
+ assert_eq!( resolve( id( a, sc) , & mut t) , 51 ) ;
840
883
// but mark on the inside does:
841
884
let a50_to_a51_b = unfold_test_sc( ~[ R ( id( a, a_to_a50) , 51 ) ,
842
885
M ( 9 ) ] ,
843
886
a_to_a50,
844
887
& mut t) ;
845
- assert_eq ! ( resolve( id( a, a50_to_a51_b) , & t) , 50 ) ; }
888
+ assert_eq!( resolve( id( a, a50_to_a51_b) , & mut t) , 50 ) ; }
889
+ }
890
+
891
+ #[ test] fn hashing_tests ( ) {
892
+ let mut t = new_sctable ( ) ;
893
+ assert_eq ! ( new_mark( 12 , empty_ctxt, & mut t) , 2 ) ;
894
+ assert_eq ! ( new_mark( 13 , empty_ctxt, & mut t) , 3 ) ;
895
+ // using the same one again should result in the same index:
896
+ assert_eq ! ( new_mark( 12 , empty_ctxt, & mut t) , 2 ) ;
897
+ // I'm assuming that the rename table will behave the same....
846
898
}
847
899
848
900
}
0 commit comments