15
15
use ast:: Name ;
16
16
17
17
use std:: borrow:: Borrow ;
18
- use std:: cell:: RefCell ;
19
18
use std:: collections:: HashMap ;
20
19
use std:: rc:: Rc ;
21
20
@@ -28,85 +27,60 @@ impl Borrow<str> for RcStr {
28
27
}
29
28
}
30
29
30
+ #[ derive( Default ) ]
31
31
pub struct Interner {
32
- map : RefCell < HashMap < RcStr , Name > > ,
33
- vect : RefCell < Vec < Rc < String > > > ,
32
+ names : HashMap < RcStr , Name > ,
33
+ strings : Vec < Rc < String > > ,
34
34
}
35
35
36
36
/// When traits can extend traits, we should extend index<Name,T> to get []
37
37
impl Interner {
38
38
pub fn new ( ) -> Self {
39
- Interner {
40
- map : RefCell :: new ( HashMap :: new ( ) ) ,
41
- vect : RefCell :: new ( Vec :: new ( ) ) ,
42
- }
39
+ Interner :: default ( )
43
40
}
44
41
45
42
pub fn prefill ( init : & [ & str ] ) -> Self {
46
- let rv = Interner :: new ( ) ;
47
- for & v in init { rv. intern ( v) ; }
48
- rv
49
- }
50
-
51
- pub fn intern < T : Borrow < str > + Into < String > > ( & self , val : T ) -> Name {
52
- let mut map = self . map . borrow_mut ( ) ;
53
- if let Some ( & idx) = map. get ( val. borrow ( ) ) {
54
- return idx;
43
+ let mut this = Interner :: new ( ) ;
44
+ for & string in init {
45
+ this. intern ( string) ;
55
46
}
56
-
57
- let new_idx = Name ( self . len ( ) as u32 ) ;
58
- let val = Rc :: new ( val. into ( ) ) ;
59
- map. insert ( RcStr ( val. clone ( ) ) , new_idx) ;
60
- self . vect . borrow_mut ( ) . push ( val) ;
61
- new_idx
47
+ this
62
48
}
63
49
64
- pub fn gensym ( & self , val : & str ) -> Name {
65
- let new_idx = Name ( self . len ( ) as u32 ) ;
66
- // leave out of .map to avoid colliding
67
- self . vect . borrow_mut ( ) . push ( Rc :: new ( val. to_owned ( ) ) ) ;
68
- new_idx
69
- }
70
-
71
- // I want these gensyms to share name pointers
72
- // with existing entries. This would be automatic,
73
- // except that the existing gensym creates its
74
- // own managed ptr using to_managed. I think that
75
- // adding this utility function is the most
76
- // lightweight way to get what I want, though not
77
- // necessarily the cleanest.
78
-
79
- /// Create a gensym with the same name as an existing
80
- /// entry.
81
- pub fn gensym_copy ( & self , idx : Name ) -> Name {
82
- let new_idx = Name ( self . len ( ) as u32 ) ;
83
- // leave out of map to avoid colliding
84
- let mut vect = self . vect . borrow_mut ( ) ;
85
- let existing = ( * vect) [ idx. 0 as usize ] . clone ( ) ;
86
- vect. push ( existing) ;
87
- new_idx
88
- }
50
+ pub fn intern < T : Borrow < str > + Into < String > > ( & mut self , string : T ) -> Name {
51
+ if let Some ( & name) = self . names . get ( string. borrow ( ) ) {
52
+ return name;
53
+ }
89
54
90
- pub fn get ( & self , idx : Name ) -> Rc < String > {
91
- ( * self . vect . borrow ( ) ) [ idx. 0 as usize ] . clone ( )
55
+ let name = Name ( self . strings . len ( ) as u32 ) ;
56
+ let string = Rc :: new ( string. into ( ) ) ;
57
+ self . strings . push ( string. clone ( ) ) ;
58
+ self . names . insert ( RcStr ( string) , name) ;
59
+ name
92
60
}
93
61
94
- pub fn len ( & self ) -> usize {
95
- self . vect . borrow ( ) . len ( )
62
+ pub fn gensym ( & mut self , string : & str ) -> Name {
63
+ let gensym = Name ( self . strings . len ( ) as u32 ) ;
64
+ // leave out of `names` to avoid colliding
65
+ self . strings . push ( Rc :: new ( string. to_owned ( ) ) ) ;
66
+ gensym
96
67
}
97
68
98
- pub fn find ( & self , val : & str ) -> Option < Name > {
99
- self . map . borrow ( ) . get ( val) . cloned ( )
69
+ /// Create a gensym with the same name as an existing entry.
70
+ pub fn gensym_copy ( & mut self , name : Name ) -> Name {
71
+ let gensym = Name ( self . strings . len ( ) as u32 ) ;
72
+ // leave out of `names` to avoid colliding
73
+ let string = self . strings [ name. 0 as usize ] . clone ( ) ;
74
+ self . strings . push ( string) ;
75
+ gensym
100
76
}
101
77
102
- pub fn clear ( & self ) {
103
- * self . map . borrow_mut ( ) = HashMap :: new ( ) ;
104
- * self . vect . borrow_mut ( ) = Vec :: new ( ) ;
78
+ pub fn get ( & self , name : Name ) -> Rc < String > {
79
+ self . strings [ name. 0 as usize ] . clone ( )
105
80
}
106
81
107
- pub fn reset ( & self , other : Interner ) {
108
- * self . map . borrow_mut ( ) = other. map . into_inner ( ) ;
109
- * self . vect . borrow_mut ( ) = other. vect . into_inner ( ) ;
82
+ pub fn find ( & self , string : & str ) -> Option < Name > {
83
+ self . names . get ( string) . cloned ( )
110
84
}
111
85
}
112
86
@@ -117,7 +91,7 @@ mod tests {
117
91
118
92
#[ test]
119
93
fn interner_tests ( ) {
120
- let i : Interner = Interner :: new ( ) ;
94
+ let mut i : Interner = Interner :: new ( ) ;
121
95
// first one is zero:
122
96
assert_eq ! ( i. intern( "dog" ) , Name ( 0 ) ) ;
123
97
// re-use gets the same entry:
0 commit comments