Skip to content

Commit

Permalink
This fixes JuliaLang#3377. It allows for writing @methods @time 1+1
Browse files Browse the repository at this point in the history
…, `@functionloc @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.
  • Loading branch information
dhoegh committed Mar 1, 2016
1 parent 3585235 commit 8ecd97f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
11 changes: 8 additions & 3 deletions base/interactiveutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,13 @@ function gen_call_with_extracted_types(fcn, ex0)
Expr(:call, typesof, map(esc, args[2:end])...))
end
exret = Expr(:none)
is_macro = false
ex = expand(ex0)
if !isa(ex, Expr)
if fcn in [:which, :less, :edit, :methods, :functionloc] && ex0.head == :macrocall
# special case @edit @time 1+2 to edit the macro
is_macro = true
exret = Expr(:call, fcn, esc(ex0.args[1]), typesof(ex0.args[2:end]...))
elseif !isa(ex, Expr)
exret = Expr(:call, :error, "expression is not a function call or symbol")
elseif ex.head == :call
if any(e->(isa(e, Expr) && e.head==:(...)), ex0.args) &&
Expand All @@ -278,15 +283,15 @@ function gen_call_with_extracted_types(fcn, ex0)
end
end
end
if ex.head == :thunk || exret.head == :none
if (!is_macro && ex.head == :thunk) || exret.head == :none
exret = Expr(:call, :error, "expression is not a function call, "
* "or is too complex for @$fcn to analyze; "
* "break it down to simpler parts if possible")
end
exret
end

for fname in [:which, :less, :edit, :code_typed, :code_warntype,
for fname in [:which, :less, :edit, :methods, :functionloc, :code_typed, :code_warntype,
:code_lowered, :code_llvm, :code_llvm_raw, :code_native]
@eval begin
macro ($fname)(ex0)
Expand Down
23 changes: 23 additions & 0 deletions test/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,26 @@ let rts = return_types(TLayout)
@test length(rts) >= 3 # general constructor, specific constructor, and call-to-convert adapter(s)
@test all(rts .== TLayout)
end

module MacroTest
export @macrotest
macro macrotest(x::Int, y::Symbol) end
macro macrotest(x::Int, y::Int)
nothing
end
end

let
using MacroTest
a = 1
m = getfield(current_module(), Symbol("@macrotest"))
@test which(m, Tuple{Int,Symbol})==@which @macrotest 1 a
@test which(m, Tuple{Int,Int})==@which @macrotest 1 1
@test methods(m, Tuple{Int,Symbol})==@methods @macrotest 1 a
@test methods(m, Tuple{Int,Int})==@methods @macrotest 1 1

@test methods(m,Tuple{Int, Int})[1]==@which MacroTest.@macrotest 1 1
@test functionloc(@which @macrotest 1 1)[1] == @functionloc @macrotest 1 1
#Uncomment when #15280 is solved
#@test basename(functionloc(@which @macrotest 1 a)[1]) == "reflection.jl"
end

0 comments on commit 8ecd97f

Please sign in to comment.