@@ -14,6 +14,8 @@ use ast::*;
14
14
use ast;
15
15
use ast_util;
16
16
use codemap:: { span, spanned} ;
17
+ use core:: cast;
18
+ use core:: local_data;
17
19
use opt_vec;
18
20
use parse:: token;
19
21
use visit;
@@ -623,12 +625,18 @@ pub enum Privacy {
623
625
pub fn new_ident( name: Name ) -> ident { ident { name: name, ctxt: 0 } }
624
626
625
627
/// Extend a syntax context with a given mark
626
- pub fn new_mark ( m: Mrk , tail: SyntaxContext , table: & mut SCTable )
628
+ pub fn new_mark( m: Mrk , tail: SyntaxContext ) -> SyntaxContext {
629
+ new_mark_internal( m, tail, get_sctable( ) )
630
+ }
631
+
632
+ // Extend a syntax context with a given mark and table
633
+ // FIXME #4536 : currently pub to allow testing
634
+ pub fn new_mark_internal( m: Mrk , tail: SyntaxContext , table: & mut SCTable )
627
635
-> SyntaxContext {
628
636
let key = ( tail, m) ;
629
637
// FIXME #5074 : can't use more natural style because we're missing
630
638
// flow-sensitivity. Results in two lookups on a hash table hit.
631
- // also applies to new_rename , below.
639
+ // also applies to new_rename_internal , below.
632
640
// let try_lookup = table.mark_memo.find(&key);
633
641
match table. mark_memo. contains_key( & key) {
634
642
false => {
@@ -646,7 +654,13 @@ pub fn new_mark (m:Mrk, tail:SyntaxContext,table:&mut SCTable)
646
654
}
647
655
648
656
/// Extend a syntax context with a given rename
649
- pub fn new_rename (id:ident, to:Name, tail:SyntaxContext, table: &mut SCTable)
657
+ pub fn new_rename(id:ident, to:Name, tail:SyntaxContext) -> SyntaxContext {
658
+ new_rename_internal(id, to, tail, get_sctable())
659
+ }
660
+
661
+ // Extend a syntax context with a given rename and sctable
662
+ // FIXME #4536 : currently pub to allow testing
663
+ pub fn new_rename_internal(id:ident, to:Name, tail:SyntaxContext, table: &mut SCTable)
650
664
-> SyntaxContext {
651
665
let key = (tail,id,to);
652
666
// FIXME #5074
@@ -668,34 +682,58 @@ pub fn new_rename (id:ident, to:Name, tail:SyntaxContext, table: &mut SCTable)
668
682
669
683
/// Make a fresh syntax context table with EmptyCtxt in slot zero
670
684
/// and IllegalCtxt in slot one.
671
- pub fn new_sctable() -> SCTable {
685
+ // FIXME #4536 : currently pub to allow testing
686
+ pub fn new_sctable_internal() -> SCTable {
672
687
SCTable {
673
688
table: ~[EmptyCtxt,IllegalCtxt],
674
689
mark_memo: HashMap::new(),
675
690
rename_memo: HashMap::new()
676
691
}
677
692
}
678
693
694
+ // fetch the SCTable from TLS, create one if it doesn't yet exist.
695
+ pub fn get_sctable() -> @mut SCTable {
696
+ unsafe {
697
+ let sctable_key = (cast::transmute::<(uint, uint),
698
+ &fn(v: @@mut SCTable)>(
699
+ (-4 as uint, 0u)));
700
+ match local_data::local_data_get(sctable_key) {
701
+ None => {
702
+ let new_table = @@mut new_sctable_internal();
703
+ local_data::local_data_set(sctable_key,new_table);
704
+ *new_table
705
+ },
706
+ Some(intr) => *intr
707
+ }
708
+ }
709
+ }
710
+
679
711
/// Add a value to the end of a vec, return its index
680
712
fn idx_push<T>(vec: &mut ~[T], val: T) -> uint {
681
713
vec.push(val);
682
714
vec.len() - 1
683
715
}
684
716
685
717
/// Resolve a syntax object to a name, per MTWT.
686
- pub fn resolve (id : ident, table : &mut SCTable) -> Name {
718
+ pub fn resolve(id : ident) -> Name {
719
+ resolve_internal(id, get_sctable())
720
+ }
721
+
722
+ // Resolve a syntax object to a name, per MTWT.
723
+ // FIXME #4536 : currently pub to allow testing
724
+ pub fn resolve_internal(id : ident, table : &mut SCTable) -> Name {
687
725
match table.table[id.ctxt] {
688
726
EmptyCtxt => id.name,
689
727
// ignore marks here:
690
- Mark(_,subctxt) => resolve (ident{name:id.name, ctxt: subctxt},table),
728
+ Mark(_,subctxt) => resolve_internal (ident{name:id.name, ctxt: subctxt},table),
691
729
// do the rename if necessary:
692
730
Rename(ident{name,ctxt},toname,subctxt) => {
693
731
// this could be cached or computed eagerly:
694
- let resolvedfrom = resolve (ident{name:name,ctxt:ctxt},table);
695
- let resolvedthis = resolve (ident{name:id.name,ctxt:subctxt},table);
732
+ let resolvedfrom = resolve_internal (ident{name:name,ctxt:ctxt},table);
733
+ let resolvedthis = resolve_internal (ident{name:id.name,ctxt:subctxt},table);
696
734
if ((resolvedthis == resolvedfrom)
697
- && (marksof (ctxt,resolvedthis,table)
698
- == marksof (subctxt,resolvedthis,table))) {
735
+ && (marksof(ctxt,resolvedthis,table)
736
+ == marksof(subctxt,resolvedthis,table))) {
699
737
toname
700
738
} else {
701
739
resolvedthis
@@ -797,8 +835,8 @@ mod test {
797
835
-> SyntaxContext {
798
836
tscs.foldr(tail, |tsc : &TestSC,tail : SyntaxContext|
799
837
{match *tsc {
800
- M(mrk) => new_mark (mrk,tail,table),
801
- R(ident,name) => new_rename (ident,name,tail,table)}})
838
+ M(mrk) => new_mark_internal (mrk,tail,table),
839
+ R(ident,name) => new_rename_internal (ident,name,tail,table)}})
802
840
}
803
841
804
842
// gather a SyntaxContext back into a vector of TestSCs
@@ -823,7 +861,7 @@ mod test {
823
861
}
824
862
825
863
#[test] fn test_unfold_refold(){
826
- let mut t = new_sctable ();
864
+ let mut t = new_sctable_internal ();
827
865
828
866
let test_sc = ~[M(3),R(id(101,0),14),M(9)];
829
867
assert_eq!(unfold_test_sc(copy test_sc,empty_ctxt,&mut t),4);
@@ -837,11 +875,11 @@ mod test {
837
875
// in a vector. v[0] will be the outermost mark.
838
876
fn unfold_marks(mrks:~[Mrk],tail:SyntaxContext,table: &mut SCTable) -> SyntaxContext {
839
877
mrks.foldr(tail, |mrk:&Mrk,tail:SyntaxContext|
840
- {new_mark (*mrk,tail,table)})
878
+ {new_mark_internal (*mrk,tail,table)})
841
879
}
842
880
843
881
#[test] fn unfold_marks_test() {
844
- let mut t = new_sctable ();
882
+ let mut t = new_sctable_internal ();
845
883
846
884
assert_eq!(unfold_marks(~[3,7],empty_ctxt,&mut t),3);
847
885
assert_eq!(t.table[2],Mark(7,0));
@@ -851,7 +889,7 @@ mod test {
851
889
#[test] fn test_marksof () {
852
890
let stopname = 242;
853
891
let name1 = 243;
854
- let mut t = new_sctable ();
892
+ let mut t = new_sctable_internal ();
855
893
assert_eq!(marksof (empty_ctxt,stopname,&t),~[]);
856
894
// FIXME #5074: ANF'd to dodge nested calls
857
895
{ let ans = unfold_marks(~[4,98],empty_ctxt,&mut t);
@@ -865,13 +903,13 @@ mod test {
865
903
// rename where stop doesn't match:
866
904
{ let chain = ~[M(9),
867
905
R(id(name1,
868
- new_mark (4, empty_ctxt,&mut t)),
906
+ new_mark_internal (4, empty_ctxt,&mut t)),
869
907
100101102),
870
908
M(14)];
871
909
let ans = unfold_test_sc(chain,empty_ctxt,&mut t);
872
910
assert_eq! (marksof (ans, stopname, &t), ~[9,14]);}
873
911
// rename where stop does match
874
- { let name1sc = new_mark (4, empty_ctxt, &mut t);
912
+ { let name1sc = new_mark_internal (4, empty_ctxt, &mut t);
875
913
let chain = ~[M(9),
876
914
R(id(name1, name1sc),
877
915
stopname),
@@ -883,59 +921,59 @@ mod test {
883
921
884
922
#[test] fn resolve_tests () {
885
923
let a = 40;
886
- let mut t = new_sctable ();
924
+ let mut t = new_sctable_internal ();
887
925
// - ctxt is MT
888
- assert_eq!(resolve (id(a,empty_ctxt),&mut t),a);
926
+ assert_eq!(resolve_internal (id(a,empty_ctxt),&mut t),a);
889
927
// - simple ignored marks
890
928
{ let sc = unfold_marks(~[1,2,3],empty_ctxt,&mut t);
891
- assert_eq!(resolve (id(a,sc),&mut t),a);}
929
+ assert_eq!(resolve_internal (id(a,sc),&mut t),a);}
892
930
// - orthogonal rename where names don't match
893
931
{ let sc = unfold_test_sc(~[R(id(50,empty_ctxt),51),M(12)],empty_ctxt,&mut t);
894
- assert_eq!(resolve (id(a,sc),&mut t),a);}
932
+ assert_eq!(resolve_internal (id(a,sc),&mut t),a);}
895
933
// - rename where names do match, but marks don't
896
- { let sc1 = new_mark (1,empty_ctxt,&mut t);
934
+ { let sc1 = new_mark_internal (1,empty_ctxt,&mut t);
897
935
let sc = unfold_test_sc(~[R(id(a,sc1),50),
898
936
M(1),
899
937
M(2)],
900
938
empty_ctxt,&mut t);
901
- assert_eq!(resolve (id(a,sc),&mut t), a);}
939
+ assert_eq!(resolve_internal (id(a,sc),&mut t), a);}
902
940
// - rename where names and marks match
903
941
{ let sc1 = unfold_test_sc(~[M(1),M(2)],empty_ctxt,&mut t);
904
942
let sc = unfold_test_sc(~[R(id(a,sc1),50),M(1),M(2)],empty_ctxt,&mut t);
905
- assert_eq!(resolve (id(a,sc),&mut t), 50); }
943
+ assert_eq!(resolve_internal (id(a,sc),&mut t), 50); }
906
944
// - rename where names and marks match by literal sharing
907
945
{ let sc1 = unfold_test_sc(~[M(1),M(2)],empty_ctxt,&mut t);
908
946
let sc = unfold_test_sc(~[R(id(a,sc1),50)],sc1,&mut t);
909
- assert_eq!(resolve (id(a,sc),&mut t), 50); }
947
+ assert_eq!(resolve_internal (id(a,sc),&mut t), 50); }
910
948
// - two renames of the same var.. can only happen if you use
911
949
// local-expand to prevent the inner binding from being renamed
912
950
// during the rename-pass caused by the first:
913
951
io::println(" about to run bad test") ;
914
952
{ let sc = unfold_test_sc( ~[ R ( id( a, empty_ctxt) , 50 ) ,
915
953
R ( id( a, empty_ctxt) , 51 ) ] ,
916
954
empty_ctxt, & mut t) ;
917
- assert_eq!( resolve ( id( a, sc) , & mut t) , 51 ) ; }
955
+ assert_eq!( resolve_internal ( id( a, sc) , & mut t) , 51 ) ; }
918
956
// the simplest double-rename:
919
- { let a_to_a50 = new_rename ( id( a, empty_ctxt) , 50 , empty_ctxt, & mut t) ;
920
- let a50_to_a51 = new_rename ( id( a, a_to_a50) , 51 , a_to_a50, & mut t) ;
921
- assert_eq!( resolve ( id( a, a50_to_a51) , & mut t) , 51 ) ;
957
+ { let a_to_a50 = new_rename_internal ( id( a, empty_ctxt) , 50 , empty_ctxt, & mut t) ;
958
+ let a50_to_a51 = new_rename_internal ( id( a, a_to_a50) , 51 , a_to_a50, & mut t) ;
959
+ assert_eq!( resolve_internal ( id( a, a50_to_a51) , & mut t) , 51 ) ;
922
960
// mark on the outside doesn't stop rename:
923
- let sc = new_mark ( 9 , a50_to_a51, & mut t) ;
924
- assert_eq!( resolve ( id( a, sc) , & mut t) , 51 ) ;
961
+ let sc = new_mark_internal ( 9 , a50_to_a51, & mut t) ;
962
+ assert_eq!( resolve_internal ( id( a, sc) , & mut t) , 51 ) ;
925
963
// but mark on the inside does:
926
964
let a50_to_a51_b = unfold_test_sc( ~[ R ( id( a, a_to_a50) , 51 ) ,
927
965
M ( 9 ) ] ,
928
966
a_to_a50,
929
967
& mut t) ;
930
- assert_eq!( resolve ( id( a, a50_to_a51_b) , & mut t) , 50 ) ; }
968
+ assert_eq!( resolve_internal ( id( a, a50_to_a51_b) , & mut t) , 50 ) ; }
931
969
}
932
970
933
971
#[ test] fn hashing_tests ( ) {
934
- let mut t = new_sctable ( ) ;
935
- assert_eq!( new_mark ( 12 , empty_ctxt, & mut t) , 2 ) ;
936
- assert_eq!( new_mark ( 13 , empty_ctxt, & mut t) , 3 ) ;
972
+ let mut t = new_sctable_internal ( ) ;
973
+ assert_eq!( new_mark_internal ( 12 , empty_ctxt, & mut t) , 2 ) ;
974
+ assert_eq!( new_mark_internal ( 13 , empty_ctxt, & mut t) , 3 ) ;
937
975
// using the same one again should result in the same index:
938
- assert_eq!( new_mark ( 12 , empty_ctxt, & mut t) , 2 ) ;
976
+ assert_eq!( new_mark_internal ( 12 , empty_ctxt, & mut t) , 2 ) ;
939
977
// I'm assuming that the rename table will behave the same....
940
978
}
941
979
0 commit comments