Optimize syntax::tokenstream::Cursor
.
This commit is contained in:
parent
0143774cb5
commit
8dca72be9b
2 changed files with 63 additions and 60 deletions
|
@ -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>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue