Giter Site home page Giter Site logo

Comments (6)

SimonSapin avatar SimonSapin commented on June 2, 2024 1

Could quote_attribute! do compile-time parsing while keeping the generality of "Anything that implements ToTokens can be used with #foo interpolation" ?

Anyway, just to write down the idea, the traits I mentioned before could look like this:

pub trait Parse: Sized {
    fn parse<I: ToSourceString>(input: I) -> Result<Self, String>;
}

// This replaces parse_expr()
impl Parse for Expr {
    fn parse<I: ToSourceString>(input: I) -> Result<Self, String> {
        unwrap("expression", expr::parsing::expr, &input.to_source_string())
    }
}

// Other impls for various AST types…

pub trait ToSourceString {
    fn to_source_string(&self) -> Cow<str>;
}

impl ToSourceString for str {
    fn to_source_string(&self) -> Cow<str> {
        // Remove leading and trailing whitespace.
        // Nom parsing functions tend to trip on the latter particularly
        self.trim().into()
    }
}

impl ToSourceString for String {
    fn to_source_string(&self) -> Cow<str> {
        (**self).to_source_string()
    }
}

impl ToSourceString for quote::Tokens {
    fn to_source_string(&self) -> Cow<str> {
        self.to_string().to_source_string().into_owned().into()
    }
}

impl ToSourceString for [TokenTree] {
    fn to_source_string(&self) -> Cow<str> {
        let mut tokens = quote::Tokens::new();
        tokens.append_all(self);
        tokens.to_string().to_source_string().into_owned().into()
    }
}

impl ToSourceString for Vec<TokenTree> {
    fn to_source_string(&self) -> Cow<str> {
        (**self).to_source_string()
    }
}

from syn.

SimonSapin avatar SimonSapin commented on June 2, 2024

Rather than a large number of macros for each type, maybe a method available on each type would be a nicer API?

let attr = Attribute::parse(quote!(#[derive(Debug, Clone, #a, #b)])).unwrap();

These methods could also replace the ad-hoc top-level parse_* functions, if they accept a generic parameter with some trait implemented by both quote::Tokens and &str (and maybe &[syn::TonkenTree] / Vec<TokenTree> / TokenTree? For dealing with expression/items macros.)

from syn.

dtolnay avatar dtolnay commented on June 2, 2024

I like it but I have two concerns:

  • I think Attribute::parse puts too much emphasis on the fact that parsing is happening, which is not what I want the user and readers of the user's code to focus on in these cases. Everyone knows parsing is something that can fail, so you need to unwrap or try!(Attribute::parse(...)). But if the thing you are parsing is right there inside a quote!(...) macro, you should write it in a way that you know will parse i.e. anything that doesn't parse is a bug in your program, not an expected failure that you can handle at runtime. I think quote_attribute!(...) captures this distinction better.
  • Once procedural macros are stable, the quote_attribute! approach allows us to do the parsing at compile time rather than run time in most cases. As I mentioned in another ticket I am not worried about performance here so that is not why I am excited about this. Instead, parsing at compile time would let us validate the thing you are quoting, and fail to compile your program if it looks wrong. We can't ever do this with the Attribute::parse(quote!(...)) approach.

I am not settled on the quote_attribute! approach yet but these are some of the advantages.

I do like Attribute::parse as an alternative to the current style of syn::parse_attribute, will think about the tradeoffs there.

from syn.

mystor avatar mystor commented on June 2, 2024

This seems like it should be doable with an external crate, which may be desirable to keep syn small.

from syn.

dtolnay avatar dtolnay commented on June 2, 2024

I added a parse_quote! macro in 01cc020 that can return any Synom implementation.

// Add a bound `T: HeapSize` to every type parameter T.
fn add_trait_bounds(mut generics: Generics) -> Generics {
    for param in &mut generics.params {
        if let GenericParam::Type(ref mut type_param) = *param {
            type_param.bounds.push(parse_quote!(HeapSize));
        }
    }
    generics
}

from syn.

mystor avatar mystor commented on June 2, 2024

@dtolnay Unfortunately this doesn't handle the case of things like Attribute which don't implement Synom, because the have specific parse_inner and parse_outer methods which are distinct.

Do you have any idea how we could go about handling that case? I think Attribute is particularly relevant (especially considering that it's the one you mention in the first comment!)

from syn.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.