Skip to content

Commit

Permalink
define at-invokelatest macro (#37971)
Browse files Browse the repository at this point in the history
- `@invokelatest f(args...; kwargs...)` will simply be expanded into 
`Base.invokelatest(f, args...; kwargs...)`
  • Loading branch information
aviatesk authored Dec 2, 2020
1 parent 319ae4a commit 97bdd8b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 0 deletions.
26 changes: 26 additions & 0 deletions base/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,32 @@ function _kwdef!(blk, params_args, call_args)
blk
end

"""
@invokelatest f(args...; kwargs...)
Provides a convenient way to call [`Base.invokelatest`](@ref).
`@invokelatest f(args...; kwargs...)` will simply be expanded into
`Base.invokelatest(f, args...; kwargs...)`.
"""
macro invokelatest(ex)
is_expr(ex, :call) || throw(ArgumentError("a call expression f(args...; kwargs...) should be given"))

f = first(ex.args)
args = []
kwargs = []
for x in ex.args[2:end]
if is_expr(x, :parameters)
append!(kwargs, x.args)
elseif is_expr(x, :kw)
push!(kwargs, x)
else
push!(args, x)
end
end

esc(:($(GlobalRef(Base, :invokelatest))($(f), $(args...); $(kwargs...))))
end

# testing

"""
Expand Down
1 change: 1 addition & 0 deletions doc/src/base/base.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ Base.hasmethod
Core.applicable
Core.invoke
Base.invokelatest
Base.@invokelatest
new
Base.:(|>)
Base.:(∘)
Expand Down
25 changes: 25 additions & 0 deletions test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,31 @@ let foo() = begin
@test foo() == 1
end

module atinvokelatest
f(x) = 1
g(x, y; z=0) = x * y + z
end

let foo() = begin
@eval atinvokelatest.f(x::Int) = 3
return Base.@invokelatest atinvokelatest.f(0)
end
@test foo() == 3
end

let foo() = begin
@eval atinvokelatest.f(x::Int) = 3
return Base.@invokelatest atinvokelatest.f(0)
end
@test foo() == 3

bar() = begin
@eval atinvokelatest.g(x::Int, y::Int; z=3) = z
return Base.@invokelatest atinvokelatest.g(2, 3; z=1)
end
@test bar() == 1
end

# Endian tests
# For now, we only support little endian.
# Add an `Sys.ARCH` test for big endian when/if we add support for that.
Expand Down

0 comments on commit 97bdd8b

Please sign in to comment.