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

Enable @edit @time 1+1, fix #3377 #15282

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 0 additions & 65 deletions base/docs/helpdb/Base.jl
Original file line number Diff line number Diff line change
@@ -218,14 +218,6 @@ Bessel function of the first kind of order `nu`, ``J_\\nu(x)``.
"""
besselj

"""
@code_lowered
Evaluates the arguments to the function call, determines their types, and calls
[`code_lowered`](:func:`code_lowered`) on the resulting expression.
"""
:@code_lowered

"""
//(num, den)
@@ -716,14 +708,6 @@ keyword arguments `addprocs` was called with.
"""
launch

"""
@code_typed
Evaluates the arguments to the function call, determines their types, and calls
[`code_typed`](:func:`code_typed`) on the resulting expression.
"""
:@code_typed

"""
invdigamma(x)
@@ -3493,13 +3477,6 @@ Returns the lower triangle of `M` starting from the `k`th superdiagonal.
"""
tril(M,k)

"""
@edit
Evaluates the arguments to the function call, determines their types, and calls the `edit`
function on the resulting expression.
"""
:@edit

"""
subtypes(T::DataType)
@@ -3614,14 +3591,6 @@ not representable.
"""
trunc

"""
@less
Evaluates the arguments to the function call, determines their types, and calls the `less`
function on the resulting expression.
"""
:@less

"""
broadcast_function(f)
@@ -5549,14 +5518,6 @@ Returns `string` with the first character converted to lowercase.
"""
lcfirst

"""
@code_native
Evaluates the arguments to the function call, determines their types, and calls
[`code_native`](:func:`code_native`) on the resulting expression.
"""
:@code_native

"""
flipbits!(B::BitArray{N}) -> BitArray{N}
@@ -5571,14 +5532,6 @@ Returns the value of a symbolic link `path`.
"""
readlink

"""
@code_warntype
Evaluates the arguments to the function call, determines their types, and calls
[`code_warntype`](:func:`code_warntype`) on the resulting expression.
"""
:@code_warntype

"""
deg2rad(x)
@@ -8257,16 +8210,6 @@ Converts a packed boolean array to an array of booleans.
"""
bitunpack

"""
@which
Applied to a function call, it evaluates the arguments to the specified function call, and
returns the `Method` object for the method that would be called for those arguments. Applied
to a variable, it returns the module in which the variable was bound. It calls out to the
`which` function.
"""
:@which

"""
size(A, [dim...])
@@ -8454,14 +8397,6 @@ address will be either IPv4 or IPv6 as appropriate.
"""
recvfrom

"""
@code_llvm
Evaluates the arguments to the function call, determines their types, and calls
[`code_llvm`](:func:`code_llvm`) on the resulting expression.
"""
:@code_llvm

"""
nextfloat(f)
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
@@ -1387,6 +1387,7 @@ export
# reflection
@which,
@edit,
@functionloc,
@less,
@code_typed,
@code_warntype,
86 changes: 82 additions & 4 deletions base/interactiveutil.jl
Original file line number Diff line number Diff line change
@@ -256,8 +256,12 @@ 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 isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro
is_macro = true
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor Author

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.

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) &&
@@ -280,15 +284,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, :functionloc, :code_typed, :code_warntype,
:code_lowered, :code_llvm, :code_llvm_raw, :code_native]
@eval begin
macro ($fname)(ex0)
@@ -297,7 +301,80 @@ for fname in [:which, :less, :edit, :code_typed, :code_warntype,
end
end

# `methodswith` -- shows a list of methods using the type given
"""
@which
Applied to a function or macro call, it evaluates the arguments to the specified call, and
returns the `Method` object for the method that would be called for those arguments. Applied
to a variable, it returns the module in which the variable was bound. It calls out to the
`which` function.
"""
:@which
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run genstdlib (make docs) and commit the updates


"""
@less
Evaluates the arguments to the function or macro call, determines their types, and calls the `less`
function on the resulting expression.
"""
:@less

"""
@edit
Evaluates the arguments to the function or macro call, determines their types, and calls the `edit`
function on the resulting expression.
"""
:@edit

"""
@functionloc
Applied to a function or macro call, it evaluates the arguments to the specified call, and
returns a tuple `(filename,line)` giving the location for the method that would be called for those arguments.
It calls out to the `functionloc` function.
"""
:@functionloc

"""
@code_typed
Evaluates the arguments to the function or macro call, determines their types, and calls
[`code_typed`](:func:`code_typed`) on the resulting expression.
"""
:@code_typed

"""
@code_warntype
Evaluates the arguments to the function or macro call, determines their types, and calls
[`code_warntype`](:func:`code_warntype`) on the resulting expression.
"""
:@code_warntype

"""
@code_lowered
Evaluates the arguments to the function or macro call, determines their types, and calls
[`code_lowered`](:func:`code_lowered`) on the resulting expression.
"""
:@code_lowered

"""
@code_llvm
Evaluates the arguments to the function or macro call, determines their types, and calls
[`code_llvm`](:func:`code_llvm`) on the resulting expression.
"""
:@code_llvm

"""
@code_native
Evaluates the arguments to the function or macro call, determines their types, and calls
[`code_native`](:func:`code_native`) on the resulting expression.
"""
:@code_native

function type_close_enough(x::ANY, t::ANY)
x == t && return true
@@ -306,6 +383,7 @@ function type_close_enough(x::ANY, t::ANY)
(isa(x,Union) && isa(t,DataType) && any(u -> is(u,t), x.types))
end

# `methodswith` -- shows a list of methods using the type given
function methodswith(t::Type, f::Function, showparents::Bool=false, meths = Method[])
mt = typeof(f).name.mt
d = mt.defs
22 changes: 14 additions & 8 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ Getting Around

.. Docstring generated from Julia source
Evaluates the arguments to the function call, determines their types, and calls the ``edit`` function on the resulting expression.
Evaluates the arguments to the function or macro call, determines their types, and calls the ``edit`` function on the resulting expression.

.. function:: less(file::AbstractString, [line])

@@ -98,7 +98,7 @@ Getting Around

.. Docstring generated from Julia source
Evaluates the arguments to the function call, determines their types, and calls the ``less`` function on the resulting expression.
Evaluates the arguments to the function or macro call, determines their types, and calls the ``less`` function on the resulting expression.

.. function:: clipboard(x)

@@ -188,7 +188,7 @@ Getting Around

.. Docstring generated from Julia source
Applied to a function call, it evaluates the arguments to the specified function call, and returns the ``Method`` object for the method that would be called for those arguments. Applied to a variable, it returns the module in which the variable was bound. It calls out to the ``which`` function.
Applied to a function or macro call, it evaluates the arguments to the specified call, and returns the ``Method`` object for the method that would be called for those arguments. Applied to a variable, it returns the module in which the variable was bound. It calls out to the ``which`` function.

.. function:: methods(f, [types])

@@ -1326,6 +1326,12 @@ Reflection
Returns a tuple ``(filename,line)`` giving the location of a ``Method`` definition.

.. function:: @functionloc

.. Docstring generated from Julia source
Applied to a function or macro call, it evaluates the arguments to the specified call, and returns a tuple ``(filename,line)`` giving the location for the method that would be called for those arguments. It calls out to the ``functionloc`` function.

Internals
---------

@@ -1363,7 +1369,7 @@ Internals

.. Docstring generated from Julia source
Evaluates the arguments to the function call, determines their types, and calls :func:`code_lowered` on the resulting expression.
Evaluates the arguments to the function or macro call, determines their types, and calls :func:`code_lowered` on the resulting expression.

.. function:: code_typed(f, types; optimize=true)

@@ -1375,7 +1381,7 @@ Internals

.. Docstring generated from Julia source
Evaluates the arguments to the function call, determines their types, and calls :func:`code_typed` on the resulting expression.
Evaluates the arguments to the function or macro call, determines their types, and calls :func:`code_typed` on the resulting expression.

.. function:: code_warntype(f, types)

@@ -1387,7 +1393,7 @@ Internals

.. Docstring generated from Julia source
Evaluates the arguments to the function call, determines their types, and calls :func:`code_warntype` on the resulting expression.
Evaluates the arguments to the function or macro call, determines their types, and calls :func:`code_warntype` on the resulting expression.

.. function:: code_llvm(f, types)

@@ -1401,7 +1407,7 @@ Internals

.. Docstring generated from Julia source
Evaluates the arguments to the function call, determines their types, and calls :func:`code_llvm` on the resulting expression.
Evaluates the arguments to the function or macro call, determines their types, and calls :func:`code_llvm` on the resulting expression.

.. function:: code_native(f, types)

@@ -1413,7 +1419,7 @@ Internals

.. Docstring generated from Julia source
Evaluates the arguments to the function call, determines their types, and calls :func:`code_native` on the resulting expression.
Evaluates the arguments to the function or macro call, determines their types, and calls :func:`code_native` on the resulting expression.

.. function:: precompile(f,args::Tuple{Vararg{Any}})

19 changes: 19 additions & 0 deletions test/reflection.jl
Original file line number Diff line number Diff line change
@@ -259,3 +259,22 @@ for (f,t) in ((definitely_not_in_sysimg,Tuple{}),
@test llvmf != C_NULL
@test ccall(:jl_get_llvm_fptr, Ptr{Void}, (Ptr{Void},), llvmf) != C_NULL
end

module MacroTest
export @macrotest
macro macrotest(x::Int, y::Symbol) end
macro macrotest(x::Int, y::Int)
nothing #This is here because of #15280
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, Int})[1]==@which MacroTest.@macrotest 1 1
@test functionloc(@which @macrotest 1 1) == @functionloc @macrotest 1 1
end