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

Expand docs on Macros By Example. #511

Open
wants to merge 1 commit into
base: master
from

Conversation

Projects
None yet
8 participants
@alercah
Copy link
Contributor

alercah commented Jan 15, 2019

The primary motivation here was to increase clarity and fully address the
scoping and naming details. The inclusion of RFC 550's formal specification is
to move it to the reference where it can be updated. I made several changes,
motivated by accommodating ? and new fragment specifiers, but there are some
other things which need highlighting so that they can be double-checked for
correctness.

  • Permit the empty string to follow on in the first invariant; this is a
    technical oversight in the definition I believe.
  • Added a requirement that repetitions obey the follow rules; this was an
    oversight in the original RFC and currently planned for fix.
  • Rewrote the definition of FIRST for complex NTs to be more clear.
  • Added a case to LAST for ? repetitions
  • Removed the last example of LAST, because it is wrong.
  • Rearranged the definition of FOLLOW to be more clear
  • Added Shl to FOLLOW(ty) and FOLLOW(path), as documented in the Reference
    already.
  • Added missing follow sets for newer fragment specifiers.

The scoping text is probably not completely accurate, but it's certainly much
better than what was there before (i.e. basically nothing).

@alercah

This comment has been minimized.

Copy link
Contributor

alercah commented Jan 15, 2019

Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
@petrochenkov

This comment has been minimized.

Copy link
Contributor

petrochenkov commented Jan 15, 2019

Reviewed.
Great work.

@nikomatsakis

This comment has been minimized.

Copy link
Member

nikomatsakis commented Jan 15, 2019

Not sure what they are up to these days, but @paulstansifer was the original author of the algorithm we use and I don't think the approach has changed much. There is at least some chance they have the time to review this PR =)

@ehuss
Copy link
Collaborator

ehuss left a comment

This is great, I have been looking forward to seeing this! Just yesterday I got a weird "import resolution is stuck, try simplifying macro imports" error, and I think this makes it clearer for me!

I've been wondering if it would be useful to make it clear somewhere that $crate is two separate tokens? There are a few places in the reference that abut tokens in such a way that makes it not clear that they are distinct. It's a minor issue, and can be inferred from the tokens chapter, just a thought.

Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macro-ambiguity.md Outdated
@alexreg

This comment has been minimized.

Copy link
Contributor

alexreg commented Jan 16, 2019

It looks like the macro guru @petrochenkov has already reviewed, so my input probably isn't needed -- but in brief, good work. :-)

@alercah alercah force-pushed the alercah:macro-names branch 2 times, most recently from 0573e53 to def43e0 Jan 19, 2019

@alercah alercah force-pushed the alercah:macro-names branch from def43e0 to a145d8e Jan 27, 2019

correct because in order for M to accept ε in the complex NT case, both the
complex NT and α must accept it. If OP = `+`, meaning that the complex NT
cannot be empty, then by definition ε ∉ ALPHA\_SET(M). Otherwise, the complex NT
can accept zero repititions, and then ALPHA\_SET(M) = FOLLOW(`α`). So this

This comment has been minimized.

@petrochenkov

petrochenkov Jan 27, 2019

Contributor

Typo: repititions -> repetitions here and in few other places below.

Second, it can be used to import macros from another crate, by attaching it to
an `extern crate` declaration appearing in the crate's root module. Macros
imported this way are imported into the prelude of the crate, not textually,
which means that they can be uare shadowed by any other name. While macros

This comment has been minimized.

@petrochenkov

petrochenkov Jan 27, 2019

Contributor

Typo: uare -> ???

@Centril
Copy link
Collaborator

Centril left a comment

Mostly proofreading...

Show resolved Hide resolved src/macro-ambiguity.md Outdated
Show resolved Hide resolved src/macro-ambiguity.md Outdated
Show resolved Hide resolved src/macro-ambiguity.md Outdated
Show resolved Hide resolved src/macro-ambiguity.md Outdated
Show resolved Hide resolved src/macro-ambiguity.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
Show resolved Hide resolved src/macros-by-example.md Outdated
// m!(); // Error: m is not in scope.
```

This comment has been minimized.

@Centril

Centril Jan 28, 2019

Collaborator

I'd break into a section for #[macro_use] here.

Show resolved Hide resolved src/macros-by-example.md
@jethrogb

This comment has been minimized.

Copy link
Contributor

jethrogb commented Jan 28, 2019

Can you add something along these lines?

When forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type. The second macro can't use literal tokens to match this in the matcher, only a fragment specifier of the same type. The ident, lifetime, and tt fragment types are an exception, and can be matched by literal tokens.

This explains the difference between:

// compiles OK
macro_rules! foo {
    ($l:tt) => { bar!($l); }
}

macro_rules! bar {
    (3) => {}
}

fn main() {
    foo!(3);
}
macro_rules! foo {
    ($l:expr) => { bar!($l); }
// ERROR:               ^^ no rules expected this token in macro call
}

macro_rules! bar {
    (3) => {}
}

fn main() {
    foo!(3);
}
Expand docs on Macros By Example.
The primary motivation here was to increase clarity and fully address the
scoping and naming details. The inclusion of RFC 550's formal specification is
to move it to the reference where it can be updated. I made several changes,
motivated by accommodating `?` and new fragment specifiers, but there are some
other things which need highlighting so that they can be double-checked for
correctness.

  * Permit the empty string to follow on in the first invariant; this is a
    technical oversight in the definition I believe.
  * Added a requirement that repetitions obey the follow rules; this was an
    oversight in the original RFC and currently planned for fix.
  * Rewrote the definition of FIRST for complex NTs to be more clear.
  * Added a case to LAST for `?` repetitions
  * Removed the last example of LAST, because it is wrong.
  * Rearranged the definition of FOLLOW to be more clear
  * Added Shl to FOLLOW(ty) and FOLLOW(path), as documented in the Reference
    already.
  * Added missing follow sets for newer fragment specifiers.

The scoping text is probably not completely accurate, but it's certainly much
better than what was there before (i.e. basically nothing).

@alercah alercah force-pushed the alercah:macro-names branch from a145d8e to 5bf2d86 Feb 2, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment