aboutsummaryrefslogtreecommitdiff
path: root/quote/src/runtime.rs
diff options
context:
space:
mode:
Diffstat (limited to 'quote/src/runtime.rs')
-rw-r--r--quote/src/runtime.rs373
1 files changed, 0 insertions, 373 deletions
diff --git a/quote/src/runtime.rs b/quote/src/runtime.rs
deleted file mode 100644
index 4a1c14c..0000000
--- a/quote/src/runtime.rs
+++ /dev/null
@@ -1,373 +0,0 @@
-use crate::{IdentFragment, ToTokens, TokenStreamExt};
-use std::fmt;
-use std::ops::BitOr;
-
-pub use proc_macro2::*;
-
-pub struct HasIterator; // True
-pub struct ThereIsNoIteratorInRepetition; // False
-
-impl BitOr<ThereIsNoIteratorInRepetition> for ThereIsNoIteratorInRepetition {
- type Output = ThereIsNoIteratorInRepetition;
- fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition {
- ThereIsNoIteratorInRepetition
- }
-}
-
-impl BitOr<ThereIsNoIteratorInRepetition> for HasIterator {
- type Output = HasIterator;
- fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator {
- HasIterator
- }
-}
-
-impl BitOr<HasIterator> for ThereIsNoIteratorInRepetition {
- type Output = HasIterator;
- fn bitor(self, _rhs: HasIterator) -> HasIterator {
- HasIterator
- }
-}
-
-impl BitOr<HasIterator> for HasIterator {
- type Output = HasIterator;
- fn bitor(self, _rhs: HasIterator) -> HasIterator {
- HasIterator
- }
-}
-
-/// Extension traits used by the implementation of `quote!`. These are defined
-/// in separate traits, rather than as a single trait due to ambiguity issues.
-///
-/// These traits expose a `quote_into_iter` method which should allow calling
-/// whichever impl happens to be applicable. Calling that method repeatedly on
-/// the returned value should be idempotent.
-pub mod ext {
- use super::RepInterp;
- use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter};
- use crate::ToTokens;
- use std::collections::btree_set::{self, BTreeSet};
- use std::slice;
-
- /// Extension trait providing the `quote_into_iter` method on iterators.
- pub trait RepIteratorExt: Iterator + Sized {
- fn quote_into_iter(self) -> (Self, HasIter) {
- (self, HasIter)
- }
- }
-
- impl<T: Iterator> RepIteratorExt for T {}
-
- /// Extension trait providing the `quote_into_iter` method for
- /// non-iterable types. These types interpolate the same value in each
- /// iteration of the repetition.
- pub trait RepToTokensExt {
- /// Pretend to be an iterator for the purposes of `quote_into_iter`.
- /// This allows repeated calls to `quote_into_iter` to continue
- /// correctly returning DoesNotHaveIter.
- fn next(&self) -> Option<&Self> {
- Some(self)
- }
-
- fn quote_into_iter(&self) -> (&Self, DoesNotHaveIter) {
- (self, DoesNotHaveIter)
- }
- }
-
- impl<T: ToTokens + ?Sized> RepToTokensExt for T {}
-
- /// Extension trait providing the `quote_into_iter` method for types that
- /// can be referenced as an iterator.
- pub trait RepAsIteratorExt<'q> {
- type Iter: Iterator;
-
- fn quote_into_iter(&'q self) -> (Self::Iter, HasIter);
- }
-
- impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a T {
- type Iter = T::Iter;
-
- fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
- <T as RepAsIteratorExt>::quote_into_iter(*self)
- }
- }
-
- impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a mut T {
- type Iter = T::Iter;
-
- fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
- <T as RepAsIteratorExt>::quote_into_iter(*self)
- }
- }
-
- impl<'q, T: 'q> RepAsIteratorExt<'q> for [T] {
- type Iter = slice::Iter<'q, T>;
-
- fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
- (self.iter(), HasIter)
- }
- }
-
- impl<'q, T: 'q> RepAsIteratorExt<'q> for Vec<T> {
- type Iter = slice::Iter<'q, T>;
-
- fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
- (self.iter(), HasIter)
- }
- }
-
- impl<'q, T: 'q> RepAsIteratorExt<'q> for BTreeSet<T> {
- type Iter = btree_set::Iter<'q, T>;
-
- fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
- (self.iter(), HasIter)
- }
- }
-
- macro_rules! array_rep_slice {
- ($($l:tt)*) => {
- $(
- impl<'q, T: 'q> RepAsIteratorExt<'q> for [T; $l] {
- type Iter = slice::Iter<'q, T>;
-
- fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
- (self.iter(), HasIter)
- }
- }
- )*
- }
- }
-
- array_rep_slice!(
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
- 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
- );
-
- impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp<T> {
- type Iter = T::Iter;
-
- fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
- self.0.quote_into_iter()
- }
- }
-}
-
-// Helper type used within interpolations to allow for repeated binding names.
-// Implements the relevant traits, and exports a dummy `next()` method.
-#[derive(Copy, Clone)]
-pub struct RepInterp<T>(pub T);
-
-impl<T> RepInterp<T> {
- // This method is intended to look like `Iterator::next`, and is called when
- // a name is bound multiple times, as the previous binding will shadow the
- // original `Iterator` object. This allows us to avoid advancing the
- // iterator multiple times per iteration.
- pub fn next(self) -> Option<T> {
- Some(self.0)
- }
-}
-
-impl<T: Iterator> Iterator for RepInterp<T> {
- type Item = T::Item;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.0.next()
- }
-}
-
-impl<T: ToTokens> ToTokens for RepInterp<T> {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- self.0.to_tokens(tokens);
- }
-}
-
-fn is_ident_start(c: u8) -> bool {
- (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_'
-}
-
-fn is_ident_continue(c: u8) -> bool {
- (b'a' <= c && c <= b'z') || (b'A' <= c && c <= b'Z') || c == b'_' || (b'0' <= c && c <= b'9')
-}
-
-fn is_ident(token: &str) -> bool {
- let mut iter = token.bytes();
- let first_ok = iter.next().map(is_ident_start).unwrap_or(false);
-
- first_ok && iter.all(is_ident_continue)
-}
-
-pub fn parse(tokens: &mut TokenStream, span: Span, s: &str) {
- if is_ident(s) {
- // Fast path, since idents are the most common token.
- tokens.append(Ident::new(s, span));
- } else {
- let s: TokenStream = s.parse().expect("invalid token stream");
- tokens.extend(s.into_iter().map(|mut t| {
- t.set_span(span);
- t
- }));
- }
-}
-
-macro_rules! push_punct {
- ($name:ident $char1:tt) => {
- pub fn $name(tokens: &mut TokenStream, span: Span) {
- let mut punct = Punct::new($char1, Spacing::Alone);
- punct.set_span(span);
- tokens.append(punct);
- }
- };
- ($name:ident $char1:tt $char2:tt) => {
- pub fn $name(tokens: &mut TokenStream, span: Span) {
- let mut punct = Punct::new($char1, Spacing::Joint);
- punct.set_span(span);
- tokens.append(punct);
- let mut punct = Punct::new($char2, Spacing::Alone);
- punct.set_span(span);
- tokens.append(punct);
- }
- };
- ($name:ident $char1:tt $char2:tt $char3:tt) => {
- pub fn $name(tokens: &mut TokenStream, span: Span) {
- let mut punct = Punct::new($char1, Spacing::Joint);
- punct.set_span(span);
- tokens.append(punct);
- let mut punct = Punct::new($char2, Spacing::Joint);
- punct.set_span(span);
- tokens.append(punct);
- let mut punct = Punct::new($char3, Spacing::Alone);
- punct.set_span(span);
- tokens.append(punct);
- }
- };
-}
-
-push_punct!(push_add '+');
-push_punct!(push_add_eq '+' '=');
-push_punct!(push_and '&');
-push_punct!(push_and_and '&' '&');
-push_punct!(push_and_eq '&' '=');
-push_punct!(push_at '@');
-push_punct!(push_bang '!');
-push_punct!(push_caret '^');
-push_punct!(push_caret_eq '^' '=');
-push_punct!(push_colon ':');
-push_punct!(push_colon2 ':' ':');
-push_punct!(push_comma ',');
-push_punct!(push_div '/');
-push_punct!(push_div_eq '/' '=');
-push_punct!(push_dot '.');
-push_punct!(push_dot2 '.' '.');
-push_punct!(push_dot3 '.' '.' '.');
-push_punct!(push_dot_dot_eq '.' '.' '=');
-push_punct!(push_eq '=');
-push_punct!(push_eq_eq '=' '=');
-push_punct!(push_ge '>' '=');
-push_punct!(push_gt '>');
-push_punct!(push_le '<' '=');
-push_punct!(push_lt '<');
-push_punct!(push_mul_eq '*' '=');
-push_punct!(push_ne '!' '=');
-push_punct!(push_or '|');
-push_punct!(push_or_eq '|' '=');
-push_punct!(push_or_or '|' '|');
-push_punct!(push_pound '#');
-push_punct!(push_question '?');
-push_punct!(push_rarrow '-' '>');
-push_punct!(push_larrow '<' '-');
-push_punct!(push_rem '%');
-push_punct!(push_rem_eq '%' '=');
-push_punct!(push_fat_arrow '=' '>');
-push_punct!(push_semi ';');
-push_punct!(push_shl '<' '<');
-push_punct!(push_shl_eq '<' '<' '=');
-push_punct!(push_shr '>' '>');
-push_punct!(push_shr_eq '>' '>' '=');
-push_punct!(push_star '*');
-push_punct!(push_sub '-');
-push_punct!(push_sub_eq '-' '=');
-
-// Helper method for constructing identifiers from the `format_ident!` macro,
-// handling `r#` prefixes.
-//
-// Directly parsing the input string may produce a valid identifier,
-// although the input string was invalid, due to ignored characters such as
-// whitespace and comments. Instead, we always create a non-raw identifier
-// to validate that the string is OK, and only parse again if needed.
-//
-// The `is_ident` method defined above is insufficient for validation, as it
-// will reject non-ASCII identifiers.
-pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
- let span = span.unwrap_or_else(Span::call_site);
-
- let is_raw = id.starts_with("r#");
- let unraw = Ident::new(if is_raw { &id[2..] } else { id }, span);
- if !is_raw {
- return unraw;
- }
-
- // At this point, the identifier is raw, and the unraw-ed version of it was
- // successfully converted into an identifier. Try to produce a valid raw
- // identifier by running the `TokenStream` parser, and unwrapping the first
- // token as an `Ident`.
- //
- // FIXME: When `Ident::new_raw` becomes stable, this method should be
- // updated to call it when available.
- match id.parse::<TokenStream>() {
- Ok(ts) => {
- let mut iter = ts.into_iter();
- match (iter.next(), iter.next()) {
- (Some(TokenTree::Ident(mut id)), None) => {
- id.set_span(span);
- id
- }
- _ => unreachable!("valid raw ident fails to parse"),
- }
- }
- Err(_) => unreachable!("valid raw ident fails to parse"),
- }
-}
-
-// Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
-// macro, and exposes span information from these fragments.
-//
-// This struct also has forwarding implementations of the formatting traits
-// `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within
-// `format_ident!`.
-#[derive(Copy, Clone)]
-pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
-
-impl<T: IdentFragment> IdentFragmentAdapter<T> {
- pub fn span(&self) -> Option<Span> {
- self.0.span()
- }
-}
-
-impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- IdentFragment::fmt(&self.0, f)
- }
-}
-
-impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Octal::fmt(&self.0, f)
- }
-}
-
-impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::LowerHex::fmt(&self.0, f)
- }
-}
-
-impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::UpperHex::fmt(&self.0, f)
- }
-}
-
-impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Binary::fmt(&self.0, f)
- }
-}