1
1
use std:: iter:: FusedIterator ;
2
2
3
+ use fixedbitset:: FixedBitSet ;
3
4
use oxc_allocator:: { Address , GetAddress } ;
4
- use oxc_ast:: { AstKind , ast:: Program } ;
5
+ use oxc_ast:: { AstKind , ast:: Program , ast_kind :: AST_TYPE_MAX } ;
5
6
use oxc_cfg:: BlockNodeId ;
6
7
use oxc_index:: { IndexSlice , IndexVec } ;
7
8
use oxc_span:: { GetSpan , Span } ;
@@ -96,14 +97,29 @@ impl GetAddress for AstNode<'_> {
96
97
}
97
98
98
99
/// Untyped AST nodes flattened into an vec
99
- #[ derive( Debug , Default ) ]
100
+ #[ derive( Debug ) ]
100
101
pub struct AstNodes < ' a > {
101
102
program : Option < & ' a Program < ' a > > ,
102
103
nodes : IndexVec < NodeId , AstNode < ' a > > ,
104
+ /// Stores a set of bits of a fixed size, where each bit represents a single [`AstKind`]. If the bit is set (1),
105
+ /// then the AST contains at least one node of that kind. If the bit is not set (0), then the AST does not contain
106
+ /// any nodes of that kind.
107
+ node_kinds_set : FixedBitSet ,
103
108
/// `node` -> `parent`
104
109
parent_ids : IndexVec < NodeId , NodeId > ,
105
110
}
106
111
112
+ impl Default for AstNodes < ' _ > {
113
+ fn default ( ) -> Self {
114
+ Self {
115
+ program : None ,
116
+ nodes : IndexVec :: new ( ) ,
117
+ node_kinds_set : FixedBitSet :: with_capacity ( AST_TYPE_MAX as usize + 1 ) ,
118
+ parent_ids : IndexVec :: new ( ) ,
119
+ }
120
+ }
121
+ }
122
+
107
123
impl < ' a > AstNodes < ' a > {
108
124
/// Iterate over all [`AstNode`]s in this AST.
109
125
pub fn iter ( & self ) -> impl Iterator < Item = & AstNode < ' a > > + ' _ {
@@ -210,6 +226,12 @@ impl<'a> AstNodes<'a> {
210
226
let node_id = self . parent_ids . push ( parent_node_id) ;
211
227
let node = AstNode :: new ( kind, scope_id, cfg_id, flags, node_id) ;
212
228
self . nodes . push ( node) ;
229
+ debug_assert ! ( ( kind. ty( ) as usize ) < self . node_kinds_set. len( ) ) ;
230
+ // SAFETY: `AstKind` maps exactly to `AstType`, and there should be exactly
231
+ // enough bits to insert it into `node_kinds`, so we can skip a bounds check here.
232
+ unsafe {
233
+ self . node_kinds_set . insert_unchecked ( kind. ty ( ) as usize ) ;
234
+ }
213
235
node_id
214
236
}
215
237
@@ -233,6 +255,12 @@ impl<'a> AstNodes<'a> {
233
255
let node_id = self . parent_ids . push ( NodeId :: ROOT ) ;
234
256
let node = AstNode :: new ( kind, scope_id, cfg_id, flags, node_id) ;
235
257
self . nodes . push ( node) ;
258
+ debug_assert ! ( ( kind. ty( ) as usize ) < self . node_kinds_set. len( ) ) ;
259
+ // SAFETY: `AstKind` maps exactly to `AstType`, and there should be exactly
260
+ // enough bits to insert it into `node_kinds`, so we can skip a bounds check here.
261
+ unsafe {
262
+ self . node_kinds_set . insert_unchecked ( kind. ty ( ) as usize ) ;
263
+ }
236
264
node_id
237
265
}
238
266
0 commit comments