Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/tt/src/lib.rs')
| -rw-r--r-- | crates/tt/src/lib.rs | 52 |
1 files changed, 31 insertions, 21 deletions
diff --git a/crates/tt/src/lib.rs b/crates/tt/src/lib.rs index b3b0eeda75..9004bff53a 100644 --- a/crates/tt/src/lib.rs +++ b/crates/tt/src/lib.rs @@ -23,10 +23,10 @@ pub enum TokenTree<S> { } impl_from!(Leaf<S>, Subtree<S> for TokenTree); impl<S: Span> TokenTree<S> { - pub const fn empty(span: S) -> Self { + pub fn empty(span: S) -> Self { Self::Subtree(Subtree { delimiter: Delimiter::invisible_spanned(span), - token_trees: vec![], + token_trees: Box::new([]), }) } @@ -34,7 +34,7 @@ impl<S: Span> TokenTree<S> { match self { TokenTree::Leaf(_) => Subtree { delimiter: Delimiter::invisible_delim_spanned(span), - token_trees: vec![self], + token_trees: Box::new([self]), }, TokenTree::Subtree(s) => s, } @@ -69,25 +69,35 @@ impl_from!(Literal<S>, Punct<S>, Ident<S> for Leaf); #[derive(Clone, PartialEq, Eq, Hash)] pub struct Subtree<S> { pub delimiter: Delimiter<S>, - pub token_trees: Vec<TokenTree<S>>, + pub token_trees: Box<[TokenTree<S>]>, } impl<S: Span> Subtree<S> { - pub const fn empty(span: DelimSpan<S>) -> Self { - Subtree { delimiter: Delimiter::invisible_delim_spanned(span), token_trees: vec![] } + pub fn empty(span: DelimSpan<S>) -> Self { + Subtree { delimiter: Delimiter::invisible_delim_spanned(span), token_trees: Box::new([]) } } - pub fn visit_ids(&mut self, f: &mut impl FnMut(S) -> S) { - self.delimiter.open = f(self.delimiter.open); - self.delimiter.close = f(self.delimiter.close); - self.token_trees.iter_mut().for_each(|tt| match tt { - crate::TokenTree::Leaf(leaf) => match leaf { - crate::Leaf::Literal(it) => it.span = f(it.span), - crate::Leaf::Punct(it) => it.span = f(it.span), - crate::Leaf::Ident(it) => it.span = f(it.span), - }, - crate::TokenTree::Subtree(s) => s.visit_ids(f), - }) + /// This is slow, and should be avoided, as it will always reallocate! + pub fn push(&mut self, subtree: TokenTree<S>) { + let mut mutable_trees = std::mem::take(&mut self.token_trees).into_vec(); + + // Reserve exactly space for one element, to avoid `into_boxed_slice` having to reallocate again. + mutable_trees.reserve_exact(1); + mutable_trees.push(subtree); + + self.token_trees = mutable_trees.into_boxed_slice(); + } +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct SubtreeBuilder<S> { + pub delimiter: Delimiter<S>, + pub token_trees: Vec<TokenTree<S>>, +} + +impl<S> SubtreeBuilder<S> { + pub fn build(self) -> Subtree<S> { + Subtree { delimiter: self.delimiter, token_trees: self.token_trees.into_boxed_slice() } } } @@ -241,7 +251,7 @@ impl<S> fmt::Display for Subtree<S> { }; f.write_str(l)?; let mut needs_space = false; - for tt in &self.token_trees { + for tt in self.token_trees.iter() { if needs_space { f.write_str(" ")?; } @@ -316,7 +326,7 @@ impl<S> Subtree<S> { let mut res = String::new(); res.push_str(delim.0); let mut last = None; - for child in &self.token_trees { + for child in self.token_trees.iter() { let s = match child { TokenTree::Leaf(it) => { let s = match it { @@ -326,11 +336,11 @@ impl<S> Subtree<S> { }; match (it, last) { (Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => { - " ".to_string() + &s + " ".to_owned() + &s } (Leaf::Punct(_), Some(TokenTree::Leaf(Leaf::Punct(punct)))) => { if punct.spacing == Spacing::Alone { - " ".to_string() + &s + " ".to_owned() + &s } else { s } |