Skip to content

Commit

Permalink
Merge pull request #215 from dtolnay/comments
Browse files Browse the repository at this point in the history
Touch up comments from PR #211
  • Loading branch information
dtolnay committed Mar 25, 2022
2 parents 927317c + 8e11f47 commit 7c357e8
Showing 1 changed file with 72 additions and 64 deletions.
136 changes: 72 additions & 64 deletions src/lib.rs
Expand Up @@ -661,67 +661,74 @@ macro_rules! quote_bind_next_or_break {
};
}

// The obvious way to implement this macro is as a tt muncher. This
// implementation does something more complex, for two reasons.
// - With a tt muncher it's easy to hit Rust's built-in `recursion_limit`,
// which this implementation avoids because it isn't tail recursive.
// - Compile times for a tt muncher are quadratic relative to the length of the
// input. This implementation is linear, so it will be faster (potentially
// much faster) for long inputs. However, the constant factors of this
// implementation are higher than that of a tt muncher, so it is somewhat
// slower than a tt muncher if there are many invocations with short inputs.
// The obvious way to write this macro is as a tt muncher. This implementation
// does something more complex for two reasons.
//
// - With a tt muncher it's easy to hit Rust's built-in recursion_limit, which
// this implementation avoids because it isn't tail recursive.
//
// - Compile times for a tt muncher are quadratic relative to the length of
// the input. This implementation is linear, so it will be faster
// (potentially much faster) for big inputs. However, the constant factors
// of this implementation are higher than that of a tt muncher, so it is
// somewhat slower than a tt muncher if there are many invocations with
// short inputs.
//
// An invocation like this:
// ```
// quote_each_token! { _s a b c d e f g h i j }
// ```
//
// quote_each_token!(_s a b c d e f g h i j);
//
// expands to this:
// ```
// quote_tokens_with_context! (_s
// (@ @ @ @ @ @ a b c d e f g h i j)
// (@ @ @ @ @ a b c d e f g h i j @)
// (@ @ @ @ a b c d e f g h i j @ @)
// (@ @ @ (a) (b) (c) (d) (e) (f) (g) (h) (i) (j) @ @ @)
// (@ @ a b c d e f g h i j @ @ @ @)
// (@ a b c d e f g h i j @ @ @ @ @)
// (a b c d e f g h i j @ @ @ @ @ @)
// );
// ```
// which expands to this:
// ```
// quote_token_with_context! (_s @ @ @ @ @ @ a);
// quote_token_with_context! (_s @ @ @ @ @ a b);
// quote_token_with_context! (_s @ @ @ @ a b c);
// quote_token_with_context! (_s @ @ @ (a) b c d);
// quote_token_with_context! (_s @ @ a (b) c d e);
// quote_token_with_context! (_s @ a b (c) d e f);
// quote_token_with_context! (_s a b c (d) e f g);
// quote_token_with_context! (_s b c d (e) f g h);
// quote_token_with_context! (_s c d e (f) g h i);
// quote_token_with_context! (_s d e f (g) h i j);
// quote_token_with_context! (_s e f g (h) i j @);
// quote_token_with_context! (_s f g h (i) j @ @);
// quote_token_with_context! (_s g h i (j) @ @ @);
// quote_token_with_context! (_s h i j @ @ @ @);
// quote_token_with_context! (_s i j @ @ @ @ @);
// quote_token_with_context! (_s j @ @ @ @ @ @);
// ``
// Without using recursion, we get one invocation of
// `quote_token_with_context!` for each tt, with three tts of context on either
// side. This is enough for the longest possible interpolation form (a
// repetition interpolation with a separator, of the form `# (var) , *`) to be
// fully represented with the first or last tt in the middle.
//
// quote_tokens_with_context!(_s
// (@ @ @ @ @ @ a b c d e f g h i j)
// (@ @ @ @ @ a b c d e f g h i j @)
// (@ @ @ @ a b c d e f g h i j @ @)
// (@ @ @ (a) (b) (c) (d) (e) (f) (g) (h) (i) (j) @ @ @)
// (@ @ a b c d e f g h i j @ @ @ @)
// (@ a b c d e f g h i j @ @ @ @ @)
// (a b c d e f g h i j @ @ @ @ @ @)
// );
//
// which gets transposed and expanded to this:
//
// quote_token_with_context!(_s @ @ @ @ @ @ a);
// quote_token_with_context!(_s @ @ @ @ @ a b);
// quote_token_with_context!(_s @ @ @ @ a b c);
// quote_token_with_context!(_s @ @ @ (a) b c d);
// quote_token_with_context!(_s @ @ a (b) c d e);
// quote_token_with_context!(_s @ a b (c) d e f);
// quote_token_with_context!(_s a b c (d) e f g);
// quote_token_with_context!(_s b c d (e) f g h);
// quote_token_with_context!(_s c d e (f) g h i);
// quote_token_with_context!(_s d e f (g) h i j);
// quote_token_with_context!(_s e f g (h) i j @);
// quote_token_with_context!(_s f g h (i) j @ @);
// quote_token_with_context!(_s g h i (j) @ @ @);
// quote_token_with_context!(_s h i j @ @ @ @);
// quote_token_with_context!(_s i j @ @ @ @ @);
// quote_token_with_context!(_s j @ @ @ @ @ @);
//
// Without having used muncher-style recursion, we get one invocation of
// quote_token_with_context for each original tt, with three tts of context on
// either side. This is enough for the longest possible interpolation form (a
// repetition with separator, as in `# (#var) , *`) to be fully represented with
// the first or last tt in the middle.
//
// The middle tt (surrounded by parentheses) is the tt being processed.
// - When it is a `#`, `quote_token_with_context!` can do an interpolation. The
// interpolation kind will depend on the three subsequent tts.
// - When it is within a later part of an interpolation, it can be ignored,
// because the interpolation has already been done.
// - When it is not part of an interpolation it can be treated normally.
// - When it is a `@` it can be ignored.
//
// The parentheses around the middle tt aren't necessary, but they make the
// macro definitions easier to read.
// - When it is a `#`, quote_token_with_context can do an interpolation. The
// interpolation kind will depend on the three subsequent tts.
//
// - When it is within a later part of an interpolation, it can be ignored
// because the interpolation has already been done.
//
// - When it is not part of an interpolation it can be pushed as a single
// token into the output.
//
// - When the middle token is an unparenthesized `@`, that call is one of the
// first 3 or last 3 calls of quote_token_with_context and does not
// correspond to one of the original input tokens, so turns into nothing.
#[macro_export]
#[doc(hidden)]
macro_rules! quote_each_token {
Expand All @@ -738,7 +745,7 @@ macro_rules! quote_each_token {
};
}

