Refactor Frame
.
It is currently an enum and the `tts` and `idx` fields are repeated across the two variants. This commit splits it into a struct `Frame` and an enum `FrameKind`, to factor out the duplication. The commit also renames `Frame::new` as `Frame::new_delimited` and adds `Frame::new_sequence`. I.e. both variants now have a constructor.
This commit is contained in:
parent
5ac017e772
commit
3a3a15d753
1 changed files with 50 additions and 48 deletions
|
@ -39,26 +39,32 @@ impl MutVisitor for Marker {
|
|||
}
|
||||
|
||||
/// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`).
|
||||
enum Frame<'a> {
|
||||
Delimited {
|
||||
tts: &'a [mbe::TokenTree],
|
||||
idx: usize,
|
||||
delim: Delimiter,
|
||||
span: DelimSpan,
|
||||
spacing: DelimSpacing,
|
||||
},
|
||||
Sequence {
|
||||
tts: &'a [mbe::TokenTree],
|
||||
idx: usize,
|
||||
sep: Option<Token>,
|
||||
kleene_op: KleeneOp,
|
||||
},
|
||||
struct Frame<'a> {
|
||||
tts: &'a [mbe::TokenTree],
|
||||
idx: usize,
|
||||
kind: FrameKind,
|
||||
}
|
||||
|
||||
enum FrameKind {
|
||||
Delimited { delim: Delimiter, span: DelimSpan, spacing: DelimSpacing },
|
||||
Sequence { sep: Option<Token>, kleene_op: KleeneOp },
|
||||
}
|
||||
|
||||
impl<'a> Frame<'a> {
|
||||
/// Construct a new frame around the delimited set of tokens.
|
||||
fn new(src: &'a mbe::Delimited, span: DelimSpan, spacing: DelimSpacing) -> Frame<'a> {
|
||||
Frame::Delimited { tts: &src.tts, idx: 0, delim: src.delim, span, spacing }
|
||||
fn new_delimited(src: &'a mbe::Delimited, span: DelimSpan, spacing: DelimSpacing) -> Frame<'a> {
|
||||
Frame {
|
||||
tts: &src.tts,
|
||||
idx: 0,
|
||||
kind: FrameKind::Delimited { delim: src.delim, span, spacing },
|
||||
}
|
||||
}
|
||||
|
||||
fn new_sequence(
|
||||
src: &'a mbe::SequenceRepetition,
|
||||
sep: Option<Token>,
|
||||
kleene_op: KleeneOp,
|
||||
) -> Frame<'a> {
|
||||
Frame { tts: &src.tts, idx: 0, kind: FrameKind::Sequence { sep, kleene_op } }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,13 +72,9 @@ impl<'a> Iterator for Frame<'a> {
|
|||
type Item = &'a mbe::TokenTree;
|
||||
|
||||
fn next(&mut self) -> Option<&'a mbe::TokenTree> {
|
||||
match self {
|
||||
Frame::Delimited { tts, idx, .. } | Frame::Sequence { tts, idx, .. } => {
|
||||
let res = tts.get(*idx);
|
||||
*idx += 1;
|
||||
res
|
||||
}
|
||||
}
|
||||
let res = self.tts.get(self.idx);
|
||||
self.idx += 1;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,8 +113,11 @@ pub(super) fn transcribe<'a>(
|
|||
// We descend into the RHS (`src`), expanding things as we go. This stack contains the things
|
||||
// we have yet to expand/are still expanding. We start the stack off with the whole RHS. The
|
||||
// choice of spacing values doesn't matter.
|
||||
let mut stack: SmallVec<[Frame<'_>; 1]> =
|
||||
smallvec![Frame::new(src, src_span, DelimSpacing::new(Spacing::Alone, Spacing::Alone))];
|
||||
let mut stack: SmallVec<[Frame<'_>; 1]> = smallvec![Frame::new_delimited(
|
||||
src,
|
||||
src_span,
|
||||
DelimSpacing::new(Spacing::Alone, Spacing::Alone)
|
||||
)];
|
||||
|
||||
// As we descend in the RHS, we will need to be able to match nested sequences of matchers.
|
||||
// `repeats` keeps track of where we are in matching at each level, with the last element being
|
||||
|
@ -142,11 +147,12 @@ pub(super) fn transcribe<'a>(
|
|||
|
||||
// Otherwise, if we have just reached the end of a sequence and we can keep repeating,
|
||||
// go back to the beginning of the sequence.
|
||||
if let Frame::Sequence { idx, sep, .. } = stack.last_mut().unwrap() {
|
||||
let frame = stack.last_mut().unwrap();
|
||||
if let FrameKind::Sequence { sep, .. } = &frame.kind {
|
||||
let (repeat_idx, repeat_len) = repeats.last_mut().unwrap();
|
||||
*repeat_idx += 1;
|
||||
if repeat_idx < repeat_len {
|
||||
*idx = 0;
|
||||
frame.idx = 0;
|
||||
if let Some(sep) = sep {
|
||||
result.push(TokenTree::Token(sep.clone(), Spacing::Alone));
|
||||
}
|
||||
|
@ -157,16 +163,16 @@ pub(super) fn transcribe<'a>(
|
|||
// We are done with the top of the stack. Pop it. Depending on what it was, we do
|
||||
// different things. Note that the outermost item must be the delimited, wrapped RHS
|
||||
// that was passed in originally to `transcribe`.
|
||||
match stack.pop().unwrap() {
|
||||
match stack.pop().unwrap().kind {
|
||||
// Done with a sequence. Pop from repeats.
|
||||
Frame::Sequence { .. } => {
|
||||
FrameKind::Sequence { .. } => {
|
||||
repeats.pop();
|
||||
}
|
||||
|
||||
// We are done processing a Delimited. If this is the top-level delimited, we are
|
||||
// done. Otherwise, we unwind the result_stack to append what we have produced to
|
||||
// any previous results.
|
||||
Frame::Delimited { delim, span, mut spacing, .. } => {
|
||||
FrameKind::Delimited { delim, span, mut spacing, .. } => {
|
||||
// Hack to force-insert a space after `]` in certain case.
|
||||
// See discussion of the `hex-literal` crate in #114571.
|
||||
if delim == Delimiter::Bracket {
|
||||
|
@ -192,7 +198,7 @@ pub(super) fn transcribe<'a>(
|
|||
// We are descending into a sequence. We first make sure that the matchers in the RHS
|
||||
// and the matches in `interp` have the same shape. Otherwise, either the caller or the
|
||||
// macro writer has made a mistake.
|
||||
seq @ mbe::TokenTree::Sequence(_, delimited) => {
|
||||
seq @ mbe::TokenTree::Sequence(_, seq_rep) => {
|
||||
match lockstep_iter_size(seq, interp, &repeats) {
|
||||
LockstepIterSize::Unconstrained => {
|
||||
return Err(cx
|
||||
|
@ -233,12 +239,11 @@ pub(super) fn transcribe<'a>(
|
|||
// The first time we encounter the sequence we push it to the stack. It
|
||||
// then gets reused (see the beginning of the loop) until we are done
|
||||
// repeating.
|
||||
stack.push(Frame::Sequence {
|
||||
idx: 0,
|
||||
sep: seq.separator.clone(),
|
||||
tts: &delimited.tts,
|
||||
kleene_op: seq.kleene.op,
|
||||
});
|
||||
stack.push(Frame::new_sequence(
|
||||
seq_rep,
|
||||
seq.separator.clone(),
|
||||
seq.kleene.op,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,13 +299,7 @@ pub(super) fn transcribe<'a>(
|
|||
// the previous results (from outside the Delimited).
|
||||
mbe::TokenTree::Delimited(mut span, spacing, delimited) => {
|
||||
mut_visit::visit_delim_span(&mut span, &mut marker);
|
||||
stack.push(Frame::Delimited {
|
||||
tts: &delimited.tts,
|
||||
delim: delimited.delim,
|
||||
idx: 0,
|
||||
span,
|
||||
spacing: *spacing,
|
||||
});
|
||||
stack.push(Frame::new_delimited(delimited, span, *spacing));
|
||||
result_stack.push(mem::take(&mut result));
|
||||
}
|
||||
|
||||
|
@ -358,10 +357,13 @@ fn maybe_use_metavar_location(
|
|||
) -> TokenTree {
|
||||
let undelimited_seq = matches!(
|
||||
stack.last(),
|
||||
Some(Frame::Sequence {
|
||||
Some(Frame {
|
||||
tts: [_],
|
||||
sep: None,
|
||||
kleene_op: KleeneOp::ZeroOrMore | KleeneOp::OneOrMore,
|
||||
kind: FrameKind::Sequence {
|
||||
sep: None,
|
||||
kleene_op: KleeneOp::ZeroOrMore | KleeneOp::OneOrMore,
|
||||
..
|
||||
},
|
||||
..
|
||||
})
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue