@@ -6,17 +6,25 @@ pub struct IntAtomBuf {
6
6
end : u32 ,
7
7
}
8
8
9
- enum NodePtr {
10
- Atom ( IntAtomBuf ) ,
11
- Pair ( u32 , u32 ) ,
9
+ #[ derive( Clone , Copy ) ]
10
+ pub struct IntPair {
11
+ first : i32 ,
12
+ rest : i32 ,
12
13
}
13
14
14
15
pub struct IntAllocator {
15
16
// this is effectively a grow-only stack where atoms are allocated. Atoms
16
17
// are immutable, so once they are created, they will stay around until the
17
18
// program completes
18
19
u8_vec : Vec < u8 > ,
19
- node_vec : Vec < NodePtr > ,
20
+
21
+ // storage for all pairs (positive indices)
22
+ pair_vec : Vec < IntPair > ,
23
+
24
+ // storage for all atoms (negative indices).
25
+ // node index -1 refers to index 0 in this vector, -2 refers to 1 and so
26
+ // on.
27
+ atom_vec : Vec < IntAtomBuf > ,
20
28
}
21
29
22
30
impl Default for IntAllocator {
@@ -29,62 +37,66 @@ impl IntAllocator {
29
37
pub fn new ( ) -> Self {
30
38
let mut r = IntAllocator {
31
39
u8_vec : Vec :: new ( ) ,
32
- node_vec : Vec :: new ( ) ,
40
+ pair_vec : Vec :: new ( ) ,
41
+ atom_vec : Vec :: new ( ) ,
33
42
} ;
34
43
r. u8_vec . reserve ( 1024 * 1024 ) ;
44
+ r. atom_vec . reserve ( 256 ) ;
45
+ r. pair_vec . reserve ( 256 ) ;
35
46
r. u8_vec . push ( 1_u8 ) ;
36
47
// Preallocated empty list
37
- r. node_vec
38
- . push ( NodePtr :: Atom ( IntAtomBuf { start : 0 , end : 0 } ) ) ;
48
+ r. atom_vec . push ( IntAtomBuf { start : 0 , end : 0 } ) ;
39
49
// Preallocated 1
40
- r. node_vec
41
- . push ( NodePtr :: Atom ( IntAtomBuf { start : 0 , end : 1 } ) ) ;
50
+ r. atom_vec . push ( IntAtomBuf { start : 0 , end : 1 } ) ;
42
51
r
43
52
}
44
53
}
45
54
46
55
impl Allocator for IntAllocator {
47
- type Ptr = u32 ;
56
+ type Ptr = i32 ;
48
57
type AtomBuf = IntAtomBuf ;
49
58
50
59
fn new_atom ( & mut self , v : & [ u8 ] ) -> Self :: Ptr {
51
60
let start = self . u8_vec . len ( ) as u32 ;
52
61
self . u8_vec . extend_from_slice ( v) ;
53
62
let end = self . u8_vec . len ( ) as u32 ;
54
- let r = self . node_vec . len ( ) as u32 ;
55
- self . node_vec . push ( NodePtr :: Atom ( IntAtomBuf { start, end } ) ) ;
56
- r
63
+ self . atom_vec . push ( IntAtomBuf { start, end } ) ;
64
+ -( self . atom_vec . len ( ) as i32 )
57
65
}
58
66
59
67
fn new_pair ( & mut self , first : Self :: Ptr , rest : Self :: Ptr ) -> Self :: Ptr {
60
- let r: u32 = self . node_vec . len ( ) as u32 ;
61
- self . node_vec . push ( NodePtr :: Pair ( first, rest) ) ;
68
+ let r = self . pair_vec . len ( ) as i32 ;
69
+ self . pair_vec . push ( IntPair { first, rest } ) ;
62
70
r
63
71
}
64
72
65
73
fn atom < ' a > ( & ' a self , node : & ' a Self :: Ptr ) -> & ' a [ u8 ] {
66
- match self . node_vec [ * node as usize ] {
67
- NodePtr :: Atom ( IntAtomBuf { start, end } ) => & self . u8_vec [ start as usize ..end as usize ] ,
68
- _ => panic ! ( "expected atom, got pair" ) ,
74
+ if * node >= 0 {
75
+ panic ! ( "expected atom, got pair" ) ;
69
76
}
77
+ let atom = self . atom_vec [ ( -* node - 1 ) as usize ] ;
78
+ & self . u8_vec [ atom. start as usize ..atom. end as usize ]
70
79
}
71
80
72
81
fn buf < ' a > ( & ' a self , node : & ' a Self :: AtomBuf ) -> & ' a [ u8 ] {
73
82
& self . u8_vec [ node. start as usize ..node. end as usize ]
74
83
}
75
84
76
85
fn sexp ( & self , node : & Self :: Ptr ) -> SExp < Self :: Ptr , Self :: AtomBuf > {
77
- match self . node_vec [ * node as usize ] {
78
- NodePtr :: Atom ( atombuf) => SExp :: Atom ( atombuf) ,
79
- NodePtr :: Pair ( left, right) => SExp :: Pair ( left, right) ,
86
+ if * node >= 0 {
87
+ let pair = self . pair_vec [ * node as usize ] ;
88
+ SExp :: Pair ( pair. first , pair. rest )
89
+ } else {
90
+ let atom = self . atom_vec [ ( -* node - 1 ) as usize ] ;
91
+ SExp :: Atom ( atom)
80
92
}
81
93
}
82
94
83
95
fn null ( & self ) -> Self :: Ptr {
84
- 0
96
+ - 1
85
97
}
86
98
87
99
fn one ( & self ) -> Self :: Ptr {
88
- 1
100
+ - 2
89
101
}
90
102
}
0 commit comments