All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Hindborg <nmi@metaspace.dk>
To: Andreas Hindborg <nmi@metaspace.dk>
Cc: y86-dev@protonmail.com, "Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Wedson Almeida Filho" <wedsonaf@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Alice Ryhl" <alice@ryhl.io>,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
	patches@lists.linux.dev
Subject: Re: [PATCH v3 01/13] rust: macros: add `quote!` macro
Date: Thu, 30 Mar 2023 14:01:21 +0200	[thread overview]
Message-ID: <87355m5tvs.fsf@metaspace.dk> (raw)
In-Reply-To: <877cuy5ur2.fsf@metaspace.dk>


Andreas Hindborg <nmi@metaspace.dk> writes:

> y86-dev@protonmail.com writes:
>
>> From: Gary Guo <gary@garyguo.net>
>>
>> Add the `quote!` macro for creating `TokenStream`s directly via the
>> given Rust tokens. It also supports repetitions using iterators.
>>
>> It will be used by the pin-init API proc-macros to generate code.
>>
>> Signed-off-by: Gary Guo <gary@garyguo.net>
>> Signed-off-by: Benno Lossin <y86-dev@protonmail.com>
>> ---
>>  rust/macros/lib.rs   |   2 +
>>  rust/macros/quote.rs | 145 +++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 147 insertions(+)
>>  create mode 100644 rust/macros/quote.rs
>>
>> diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
>> index c1d385e345b9..82b520f024dd 100644
>> --- a/rust/macros/lib.rs
>> +++ b/rust/macros/lib.rs
>> @@ -2,6 +2,8 @@
>>
>>  //! Crate for all kernel procedural macros.
>>
>> +#[macro_use]
>> +mod quote;
>>  mod concat_idents;
>>  mod helpers;
>>  mod module;
>> diff --git a/rust/macros/quote.rs b/rust/macros/quote.rs
>> new file mode 100644
>> index 000000000000..7efb009c25a9
>> --- /dev/null
>> +++ b/rust/macros/quote.rs
>> @@ -0,0 +1,145 @@
>> +// SPDX-License-Identifier: Apache-2.0 OR MIT
>> +
>> +use proc_macro::{TokenStream, TokenTree};
>> +
>> +pub(crate) trait ToTokens {
>> +    fn to_tokens(&self, tokens: &mut TokenStream);
>> +}
>> +
>> +impl<T: ToTokens> ToTokens for Option<T> {
>> +    fn to_tokens(&self, tokens: &mut TokenStream) {
>> +        if let Some(v) = self {
>> +            v.to_tokens(tokens);
>> +        }
>> +    }
>> +}
>> +
>> +impl ToTokens for proc_macro::Group {
>> +    fn to_tokens(&self, tokens: &mut TokenStream) {
>> +        tokens.extend([TokenTree::from(self.clone())]);
>> +    }
>> +}
>> +
>> +impl ToTokens for TokenTree {
>> +    fn to_tokens(&self, tokens: &mut TokenStream) {
>> +        tokens.extend([self.clone()]);
>> +    }
>> +}
>> +
>> +impl ToTokens for TokenStream {
>> +    fn to_tokens(&self, tokens: &mut TokenStream) {
>> +        tokens.extend(self.clone());
>> +    }
>> +}
>> +
>> +/// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with
>> +/// the given span.
>> +///
>> +/// This is a similar to the
>> +/// [`quote_spanned!`](https://docs.rs/quote/latest/quote/macro.quote_spanned.html) macro from the
>> +/// `quote` crate but provides only just enough functionality needed by the current `macros` crate.
>> +#[allow(unused_macros)]
>> +macro_rules! quote_spanned {
>> +    ($span:expr => $($tt:tt)*) => {
>> +    #[allow(clippy::vec_init_then_push)]
>> +    {
>> +        let mut tokens = Vec::new();
>> +        let span = $span;
>> +        quote_spanned!(@proc tokens span $($tt)*);
>> +        proc_macro::TokenStream::from_iter(tokens)
>
> Should this be `::alloc::vec::Vec` and
> `::proc_macro::TokenStream::from_iter` ?
>
> Best regards,
> Andreas
>
>> +    }};
>> +    (@proc $v:ident $span:ident) => {};
>> +    (@proc $v:ident $span:ident #$id:ident $($tt:tt)*) => {
>> +        let mut ts = proc_macro::TokenStream::new();
>> +        crate::quote::ToTokens::to_tokens(&$id, &mut ts);
>> +        $v.extend(ts.into_iter());
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +    (@proc $v:ident $span:ident #(#$id:ident)* $($tt:tt)*) => {
>> +        for token in $id {
>> +            let mut ts = proc_macro::TokenStream::new();
>> +            crate::quote::ToTokens::to_tokens(&token, &mut ts);
>> +            $v.extend(ts.into_iter());

Also, could this be without `into_iter()`: `$v.extend(ts)`?

BR Andreas

>> +        }
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +    (@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => {
>> +        let mut tokens = Vec::new();
>> +        quote_spanned!(@proc tokens $span $($inner)*);
>> +        $v.push(proc_macro::TokenTree::Group(proc_macro::Group::new(
>> +            proc_macro::Delimiter::Parenthesis,
>> +            proc_macro::TokenStream::from_iter(tokens)
>> +        )));
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +    (@proc $v:ident $span:ident [ $($inner:tt)* ] $($tt:tt)*) => {
>> +        let mut tokens = Vec::new();
>> +        quote_spanned!(@proc tokens $span $($inner)*);
>> +        $v.push(proc_macro::TokenTree::Group(proc_macro::Group::new(
>> +            proc_macro::Delimiter::Bracket,
>> +            proc_macro::TokenStream::from_iter(tokens)
>> +        )));
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +    (@proc $v:ident $span:ident { $($inner:tt)* } $($tt:tt)*) => {
>> +        let mut tokens = Vec::new();
>> +        quote_spanned!(@proc tokens $span $($inner)*);
>> +        $v.push(proc_macro::TokenTree::Group(proc_macro::Group::new(
>> +            proc_macro::Delimiter::Brace,
>> +            proc_macro::TokenStream::from_iter(tokens)
>> +        )));
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +    (@proc $v:ident $span:ident :: $($tt:tt)*) => {
>> +        $v.push(
>> +            proc_macro::TokenTree::Punct(proc_macro::Punct::new(':', proc_macro::Spacing::Joint))
>> +        );
>> +        $v.push(
>> +            proc_macro::TokenTree::Punct(proc_macro::Punct::new(':', proc_macro::Spacing::Alone))
>> +        );
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +    (@proc $v:ident $span:ident : $($tt:tt)*) => {
>> +        $v.push(
>> +            proc_macro::TokenTree::Punct(proc_macro::Punct::new(':', proc_macro::Spacing::Alone))
>> +        );
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +    (@proc $v:ident $span:ident , $($tt:tt)*) => {
>> +        $v.push(
>> +            proc_macro::TokenTree::Punct(proc_macro::Punct::new(',', proc_macro::Spacing::Alone))
>> +        );
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +    (@proc $v:ident $span:ident @ $($tt:tt)*) => {
>> +        $v.push(
>> +            proc_macro::TokenTree::Punct(proc_macro::Punct::new('@', proc_macro::Spacing::Alone))
>> +        );
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +    (@proc $v:ident $span:ident ! $($tt:tt)*) => {
>> +        $v.push(
>> +            proc_macro::TokenTree::Punct(proc_macro::Punct::new('!', proc_macro::Spacing::Alone))
>> +        );
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +    (@proc $v:ident $span:ident $id:ident $($tt:tt)*) => {
>> +        $v.push(proc_macro::TokenTree::Ident(proc_macro::Ident::new(stringify!($id), $span)));
>> +        quote_spanned!(@proc $v $span $($tt)*);
>> +    };
>> +}
>> +
>> +/// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with
>> +/// mixed site span ([`Span::mixed_site()`]).
>> +///
>> +/// This is a similar to the [`quote!`](https://docs.rs/quote/latest/quote/macro.quote.html) macro
>> +/// from the `quote` crate but provides only just enough functionality needed by the current
>> +/// `macros` crate.
>> +///
>> +/// [`Span::mixed_site()`]: https://doc.rust-lang.org/proc_macro/struct.Span.html#method.mixed_site
>> +#[allow(unused_macros)]
>> +macro_rules! quote {
>> +    ($($tt:tt)*) => {
>> +        quote_spanned!(proc_macro::Span::mixed_site() => $($tt)*)
>> +    }
>> +}


  reply	other threads:[~2023-03-30 12:03 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-29 22:32 [PATCH v3 00/13] Rust pin-init API for pinned initialization of structs y86-dev
2023-03-29 22:32 ` [PATCH v3 01/13] rust: macros: add `quote!` macro y86-dev
2023-03-30 11:42   ` Andreas Hindborg
2023-03-30 12:01     ` Andreas Hindborg [this message]
2023-03-30 13:11     ` Gary Guo
2023-03-30 13:33   ` Alice Ryhl
2023-03-31 10:43   ` Andreas Hindborg
2023-03-29 22:32 ` [PATCH v3 02/13] rust: sync: add `assume_init` to `UniqueArc` y86-dev
2023-03-30  4:13   ` Wedson Almeida Filho
2023-03-30 12:18   ` Andreas Hindborg
2023-03-30 13:33   ` Alice Ryhl
2023-03-29 22:33 ` [PATCH v3 03/13] rust: types: add `Opaque::raw_get` y86-dev
2023-03-30 10:49   ` Gary Guo
2023-03-30 12:32   ` Andreas Hindborg
2023-03-30 13:33   ` Alice Ryhl
2023-03-29 22:33 ` [PATCH v3 04/13] rust: add pin-init API core y86-dev
2023-03-30 13:05   ` Andreas Hindborg
2023-03-30 15:46     ` Benno Lossin
2023-03-31  8:16       ` Andreas Hindborg
2023-03-30 13:17   ` Alice Ryhl
2023-03-30 13:33   ` Alice Ryhl
2023-03-30 14:16     ` Andreas Hindborg
2023-03-30 15:37       ` Benno Lossin
2023-03-30 15:36     ` Benno Lossin
2023-03-31 12:00   ` Andreas Hindborg
2023-03-29 22:33 ` [PATCH v3 05/13] rust: init: add initialization macros y86-dev
2023-03-30 14:21   ` Alice Ryhl
2023-03-30 15:38     ` Benno Lossin
2023-03-31 12:02   ` Andreas Hindborg
2023-03-29 22:33 ` [PATCH v3 06/13] rust: init/sync: add `InPlaceInit` trait to pin-initialize smart pointers y86-dev
2023-03-30 10:58   ` Gary Guo
2023-03-30 13:39   ` Andreas Hindborg
2023-03-30 14:37   ` Alice Ryhl
2023-03-30 15:28     ` Benno Lossin
2023-03-30 20:24       ` Alice Ryhl
2023-03-29 22:33 ` [PATCH v3 07/13] rust: init: add `PinnedDrop` trait and macros y86-dev
2023-03-30 11:01   ` Gary Guo
2023-03-30 15:41     ` Benno Lossin
2023-03-30 14:45   ` Alice Ryhl
2023-03-31 12:31   ` Andreas Hindborg
2023-03-29 22:33 ` [PATCH v3 08/13] rust: init: add `stack_pin_init!` macro y86-dev
2023-03-30 11:06   ` Gary Guo
2023-03-30 15:07     ` Alice Ryhl
2023-03-30 15:00   ` Alice Ryhl
2023-03-30 15:19     ` Benno Lossin
2023-03-30 20:28       ` Alice Ryhl
2023-03-31 12:43   ` Andreas Hindborg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87355m5tvs.fsf@metaspace.dk \
    --to=nmi@metaspace.dk \
    --cc=alex.gaynor@gmail.com \
    --cc=alice@ryhl.io \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=gary@garyguo.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=patches@lists.linux.dev \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=wedsonaf@gmail.com \
    --cc=y86-dev@protonmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.