1
Fork 0

Optimize syntax::tokenstream::Cursor.

This commit is contained in:
Jeffrey Seyfried 2017-02-18 12:45:32 +00:00
parent 0143774cb5
commit 8dca72be9b
2 changed files with 63 additions and 60 deletions

View file

@ -17,6 +17,7 @@ use syntax::symbol::Symbol;
use syntax::tokenstream::{self, Delimited, TokenTree, TokenStream}; use syntax::tokenstream::{self, Delimited, TokenTree, TokenStream};
use syntax_pos::DUMMY_SP; use syntax_pos::DUMMY_SP;
use std::iter;
use std::rc::Rc; use std::rc::Rc;
pub fn qquote<'cx>(stream: TokenStream) -> TokenStream { pub fn qquote<'cx>(stream: TokenStream) -> TokenStream {
@ -75,14 +76,14 @@ impl Quote for TokenStream {
return quote!(::syntax::tokenstream::TokenStream::empty()); return quote!(::syntax::tokenstream::TokenStream::empty());
} }
struct Quote(tokenstream::Cursor); struct Quote(iter::Peekable<tokenstream::Cursor>);
impl Iterator for Quote { impl Iterator for Quote {
type Item = TokenStream; type Item = TokenStream;
fn next(&mut self) -> Option<TokenStream> { fn next(&mut self) -> Option<TokenStream> {
let is_unquote = match self.0.peek() { let is_unquote = match self.0.peek() {
Some(TokenTree::Token(_, Token::Ident(ident))) if ident.name == "unquote" => { Some(&TokenTree::Token(_, Token::Ident(ident))) if ident.name == "unquote" => {
self.0.next(); self.0.next();
true true
} }
@ -96,7 +97,7 @@ impl Quote for TokenStream {
} }
} }
let quoted = Quote(self.trees()).collect::<TokenStream>(); let quoted = Quote(self.trees().peekable()).collect::<TokenStream>();
quote!([(unquote quoted)].iter().cloned().collect::<::syntax::tokenstream::TokenStream>()) quote!([(unquote quoted)].iter().cloned().collect::<::syntax::tokenstream::TokenStream>())
} }
} }

View file

@ -299,7 +299,7 @@ impl From<TokenTree> for TokenStream {
impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream { impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
TokenStream::concat(iter.into_iter().map(Into::into)) TokenStream::concat(iter.into_iter().map(Into::into).collect::<Vec<_>>())
} }
} }
@ -323,19 +323,16 @@ impl TokenStream {
} }
} }
pub fn concat<I: IntoIterator<Item = TokenStream>>(streams: I) -> TokenStream { pub fn concat(mut streams: Vec<TokenStream>) -> TokenStream {
let mut streams = streams.into_iter().filter(|stream| !stream.is_empty()); match streams.len() {
let first_stream = match streams.next() { 0 => TokenStream::empty(),
Some(stream) => stream, 1 => TokenStream::from(streams.pop().unwrap()),
None => return TokenStream::empty(), _ => TokenStream::concat_rc_slice(RcSlice::new(streams)),
}; }
let second_stream = match streams.next() { }
Some(stream) => stream,
None => return first_stream, fn concat_rc_slice(streams: RcSlice<TokenStream>) -> TokenStream {
}; TokenStream { kind: TokenStreamKind::Stream(streams) }
let mut vec = vec![first_stream, second_stream];
vec.extend(streams);
TokenStream { kind: TokenStreamKind::Stream(RcSlice::new(vec)) }
} }
pub fn trees(&self) -> Cursor { pub fn trees(&self) -> Cursor {
@ -357,62 +354,67 @@ impl TokenStream {
} }
} }
pub struct Cursor { pub struct Cursor(CursorKind);
current_frame: CursorFrame,
stack: Vec<CursorFrame>, enum CursorKind {
Empty,
Tree(TokenTree, bool /* consumed? */),
Stream(StreamCursor),
}
struct StreamCursor {
stream: RcSlice<TokenStream>,
index: usize,
stack: Vec<(RcSlice<TokenStream>, usize)>,
} }
impl Iterator for Cursor { impl Iterator for Cursor {
type Item = TokenTree; type Item = TokenTree;
fn next(&mut self) -> Option<TokenTree> { fn next(&mut self) -> Option<TokenTree> {
let tree = self.peek(); let cursor = match self.0 {
self.current_frame = self.stack.pop().unwrap_or(CursorFrame::Empty); CursorKind::Stream(ref mut cursor) => cursor,
tree CursorKind::Tree(ref tree, ref mut consumed @ false) => {
} *consumed = true;
} return Some(tree.clone());
}
_ => return None,
};
enum CursorFrame { loop {
Empty, if cursor.index < cursor.stream.len() {
Tree(TokenTree), match cursor.stream[cursor.index].kind.clone() {
Stream(RcSlice<TokenStream>, usize), TokenStreamKind::Tree(tree) => {
} cursor.index += 1;
return Some(tree);
impl CursorFrame { }
fn new(stream: TokenStream) -> Self { TokenStreamKind::Stream(stream) => {
match stream.kind { cursor.stack.push((mem::replace(&mut cursor.stream, stream),
TokenStreamKind::Empty => CursorFrame::Empty, mem::replace(&mut cursor.index, 0) + 1));
TokenStreamKind::Tree(tree) => CursorFrame::Tree(tree), }
TokenStreamKind::Stream(stream) => CursorFrame::Stream(stream, 0), TokenStreamKind::Empty => {
cursor.index += 1;
}
}
} else if let Some((stream, index)) = cursor.stack.pop() {
cursor.stream = stream;
cursor.index = index;
} else {
return None;
}
} }
} }
} }
impl Cursor { impl Cursor {
fn new(stream: TokenStream) -> Self { fn new(stream: TokenStream) -> Self {
Cursor { Cursor(match stream.kind {
current_frame: CursorFrame::new(stream), TokenStreamKind::Empty => CursorKind::Empty,
stack: Vec::new(), TokenStreamKind::Tree(tree) => CursorKind::Tree(tree, false),
} TokenStreamKind::Stream(stream) => {
} CursorKind::Stream(StreamCursor { stream: stream, index: 0, stack: Vec::new() })
}
pub fn peek(&mut self) -> Option<TokenTree> { })
while let CursorFrame::Stream(stream, index) =
mem::replace(&mut self.current_frame, CursorFrame::Empty) {
self.current_frame = if index == stream.len() {
self.stack.pop().unwrap_or(CursorFrame::Empty)
} else {
let frame = CursorFrame::new(stream[index].clone());
self.stack.push(CursorFrame::Stream(stream, index + 1));
frame
};
}
match self.current_frame {
CursorFrame::Empty => None,
CursorFrame::Tree(ref tree) => Some(tree.clone()),
CursorFrame::Stream(..) => unreachable!(),
}
} }
} }