-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
Enable @edit @time 1+1
, fix #3377
#15282
Conversation
💯 |
if !isa(ex, Expr) | ||
if fcn in [:which, :less, :edit] && ex0.head == :macrocall | ||
# special case @edit @time 1+2 to edit the macro | ||
is_macro = true |
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.
Why is the special case needed?
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 special case is needed because when the expand
function called above expands the macro/insert its code into the expression, and hence the edit
call will call edit on the expanded code. The special casing makes which
, less
and edit
macro call the macrocall instead of the code the macro expands to. This enables the user to write: @edit @time 1+1
, this will go to the @time
macro's definition.
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.
Is there a case you don't want to use operate on the macro?
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.
My main concern is that this doesn't seem to be the way this should work. If it is somehow really necessary to have different behavior for different macros that use this function, it should be controlled explicitly with a optional/keyword argument to this function instead.
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 understand your concern, but from my point of view it do not make sense to ask for @edit @random_macro max(1,1)
and not point to the macro. As a macro can generate arbitrary code for you, and hence you do not know what you call @edit
on.
I have pushed a new commit which adresses the comments. I did also find a bug, caused by wrong |
I have squashed the commits. |
@@ -179,6 +194,10 @@ function methods(f::ANY,t::ANY) | |||
Any[m[3] for m in _methods(f,t,-1)] | |||
end | |||
function _methods(f::ANY,t::ANY,lim) | |||
#special case Expr to allow methods(@time,Tuple{Any}) | |||
if _is_empty_macrocall(f) | |||
f = _get_macro(current_module(),f.args[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 code is incorrect --- it makes it impossible for the system to query the methods of an Expr
object. Exprs don't have any methods of course, but that just means this function must return an empty array.
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 do not quite follow you. The meaning of the function is to get function object of the macro from the getfield
expression. Do you have an alternative way of obtaining the result?
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.
You can't do this in _methods
. _methods(f, ...)
must return the list of methods you could call by doing f(...)
with the specific object f
. The following (current) behavior is correct:
julia> e = Expr(:macrocall, symbol("@time"))
:(@time)
julia> e()
ERROR: MethodError: objects of type Expr are not callable
in eval(::Module, ::Any) at ./boot.jl:275
julia> methods(e)
# 0 methods for generic function "(::Expr)":
This functionality is great, but we need to figure out a different way to provide it. This implementation works via a pun, where |
If there was a way to obtain the function object of the macro, then it would be easier, to solve correctly. Because |
I think the best approach for now is to limit this to user-interface-level features like |
ca9241e
to
8ecd97f
Compare
@JeffBezanson I have changed the PR to suite your comments. I have added
|
methods(:@time)
, fix #3377@edit @time 1+1
, fix #3377
I have added docs to |
ex = expand(ex0) | ||
if !isa(ex, Expr) | ||
if fcn in [:which, :less, :edit, :functionloc] && ex0.head == :macrocall |
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 you should check isa(ex0, Expr)
here.
Also, I still don't understand why are the special cases necessary here. Why do you want @code_lowered @time 1 + 2
to error instead of showing the ast?
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 see where you are going now:). I have removed the special casing of @edit
etc. The Ast displayed by @code_warntype
is pretty ugly, but it displays.
julia> @code_warntype @time 1+1
Variables:
#self#::Base.#@time
ex::Expr
####args#787#8911::TUPLE
Body:
begin # util.jl, line 152:
return (top(_expr))(:block,$(Expr(:copyast, :($(QuoteNode(:( # util.jl, line 153:)))))),$(Expr(:copyast, :($(QuoteNode(:(local stats = gc_num())))))),$(Expr(:copyast, :($(QuoteNode(:( # util.jl, line 154:)))))),$(Expr(:copyast, :($(QuoteNode(:(local elapsedtime = time_ns())))))),$(Expr(:copyast, :($(QuoteNode(:( # util.jl, line 155:)))))),(top(_expr))(:local,(top(_expr))(:(=),:val,(Core._expr)(:escape,ex::Expr)::ANY)::Expr)::Expr,$(Expr(:copyast, :($(QuoteNode(:( # util.jl, line 156:)))))),$(Expr(:copyast, :($(QuoteNode(:(elapsedtime = time_ns() - elapsedtime)))))),$(Expr(:copyast, :($(QuoteNode(:( # util.jl, line 157:)))))),$(Expr(:copyast, :($(QuoteNode(:(local diff = GC_Diff(gc_num(),stats))))))),$(Expr(:copyast, :($(QuoteNode(:( # util.jl, line 158:)))))),$(Expr(:copyast, :($(QuoteNode(:(time_print(elapsedtime,diff.allocd,diff.total_time,gc_alloc_count(diff)))))))),$(Expr(:copyast, :($(QuoteNode(:( # util.jl, line 160:)))))),:val)::Expr
end::Expr
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.
Trust me, it's not going to be "uglier" than the AST of this function (gen_call_with_extracted_types
) itself.
I will do. I will squash the commit away, when I have updated genstdlib.jl |
9be0c68
to
6c4e05c
Compare
I have executed |
@functionloc | ||
|
||
Applied to a function or macro call, it evaluates the arguments to the specified call, and | ||
return a tuple `(filename,line)` giving the location for the method that would be called for those arguments. |
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.
returns
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.
Thank you. I have fixed it and updated the PR.
bb1e957
to
09507d7
Compare
Bump, I have rebased the PR to resolve merge conflicts. |
Bump/any further comment's? |
@JeffBezanson, you're the one who had objections before, so please take a look and merge if it's ok. |
Bump. |
LGTM. @JeffBezanson ? |
@dhoegh I think I'll merge this if you can rebase again and no one have further comment. |
…ctionloc @time 1+1` plus the equivalent for `@which`, `@edit` and `@less`. The macros check for method specialization of the macro and return the dispatched macro. The `@functionloc` macro is exported and the documentation is updated.
@yuyichao thank you. I have rebased the PR and it should be good to merge when the CI is finished. |
.... Somehow the commit was merged but @github thinks the PR is still open and now with conflicts ..... Manually close since the merge is done.... |
Enable `@edit @time 1+1`, fix JuliaLang#3377
This allows for writing
methods(:@time)
,edit(:@time)
and@edit @time 1+1
plus the equivalent forwhich
andless
.. Themethods
can also check for macro methods asmethods(:@time, Tuple{Any})
@edit
,@less
and@which
do also check for method specialization of the macro.