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).
This commit is contained in:
Aleksey Kladov 2018-07-30 03:21:17 +03:00
parent 83acbc06bd
commit ae849cf134
4 changed files with 42 additions and 21 deletions

View File

@ -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<SyntaxError>) {
fn go(node: SyntaxNodeRef, buff: &mut String, level: usize, errors: &mut BTreeSet<SyntaxError>) {
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)
}

View File

@ -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)
}
}

View File

@ -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};

View File

@ -10,17 +10,28 @@ use {
yellow::{RedNode, GreenNode},
};
#[derive(Clone)]
pub struct SyntaxNode {
pub(crate) root: SyntaxRoot,
#[derive(Clone, Copy)]
pub struct SyntaxNode<ROOT: ::std::ops::Deref<Target=SyntaxRoot> + Clone = Arc<SyntaxRoot>> {
pub(crate) root: ROOT,
// guaranteed to be alive bc SyntaxRoot holds a strong ref
red: ptr::NonNull<RedNode>,
}
#[derive(Clone)]
pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>;
#[derive(Debug)]
pub struct SyntaxRoot {
red: Arc<RedNode>,
pub(crate) errors: Arc<Vec<SyntaxError>>,
red: RedNode,
pub(crate) errors: Vec<SyntaxError>,
}
impl SyntaxRoot {
pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> 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<SyntaxError>) -> SyntaxNode {
let red = Arc::new(RedNode::new_root(root));
let red_weak: ptr::NonNull<RedNode> = (&*red).into();
let root = SyntaxRoot { red, errors: Arc::new(errors) };
impl SyntaxNode<Arc<SyntaxRoot>> {
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<ROOT: ::std::ops::Deref<Target=SyntaxRoot> + Clone> SyntaxNode<ROOT> {
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<SyntaxNode> {
pub fn children(&self) -> Vec<SyntaxNode<ROOT>> {
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<ROOT: ::std::ops::Deref<Target=SyntaxRoot> + Clone> fmt::Debug for SyntaxNode<ROOT> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
if has_short_text(self.kind()) {