Remove dyn dispatch

This commit is contained in:
Aleksey Kladov 2018-09-08 01:16:07 +03:00
parent fcfda94664
commit ff1c82216c
3 changed files with 65 additions and 21 deletions

View file

@ -1,10 +1,13 @@
mod generated; mod generated;
use std::marker::PhantomData;
use itertools::Itertools; use itertools::Itertools;
use smol_str::SmolStr; use smol_str::SmolStr;
use { use {
SyntaxNodeRef, SyntaxKind::*, SyntaxNodeRef, SyntaxKind::*,
yellow::{RefRoot, SyntaxNodeChildren},
}; };
pub use self::generated::*; pub use self::generated::*;
@ -33,8 +36,8 @@ pub trait ArgListOwner<'a>: AstNode<'a> {
} }
pub trait FnDefOwner<'a>: AstNode<'a> { pub trait FnDefOwner<'a>: AstNode<'a> {
fn functions(self) -> Box<Iterator<Item=FnDef<'a>> + 'a> { fn functions(self) -> AstNodeChildren<'a, FnDef<'a>> {
Box::new(children(self)) children(self)
} }
} }
@ -49,8 +52,8 @@ pub trait TypeParamsOwner<'a>: AstNode<'a> {
} }
pub trait AttrsOwner<'a>: AstNode<'a> { pub trait AttrsOwner<'a>: AstNode<'a> {
fn attrs(self) -> Box<Iterator<Item=Attr<'a>> + 'a> { fn attrs(self) -> AstNodeChildren<'a, Attr<'a>> {
Box::new(children(self)) children(self)
} }
} }
@ -155,7 +158,7 @@ impl<'a> IfExpr<'a> {
pub fn else_branch(self) -> Option<Block<'a>> { pub fn else_branch(self) -> Option<Block<'a>> {
self.blocks().nth(1) self.blocks().nth(1)
} }
fn blocks(self) -> impl Iterator<Item=Block<'a>> { fn blocks(self) -> AstNodeChildren<'a, Block<'a>> {
children(self) children(self)
} }
} }
@ -164,8 +167,34 @@ fn child_opt<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> Option<C> {
children(parent).next() children(parent).next()
} }
fn children<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> impl Iterator<Item=C> + 'a { fn children<'a, P: AstNode<'a>, C: AstNode<'a>>(parent: P) -> AstNodeChildren<'a, C> {
parent.syntax() AstNodeChildren::new(parent.syntax())
.children() }
.filter_map(C::cast)
#[derive(Debug)]
pub struct AstNodeChildren<'a, N> {
inner: SyntaxNodeChildren<RefRoot<'a>>,
ph: PhantomData<N>,
}
impl<'a, N> AstNodeChildren<'a, N> {
fn new(parent: SyntaxNodeRef<'a>) -> Self {
AstNodeChildren {
inner: parent.children(),
ph: PhantomData,
}
}
}
impl<'a, N: AstNode<'a>> Iterator for AstNodeChildren<'a, N> {
type Item = N;
fn next(&mut self) -> Option<N> {
loop {
match N::cast(self.inner.next()?) {
Some(n) => return Some(n),
None => (),
}
}
}
} }

View file

@ -8,7 +8,7 @@ use std::{
sync::Arc, sync::Arc,
ptr, ptr,
}; };
pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError}; pub use self::syntax::{SyntaxNode, SyntaxNodeRef, SyntaxError, SyntaxNodeChildren};
pub(crate) use self::{ pub(crate) use self::{
builder::GreenBuilder, builder::GreenBuilder,
green::GreenNode, green::GreenNode,

View file

@ -1,6 +1,7 @@
use std::{ use std::{
fmt, sync::Arc, fmt, sync::Arc,
hash::{Hasher, Hash}, hash::{Hasher, Hash},
ops::Range,
}; };
use smol_str::SmolStr; use smol_str::SmolStr;
@ -93,17 +94,11 @@ impl<R: TreeRoot> SyntaxNode<R> {
SyntaxText::new(self.borrowed()) SyntaxText::new(self.borrowed())
} }
pub fn children(&self) -> impl Iterator<Item = SyntaxNode<R>> { pub fn children(&self) -> SyntaxNodeChildren<R> {
let red = self.red; SyntaxNodeChildren {
let n_children = self.red().n_children(); parent: self.clone(),
let root = self.root.clone(); iter: (0..self.red().n_children())
(0..n_children).map(move |i| { }
let red = unsafe { red.get(root.syntax_root()) };
SyntaxNode {
root: root.clone(),
red: red.get_child(i).unwrap(),
}
})
} }
pub fn parent(&self) -> Option<SyntaxNode<R>> { pub fn parent(&self) -> Option<SyntaxNode<R>> {
@ -192,6 +187,26 @@ impl<R: TreeRoot> fmt::Debug for SyntaxNode<R> {
} }
} }
#[derive(Debug)]
pub struct SyntaxNodeChildren<R: TreeRoot> {
parent: SyntaxNode<R>,
iter: Range<usize>,
}
impl<R: TreeRoot> Iterator for SyntaxNodeChildren<R> {
type Item = SyntaxNode<R>;
fn next(&mut self) -> Option<SyntaxNode<R>> {
self.iter.next().map(|i| {
let red = self.parent.red();
SyntaxNode {
root: self.parent.root.clone(),
red: red.get_child(i).unwrap(),
}
})
}
}
fn has_short_text(kind: SyntaxKind) -> bool { fn has_short_text(kind: SyntaxKind) -> bool {
match kind { match kind {
IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true,