-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor to keep up with changes to proc_macro #122
Refactor to keep up with changes to proc_macro #122
Conversation
maud_macros/src/lib.rs
Outdated
let stmts = match parse::parse(input, output_ident.clone()) { | ||
Ok(stmts) => stmts, | ||
Err(e) => panic!(e), | ||
}; | ||
quote!({ | ||
extern crate maud; | ||
let mut $output_ident = String::with_capacity($size_hint as usize); | ||
//let mut $output_ident = String::with_capacity($size_hint as usize); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compiler complains about $size_hint
here
@lfairy This compiles, but I have introduced some parsing errors in the process. My hope is that we can work through these and keep the broad structure of the code intact. |
I don't have time to look at this yet, but if you change the |
maud_macros/src/build.rs
Outdated
tts.extend(i); | ||
} | ||
|
||
tts.into_iter().collect() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this change can be reverted once rust-lang/rust#49734 lands
maud_macros/src/parse.rs
Outdated
@@ -309,24 +295,22 @@ impl Parser { | |||
} | |||
|
|||
fn match_arms(&mut self) -> ParseResult<TokenStream> { | |||
let mut arms = Vec::new(); | |||
let mut arms: Vec<TokenTree> = Vec::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rust-lang/rust#49734 applies here as well
Life on the bleeding edge! 🐎 💨 |
I think we're close. Tests pass for me locally, but on CI the hyper dependency doesn't compile. I'll clean up warnings and try to work it out. There are newer releases of hyper: https://github.com/hyperium/hyper/releases |
Clippy failing on Hyper is a known issue (rust-lang/rust#49643; there's a Clippy issue as well but I can't find it right now). Since it's not our fault I think we can ignore it for now 🙂 |
Alrighty. I'll squash these down. |
aee31d4
to
716824a
Compare
Instead of a `kind` field containting a `TokenNode` variant, a TokenTree is now an enum with variants of different types (Literal, Op, Term, etc). Note that a TokenTree could be a sequence of TokenTrees if it is a Group variant. Other notes: I'm unsure about the set_span call in Builder::emit_if, but I did not want to throw away the passed in Span. Parsing relies on destructuring references to the values associated with TokenTree enum variants It doesn't seem as easy to compose/chain TokenStreams as it is to collect a Vec<TokenTree> into a TokenStream. There is probably some iterator API I could use instead. See `match_arms` and build.rs Refs lambda-fairy#121
716824a
to
0f453a5
Compare
rust-lang/rust#49734 was merged 21 hours ago. I think we might need to wait another day before it's in nightly. |
Also remove conservative_impl_trait feature flag, as this is now a stable feature. Refs lambda-fairy#121
I've addressed the previous comments now that the iterator changes have landed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for sticking through with this!
I have a few comments to make, but as they're pretty minor I'll merge your changes as-is and fix it up myself.
}); | ||
let mut g = Group::new(Delimiter::Parenthesis, cond); | ||
// NOTE: Do we need to do this? | ||
g.set_span(cond_span); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest I'm not actually sure 😛
My original thought was that using the source spans more often would improve compiler diagnostics. But since we're creating these parentheses out of whole cloth it's a bit questionable to use them here.
I'm in the process of rewriting this file in another branch, so I'll address this point there.
if cond.clone().into_iter().any(|token| match token.kind { | ||
TokenNode::Group(Delimiter::Brace, _) => true, | ||
if cond.clone().into_iter().any(|token| match token { | ||
TokenTree::Group(grp) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general I tend to avoid minor abbreviations like this.
cond
is okay because condition
is pretty long. But group
vs grp
isn't such a clear win.
(I realize I abbreviate pattern
to pat
elsewhere... should probably fix that)
@@ -28,7 +29,7 @@ struct Parser { | |||
output_ident: TokenTree, | |||
/// Indicates whether we're inside an attribute node. | |||
in_attr: bool, | |||
input: TokenTreeIter, | |||
input: token_stream::IntoIter, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<TokenStream as IntoIterator>::IntoIter
will avoid the import (as well as signal our intentions more clearly)
// When emitting a `@let`, wrap the rest of the block in a | ||
// new block to avoid scoping issues | ||
let keyword = TokenTree { kind: TokenNode::Term(term), span }; | ||
let keyword = Term::new(term.as_str(), term.span()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old code did this term wrapping dance because the identifier and span used to be in separate fields, such that matching the term required pulling it apart and putting it back together again.
But now that the Term
data type contains its own span, we can use the original term without the dance.
let block = self.block(grp.stream(), grp.span())?; | ||
builder.push(block); | ||
}, | ||
_ => { return self.error("expected body for @else"); }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return
is an expression -- you can omit the braces if it's the only thing in the block:
_ => return self.error("..."),
kind: TokenNode::Group(Delimiter::Brace, builder.build()), | ||
span, | ||
}) | ||
Ok(TokenTree::Group(Group::new(Delimiter::Brace, builder.build()))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code should call .set_span()
on the generated Group
Instead of a
kind
field containting aTokenNode
variant, aTokenTree is now an enum with variants of different types (Literal, Op,
Term, etc). Note that a TokenTree could be a sequence of TokenTrees if it is a
Group variant.
Other notes:
I'm unsure about the set_span call in Builder::emit_if, but I did not want to
throw away the passed in Span.
Parsing relies on destructuring references to the values associated with
TokenTree enum variants
Refs #121