diff --git a/base/coreimg.jl b/base/coreimg.jl index e960008ff34a4..829d371cbd595 100644 --- a/base/coreimg.jl +++ b/base/coreimg.jl @@ -29,9 +29,9 @@ include("options.jl") typealias Cint Int32 typealias Csize_t UInt include("promotion.jl") +include("expr.jl") include("tuple.jl") include("range.jl") -include("expr.jl") include("error.jl") # core numeric operations & types diff --git a/base/deprecated.jl b/base/deprecated.jl index df4a5a144f831..b9e080dc1573f 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -403,8 +403,6 @@ end @deprecate with_env(f::Function, key::AbstractString, val) withenv(f, key=>val) -@deprecate ntuple(n::Integer, f::Function) ntuple(f, n) - # 0.4 discontinued functions @noinline function subtypetree(x::DataType, level=-1) @@ -841,4 +839,4 @@ for f in (:remotecall, :remotecall_fetch, :remotecall_wait) @deprecate ($f)(w::Worker, f::Function, args...) ($f)(f, w::Worker, args...) @deprecate ($f)(id::Integer, f::Function, args...) ($f)(f, id::Integer, args...) end -end \ No newline at end of file +end diff --git a/base/inference.jl b/base/inference.jl index fc190395ebb30..f7293c63b7164 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -458,6 +458,9 @@ const apply_type_tfunc = function (A, args...) end add_tfunc(apply_type, 1, IInf, apply_type_tfunc) +## external tfunc additions ## +add_tfunc(ntuple, 2, 2, _ntuple_tfunc) + function tuple_tfunc(argtype::ANY) if isa(argtype,DataType) && argtype.name === Tuple.name p = map(x->(isType(x) && !isa(x.parameters[1],TypeVar) ? typeof(x.parameters[1]) : x), diff --git a/base/sysimg.jl b/base/sysimg.jl index c555a41cf6d6c..caf504af99253 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -35,9 +35,9 @@ include("options.jl") # core operations & types include("promotion.jl") +include("expr.jl") include("tuple.jl") include("range.jl") -include("expr.jl") include("error.jl") # core numeric operations & types diff --git a/base/tuple.jl b/base/tuple.jl index 270f44e9e4f71..8c507ebab431b 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -29,29 +29,43 @@ eltype{T,_}(::Type{NTuple{_,T}}) = T ## mapping ## -ntuple(f::Function, n::Integer) = +const ntuple = function(f, n::Integer) n<=0 ? () : n==1 ? (f(1),) : n==2 ? (f(1),f(2),) : n==3 ? (f(1),f(2),f(3),) : - n==4 ? (f(1),f(2),f(3),f(4),) : - n==5 ? (f(1),f(2),f(3),f(4),f(5),) : - tuple(ntuple(f,n-5)..., f(n-4), f(n-3), f(n-2), f(n-1), f(n)) - -ntuple(f, ::Type{Val{0}}) = () -ntuple(f, ::Type{Val{1}}) = (f(1),) -ntuple(f, ::Type{Val{2}}) = (f(1),f(2)) -ntuple(f, ::Type{Val{3}}) = (f(1),f(2),f(3)) -ntuple(f, ::Type{Val{4}}) = (f(1),f(2),f(3),f(4)) -ntuple(f, ::Type{Val{5}}) = (f(1),f(2),f(3),f(4),f(5)) -@generated function ntuple{N}(f, ::Type{Val{N}}) - if !isa(N,Int) - :(throw(TypeError(:ntuple, "", Int, $(QuoteNode(N))))) + tuple([f(i) for i = 1:Int(n)]...) +end + +const _ntuple_tfunc_gensym = gensym() +const _ntuple_tfunc = function(argtypes, argexprs, vtypes, sv) + n = false + if isa(argexprs[2], Integer) + try + n = Int(argexprs[2]) + end + end + + Core.Inference.setindex!(vtypes, + Core.Inference.call(Core.Inference.VarState, Int, false), + _ntuple_tfunc_gensym) + F = Core.Inference.abstract_eval_call( + Expr(:call, argexprs[1], _ntuple_tfunc_gensym), + vtypes, sv) + Core.Inference.delete!(vtypes, + _ntuple_tfunc_gensym) + + if isa(n, Int) + return NTuple{n, F} + elseif F === Any + return Tuple else - M = N-5 - :(tuple(ntuple(f, Val{$M})..., f($N-4), f($N-3), f($N-2), f($N-1), f($N))) + return Tuple{Vararg{F}} end end +if isdefined(Core, :Inference) && isdefined(Core.Inference, :add_tfunc) + Core.Inference.add_tfunc(ntuple, 2, 2, _ntuple_tfunc) +end # 0 argument function map(f) = f() diff --git a/test/tuple.jl b/test/tuple.jl index 7412850ba4abe..c4a4dda8e4e8c 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -145,12 +145,14 @@ foo(x, y, z) = x + y + z @test any((true,true,false)) === true @test any((true,true,true)) === true -@test @inferred(ntuple(Base.Abs2Fun(), Val{0})) == () -@test @inferred(ntuple(Base.Abs2Fun(), Val{2})) == (1, 4) -@test @inferred(ntuple(Base.Abs2Fun(), Val{3})) == (1, 4, 9) -@test @inferred(ntuple(Base.Abs2Fun(), Val{4})) == (1, 4, 9, 16) -@test @inferred(ntuple(Base.Abs2Fun(), Val{5})) == (1, 4, 9, 16, 25) -@test @inferred(ntuple(Base.Abs2Fun(), Val{6})) == (1, 4, 9, 16, 25, 36) +ntuple_val{T}(x, ::Type{Val{T}}) = ntuple(x, T) +@test @inferred(ntuple_val(Base.Abs2Fun(), Val{0})) == () +@test @inferred(ntuple_val(Base.Abs2Fun(), Val{2})) == (1, 4) +@test @inferred(ntuple_val(Base.Abs2Fun(), Val{3})) == (1, 4, 9) +@test @inferred(ntuple_val(Base.Abs2Fun(), Val{4})) == (1, 4, 9, 16) +@test @inferred(ntuple_val(Base.Abs2Fun(), Val{5})) == (1, 4, 9, 16, 25) +@test @inferred(ntuple_val(Base.Abs2Fun(), Val{6})) == (1, 4, 9, 16, 25, 36) # issue #12854 -@test_throws TypeError ntuple(identity, Val{1:2}) +@test_throws TypeError ntuple(identity, Val{1}) +@test_throws TypeError ntuple_val(identity, Val{1:2})