From 5b0aedd38e73c0bc3a071c46b9f459e4d92166b9 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 12 Aug 2014 16:03:41 -0400 Subject: [PATCH] fix call overloading for type constructors, add some tests --- base/base.jl | 5 ++++- base/boot.jl | 1 - src/codegen.cpp | 11 +++++++++-- src/interpreter.c | 2 +- test/core.jl | 18 ++++++++++++++++++ 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/base/base.jl b/base/base.jl index 05b8c2a9e20ed..a726c55202145 100644 --- a/base/base.jl +++ b/base/base.jl @@ -4,7 +4,7 @@ using Core: Intrinsics, arraylen, arrayref, arrayset, arraysize, tuplelen, tupleref, convert_default, kwcall, typeassert, apply_type -import Core.Array # to add methods +import Core: Array, call # to add methods const NonTupleType = Union(DataType,UnionType,TypeConstructor) @@ -15,6 +15,9 @@ convert(T, x) = convert_default(T, x, convert) convert(::(), ::()) = () convert(::Type{Tuple}, x::Tuple) = x +# allow convert to be called as if it were a single-argument constructor +call{T}(::Type{T}, x) = convert(T, x) + argtail(x, rest...) = rest tupletail(x::Tuple) = argtail(x...) diff --git a/base/boot.jl b/base/boot.jl index 490d8c8426354..2f964530110a7 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -245,4 +245,3 @@ typealias ByteString Union(ASCIIString,UTF8String) include(fname::ByteString) = ccall(:jl_load_, Any, (Any,), fname) call(f::Function, args...; kws...) = f(args...; kws...) -call{T}(::Type{T}, x) = convert(T, x) diff --git a/src/codegen.cpp b/src/codegen.cpp index c487ef28c75b2..a2348f7b1e01a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2201,9 +2201,16 @@ static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx, jl_function_t *f = (jl_function_t*)static_eval(a0, ctx, true); if (f != NULL) { + Value *result; headIsGlobal = true; - Value *result = emit_known_call((jl_value_t*)f, args, nargs, ctx, - &theFptr, &f, expr); + if (f->fptr != jl_f_no_function) { + result = emit_known_call((jl_value_t*)f, args, nargs, ctx, + &theFptr, &f, expr); + } + else { + result = emit_known_call((jl_value_t*)jl_call_func, + --args, ++nargs, ctx, &theFptr, &f, expr); + } if (result != NULL) return result; } bool specialized = true; diff --git a/src/interpreter.c b/src/interpreter.c index 0b0bac92fe1e3..7e006cae03761 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -208,7 +208,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) } } jl_function_t *f = (jl_function_t*)eval(args[0], locals, nl); - if (jl_is_func(f)) + if (jl_is_func(f) && f->fptr != jl_f_no_function) return do_call(f, &args[1], nargs-1, NULL, locals, nl); else return do_call(jl_call_func, args, nargs, (jl_value_t*)f, diff --git a/test/core.jl b/test/core.jl index a04bf1443ac20..3e7ca148a8d9e 100644 --- a/test/core.jl +++ b/test/core.jl @@ -1829,3 +1829,21 @@ end # issue #7582 aₜ = "a variable using Unicode 6" + +# call and constructor overloading (#1470, #2403) +typealias FooInt32 Int32 +@test isa(FooInt32(3), FooInt32) +Base.call(x::Int, y::Int) = x + 3y +issue2403func(f) = f(7) +let x = 10 + @test x(3) == 19 + @test issue2403func(x) == 31 +end +type Issue2403 + x +end +Base.call(i::Issue2403, y) = i.x + 2y +let x = Issue2403(20) + @test x(3) == 26 + # @test issue2403func(x) == 34 -- FIXME +end