Skip to content
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

Implement a concat!() format extension #9740

Merged
merged 1 commit into from
Nov 1, 2013
Merged

Conversation

alexcrichton
Copy link
Member

This extension can be used to concatenate string literals at compile time. C has
this useful ability when placing string literals lexically next to one another,
but this needs to be handled at the syntax extension level to recursively expand
macros.

The major use case for this is something like:

macro_rules! mylog( ($fmt:expr $($arg:tt)*) => {
    error2!(concat!(file!(), ":", line!(), " - ", $fmt) $($arg)*);
})

Where the mylog macro will automatically prepend the filename/line number to the
beginning of every log message.

@huonw
Copy link
Member

huonw commented Oct 6, 2013

It seems like the interior expansion could be generalised to something like LaTeX's \expandafter (this is getting to the realm of quite complicated):

expand_inner!(foo!(bar!(), baz!()))
// is the same as
foo!("bar", 100)

assuming bar and baz expand to "bar" and 100 respectively.

@alexcrichton
Copy link
Member Author

Oh hm that would be nice to have so we don't have to re-implement it for each thing individually. I suppose though that expand_inner! would take an @Expr which must be an ExprMac, but how does it know how to expand the inner macros? It doesn't know the format of the inner syntax extension. In the case of format!, it's not necessarily a comma-separated list of expressions.

@huonw
Copy link
Member

huonw commented Oct 6, 2013

Yeah, I agree that it's not simple: I think either we just say "expand_inner only works with comma-separated exprs", or somehow override the .parse_{expr,stmt,item} methods (e.g. route them through the ExtCtxt), so expand_inner sets a flag that means everything gets expanded. It seems like the latter is the "correctest", but also the hardest to (1) implement reliably, and (2) specify properly.

@emberian
Copy link
Member

@alexcrichton @huonw is this worth holding back for an expand_inner!? This still seems desirable to me.

@huonw
Copy link
Member

huonw commented Oct 31, 2013

I have no particular opinion either way.

@alexcrichton
Copy link
Member Author

I'm not seeing how this would get implemented with an inner-expansion macro. The reason macros don't do that right now is because they don't know that they have sub-expressions. I don't mind implementing another convenience macro, but I'm not sure what it would look like (which is why I'd still like to merge this).

This extension can be used to concatenate string literals at compile time. C has
this useful ability when placing string literals lexically next to one another,
but this needs to be handled at the syntax extension level to recursively expand
macros.

The major use case for this is something like:

    macro_rules! mylog( ($fmt:expr $($arg:tt)*) => {
        error2!(concat!(file!(), ":", line!(), " - ", $fmt) $($arg)*);
    })

Where the mylog macro will automatically prepend the filename/line number to the
beginning of every log message.
bors added a commit that referenced this pull request Nov 1, 2013
This extension can be used to concatenate string literals at compile time. C has
this useful ability when placing string literals lexically next to one another,
but this needs to be handled at the syntax extension level to recursively expand
macros.

The major use case for this is something like:

    macro_rules! mylog( ($fmt:expr $($arg:tt)*) => {
        error2!(concat!(file!(), ":", line!(), " - ", $fmt) $($arg)*);
    })

Where the mylog macro will automatically prepend the filename/line number to the
beginning of every log message.
@bors bors merged commit a49e65c into rust-lang:master Nov 1, 2013
@alexcrichton alexcrichton deleted the concat branch November 1, 2013 18:14
@jbclements
Copy link
Contributor

oh dear... oh dear... local-expand is really scary. @alexcrichton, @huonw, Have you guys thought about how this affects hygiene?

@alexcrichton
Copy link
Member Author

Sadly not a whole lot. I imagine that yoiu're much more qualified to think about that than I am, but at least for the time being local-expand is only really useful when things are constants and/or take no arguments. The only use case for this is concatenating strings and getting a string literal for a format string, so I don't think that it will affect any existing code today unless we start using it elsewhere (which we probably shouldn't from what it sounds like).

Is there a more proper way to do this? Or is there even a good way to do this at all?

@huonw
Copy link
Member

huonw commented Nov 12, 2013

This is only used in the tests in the main codebase, so it could easily be reverted until we have resolved hygiene issues.

@jbclements
Copy link
Contributor

I'm furiously re-reading MTWT right now. Let me see what I can come up with. Racket does support local-expand, but there's some really complex machinery that goes along with it, that we don't have and probably don't want.

@jbclements
Copy link
Contributor

okay, I just posted to the racket list... let's see what they can add, if anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants