diff options
Diffstat (limited to 'src/yellow')
-rw-r--r-- | src/yellow/green.rs | 6 | ||||
-rw-r--r-- | src/yellow/mod.rs | 53 | ||||
-rw-r--r-- | src/yellow/red.rs | 18 | ||||
-rw-r--r-- | src/yellow/syntax.rs | 40 |
4 files changed, 70 insertions, 47 deletions
diff --git a/src/yellow/green.rs b/src/yellow/green.rs index 787968363..f505b26d7 100644 --- a/src/yellow/green.rs +++ b/src/yellow/green.rs | |||
@@ -56,12 +56,6 @@ impl GreenNode { | |||
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | #[test] | ||
60 | fn assert_send_sync() { | ||
61 | fn f<T: Send + Sync>() {} | ||
62 | f::<GreenNode>(); | ||
63 | } | ||
64 | |||
65 | #[derive(Clone, Debug)] | 59 | #[derive(Clone, Debug)] |
66 | pub(crate) struct GreenBranch { | 60 | pub(crate) struct GreenBranch { |
67 | text_len: TextUnit, | 61 | text_len: TextUnit, |
diff --git a/src/yellow/mod.rs b/src/yellow/mod.rs index 6129ecb99..ff3bb221b 100644 --- a/src/yellow/mod.rs +++ b/src/yellow/mod.rs | |||
@@ -3,9 +3,60 @@ mod green; | |||
3 | mod red; | 3 | mod red; |
4 | mod syntax; | 4 | mod syntax; |
5 | 5 | ||
6 | pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot, SyntaxError}; | 6 | use std::{ |
7 | ops::Deref, | ||
8 | sync::Arc, | ||
9 | ptr, | ||
10 | }; | ||
11 | pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError}; | ||
7 | pub(crate) use self::{ | 12 | pub(crate) use self::{ |
8 | builder::GreenBuilder, | 13 | builder::GreenBuilder, |
9 | green::GreenNode, | 14 | green::GreenNode, |
10 | red::RedNode, | 15 | red::RedNode, |
11 | }; | 16 | }; |
17 | |||
18 | pub trait TreeRoot: Deref<Target=SyntaxRoot> + Clone + Send + Sync {} | ||
19 | |||
20 | #[derive(Debug)] | ||
21 | pub struct SyntaxRoot { | ||
22 | red: RedNode, | ||
23 | pub(crate) errors: Vec<SyntaxError>, | ||
24 | } | ||
25 | |||
26 | impl TreeRoot for Arc<SyntaxRoot> {} | ||
27 | |||
28 | impl<'a> TreeRoot for &'a SyntaxRoot {} | ||
29 | |||
30 | impl SyntaxRoot { | ||
31 | pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxRoot { | ||
32 | SyntaxRoot { | ||
33 | red: RedNode::new_root(green), | ||
34 | errors, | ||
35 | } | ||
36 | } | ||
37 | } | ||
38 | |||
39 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | ||
40 | pub(crate) struct RedPtr(ptr::NonNull<RedNode>); | ||
41 | |||
42 | unsafe impl Send for RedPtr {} | ||
43 | |||
44 | unsafe impl Sync for RedPtr {} | ||
45 | |||
46 | impl RedPtr { | ||
47 | fn new(red: &RedNode) -> RedPtr { | ||
48 | RedPtr(red.into()) | ||
49 | } | ||
50 | |||
51 | unsafe fn get<'a>(self, _root: &'a impl TreeRoot) -> &'a RedNode { | ||
52 | &*self.0.as_ptr() | ||
53 | } | ||
54 | } | ||
55 | |||
56 | #[test] | ||
57 | fn assert_send_sync() { | ||
58 | fn f<T: Send + Sync>() {} | ||
59 | f::<GreenNode>(); | ||
60 | f::<RedNode>(); | ||
61 | f::<SyntaxNode>(); | ||
62 | } | ||
diff --git a/src/yellow/red.rs b/src/yellow/red.rs index f57c4a9b7..13ad44c65 100644 --- a/src/yellow/red.rs +++ b/src/yellow/red.rs | |||
@@ -1,7 +1,5 @@ | |||
1 | use std::ptr; | ||
2 | |||
3 | use parking_lot::RwLock; | 1 | use parking_lot::RwLock; |
4 | use {yellow::GreenNode, TextUnit}; | 2 | use {yellow::{GreenNode, RedPtr}, TextUnit}; |
5 | 3 | ||
6 | #[derive(Debug)] | 4 | #[derive(Debug)] |
7 | pub(crate) struct RedNode { | 5 | pub(crate) struct RedNode { |
@@ -12,7 +10,7 @@ pub(crate) struct RedNode { | |||
12 | 10 | ||
13 | #[derive(Debug)] | 11 | #[derive(Debug)] |
14 | struct ParentData { | 12 | struct ParentData { |
15 | parent: ptr::NonNull<RedNode>, | 13 | parent: RedPtr, |
16 | start_offset: TextUnit, | 14 | start_offset: TextUnit, |
17 | index_in_parent: usize, | 15 | index_in_parent: usize, |
18 | } | 16 | } |
@@ -24,7 +22,7 @@ impl RedNode { | |||
24 | 22 | ||
25 | fn new_child( | 23 | fn new_child( |
26 | green: GreenNode, | 24 | green: GreenNode, |
27 | parent: ptr::NonNull<RedNode>, | 25 | parent: RedPtr, |
28 | start_offset: TextUnit, | 26 | start_offset: TextUnit, |
29 | index_in_parent: usize, | 27 | index_in_parent: usize, |
30 | ) -> RedNode { | 28 | ) -> RedNode { |
@@ -64,12 +62,12 @@ impl RedNode { | |||
64 | self.green.children().len() | 62 | self.green.children().len() |
65 | } | 63 | } |
66 | 64 | ||
67 | pub(crate) fn get_child(&self, idx: usize) -> Option<ptr::NonNull<RedNode>> { | 65 | pub(crate) fn get_child(&self, idx: usize) -> Option<RedPtr> { |
68 | if idx >= self.n_children() { | 66 | if idx >= self.n_children() { |
69 | return None; | 67 | return None; |
70 | } | 68 | } |
71 | match &self.children.read()[idx] { | 69 | match &self.children.read()[idx] { |
72 | Some(child) => return Some(child.into()), | 70 | Some(child) => return Some(RedPtr::new(child)), |
73 | None => (), | 71 | None => (), |
74 | }; | 72 | }; |
75 | let green_children = self.green.children(); | 73 | let green_children = self.green.children(); |
@@ -79,15 +77,15 @@ impl RedNode { | |||
79 | .map(|x| x.text_len()) | 77 | .map(|x| x.text_len()) |
80 | .sum::<TextUnit>(); | 78 | .sum::<TextUnit>(); |
81 | let child = | 79 | let child = |
82 | RedNode::new_child(green_children[idx].clone(), self.into(), start_offset, idx); | 80 | RedNode::new_child(green_children[idx].clone(), RedPtr::new(self), start_offset, idx); |
83 | let mut children = self.children.write(); | 81 | let mut children = self.children.write(); |
84 | if children[idx].is_none() { | 82 | if children[idx].is_none() { |
85 | children[idx] = Some(child) | 83 | children[idx] = Some(child) |
86 | } | 84 | } |
87 | Some(children[idx].as_ref().unwrap().into()) | 85 | Some(RedPtr::new(children[idx].as_ref().unwrap())) |
88 | } | 86 | } |
89 | 87 | ||
90 | pub(crate) fn parent(&self) -> Option<ptr::NonNull<RedNode>> { | 88 | pub(crate) fn parent(&self) -> Option<RedPtr> { |
91 | Some(self.parent.as_ref()?.parent) | 89 | Some(self.parent.as_ref()?.parent) |
92 | } | 90 | } |
93 | pub(crate) fn index_in_parent(&self) -> Option<usize> { | 91 | pub(crate) fn index_in_parent(&self) -> Option<usize> { |
diff --git a/src/yellow/syntax.rs b/src/yellow/syntax.rs index 2ba9281fc..6e33310f1 100644 --- a/src/yellow/syntax.rs +++ b/src/yellow/syntax.rs | |||
@@ -1,25 +1,23 @@ | |||
1 | use std::{fmt, ops::Deref, ptr, sync::Arc}; | 1 | use std::{fmt, sync::Arc}; |
2 | 2 | ||
3 | use { | 3 | use { |
4 | yellow::{GreenNode, RedNode}, | 4 | yellow::{RedNode, TreeRoot, SyntaxRoot, RedPtr}, |
5 | SyntaxKind::{self, *}, | 5 | SyntaxKind::{self, *}, |
6 | TextRange, TextUnit, | 6 | TextRange, TextUnit, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | pub trait TreeRoot: Deref<Target = SyntaxRoot> + Clone {} | ||
10 | |||
11 | impl TreeRoot for Arc<SyntaxRoot> {} | ||
12 | |||
13 | impl<'a> TreeRoot for &'a SyntaxRoot {} | ||
14 | 9 | ||
15 | #[derive(Clone, Copy)] | 10 | #[derive(Clone, Copy)] |
16 | pub struct SyntaxNode<R: TreeRoot = Arc<SyntaxRoot>> { | 11 | pub struct SyntaxNode<R: TreeRoot = Arc<SyntaxRoot>> { |
17 | pub(crate) root: R, | 12 | pub(crate) root: R, |
18 | // Guaranteed to not dangle, because `root` holds a | 13 | // Guaranteed to not dangle, because `root` holds a |
19 | // strong reference to red's ancestor | 14 | // strong reference to red's ancestor |
20 | red: ptr::NonNull<RedNode>, | 15 | red: RedPtr, |
21 | } | 16 | } |
22 | 17 | ||
18 | unsafe impl<R: TreeRoot> Send for SyntaxNode<R> {} | ||
19 | unsafe impl<R: TreeRoot> Sync for SyntaxNode<R> {} | ||
20 | |||
23 | impl<R1: TreeRoot, R2: TreeRoot> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2> { | 21 | impl<R1: TreeRoot, R2: TreeRoot> PartialEq<SyntaxNode<R1>> for SyntaxNode<R2> { |
24 | fn eq(&self, other: &SyntaxNode<R1>) -> bool { | 22 | fn eq(&self, other: &SyntaxNode<R1>) -> bool { |
25 | self.red == other.red | 23 | self.red == other.red |
@@ -30,21 +28,6 @@ impl<R: TreeRoot> Eq for SyntaxNode<R> {} | |||
30 | 28 | ||
31 | pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>; | 29 | pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>; |
32 | 30 | ||
33 | #[derive(Debug)] | ||
34 | pub struct SyntaxRoot { | ||
35 | red: RedNode, | ||
36 | pub(crate) errors: Vec<SyntaxError>, | ||
37 | } | ||
38 | |||
39 | impl SyntaxRoot { | ||
40 | pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> SyntaxRoot { | ||
41 | SyntaxRoot { | ||
42 | red: RedNode::new_root(green), | ||
43 | errors, | ||
44 | } | ||
45 | } | ||
46 | } | ||
47 | |||
48 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] | 31 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] |
49 | pub struct SyntaxError { | 32 | pub struct SyntaxError { |
50 | pub msg: String, | 33 | pub msg: String, |
@@ -54,11 +37,8 @@ pub struct SyntaxError { | |||
54 | impl SyntaxNode<Arc<SyntaxRoot>> { | 37 | impl SyntaxNode<Arc<SyntaxRoot>> { |
55 | pub(crate) fn new_owned(root: SyntaxRoot) -> Self { | 38 | pub(crate) fn new_owned(root: SyntaxRoot) -> Self { |
56 | let root = Arc::new(root); | 39 | let root = Arc::new(root); |
57 | let red_weak = ptr::NonNull::from(&root.red); | 40 | let red = RedPtr::new(&root.red); |
58 | SyntaxNode { | 41 | SyntaxNode { root, red } |
59 | root, | ||
60 | red: red_weak, | ||
61 | } | ||
62 | } | 42 | } |
63 | } | 43 | } |
64 | 44 | ||
@@ -66,7 +46,7 @@ impl<R: TreeRoot> SyntaxNode<R> { | |||
66 | pub fn as_ref<'a>(&'a self) -> SyntaxNode<&'a SyntaxRoot> { | 46 | pub fn as_ref<'a>(&'a self) -> SyntaxNode<&'a SyntaxRoot> { |
67 | SyntaxNode { | 47 | SyntaxNode { |
68 | root: &*self.root, | 48 | root: &*self.root, |
69 | red: ptr::NonNull::clone(&self.red), | 49 | red: self.red, |
70 | } | 50 | } |
71 | } | 51 | } |
72 | 52 | ||
@@ -120,7 +100,7 @@ impl<R: TreeRoot> SyntaxNode<R> { | |||
120 | } | 100 | } |
121 | 101 | ||
122 | fn red(&self) -> &RedNode { | 102 | fn red(&self) -> &RedNode { |
123 | unsafe { self.red.as_ref() } | 103 | unsafe { self.red.get(&self.root) } |
124 | } | 104 | } |
125 | } | 105 | } |
126 | 106 | ||