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

@macroexpand macro #18240

Closed
StefanKarpinski opened this issue Aug 25, 2016 · 15 comments
Closed

@macroexpand macro #18240

StefanKarpinski opened this issue Aug 25, 2016 · 15 comments
Labels
good first issue Indicates a good issue for first-time contributors to Julia help wanted Indicates that a maintainer wants help on an issue or pull request
Milestone

Comments

@StefanKarpinski
Copy link
Member

Writing macroexpand(:(@foo x y z)) is a bit of a mouthful, but the expression passed to the macroexpand function needs to be quoted, of course. With a @macroexpand macro, this could be less annoying: @macroexpand @foo x y z

@StefanKarpinski StefanKarpinski added help wanted Indicates that a maintainer wants help on an issue or pull request good first issue Indicates a good issue for first-time contributors to Julia labels Aug 25, 2016
@StefanKarpinski StefanKarpinski added this to the 0.6.0 milestone Aug 25, 2016
@simonbyrne
Copy link
Contributor

I think the extra complications to the above are the handling of $ in expressions (e.g. @foo $x may not expand correctly using macroexpand(:(@foo $x))), and his funny gensym names.

@jw3126
Copy link
Contributor

jw3126 commented Sep 23, 2016

A naive implementation would be as follows:

macro macroexpand(code)
    Expr(:call, :macroexpand, Expr(:quote, code))
end

It would be good to have a concrete example that breaks this.

@simonbyrne
Copy link
Contributor

simonbyrne commented Sep 23, 2016

macro foo(ex)
    isa(ex,Expr) && ex.head == :$ ? 7 : ex
end

gives

julia> @macroexpand @foo $bar
ERROR: UndefVarError: bar not defined

julia> @foo $bar
7

@vtjnash
Copy link
Member

vtjnash commented Sep 23, 2016

the macroexpand also shouldn't be inside the esc() and only happens to work since you haven't put this inside a module and tested from a different module (with a different idea of what macroexpand means)

@jw3126
Copy link
Contributor

jw3126 commented Sep 23, 2016

Okay, if I run the function version of simonbyrne's example I get the same error:

julia> macroexpand(:(@foo $bar))
ERROR: UndefVarError: bar not defined

The problem is julia trying to interpolate bar into the expression, before the function gets even called. So this means getting the correct expansion of simonbyrne's example using a function is impossible. Do I see this correctly?

@simonbyrne
Copy link
Contributor

Well, it is possible, just a bit more complicated: see the MacroTools link above.

@jw3126
Copy link
Contributor

jw3126 commented Sep 23, 2016

I just meant it is impossible by using a function e.g. one has to write a macro which does not rely on a function, like the current macroexpand function.

@yuyichao
Copy link
Contributor

The error has nothing to do with the function it's from the expression object. What you need is to properly convert the expression object before returning it from the macro.

@jw3126
Copy link
Contributor

jw3126 commented Sep 24, 2016

Thanks for the help and sorry for the confusion. It seems that MacroTools also has problems with the example:

julia> using MacroTools

julia> macro foo(ex)
          isa(ex,Expr) && ex.head == :$ ? 7 : ex
       end
@foo (macro with 1 method)

julia> @expand @foo $bar 
:bar

@jw3126
Copy link
Contributor

jw3126 commented Sep 24, 2016

macro macroexpand(code)
    Expr(:quote, ccall(:jl_macroexpand, Any, (Any,), code))
end

Passes the simonbyrne example. In this case the code gets passed directly to jl_macroexpand so there is no chance for $ interpolation to cause confusion. Any objections?

@yuyichao
Copy link
Contributor

No need to use ccall the function call is NOT the problem.
It's a smart solution to do the expansion first. It changes the module the expansion takes place but that shouldn't be too bad for interactive use (and potentially better for that).

@jw3126
Copy link
Contributor

jw3126 commented Sep 24, 2016

Yes I know that the function call is not the problem, but $ interpolation that takes place before function is even called.
So you suggest, to use the macroexpand function instead of the ccall?
How to circumvent the $ interpolation then?
Do you need some recursive replacement thing like in MacroTools or is there an easy way?
And what is the problem with the ccall?

@yuyichao
Copy link
Contributor

Yes I know that the function call is not the problem, but $ interpolation that takes place before function is even called.

Only after the macro returns

So you suggest, to use the macroexpand function instead of the ccall?

Yes

How to circumvent the $ interpolation then?

It won't happen.

Do you need some recursive replacement thing like in MacroTools or is there an easy way?

No

And what is the problem with the ccall?

There's a function for it already.

@jw3126
Copy link
Contributor

jw3126 commented Sep 24, 2016

Thanks, finally I can see clear. I will put together a PR using

macro macroexpand(code)
    code_expanded = macroexpand(code)
    Expr(:quote, code_expanded)
end

yuyichao pushed a commit that referenced this issue Sep 30, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Indicates a good issue for first-time contributors to Julia help wanted Indicates that a maintainer wants help on an issue or pull request
Projects
None yet
Development

No branches or pull requests

5 participants