1use std::cell::Cell;
2use std::hint;
3
4use cfg::symbol::Symbol;
5
6pub use self::Node::*;
7use self::Tag::*;
8use forest::node_handle::{NodeHandle, NULL_HANDLE};
9
10pub struct Graph {
11 pub(crate) vec: Vec<Cell<u16>>,
12}
13
14impl Graph {
15 pub(crate) fn with_capacity(capacity: usize) -> Self {
16 Graph {
17 vec: Vec::with_capacity(capacity),
18 }
19 }
20
21 pub(crate) fn push(&mut self, node: Node) -> NodeHandle {
22 let position = self.vec.len() as u32;
23 let (node_repr, size) = node.to_repr(position);
24 unsafe {
25 self.vec
26 .extend(node_repr.fields[..size].iter().cloned().map(Cell::new));
27 }
28 NodeHandle(position)
29 }
30
31 pub(crate) fn set_up(&mut self, mut handle: NodeHandle, node: Node) {
32 let (node_repr, size) = node.to_repr(handle.0);
33 let mut current_handle = handle;
34 while current_handle.usize() < handle.usize() + size {
35 let current_node = self.get(current_handle);
36 self.push(current_node);
37 current_handle.0 += current_node.classify(current_handle.0).size() as u32;
38 }
39 for i in 0..size {
40 unsafe {
41 self.vec[handle.usize() + i].set(node_repr.fields[i]);
42 }
43 }
44 handle.0 += size as u32;
45 while handle.0 < current_handle.0 {
46 self.vec[handle.usize()].set(NopTag.to_u16());
47 handle.0 += 1;
48 }
49 }
50
51 pub(crate) fn get(&self, handle: NodeHandle) -> Node {
52 self.iter_from(handle).next().unwrap()
53 }
54
55 pub(crate) fn iter_from(&self, handle: NodeHandle) -> Iter {
56 Iter {
57 vec: &self.vec[..],
58 handle,
59 }
60 }
61}
62
63#[derive(Clone, Copy)]
64pub(crate) struct Iter<'a> {
65 pub(crate) vec: &'a [Cell<u16>],
66 pub(crate) handle: NodeHandle,
67}
68
69impl<'a> Iterator for Iter<'a> {
70 type Item = Node;
71
72 fn next(&mut self) -> Option<Node> {
73 unsafe {
74 let head = if let Some(head) = self.vec.get(self.handle.usize()).cloned() {
75 head.get()
76 } else {
77 return None;
78 };
79 let (tag, head) = get_and_erase_tag(head);
80 if let NopTag = tag {
81 self.handle.0 += 1;
82 self.next()
83 } else {
84 let mut node_repr = NodeRepr { fields: [0; 6] };
85 node_repr.fields[0] = head;
86 let slice = &self.vec[self.handle.usize() + 1..self.handle.usize() + tag.size()];
87 for (i, val) in slice.iter().enumerate() {
88 node_repr.fields[1 + i] = val.get();
89 }
90 let result = node_repr.expand(tag, self.handle.0);
91 self.handle.0 += tag.size() as u32;
92 Some(result)
93 }
94 }
95 }
96}
97
98impl<'a> Iter<'a> {
99 #[inline]
100 pub(crate) fn peek(&mut self) -> Option<Node> {
101 self.clone().next()
102 }
103}
104
105#[derive(Copy, Clone, Debug, Eq, PartialEq)]
107pub enum Node {
108 Sum {
109 count: u32,
113 nonterminal: Symbol,
114 },
115 Product {
116 action: u32,
118 left_factor: NodeHandle,
119 right_factor: Option<NodeHandle>,
120 },
121 NullingLeaf {
122 symbol: Symbol,
124 },
125 Evaluated {
126 symbol: Symbol,
128 },
129}
130
131#[derive(Clone, Copy)]
132union NodeRepr {
133 fields: [u16; 6],
134 small_sum: SmallSumRepr,
135 small_link: SmallLinkRepr,
136 medium_link: MediumLinkRepr,
137 small_product: SmallProductRepr,
138 small_leaf: SmallLeafRepr,
139 small_nulling_leaf: SmallNullingLeafRepr,
140 sum: SumRepr,
141 product: ProductRepr,
142 leaf: LeafRepr,
143 nop: NopRepr,
144}
145
146#[derive(Clone, Copy)]
147struct SmallSumRepr {
148 nonterminal: u8,
149 count: u8,
151}
152
153#[derive(Clone, Copy)]
154struct SumRepr {
155 count: u32,
156 nonterminal: Symbol,
157}
158
159#[derive(Clone, Copy)]
160struct SmallLinkRepr {
161 action: u8,
162 distance: u8,
164}
165
166#[derive(Clone, Copy)]
167struct MediumLinkRepr {
168 distance: u16,
169 action: u16,
170}
171
172#[derive(Clone, Copy)]
173struct SmallProductRepr {
174 left_distance: u8,
175 right_distance: u8,
177 action: u16,
178}
179
180#[derive(Clone, Copy)]
181#[repr(packed)]
182struct ProductRepr {
183 upper_action: u16,
184 lower_action: u16,
185 left_factor: NodeHandle,
186 right_factor: NodeHandle,
187}
188
189#[derive(Clone, Copy)]
190struct SmallNullingLeafRepr {
191 symbol: u16,
192}
193
194#[derive(Clone, Copy)]
195struct LeafRepr {
196 symbol: Symbol,
197}
198
199#[derive(Clone, Copy)]
200struct SmallLeafRepr {
201 symbol: u16,
202}
203
204#[derive(Clone, Copy)]
205struct NopRepr {
206 nop: u16,
207}
208
209#[derive(Copy, Clone, Eq, PartialEq, Debug)]
210pub(super) enum Tag {
211 SmallSumTag = 0b000 << TAG_BIT,
212 SmallLinkTag = 0b001 << TAG_BIT,
213 MediumLinkTag = 0b010 << TAG_BIT,
214 SmallProductTag = 0b011 << TAG_BIT,
215 SmallLeafTag = 0b100 << TAG_BIT,
216 SmallNullingLeafTag = 0b1001 << (TAG_BIT - 1),
218 LeafTag = 0b101 << TAG_BIT,
219 SumTag = 0b111 << TAG_BIT,
220 ProductTag = 0b110 << TAG_BIT,
221 NopTag = 0b1111_1111_1111_1111,
222}
223
224impl Tag {
225 #[inline]
226 fn from_u16(num: u16) -> Option<Self> {
227 let n = num & TAG_MASK;
228 if num == NopTag.to_u16() {
229 Some(NopTag)
230 } else if n == LeafTag.to_u16() {
231 Some(LeafTag)
232 } else if n == SumTag.to_u16() {
233 Some(SumTag)
234 } else if n == ProductTag.to_u16() {
235 Some(ProductTag)
236 } else if n == SmallSumTag.to_u16() {
237 Some(SmallSumTag)
238 } else if n == SmallLinkTag.to_u16() {
239 Some(SmallLinkTag)
240 } else if n == MediumLinkTag.to_u16() {
241 Some(MediumLinkTag)
242 } else if n == SmallProductTag.to_u16() {
243 Some(SmallProductTag)
244 } else if n == SmallLeafTag.to_u16() {
245 let n = num & SMALL_LEAF_TAG_MASK;
246 if n == SmallLeafTag.to_u16() {
247 Some(SmallLeafTag)
248 } else if n == SmallNullingLeafTag.to_u16() {
249 Some(SmallNullingLeafTag)
250 } else {
251 None
252 }
253 } else {
254 None
255 }
256 }
257
258 #[inline]
259 pub(super) fn to_u16(self) -> u16 {
260 match self {
261 SmallSumTag => 0b000 << TAG_BIT,
262 SmallLinkTag => 0b001 << TAG_BIT,
263 MediumLinkTag => 0b010 << TAG_BIT,
264 SmallProductTag => 0b011 << TAG_BIT,
265 SmallLeafTag => 0b100 << TAG_BIT,
266 SmallNullingLeafTag => 0b1001 << (TAG_BIT - 1),
268 LeafTag => 0b101 << TAG_BIT,
269 SumTag => 0b111 << TAG_BIT,
270 ProductTag => 0b110 << TAG_BIT,
271 NopTag => 0b1111_1111_1111_1111,
272 }
273 }
274
275 #[inline]
276 fn mask(self) -> u16 {
277 match self {
278 SmallSumTag => TAG_MASK,
279 SmallLinkTag => TAG_MASK,
280 MediumLinkTag => TAG_MASK,
281 SmallProductTag => TAG_MASK,
282 SmallLeafTag => SMALL_LEAF_TAG_MASK,
283 SmallNullingLeafTag => SMALL_LEAF_TAG_MASK,
285 LeafTag => TAG_MASK,
286 SumTag => TAG_MASK,
287 ProductTag => TAG_MASK,
288 NopTag => 0b1111_1111_1111_1111,
289 }
290 }
291
292 #[inline]
293 pub(super) fn size(self) -> usize {
294 match self {
295 SmallSumTag => 1,
296 SmallLinkTag => 1,
297 MediumLinkTag => 2,
298 SmallProductTag => 2,
299 SmallLeafTag => 1,
300 SmallNullingLeafTag => 1,
301 LeafTag => 4,
302 SumTag => 4,
303 ProductTag => 6,
304 NopTag => 1,
305 }
306 }
307}
308
309const TAG_BIT: usize = 5 + 8;
310const TAG_MASK: u16 = 0b111 << TAG_BIT;
311const SMALL_LEAF_TAG_MASK: u16 = 0b1111 << (TAG_BIT - 1);
312pub(super) const NULL_ACTION: u32 = !((TAG_MASK as u32) << 16);
313
314impl NodeRepr {
315 fn expand(self, tag: Tag, position: u32) -> Node {
316 unsafe {
317 match (self, tag) {
318 (
319 NodeRepr {
320 small_sum: SmallSumRepr { nonterminal, count },
321 },
322 SmallSumTag,
323 ) => Sum {
324 nonterminal: Symbol::from(nonterminal as u32),
325 count: count as u32,
326 },
327 (
328 NodeRepr {
329 sum: SumRepr { nonterminal, count },
330 },
331 SumTag,
332 ) => Sum { nonterminal, count },
333 (
334 NodeRepr {
335 small_link: SmallLinkRepr { distance, action },
336 },
337 SmallLinkTag,
338 ) => Product {
339 action: action as u32,
340 left_factor: NodeHandle(position - distance as u32),
341 right_factor: None,
342 },
343 (
344 NodeRepr {
345 medium_link: MediumLinkRepr { distance, action },
346 },
347 MediumLinkTag,
348 ) => Product {
349 action: action as u32,
350 left_factor: NodeHandle(position - distance as u32),
351 right_factor: None,
352 },
353 (
354 NodeRepr {
355 small_product:
356 SmallProductRepr {
357 right_distance,
358 left_distance,
359 action,
360 },
361 },
362 SmallProductTag,
363 ) => Product {
364 action: action as u32,
365 left_factor: NodeHandle(position - left_distance as u32),
366 right_factor: Some(NodeHandle(position - right_distance as u32)),
367 },
368 (
369 NodeRepr {
370 product:
371 ProductRepr {
372 upper_action,
373 lower_action,
374 left_factor,
375 right_factor,
376 },
377 },
378 ProductTag,
379 ) => Product {
380 action: (upper_action as u32) << 16 | (lower_action as u32),
381 left_factor,
382 right_factor: right_factor.to_option(),
383 },
384 (
385 NodeRepr {
386 small_nulling_leaf: SmallNullingLeafRepr { symbol },
387 },
388 SmallNullingLeafTag,
389 ) => NullingLeaf {
390 symbol: Symbol::from(symbol as u32),
391 },
392 (
393 NodeRepr {
394 small_leaf: SmallLeafRepr { symbol },
395 },
396 SmallLeafTag,
397 ) => Evaluated {
398 symbol: Symbol::from(symbol as u32),
399 },
400 (
401 NodeRepr {
402 leaf: LeafRepr { symbol },
403 },
404 LeafTag,
405 ) => Evaluated { symbol },
406 _ => unreachable!(),
407 }
408 }
409 }
410}
411
412impl Node {
413 #[inline]
414 fn to_repr(self, position: u32) -> (NodeRepr, usize) {
415 let tag = self.classify(position);
416 unsafe {
417 let mut result = match (self, tag) {
418 (Sum { nonterminal, count }, SmallSumTag) => NodeRepr {
419 small_sum: SmallSumRepr {
420 nonterminal: nonterminal.usize() as u8,
421 count: count as u8,
422 },
423 },
424 (Sum { nonterminal, count }, SumTag) => NodeRepr {
425 sum: SumRepr { nonterminal, count },
426 },
427 (
428 Product {
429 left_factor,
430 right_factor: None,
431 action,
432 },
433 SmallLinkTag,
434 ) => NodeRepr {
435 small_link: SmallLinkRepr {
436 distance: (position - left_factor.0) as u8,
437 action: action as u8,
438 },
439 },
440 (
441 Product {
442 left_factor,
443 right_factor: None,
444 action,
445 },
446 MediumLinkTag,
447 ) => NodeRepr {
448 medium_link: MediumLinkRepr {
449 distance: (position - left_factor.0) as u16,
450 action: action as u16,
451 },
452 },
453 (
454 Product {
455 left_factor,
456 right_factor: Some(right),
457 action,
458 },
459 SmallProductTag,
460 ) => NodeRepr {
461 small_product: SmallProductRepr {
462 right_distance: (position - right.0) as u8,
463 left_distance: (position - left_factor.0) as u8,
464 action: action as u16,
465 },
466 },
467 (
468 Product {
469 left_factor,
470 right_factor,
471 action,
472 },
473 ProductTag,
474 ) => NodeRepr {
475 product: ProductRepr {
476 upper_action: (action >> 16) as u16,
477 lower_action: action as u16,
478 left_factor,
479 right_factor: right_factor.unwrap_or(NULL_HANDLE),
480 },
481 },
482 (NullingLeaf { symbol }, SmallNullingLeafTag) => NodeRepr {
483 small_nulling_leaf: SmallNullingLeafRepr {
484 symbol: symbol.usize() as u16,
485 },
486 },
487 (NullingLeaf { symbol }, LeafTag) => NodeRepr {
488 leaf: LeafRepr { symbol },
489 },
490 (Evaluated { symbol }, SmallLeafTag) => NodeRepr {
491 small_leaf: SmallLeafRepr {
492 symbol: symbol.usize() as u16,
493 },
494 },
495 (Evaluated { symbol }, LeafTag) => NodeRepr {
496 leaf: LeafRepr { symbol },
497 },
498 _ => unreachable!(),
499 };
500 result.fields[0] |= tag.to_u16();
501 (result, tag.size())
502 }
503 }
504
505 #[inline]
506 pub(super) fn classify(self, position: u32) -> Tag {
507 match self {
508 Product {
509 left_factor,
510 right_factor,
511 action,
512 } => match right_factor {
513 Some(handle) => {
514 if position >= handle.0
515 && position >= left_factor.0
516 && position - handle.0 < (1 << 5)
517 && position - left_factor.0 < (1 << 8)
518 && action < (1 << 16)
519 {
520 SmallProductTag
521 } else {
522 ProductTag
523 }
524 }
525 None => {
526 if position >= left_factor.0
527 && position - left_factor.0 < (1 << 5)
528 && action < (1 << 8)
529 {
530 SmallLinkTag
531 } else if position >= left_factor.0
532 && position - left_factor.0 < (1 << (5 + 8))
533 && action < (1 << 16)
534 {
535 MediumLinkTag
536 } else {
537 ProductTag
538 }
539 }
540 },
541 NullingLeaf { symbol } => {
542 if symbol.usize() < (1 << (4 + 8)) {
543 SmallNullingLeafTag
544 } else {
545 LeafTag
546 }
547 }
548 Evaluated { symbol } => {
549 if symbol.usize() < (1 << (4 + 8)) {
550 SmallLeafTag
551 } else {
552 LeafTag
553 }
554 }
555 Sum { nonterminal, count } => {
556 if count < (1 << 5) && nonterminal.usize() < (1 << 8) {
557 SmallSumTag
558 } else {
559 SumTag
560 }
561 }
562 }
563 }
564}
565
566#[inline]
567unsafe fn unwrap_unchecked<T>(opt: Option<T>) -> T {
568 match opt {
569 Some(val) => val,
570 None => hint::unreachable_unchecked(),
571 }
572}
573
574#[inline]
575unsafe fn get_and_erase_tag(field: u16) -> (Tag, u16) {
576 let tag = unwrap_unchecked(Tag::from_u16(field));
577 (tag, field & !tag.mask())
578}