-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Macroexpand1 #21662
Macroexpand1 #21662
Conversation
test/replutil.jl
Outdated
@test macroexpand1(macroexpand1(ex)) == macroexpand(ex) | ||
ex = :(@nest2b 42) | ||
@test macroexpand1(ex) != macroexpand(ex) | ||
@test macroexpand1(macroexpand1(ex)) == macroexpand(ex) |
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.
Should be 4 spaces.
src/macroexpand.scm
Outdated
@@ -411,8 +412,10 @@ | |||
(m (cdr form))) | |||
;; m is the macro's def module | |||
(rename-symbolic-labels | |||
(julia-expand-macros | |||
((lambda (ex) (julia-expand-macros-limited ex (- max-depth 1))) |
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 lambda is not necessary.
src/macroexpand.scm
Outdated
(define (julia-expand-macros e) | ||
(cond ((not (pair? e)) e) | ||
(define (julia-expand-macros-limited e max-depth) | ||
(cond ((eq? max-depth 0) e) |
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.
Should use =
.
Since we have both macro and function versions of |
How about expressing this with a |
@StefanKarpinski I though about this. Since |
One can also use |
In principle one could have |
Could we make |
@vtjnash I like this idea, I guess the cases where you actually want to expand everything are library code, where typing some keyword does not hurt much. Of course this change is breaking in a subtle way. |
So do you guys prefer @vtjnash idea of having only |
I think the usage pattern is as follows:
|
What is the difference between this function and simply calling the macro itself (e.g. with |
In this case, both exist because a macro is a convenient way to quote an expression. In other cases, they differ in the post-processing done by a macro to apply hygiene. In fact, I was working on making an example of this today! The following diff should have no functional change (other than the catch_backtrace on error, given that I know |
@TotalVerb I was not aware, that you could get a handle on a macro like that. Here is a concrete example of hygiene application: julia> getfield(current_module(), Symbol("@show"))(:x)
quote
println("x = ", repr(begin # show.jl, line 243:
value = $(Expr(:escape, :x))
end))
value
end
julia> macroexpand1(:(@show x))
quote
(Base.println)("x = ", (Base.repr)(begin # show.jl, line 243:
#6#value = x
end))
#6#value
end |
Sorry, something went terribly wrong during rebase. |
c65d9fb
to
7d99913
Compare
base/expr.jl
Outdated
|
||
* While [`macroexpand`](@ref) has an explicit `module` argument, `@macroexpand` always expands with respect to the module in which it is called. This is best seen in the following example: |
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.
wrap long lines
What are the CI fails about? |
doc/src/stdlib/base.md
Outdated
@@ -275,6 +275,8 @@ Base.gc | |||
Base.gc_enable | |||
Base.macroexpand | |||
Base.@macroexpand | |||
Base.macroexpand1 |
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 documentation fails to build because this doesn't exist any more
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 very much!
I think this PR is ready for merge. |
Bump on review. @vtjnash? |
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.
Just some minor comments. This looks good – thanks for implementing it!
src/macroexpand.scm
Outdated
(julia-expand-macros | ||
(resolve-expansion-vars form m)))))) | ||
(julia-expand-macros-limited (resolve-expansion-vars form m) (- max-depth 1)) | ||
)))) |
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.
closing parens should be all on the same (previous) line
src/macroexpand.scm
Outdated
((eq? (car e) 'module) e) | ||
(else | ||
(map julia-expand-macros e)))) | ||
(map (lambda (ex) (julia-expand-macros-limited ex max-depth) ) e)))) |
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.
no space before closing parens
src/macroexpand.scm
Outdated
@@ -466,11 +466,12 @@ | |||
|
|||
;; macro expander entry point | |||
|
|||
(define (julia-expand-macros e) | |||
(cond ((not (pair? e)) e) | |||
(define (julia-expand-macros-limited e max-depth) |
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 think it might be more straightforward to define this as a boolean with a default value:
(define (julia-expand-macros e (recursive #t))
I'm not sure there's going to be a use case for arbitrary depths, so it's nice just to keep the implementation simple.
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 find the max depth implementation actually slightly simpler.
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.
But I will try a default value (define (julia-expand-macros e (max-depth -1))
. Did not expect this feature.
base/expr.jl
Outdated
|
||
Takes the expression `x` and returns an equivalent expression with all macros removed (expanded) | ||
for executing in module `m`. | ||
The `recursive` keyword controls whether deeper levels of nested macros are also expanded. | ||
This is demonstrated in the example below: | ||
```julia |
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 think this can be jldoctest
, but would be good for someone else to confirm
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.
It contains stuff like
:(#= REPL[16]:6 =# M.@m1)
that probably makes the doctest very fragile?
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.
Should be julia-repl
if it uses repl format but is not a doctest.
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 was not aware of julia-repl
.
@vtjnash LGTY? |
does this really need to be exported? |
We could move them to Base.Meta or interactiveutils.jl, but it would be really annoying for these not to be easily available at the REPL. |
how often is the non recursive version needed? |
More often than the recursive? |
`@macroexpand1` is a non recursive variant of `@macroexpand` The `macroexpand` function now also takes an keyword argument `recursive` to indicate whether to expand one level of macros or all macros recursively.
This PR adds a non recursive variant of
macroexpand
, see #19365. What is the preferred API?macroexpand1(ex)
,@macroexpand1(ex)
?macroexpand(ex, recursive::Bool)
,@macroexpand(ex, recursive)
?Both? Something else? For REPL usage I think
@macroexpand1
is the most convenient, albeit a bit cryptic.