// See the comments on `quote_each_token`.
// See the explanation on quote_each_token.
#[macro_export]
#[doc(hidden)]
macro_rules! quote_each_token_spanned {
Expand All @@ -755,7 +762,7 @@ macro_rules! quote_each_token_spanned {
};
}

// See the comments on `quote_each_token`.
// See the explanation on quote_each_token.
#[macro_export]
#[doc(hidden)]
macro_rules! quote_tokens_with_context {
Expand All @@ -770,7 +777,7 @@ macro_rules! quote_tokens_with_context {
};
}

// See the comments on `quote_each_token`.
// See the explanation on quote_each_token.
#[macro_export]
#[doc(hidden)]
macro_rules! quote_tokens_with_context_spanned {
Expand All @@ -785,14 +792,15 @@ macro_rules! quote_tokens_with_context_spanned {
};
}

// See the comments on `quote_each_token`.
// See the explanation on quote_each_token.
#[macro_export]
#[doc(hidden)]
macro_rules! quote_token_with_context {
// `@` is the leading/trailing context character. Ignore it.
// Unparenthesized `@` indicates this call does not correspond to one of the
// original input tokens. Ignore it.
($tokens:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {};

// A repetition interpolation with no separator.
// A repetition with no separator.
($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{
use $crate::__private::ext::*;
let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
Expand All @@ -814,7 +822,7 @@ macro_rules! quote_token_with_context {
// ... and one step later.
($tokens:ident $b3:tt # ( $($inner:tt)* ) (*) $a1:tt $a2:tt $a3:tt) => {};

// A repetition interpolation with a separator.
// A repetition with separator.
($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) $sep:tt *) => {{
use $crate::__private::ext::*;
let mut _i = 0usize;
Expand Down Expand Up @@ -856,8 +864,8 @@ macro_rules! quote_token_with_context {
};
}

// See the comments on `quote_each_token`, and on the individual rules for
// `quote_token_with_context`.
// See the explanation on quote_each_token, and on the individual rules of
// quote_token_with_context.
#[macro_export]
#[doc(hidden)]
macro_rules! quote_token_with_context_spanned {
Expand Down

0 comments on commit 7c357e8

Please sign in to comment.