From 236fda2946159a9f97e7066a4b04df697a3ccb30 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 19 Jan 2017 21:11:28 +0000 Subject: [PATCH 1/2] Add callsuper macro. Fixes #18252. --- base/exports.jl | 1 + base/util.jl | 44 ++++++++++++++++++++++++++++++++++++++++++++ test/misc.jl | 13 +++++++++++++ 3 files changed, 58 insertions(+) diff --git a/base/exports.jl b/base/exports.jl index d9b0b745312eb..f932518729388 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1379,6 +1379,7 @@ export @polly, @assert, + @callsuper, @enum, @label, @goto, diff --git a/base/util.jl b/base/util.jl index 6cf42650cb7e1..c3d2e81451b85 100644 --- a/base/util.jl +++ b/base/util.jl @@ -750,3 +750,47 @@ kwdef_val(::Type{Cwstring}) = Cwstring(C_NULL) kwdef_val{T<:Integer}(::Type{T}) = zero(T) kwdef_val{T}(::Type{T}) = T() + +""" + @callsuper f(x::T, y::S, ...) + +Call the method of function `f` with parameter signature specified by `T`, `S`, etc. +""" +macro callsuper(ex) + ex.head == :call || error("@invoke requires a call expression") + fname = ex.args[1] + args = ex.args[2:end] + types = Symbol[] + vals = Symbol[] + kwargs = Any[] + blk = quote end + for arg in args + if isa(arg,Expr) && arg.head == :kw + push!(kwargs, QuoteNode(arg.args[1])) + push!(kwargs, esc(arg.args[2])) + elseif isa(arg,Expr) && arg.head == :parameters + for aarg in arg.args + push!(kwargs, QuoteNode(aarg.args[1])) + push!(kwargs, esc(aarg.args[2])) + end + else + val = gensym() + typ = gensym() + push!(vals, val) + push!(types, typ) + if isa(arg,Expr) && arg.head == :(::) && length(arg.args) == 2 + push!(blk.args, :($typ = $(esc(arg.args[2])))) + push!(blk.args, :($val = $(esc(arg.args[1]))::$typ)) + else + push!(blk.args, :($val = $(esc(arg)))) + push!(blk.args, :($typ = typeof($val))) + end + end + end + if isempty(kwargs) + push!(blk.args, :(invoke($(esc(fname)), Tuple{$(types...)}, $(vals...)))) + else + push!(blk.args, :(invoke(Core.kwfunc($(esc(fname))), Tuple{Vector{Any}, typeof($(esc(fname))), $(types...)}, [$(kwargs...)], $(esc(fname)), $(vals...)))) + end + return blk +end diff --git a/test/misc.jl b/test/misc.jl index af9972d1f8210..04226a294f7ce 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -589,3 +589,16 @@ let eval(Base, :(have_color = $(old_have_color))) end end + +@testset "callsuper" begin + f18252(x; y=1) = x+y + f18252(x::Int; y=1) = x-y + @test 0 == @callsuper f18252(1) + @test -1 == @callsuper f18252(1, y=2) + @test -2 == @callsuper f18252(1; y=3) + @test 2 == @callsuper f18252(1::Any) + @test 3 == @callsuper f18252(1::Any, y=2) + @test 4 == @callsuper f18252(1::Any; y=3) + @test_throws MethodError @callsuper f18252(1, y=3, z=2) + @test_throws MethodError @callsuper f18252(1::Any, y=3, z=2) +end From d846bf2287363f168c9038d2b96dee00f6608d18 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 19 Jan 2017 21:19:58 +0000 Subject: [PATCH 2/2] add to docs --- doc/src/stdlib/base.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/src/stdlib/base.md b/doc/src/stdlib/base.md index ec8ff88a4ad51..fb54777e0c441 100644 --- a/doc/src/stdlib/base.md +++ b/doc/src/stdlib/base.md @@ -123,6 +123,7 @@ Core.applicable Core.invoke Base.:(|>) Base.:(∘) +Base.@callsuper ``` ## Syntax