Skip to content

Commit 8dca72b

Browse files
committed
Optimize syntax::tokenstream::Cursor.
1 parent 0143774 commit 8dca72b

File tree

2 files changed

+63
-60
lines changed

2 files changed

+63
-60
lines changed

src/libproc_macro_plugin/qquote.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use syntax::symbol::Symbol;
1717
use syntax::tokenstream::{self, Delimited, TokenTree, TokenStream};
1818
use syntax_pos::DUMMY_SP;
1919

20+
use std::iter;
2021
use std::rc::Rc;
2122

2223
pub fn qquote<'cx>(stream: TokenStream) -> TokenStream {
@@ -75,14 +76,14 @@ impl Quote for TokenStream {
7576
return quote!(::syntax::tokenstream::TokenStream::empty());
7677
}
7778

78-
struct Quote(tokenstream::Cursor);
79+
struct Quote(iter::Peekable<tokenstream::Cursor>);
7980

8081
impl Iterator for Quote {
8182
type Item = TokenStream;
8283

8384
fn next(&mut self) -> Option<TokenStream> {
8485
let is_unquote = match self.0.peek() {
85-
Some(TokenTree::Token(_, Token::Ident(ident))) if ident.name == "unquote" => {
86+
Some(&TokenTree::Token(_, Token::Ident(ident))) if ident.name == "unquote" => {
8687
self.0.next();
8788
true
8889
}
@@ -96,7 +97,7 @@ impl Quote for TokenStream {
9697
}
9798
}
9899

99-
let quoted = Quote(self.trees()).collect::<TokenStream>();
100+
let quoted = Quote(self.trees().peekable()).collect::<TokenStream>();
100101
quote!([(unquote quoted)].iter().cloned().collect::<::syntax::tokenstream::TokenStream>())
101102
}
102103
}

src/libsyntax/tokenstream.rs

+59-57
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ impl From<TokenTree> for TokenStream {
299299

300300
impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
301301
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
302-
TokenStream::concat(iter.into_iter().map(Into::into))
302+
TokenStream::concat(iter.into_iter().map(Into::into).collect::<Vec<_>>())
303303
}
304304
}
305305

@@ -323,19 +323,16 @@ impl TokenStream {
323323
}
324324
}
325325

326-
pub fn concat<I: IntoIterator<Item = TokenStream>>(streams: I) -> TokenStream {
327-
let mut streams = streams.into_iter().filter(|stream| !stream.is_empty());
328-
let first_stream = match streams.next() {
329-
Some(stream) => stream,
330-
None => return TokenStream::empty(),
331-
};
332-
let second_stream = match streams.next() {
333-
Some(stream) => stream,
334-
None => return first_stream,
335-
};
336-
let mut vec = vec![first_stream, second_stream];
337-
vec.extend(streams);
338-
TokenStream { kind: TokenStreamKind::Stream(RcSlice::new(vec)) }
326+
pub fn concat(mut streams: Vec<TokenStream>) -> TokenStream {
327+
match streams.len() {
328+
0 => TokenStream::empty(),
329+
1 => TokenStream::from(streams.pop().unwrap()),
330+
_ => TokenStream::concat_rc_slice(RcSlice::new(streams)),
331+
}
332+
}
333+
334+
fn concat_rc_slice(streams: RcSlice<TokenStream>) -> TokenStream {
335+
TokenStream { kind: TokenStreamKind::Stream(streams) }
339336
}
340337

341338
pub fn trees(&self) -> Cursor {
@@ -357,62 +354,67 @@ impl TokenStream {
357354
}
358355
}
359356

360-
pub struct Cursor {
361-
current_frame: CursorFrame,
362-
stack: Vec<CursorFrame>,
357+
pub struct Cursor(CursorKind);
358+
359+
enum CursorKind {
360+
Empty,
361+
Tree(TokenTree, bool /* consumed? */),
362+
Stream(StreamCursor),
363+
}
364+
365+
struct StreamCursor {
366+
stream: RcSlice<TokenStream>,
367+
index: usize,
368+
stack: Vec<(RcSlice<TokenStream>, usize)>,
363369
}
364370

365371
impl Iterator for Cursor {
366372
type Item = TokenTree;
367373

368374
fn next(&mut self) -> Option<TokenTree> {
369-
let tree = self.peek();
370-
self.current_frame = self.stack.pop().unwrap_or(CursorFrame::Empty);
371-
tree
372-
}
373-
}
374-
375-
enum CursorFrame {
376-
Empty,
377-
Tree(TokenTree),
378-
Stream(RcSlice<TokenStream>, usize),
379-
}
375+
let cursor = match self.0 {
376+
CursorKind::Stream(ref mut cursor) => cursor,
377+
CursorKind::Tree(ref tree, ref mut consumed @ false) => {
378+
*consumed = true;
379+
return Some(tree.clone());
380+
}
381+
_ => return None,
382+
};
380383

381-
impl CursorFrame {
382-
fn new(stream: TokenStream) -> Self {
383-
match stream.kind {
384-
TokenStreamKind::Empty => CursorFrame::Empty,
385-
TokenStreamKind::Tree(tree) => CursorFrame::Tree(tree),
386-
TokenStreamKind::Stream(stream) => CursorFrame::Stream(stream, 0),
384+
loop {
385+
if cursor.index < cursor.stream.len() {
386+
match cursor.stream[cursor.index].kind.clone() {
387+
TokenStreamKind::Tree(tree) => {
388+
cursor.index += 1;
389+
return Some(tree);
390+
}
391+
TokenStreamKind::Stream(stream) => {
392+
cursor.stack.push((mem::replace(&mut cursor.stream, stream),
393+
mem::replace(&mut cursor.index, 0) + 1));
394+
}
395+
TokenStreamKind::Empty => {
396+
cursor.index += 1;
397+
}
398+
}
399+
} else if let Some((stream, index)) = cursor.stack.pop() {
400+
cursor.stream = stream;
401+
cursor.index = index;
402+
} else {
403+
return None;
404+
}
387405
}
388406
}
389407
}
390408

391409
impl Cursor {
392410
fn new(stream: TokenStream) -> Self {
393-
Cursor {
394-
current_frame: CursorFrame::new(stream),
395-
stack: Vec::new(),
396-
}
397-
}
398-
399-
pub fn peek(&mut self) -> Option<TokenTree> {
400-
while let CursorFrame::Stream(stream, index) =
401-
mem::replace(&mut self.current_frame, CursorFrame::Empty) {
402-
self.current_frame = if index == stream.len() {
403-
self.stack.pop().unwrap_or(CursorFrame::Empty)
404-
} else {
405-
let frame = CursorFrame::new(stream[index].clone());
406-
self.stack.push(CursorFrame::Stream(stream, index + 1));
407-
frame
408-
};
409-
}
410-
411-
match self.current_frame {
412-
CursorFrame::Empty => None,
413-
CursorFrame::Tree(ref tree) => Some(tree.clone()),
414-
CursorFrame::Stream(..) => unreachable!(),
415-
}
411+
Cursor(match stream.kind {
412+
TokenStreamKind::Empty => CursorKind::Empty,
413+
TokenStreamKind::Tree(tree) => CursorKind::Tree(tree, false),
414+
TokenStreamKind::Stream(stream) => {
415+
CursorKind::Stream(StreamCursor { stream: stream, index: 0, stack: Vec::new() })
416+
}
417+
})
416418
}
417419
}
418420

0 commit comments

Comments
 (0)