aboutsummaryrefslogtreecommitdiff
path: root/src/yellow/red.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/yellow/red.rs')
-rw-r--r--src/yellow/red.rs87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/yellow/red.rs b/src/yellow/red.rs
new file mode 100644
index 000000000..feba99faa
--- /dev/null
+++ b/src/yellow/red.rs
@@ -0,0 +1,87 @@
1use std::sync::{Arc, Weak, RwLock};
2use {
3 TextUnit, SyntaxKind, TextRange,
4 yellow::{Ptr, GreenNode, TextLen}
5};
6
7#[derive(Debug)]
8pub(crate) struct RedNode {
9 green: Arc<GreenNode>,
10 parent: Option<ParentData>,
11 children: RwLock<Vec<Option<Arc<RedNode>>>>,
12}
13
14#[derive(Debug)]
15struct ParentData {
16 parent: Ptr<RedNode>,
17 start_offset: TextUnit,
18 index_in_parent: usize,
19}
20
21impl RedNode {
22 pub fn new_root(
23 green: Arc<GreenNode>,
24 ) -> RedNode {
25 RedNode::new(green, None)
26 }
27
28 fn new_child(
29 green: Arc<GreenNode>,
30 parent: Ptr<RedNode>,
31 start_offset: TextUnit,
32 index_in_parent: usize
33 ) -> RedNode {
34 let parent_data = ParentData {
35 parent,
36 start_offset,
37 index_in_parent
38 };
39 RedNode::new(green, Some(parent_data))
40 }
41
42 fn new(
43 green: Arc<GreenNode>,
44 parent: Option<ParentData>,
45 ) -> RedNode {
46 let children = vec![None; green.n_children()];
47 RedNode { green, parent, children: RwLock::new(children) }
48 }
49
50 pub(crate) fn green(&self) -> &GreenNode {
51 &self.green
52 }
53
54 pub(crate) fn start_offset(&self) -> TextUnit {
55 match &self.parent {
56 None => 0.into(),
57 Some(p) => p.start_offset,
58 }
59 }
60
61 pub(crate) fn n_children(&self) -> usize {
62 self.green.n_children()
63 }
64
65 pub(crate) fn nth_child(&self, me: Ptr<RedNode>, n: usize) -> Arc<RedNode> {
66 match &self.children.read().unwrap()[n] {
67 Some(child) => return child.clone(),
68 None => (),
69 }
70 let mut children = self.children.write().unwrap();
71 if children[n].is_none() {
72 let start_offset = {
73 let mut acc = self.start_offset();
74 for i in 0..n {
75 acc += self.green.nth_trivias(i).text_len();
76 acc += self.green.nth_child(i).text_len();
77 }
78 acc += self.green.nth_trivias(n).text_len();
79 acc
80 };
81 let green = self.green.nth_child(n).clone();
82 let child = RedNode::new_child(green, me, start_offset, n);
83 children[n] = Some(Arc::new(child))
84 }
85 children[n].as_ref().unwrap().clone()
86 }
87}