From ae849cf134f3ff21261e175d95ba994e86ffe81a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 30 Jul 2018 03:21:17 +0300 Subject: Owned&Borrowed nodes HOLLY COW, UNLIKE C++, WE CAN BE GENERIC WRT OWNERSHIP/BORROWING, SO WE CAN BOTH MAKE SYNTAX NODES OWNED (WHICH IS CONVENIENT) AND BORROWED (WHICH IS CONVENIENT FOR LOCAL PROCESSING, BC YOU DON'T NEED TO BUMP REFCOUNTS). --- src/lib.rs | 9 +++++---- src/yellow/builder.rs | 5 +++-- src/yellow/mod.rs | 4 ++-- src/yellow/syntax.rs | 45 ++++++++++++++++++++++++++++++++------------- 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4260e22e7..34c71fd2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ mod syntax_kinds; pub use { text_unit::{TextRange, TextUnit}, syntax_kinds::SyntaxKind, - yellow::{SyntaxNode}, + yellow::{SyntaxNode, SyntaxNodeRef}, lexer::{tokenize, Token}, }; @@ -48,16 +48,17 @@ pub mod utils { collections::BTreeSet }; - use {SyntaxNode, SyntaxError}; + use {SyntaxNode, SyntaxNodeRef, SyntaxError}; /// Parse a file and create a string representation of the resulting parse tree. pub fn dump_tree_green(syntax: &SyntaxNode) -> String { + let syntax = syntax.borrow(); let mut errors: BTreeSet<_> = syntax.root.errors.iter().cloned().collect(); let mut result = String::new(); go(syntax, &mut result, 0, &mut errors); return result; - fn go(node: &SyntaxNode, buff: &mut String, level: usize, errors: &mut BTreeSet) { + fn go(node: SyntaxNodeRef, buff: &mut String, level: usize, errors: &mut BTreeSet) { buff.push_str(&String::from(" ").repeat(level)); write!(buff, "{:?}\n", node).unwrap(); let my_errors: Vec<_> = errors.iter().filter(|e| e.offset == node.range().start()) @@ -68,7 +69,7 @@ pub mod utils { write!(buff, "err: `{}`\n", err.message).unwrap(); } - for child in node.children().iter() { + for child in node.children() { go(child, buff, level + 1, errors) } diff --git a/src/yellow/builder.rs b/src/yellow/builder.rs index 73b4b5ff9..65cc97ff9 100644 --- a/src/yellow/builder.rs +++ b/src/yellow/builder.rs @@ -1,6 +1,6 @@ use { SyntaxKind, TextRange, TextUnit, - yellow::{SyntaxNode, GreenNode, GreenNodeBuilder, SyntaxError}, + yellow::{SyntaxNode, SyntaxRoot, GreenNode, GreenNodeBuilder, SyntaxError}, parser::Sink }; @@ -57,7 +57,8 @@ impl Sink for GreenBuilder { } fn finish(self) -> SyntaxNode { - SyntaxNode::new(self.root.unwrap(), self.errors) + let root = SyntaxRoot::new(self.root.unwrap(), self.errors); + SyntaxNode::new_owned(root) } } diff --git a/src/yellow/mod.rs b/src/yellow/mod.rs index 4fd0d24d7..89eefc98b 100644 --- a/src/yellow/mod.rs +++ b/src/yellow/mod.rs @@ -6,7 +6,7 @@ mod builder; pub(crate) use self::{ green::{GreenNode, GreenNodeBuilder}, red::RedNode, - syntax::SyntaxError, + syntax::{SyntaxError, SyntaxRoot}, builder::GreenBuilder, }; -pub use self::syntax::SyntaxNode; +pub use self::syntax::{SyntaxNode, SyntaxNodeRef}; diff --git a/src/yellow/syntax.rs b/src/yellow/syntax.rs index cc6122689..0fa24fb47 100644 --- a/src/yellow/syntax.rs +++ b/src/yellow/syntax.rs @@ -10,17 +10,28 @@ use { yellow::{RedNode, GreenNode}, }; -#[derive(Clone)] -pub struct SyntaxNode { - pub(crate) root: SyntaxRoot, +#[derive(Clone, Copy)] +pub struct SyntaxNode + Clone = Arc> { + pub(crate) root: ROOT, // guaranteed to be alive bc SyntaxRoot holds a strong ref red: ptr::NonNull, } -#[derive(Clone)] +pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>; + +#[derive(Debug)] pub struct SyntaxRoot { - red: Arc, - pub(crate) errors: Arc>, + red: RedNode, + pub(crate) errors: Vec, +} + +impl SyntaxRoot { + pub(crate) fn new(green: GreenNode, errors: Vec) -> SyntaxRoot { + SyntaxRoot { + red: RedNode::new_root(green), + errors, + } + } } #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] @@ -29,13 +40,21 @@ pub(crate) struct SyntaxError { pub(crate) offset: TextUnit, } -impl SyntaxNode { - pub(crate) fn new(root: GreenNode, errors: Vec) -> SyntaxNode { - let red = Arc::new(RedNode::new_root(root)); - let red_weak: ptr::NonNull = (&*red).into(); - let root = SyntaxRoot { red, errors: Arc::new(errors) }; +impl SyntaxNode> { + pub(crate) fn new_owned(root: SyntaxRoot) -> Self { + let root = Arc::new(root); + let red_weak = ptr::NonNull::from(&root.red); SyntaxNode { root, red: red_weak } } +} + +impl + Clone> SyntaxNode { + pub fn borrow<'a>(&'a self) -> SyntaxNode<&'a SyntaxRoot> { + SyntaxNode { + root: &*self.root, + red: ptr::NonNull::clone(&self.red), + } + } pub fn kind(&self) -> SyntaxKind { self.red().green().kind() @@ -53,7 +72,7 @@ impl SyntaxNode { self.red().green().text() } - pub fn children(&self) -> Vec { + pub fn children(&self) -> Vec> { let red = self.red(); let n_children = red.n_children(); let mut res = Vec::with_capacity(n_children); @@ -71,7 +90,7 @@ impl SyntaxNode { } } -impl fmt::Debug for SyntaxNode { +impl + Clone> fmt::Debug for SyntaxNode { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; if has_short_text(self.kind()) { -- cgit v1.2.3