From afd4eb038dcd9fa3e512509f4c332a9e7763ba59 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 2 Mar 2015 16:54:50 -0500 Subject: [PATCH 1/7] redesign tuple types --- base/Enums.jl | 2 +- base/REPLCompletions.jl | 4 +- base/abstractarray.jl | 46 +- base/array.jl | 27 +- base/base.jl | 63 +- base/bitarray.jl | 4 +- base/boot.jl | 10 +- base/broadcast.jl | 6 +- base/c.jl | 4 +- base/collections.jl | 2 +- base/combinatorics.jl | 2 +- base/deprecated.jl | 6 +- base/dict.jl | 47 +- base/docs.jl | 2 +- base/env.jl | 4 +- base/inference.jl | 561 ++++------ base/interactiveutil.jl | 14 +- base/io.jl | 2 +- base/linalg/diagonal.jl | 2 +- base/methodshow.jl | 20 +- base/multi.jl | 4 +- base/multidimensional.jl | 6 +- base/operators.jl | 22 +- base/pkg/query.jl | 4 +- base/pkg/read.jl | 2 +- base/pkg/resolve.jl | 6 +- base/pkg/resolve/versionweight.jl | 2 +- base/pointer.jl | 2 +- base/precompile.jl | 6 - base/promotion.jl | 49 +- base/random.jl | 12 +- base/range.jl | 4 +- base/reducedim.jl | 2 +- base/reflection.jl | 48 +- base/replutil.jl | 58 +- base/serialize.jl | 33 +- base/sharedarray.jl | 2 +- base/show.jl | 22 +- base/socket.jl | 3 +- base/sparse.jl | 2 +- base/sparse/sparsematrix.jl | 6 +- base/stream.jl | 2 +- base/subarray.jl | 131 +-- base/subarray2.jl | 5 +- base/sysimg.jl | 8 +- base/tuple.jl | 64 +- base/version.jl | 10 +- examples/lru_test.jl | 2 +- src/Makefile | 2 +- src/abi_x86_64.cpp | 4 +- src/alloc.c | 210 +--- src/array.c | 51 +- src/ast.c | 55 +- src/builtin_proto.h | 3 +- src/builtins.c | 249 +++-- src/ccall.cpp | 111 +- src/cgutils.cpp | 540 ++++------ src/codegen.cpp | 583 +++------- src/dump.c | 117 +- src/gc.c | 19 +- src/gf.c | 698 ++++++------ src/init.c | 3 +- src/interpreter.c | 51 +- src/intrinsics.cpp | 72 +- src/jl_uv.c | 13 +- src/jlapi.c | 4 +- src/jltypes.c | 1669 ++++++++++++++--------------- src/julia-parser.scm | 4 +- src/julia-syntax.scm | 75 +- src/julia.h | 209 ++-- src/julia_internal.h | 10 +- src/simplevector.c | 98 ++ src/sys.c | 4 +- src/task.c | 44 +- src/toplevel.c | 91 +- test/arrayops.jl | 16 +- test/bitarray.jl | 4 +- test/broadcast.jl | 6 +- test/core.jl | 256 +++-- test/llvmcall.jl | 10 +- test/math.jl | 2 +- test/meta.jl | 2 +- test/reducedim.jl | 2 +- test/reflection.jl | 24 +- test/replcompletions.jl | 12 +- test/staged.jl | 5 +- 86 files changed, 3073 insertions(+), 3600 deletions(-) create mode 100644 src/simplevector.c diff --git a/base/Enums.jl b/base/Enums.jl index dab7f23c94069..88cd704ef0741 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -35,7 +35,7 @@ macro enum(T,syms...) else throw(ArgumentError("invalid type expression for enum $T")) end - vals = Array((Symbol,Integer),0) + vals = Array(Tuple{Symbol,Integer},0) lo = hi = 0 i = -1 enumT = typeof(i) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 78f2383d50aa6..a792d63a081b9 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -226,10 +226,10 @@ function complete_methods(ex_org::Expr) found ? push!(args_ex, method_type_of_arg(val)) : push!(args_ex, Any) end out = UTF8String[] - t_in = tuple(args_ex...) # Input types + t_in = Tuple{args_ex...} # Input types for method in methods(func) # Check if the method's type signature intersects the input types - typeintersect(method.sig[1 : min(length(args_ex), end)], t_in) != None && + typeintersect(Tuple{method.sig.parameters[1 : min(length(args_ex), end)]...}, t_in) != None && push!(out,string(method)) end return out diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 24042be4a7137..36a07bdd98b74 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -185,8 +185,8 @@ reshape(a::AbstractArray, dims::Int...) = reshape(a, dims) vec(a::AbstractArray) = reshape(a,length(a)) vec(a::AbstractVector) = a -_sub(::(), ::()) = () -_sub(t::Tuple, ::()) = t +_sub(::Tuple{}, ::Tuple{}) = () +_sub(t::Tuple, ::Tuple{}) = t _sub(t::Tuple, s::Tuple) = _sub(tail(t), tail(s)) function squeeze(A::AbstractArray, dims::Dims) @@ -526,10 +526,10 @@ end ## get (getindex with a default value) ## -typealias RangeVecIntList{A<:AbstractVector{Int}} Union((Union(Range, AbstractVector{Int})...), AbstractVector{UnitRange{Int}}, AbstractVector{Range{Int}}, AbstractVector{A}) +typealias RangeVecIntList{A<:AbstractVector{Int}} Union(Tuple{Union(Range, AbstractVector{Int}),...}, AbstractVector{UnitRange{Int}}, AbstractVector{Range{Int}}, AbstractVector{A}) get(A::AbstractArray, i::Integer, default) = in_bounds(length(A), i) ? A[i] : default -get(A::AbstractArray, I::(), default) = similar(A, typeof(default), 0) +get(A::AbstractArray, I::Tuple{}, default) = similar(A, typeof(default), 0) get(A::AbstractArray, I::Dims, default) = in_bounds(size(A), I...) ? A[I...] : default function get!{T}(X::AbstractArray{T}, A::AbstractArray, I::Union(Range, AbstractVector{Int}), default::T) @@ -727,7 +727,7 @@ function hvcat(nbc::Integer, as...) hvcat(ntuple(nbr, i->nbc), as...) end -function hvcat{T}(rows::(Int...), as::AbstractMatrix{T}...) +function hvcat{T}(rows::Tuple{Int,...}, as::AbstractMatrix{T}...) nbr = length(rows) # number of block rows nc = 0 @@ -770,9 +770,9 @@ function hvcat{T}(rows::(Int...), as::AbstractMatrix{T}...) out end -hvcat(rows::(Int...)) = [] +hvcat(rows::Tuple{Int,...}) = [] -function hvcat{T<:Number}(rows::(Int...), xs::T...) +function hvcat{T<:Number}(rows::Tuple{Int,...}, xs::T...) nr = length(rows) nc = rows[1] @@ -805,7 +805,7 @@ function hvcat_fill(a, xs) a end -function typed_hvcat(T::Type, rows::(Int...), xs::Number...) +function typed_hvcat(T::Type, rows::Tuple{Int,...}, xs::Number...) nr = length(rows) nc = rows[1] for i = 2:nr @@ -820,13 +820,13 @@ function typed_hvcat(T::Type, rows::(Int...), xs::Number...) hvcat_fill(Array(T, nr, nc), xs) end -function hvcat(rows::(Int...), xs::Number...) +function hvcat(rows::Tuple{Int,...}, xs::Number...) T = promote_typeof(xs...) typed_hvcat(T, rows, xs...) end # fallback definition of hvcat in terms of hcat and vcat -function hvcat(rows::(Int...), as...) +function hvcat(rows::Tuple{Int,...}, as...) nbr = length(rows) # number of block rows rs = cell(nbr) a = 1 @@ -837,7 +837,7 @@ function hvcat(rows::(Int...), as...) vcat(rs...) end -function typed_hvcat(T::Type, rows::(Int...), as...) +function typed_hvcat(T::Type, rows::Tuple{Int,...}, as...) nbr = length(rows) # number of block rows rs = cell(nbr) a = 1 @@ -1021,7 +1021,7 @@ end sub2ind{T<:Integer}(dims, I::AbstractVector{T}...) = [ sub2ind(dims, map(X->X[i], I)...)::Int for i=1:length(I[1]) ] -function ind2sub(dims::(Integer,Integer...), ind::Int) +function ind2sub(dims::Tuple{Integer,Integer,...}, ind::Int) ndims = length(dims) stride = dims[1] for i=2:ndims-1 @@ -1038,17 +1038,17 @@ function ind2sub(dims::(Integer,Integer...), ind::Int) return tuple(ind, sub...) end -ind2sub(dims::(Integer...), ind::Integer) = ind2sub(dims, Int(ind)) -ind2sub(dims::(), ind::Integer) = ind==1 ? () : throw(BoundsError()) -ind2sub(dims::(Integer,), ind::Int) = (ind,) -ind2sub(dims::(Integer,Integer), ind::Int) = +ind2sub(dims::Tuple{Integer,...}, ind::Integer) = ind2sub(dims, Int(ind)) +ind2sub(dims::Tuple{}, ind::Integer) = ind==1 ? () : throw(BoundsError()) +ind2sub(dims::Tuple{Integer,}, ind::Int) = (ind,) +ind2sub(dims::Tuple{Integer,Integer}, ind::Int) = (rem(ind-1,dims[1])+1, div(ind-1,dims[1])+1) -ind2sub(dims::(Integer,Integer,Integer), ind::Int) = +ind2sub(dims::Tuple{Integer,Integer,Integer}, ind::Int) = (rem(ind-1,dims[1])+1, div(rem(ind-1,dims[1]*dims[2]), dims[1])+1, div(rem(ind-1,dims[1]*dims[2]*dims[3]), dims[1]*dims[2])+1) ind2sub(a::AbstractArray, ind::Integer) = ind2sub(size(a), Int(ind)) -function ind2sub{T<:Integer}(dims::(Integer,Integer...), ind::AbstractVector{T}) +function ind2sub{T<:Integer}(dims::Tuple{Integer,Integer,...}, ind::AbstractVector{T}) n = length(dims) l = length(ind) t = ntuple(n, x->Array(Int, l)) @@ -1131,7 +1131,7 @@ end ## iteration utilities ## # slow, but useful -function cartesianmap(body, t::(Int...), it...) +function cartesianmap(body, t::Tuple{Int,...}, it...) idx = length(t)-length(it) if idx == 1 for i = 1:t[1] @@ -1154,15 +1154,15 @@ function cartesianmap(body, t::(Int...), it...) end end -cartesianmap(body, t::()) = (body(); nothing) +cartesianmap(body, t::Tuple{}) = (body(); nothing) -function cartesianmap(body, t::(Int,)) +function cartesianmap(body, t::Tuple{Int,}) for i = 1:t[1] body(i) end end -function cartesianmap(body, t::(Int,Int)) +function cartesianmap(body, t::Tuple{Int,Int}) for j = 1:t[2] for i = 1:t[1] body(i,j) @@ -1170,7 +1170,7 @@ function cartesianmap(body, t::(Int,Int)) end end -function cartesianmap(body, t::(Int,Int,Int)) +function cartesianmap(body, t::Tuple{Int,Int,Int}) for k = 1:t[3] for j = 1:t[2] for i = 1:t[1] diff --git a/base/array.jl b/base/array.jl index b61035ac137dc..235d7a1a04272 100644 --- a/base/array.jl +++ b/base/array.jl @@ -8,9 +8,9 @@ typealias DenseVector{T} DenseArray{T,1} typealias DenseMatrix{T} DenseArray{T,2} typealias DenseVecOrMat{T} Union(DenseVector{T}, DenseMatrix{T}) -typealias StridedArray{T,N,A<:DenseArray,I<:(RangeIndex...)} Union(DenseArray{T,N}, SubArray{T,N,A,I}) -typealias StridedVector{T,A<:DenseArray,I<:(RangeIndex...)} Union(DenseArray{T,1}, SubArray{T,1,A,I}) -typealias StridedMatrix{T,A<:DenseArray,I<:(RangeIndex...)} Union(DenseArray{T,2}, SubArray{T,2,A,I}) +typealias StridedArray{T,N,A<:DenseArray,I<:Tuple{RangeIndex,...}} Union(DenseArray{T,N}, SubArray{T,N,A,I}) +typealias StridedVector{T,A<:DenseArray,I<:Tuple{RangeIndex,...}} Union(DenseArray{T,1}, SubArray{T,1,A,I}) +typealias StridedMatrix{T,A<:DenseArray,I<:Tuple{RangeIndex,...}} Union(DenseArray{T,2}, SubArray{T,2,A,I}) typealias StridedVecOrMat{T} Union(StridedVector{T}, StridedMatrix{T}) call{T}(::Type{Vector{T}}, m::Integer) = Array{T}(m) @@ -41,9 +41,14 @@ end cconvert{P<:Ptr,T<:Ptr}(::Union(Type{Ptr{P}},Type{Ref{P}}), a::Array{T}) = a cconvert{P<:Ptr}(::Union(Type{Ptr{P}},Type{Ref{P}}), a::Array) = Ref{P}(a) -size(a::Array) = arraysize(a) size(a::Array, d) = arraysize(a, d) +size(a::Vector) = (arraysize(a,1),) size(a::Matrix) = (arraysize(a,1), arraysize(a,2)) +size{_}(a::Array{_,3}) = (arraysize(a,1), arraysize(a,2), arraysize(a,3)) +size{_}(a::Array{_,4}) = (arraysize(a,1), arraysize(a,2), arraysize(a,3), arraysize(a,4)) +asize_from(a::Array, n) = n > ndims(a) ? () : (arraysize(a,n), asize_from(a, n+1)...) +size{_,N}(a::Array{_,N}) = asize_from(a, 1)::NTuple{N,Int} + length(a::Array) = arraylen(a) elsize{T}(a::Array{T}) = isbits(T) ? sizeof(T) : sizeof(Ptr) sizeof(a::Array) = elsize(a) * length(a) @@ -148,7 +153,7 @@ similar{T}(a::Array{T,2}, m::Int) = Array(T, m) similar{T}(a::Array{T,2}, S) = Array(S, size(a,1), size(a,2)) # T[x...] constructs Array{T,1} -function getindex(T::NonTupleType, vals...) +function getindex(T::Type, vals...) a = Array(T,length(vals)) @inbounds for i = 1:length(vals) a[i] = vals[i] @@ -164,14 +169,6 @@ function getindex(::Type{Any}, vals::ANY...) return a end -function getindex(T::(Type...), vals::Tuple...) - a = Array(T,length(vals)) - @inbounds for i = 1:length(vals) - a[i] = vals[i] - end - return a -end - if _oldstyle_array_vcat_ # T[a:b] and T[a:s:b] also construct typed ranges function getindex{T<:Union(Char,Number)}(::Type{T}, r::Range) @@ -218,7 +215,7 @@ fill(v, dims::Dims) = fill!(Array(typeof(v), dims), v) fill(v, dims::Integer...) = fill!(Array(typeof(v), dims...), v) cell(dims::Integer...) = Array(Any, dims...) -cell(dims::(Integer...)) = Array(Any, convert((Int...), dims)) +cell(dims::Tuple{Integer,...}) = Array(Any, convert(Tuple{Int,...}, dims)) for (fname, felt) in ((:zeros,:zero), (:ones,:one)) @eval begin @@ -1289,7 +1286,7 @@ function indcopy(sz::Dims, I::Vector) dst, src end -function indcopy(sz::Dims, I::(RangeIndex...)) +function indcopy(sz::Dims, I::Tuple{RangeIndex,...}) n = length(I) s = sz[n] for i = n+1:length(sz) diff --git a/base/base.jl b/base/base.jl index f71f057e469e2..a9ef4f4597864 100644 --- a/base/base.jl +++ b/base/base.jl @@ -1,5 +1,3 @@ -const NonTupleType = Union(DataType,UnionType,TypeConstructor) - typealias Callable Union(Function,DataType) const Bottom = Union() @@ -39,20 +37,37 @@ call{T}(::Type{T}, args...) = convert(T, args...)::T convert{T}(::Type{T}, x::T) = x -convert(::(), ::()) = () +convert(::Type{Tuple{}}, ::Tuple{}) = () convert(::Type{Tuple}, x::Tuple) = x +convert{T}(::Type{Tuple{T,...}}, x::Tuple) = cnvt_all(T, x...) +cnvt_all(T) = () +cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...) + +stagedfunction tuple_type_head{T<:Tuple}(::Type{T}) + T.parameters[1] +end + +isvarargtype(t::ANY) = isa(t,DataType)&&is((t::DataType).name,Vararg.name) +isvatuple(t::DataType) = (n = length(t.parameters); n > 0 && isvarargtype(t.parameters[n])) +unwrapva(t::ANY) = isvarargtype(t) ? t.parameters[1] : t + +stagedfunction tuple_type_tail{T<:Tuple}(::Type{T}) + if isvatuple(T) && length(T.parameters) == 1 + return T + end + Tuple{argtail(T.parameters...)...} +end argtail(x, rest...) = rest tail(x::Tuple) = argtail(x...) -convert(T::(Type, Type...), x::(Any, Any...)) = - tuple(convert(T[1],x[1]), convert(tail(T), tail(x))...) -convert(T::(Any, Any...), x::(Any, Any...)) = - tuple(convert(T[1],x[1]), convert(tail(T), tail(x))...) +convert{T<:Tuple{Any,Any,...}}(::Type{T}, x::Tuple{Any, Any, ...}) = + tuple(convert(tuple_type_head(T),x[1]), convert(tuple_type_tail(T), tail(x))...) -convert{T}(::Type{(T...)}, x::Tuple) = cnvt_all(T, x...) -cnvt_all(T) = () -cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...) +oftype(x,c) = convert(typeof(x),c) + +unsigned(x::Int) = reinterpret(UInt, x) +signed(x::UInt) = reinterpret(Int, x) # conversions used by ccall ptr_arg_cconvert{T}(::Type{Ptr{T}}, x) = cconvert(T, x) @@ -66,6 +81,8 @@ unsafe_convert{P<:Ptr}(::Type{P}, x::Ptr) = convert(P, x) reinterpret{T,S}(::Type{T}, x::S) = box(T,unbox(S,x)) +sizeof(x) = Core.sizeof(x) + abstract IO type ErrorException <: Exception @@ -220,7 +237,7 @@ function precompile(f::ANY, args::Tuple) f = f.name.module.call end if isgeneric(f) - ccall(:jl_compile_hint, Void, (Any, Any), f, args) + ccall(:jl_compile_hint, Void, (Any, Any), f, Tuple{args...}) end end @@ -247,7 +264,7 @@ end call{T,N}(::Type{Array{T}}, d::NTuple{N,Int}) = ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d) -call{T}(::Type{Array{T}}, d::Integer...) = Array{T}(convert((Int...), d)) +call{T}(::Type{Array{T}}, d::Integer...) = Array{T}(convert(Tuple{Int,...}, d)) call{T}(::Type{Array{T}}, m::Integer) = ccall(:jl_alloc_array_1d, Array{T,1}, (Any,Int), Array{T,1}, m) @@ -258,11 +275,31 @@ call{T}(::Type{Array{T}}, m::Integer, n::Integer, o::Integer) = # TODO: possibly turn these into deprecations Array{T,N}(::Type{T}, d::NTuple{N,Int}) = Array{T}(d) -Array{T}(::Type{T}, d::Integer...) = Array{T}(convert((Int...), d)) +Array{T}(::Type{T}, d::Integer...) = Array{T}(convert(Tuple{Int,...}, d)) Array{T}(::Type{T}, m::Integer) = Array{T}(m) Array{T}(::Type{T}, m::Integer,n::Integer) = Array{T}(m,n) Array{T}(::Type{T}, m::Integer,n::Integer,o::Integer) = Array{T}(m,n,o) +# SimpleVector + +function getindex(v::SimpleVector, i::Int) + if !(1 <= i <= length(v)) + throw(BoundsError()) + end + unsafe_load(convert(Ptr{Any},data_pointer_from_objref(v)) + i*sizeof(Ptr)) +end + +length(v::SimpleVector) = v.length +endof(v::SimpleVector) = v.length +start(v::SimpleVector) = 1 +next(v::SimpleVector,i) = (v[i],i+1) +done(v::SimpleVector,i) = (i > v.length) +isempty(v::SimpleVector) = (v.length == 0) + +map(f, v::SimpleVector) = Any[ f(v[i]) for i = 1:length(v) ] + +getindex(v::SimpleVector, I::AbstractArray) = Any[ v[i] for i in I ] + immutable Nullable{T} isnull::Bool value::T diff --git a/base/bitarray.jl b/base/bitarray.jl index f6382ce112e32..ceb0e0086186d 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -1808,7 +1808,7 @@ function cat(catdim::Integer, X::Union(BitArray, Integer)...) end end # just integers and no BitArrays -> general case - has_bitarray || return invoke(cat, (Integer, Any...), catdim, X...) + has_bitarray || return invoke(cat, Tuple{Integer, Any, ...}, catdim, X...) dimsX = map((a->isa(a,BitArray) ? size(a) : (1,)), X) ndimsX = map((a->isa(a,BitArray) ? ndims(a) : 1), X) d_max = maximum(ndimsX) @@ -1842,7 +1842,7 @@ function cat(catdim::Integer, X::Union(BitArray, Integer)...) end ndimsC = max(catdim, d_max) - dimsC = ntuple(ndimsC, compute_dims)::(Int...) + dimsC = ntuple(ndimsC, compute_dims)::Tuple{Int,...} typeC = promote_type(map(x->isa(x,BitArray) ? eltype(x) : typeof(x), X)...) if !has_integer || typeC == Bool C = BitArray(dimsC) diff --git a/base/boot.jl b/base/boot.jl index f8c0708fed271..f86694b29cf8b 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -120,7 +120,7 @@ export # key types Any, DataType, Vararg, ANY, NTuple, Tuple, Type, TypeConstructor, TypeName, TypeVar, Union, UnionType, Void, - AbstractArray, DenseArray, + SimpleVector, AbstractArray, DenseArray, # special objects Box, Function, IntrinsicFunction, LambdaStaticData, Method, MethodTable, Module, Symbol, Task, Array, WeakRef, @@ -140,7 +140,7 @@ export GlobalRef, NewvarNode, GenSym, # object model functions fieldtype, getfield, setfield!, yieldto, throw, tuple, is, ===, isdefined, - # arraylen, arrayref, arrayset, arraysize, tuplelen, tupleref, + # arraylen, arrayref, arrayset, arraysize, # _apply, kwcall, # sizeof # not exported, to avoid conflicting with Base.sizeof # type reflection @@ -270,11 +270,11 @@ TypeVar(n::Symbol, lb::ANY, ub::ANY) = TypeVar(n::Symbol, lb::ANY, ub::ANY, b::Bool) = ccall(:jl_new_typevar_, Any, (Any, Any, Any, Any), n, lb::Type, ub::Type, b)::TypeVar -TypeConstructor(p::ANY, t::ANY) = ccall(:jl_new_type_constructor, Any, (Any, Any), p::Tuple, t::Type) +TypeConstructor(p::ANY, t::ANY) = ccall(:jl_new_type_constructor, Any, (Any, Any), p::SimpleVector, t::Type) Expr(args::ANY...) = _expr(args...) -_new(typ::Symbol, argty::Symbol) = eval(:(Core.call(::$(Expr(:call, :(Core.apply_type), :Type, typ)), n::$argty) = $(Expr(:new, typ, :n)))) +_new(typ::Symbol, argty::Symbol) = eval(:(Core.call(::Type{$typ}, n::$argty) = $(Expr(:new, typ, :n)))) _new(:LineNumberNode, :Int) _new(:LabelNode, :Int) _new(:GotoNode, :Int) @@ -291,3 +291,5 @@ Task(f::ANY) = ccall(:jl_new_task, Any, (Any, Int), f::Function, 0)::Task # simple convert for use by constructors of types in Core convert(::Type{Any}, x::ANY) = x convert{T}(::Type{T}, x::T) = x +cconvert(T::Type, x) = convert(T, x) +unsafe_convert{T}(::Type{T}, x::T) = x diff --git a/base/broadcast.jl b/base/broadcast.jl index 49159bdb2f0aa..90317d2b76967 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -13,9 +13,9 @@ export broadcast_getindex, broadcast_setindex! droparg1(a, args...) = args -longer_tuple(x::(), retx::Tuple, y::(), rety::Tuple) = retx -longer_tuple(x::(), retx::Tuple, y::Tuple, rety::Tuple) = rety -longer_tuple(x::Tuple, retx::Tuple, y::(), rety::Tuple) = retx +longer_tuple(x::Tuple{}, retx::Tuple, y::Tuple{}, rety::Tuple) = retx +longer_tuple(x::Tuple{}, retx::Tuple, y::Tuple, rety::Tuple) = rety +longer_tuple(x::Tuple, retx::Tuple, y::Tuple{}, rety::Tuple) = retx longer_tuple(x::Tuple, retx::Tuple, y::Tuple, rety::Tuple) = longer_tuple(droparg1(x...), retx, droparg1(y...), rety) longer_tuple(x::Tuple, y::Tuple) = longer_tuple(x, x, y, y) diff --git a/base/c.jl b/base/c.jl index 4138b8d7161ae..b15d4b3a72713 100644 --- a/base/c.jl +++ b/base/c.jl @@ -55,11 +55,11 @@ sigatomic_end() = ccall(:jl_sigatomic_end, Void, ()) disable_sigint(f::Function) = try sigatomic_begin(); f(); finally sigatomic_end(); end reenable_sigint(f::Function) = try sigatomic_end(); f(); finally sigatomic_begin(); end -function ccallable(f::Function, rt::Type, argt::(Type...), name::Union(AbstractString,Symbol)=string(f)) +function ccallable(f::Function, rt::Type, argt::Type, name::Union(AbstractString,Symbol)=string(f)) ccall(:jl_extern_c, Void, (Any, Any, Any, Ptr{UInt8}), f, rt, argt, name) end -function ccallable(f::Function, argt::(Type...), name::Union(AbstractString,Symbol)=string(f)) +function ccallable(f::Function, argt::Type, name::Union(AbstractString,Symbol)=string(f)) ccall(:jl_extern_c, Void, (Any, Ptr{Void}, Any, Ptr{UInt8}), f, C_NULL, argt, name) end diff --git a/base/collections.jl b/base/collections.jl index 419456d9cd6d1..bcaa6328c6bd6 100644 --- a/base/collections.jl +++ b/base/collections.jl @@ -161,7 +161,7 @@ PriorityQueue{K,V}(ks::AbstractArray{K}, vs::AbstractArray{V}, PriorityQueue{K,V}(kvs::Associative{K,V}, o::Ordering=Forward) = PriorityQueue{K,V,typeof(o)}(kvs, o) -PriorityQueue{K,V}(a::AbstractArray{(K,V)}, o::Ordering=Forward) = PriorityQueue{K,V,typeof(o)}(a, o) +PriorityQueue{K,V}(a::AbstractArray{Tuple{K,V}}, o::Ordering=Forward) = PriorityQueue{K,V,typeof(o)}(a, o) length(pq::PriorityQueue) = length(pq.xs) isempty(pq::PriorityQueue) = isempty(pq.xs) diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 1e654610f6e14..115e001c89a97 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -351,7 +351,7 @@ function nextfixedpartition(n, m, bs) return as end -let _nipartitions = Dict{(Int,Int),Int}() +let _nipartitions = Dict{Tuple{Int,Int},Int}() global npartitions function npartitions(n::Int,m::Int) if n < m || m == 0 diff --git a/base/deprecated.jl b/base/deprecated.jl index 5987fc7f92af1..27aa20179267b 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -200,9 +200,9 @@ end @deprecate median!(v::AbstractVector; checknan::Bool=true) median!(v) @deprecate Dict{K,V}(ks::AbstractArray{K}, vs::AbstractArray{V}) Dict{K,V}(zip(ks, vs)) -@deprecate Dict{K,V}(ks::(K...), vs::(V...)) Dict{K,V}(zip(ks, vs)) -@deprecate Dict{K}(ks::(K...), vs::Tuple) Dict{K,Any}(zip(ks, vs)) -@deprecate Dict{V}(ks::Tuple, vs::(V...)) Dict{Any,V}(zip(ks, vs)) +@deprecate Dict{K,V}(ks::Tuple{K,...}, vs::Tuple{V,...}) Dict{K,V}(zip(ks, vs)) +@deprecate Dict{K}(ks::Tuple{K,...}, vs::Tuple) Dict{K,Any}(zip(ks, vs)) +@deprecate Dict{V}(ks::Tuple, vs::Tuple{V,...}) Dict{Any,V}(zip(ks, vs)) @deprecate Dict(ks, vs) Dict{Any,Any}(zip(ks, vs)) @deprecate itrunc{T<:Integer}(::Type{T}, n::Integer) (n % T) diff --git a/base/dict.jl b/base/dict.jl index 77e4ed5b8cb48..5dcb9ef6889ac 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -6,7 +6,7 @@ const secret_table_token = :__c782dbf1cf4d6a2e5e3865d7e95634f2e09b5902__ haskey(d::Associative, k) = in(k,keys(d)) -function in(p::(Any,Any), a::Associative) +function in(p::Tuple{Any,Any}, a::Associative) v = get(a,p[1],secret_table_token) !is(v, secret_table_token) && (v == p[2]) end @@ -149,8 +149,10 @@ end length(v::Union(KeyIterator,ValueIterator)) = length(v.dict) isempty(v::Union(KeyIterator,ValueIterator)) = isempty(v.dict) -eltype{D}(::Type{KeyIterator{D}}) = eltype(D)[1] -eltype{D}(::Type{ValueIterator{D}}) = eltype(D)[2] +_tt1{A,B}(::Type{Tuple{A,B}}) = A +_tt2{A,B}(::Type{Tuple{A,B}}) = B +eltype{D}(::Type{KeyIterator{D}}) = _tt1(eltype(D)) +eltype{D}(::Type{ValueIterator{D}}) = _tt2(eltype(D)) start(v::Union(KeyIterator,ValueIterator)) = start(v.dict) done(v::Union(KeyIterator,ValueIterator), state) = done(v.dict, state) @@ -187,12 +189,13 @@ function merge!(d::Associative, others::Associative...) end return d end +keytype{K,V}(::Associative{K,V}) = K +valtype{K,V}(::Associative{K,V}) = V function merge(d::Associative, others::Associative...) - K, V = eltype(d) + K, V = keytype(d), valtype(d) for other in others - (Ko, Vo) = eltype(other) - K = promote_type(K, Ko) - V = promote_type(V, Vo) + K = promote_type(K, keytype(other)) + V = promote_type(V, valtype(other)) end merge!(Dict{K,V}(), d, others...) end @@ -207,7 +210,7 @@ function filter!(f, d::Associative) end filter(f, d::Associative) = filter!(f,copy(d)) -eltype{K,V}(::Type{Associative{K,V}}) = (K,V) +eltype{K,V}(::Type{Associative{K,V}}) = Tuple{K,V} function isequal(l::Associative, r::Associative) if isa(l,ObjectIdDict) != isa(r,ObjectIdDict) @@ -356,23 +359,23 @@ type Dict{K,V} <: Associative{K,V} end end Dict() = Dict{Any,Any}() -Dict(kv::()) = Dict() +Dict(kv::Tuple{}) = Dict() copy(d::Dict) = Dict(d) const AnyDict = Dict{Any,Any} # TODO: this can probably be simplified using `eltype` as a THT (Tim Holy trait) -Dict{K,V}(kv::((K,V)...,)) = Dict{K,V}(kv) -Dict{K }(kv::((K,Any)...,)) = Dict{K,Any}(kv) -Dict{V }(kv::((Any,V)...,)) = Dict{Any,V}(kv) -Dict{K,V}(kv::(Pair{K,V}...,)) = Dict{K,V}(kv) -Dict{K} (kv::(Pair{K}...,)) = Dict{K,Any}(kv) -Dict{V} (kv::(Pair{TypeVar(:K),V}...,)) = Dict{Any,V}(kv) -Dict (kv::(Pair...,)) = Dict{Any,Any}(kv) - -Dict{K,V}(kv::AbstractArray{(K,V)}) = Dict{K,V}(kv) -Dict{K,V}(kv::AbstractArray{Pair{K,V}}) = Dict{K,V}(kv) -Dict{K,V}(kv::Associative{K,V}) = Dict{K,V}(kv) +Dict{K,V}(kv::Tuple{Tuple{K,V},...}) = Dict{K,V}(kv) +Dict{K }(kv::Tuple{Tuple{K,Any},...}) = Dict{K,Any}(kv) +Dict{V }(kv::Tuple{Tuple{Any,V},...}) = Dict{Any,V}(kv) +Dict{K,V}(kv::Tuple{Pair{K,V},...}) = Dict{K,V}(kv) +Dict{K} (kv::Tuple{Pair{K},...}) = Dict{K,Any}(kv) +Dict{V} (kv::Tuple{Pair{TypeVar(:K),V},...}) = Dict{Any,V}(kv) +Dict (kv::Tuple{Pair,...}) = Dict{Any,Any}(kv) + +Dict{K,V}(kv::AbstractArray{Tuple{K,V}}) = Dict{K,V}(kv) +Dict{K,V}(kv::AbstractArray{Pair{K,V}}) = Dict{K,V}(kv) +Dict{K,V}(kv::Associative{K,V}) = Dict{K,V}(kv) Dict{K,V}(ps::Pair{K,V}...) = Dict{K,V}(ps) Dict{K} (ps::Pair{K}...,) = Dict{K,Any}(ps) @@ -380,7 +383,7 @@ Dict{V} (ps::Pair{TypeVar(:K),V}...,) = Dict{Any,V}(ps) Dict (ps::Pair...) = Dict{Any,Any}(ps) Dict(kv) = dict_with_eltype(kv, eltype(kv)) -dict_with_eltype{K,V}(kv, ::Type{(K,V)}) = Dict{K,V}(kv) +dict_with_eltype{K,V}(kv, ::Type{Tuple{K,V}}) = Dict{K,V}(kv) dict_with_eltype{K,V}(kv, ::Type{Pair{K,V}}) = Dict{K,V}(kv) dict_with_eltype(kv, t) = Dict{Any,Any}(kv) @@ -632,7 +635,7 @@ end # therefore not be exported as-is: it's for internal use only. macro get!(h, key0, default) quote - K, V = eltype($(esc(h))) + K, V = keytype($(esc(h))), valtype($(esc(h))) key = convert(K, $(esc(key0))) if !isequal(key, $(esc(key0))) throw(ArgumentError(string($(esc(key0)), " is not a valid key for type ", K))) diff --git a/base/docs.jl b/base/docs.jl index b4dbeb4fe602e..1355b394cdc84 100644 --- a/base/docs.jl +++ b/base/docs.jl @@ -38,7 +38,7 @@ function newmethod(defs) keylen = -1 key = nothing for def in defs - length(def.sig) > keylen && (keylen = length(def.sig); key = def) + length(def.sig.parameters) > keylen && (keylen = length(def.sig.parameters); key = def) end return key end diff --git a/base/env.jl b/base/env.jl index 4d25f5563e0ad..624d2188b833d 100644 --- a/base/env.jl +++ b/base/env.jl @@ -131,14 +131,14 @@ end @windows_only begin start(hash::EnvHash) = (pos = ccall(:GetEnvironmentStringsW,stdcall,Ptr{UInt16},()); (pos,pos)) -function done(hash::EnvHash, block::(Ptr{UInt16},Ptr{UInt16})) +function done(hash::EnvHash, block::Tuple{Ptr{UInt16},Ptr{UInt16}}) if unsafe_load(block[1])==0 ccall(:FreeEnvironmentStringsW,stdcall,Int32,(Ptr{UInt16},),block[2]) return true end false end -function next(hash::EnvHash, block::(Ptr{UInt16},Ptr{UInt16})) +function next(hash::EnvHash, block::Tuple{Ptr{UInt16},Ptr{UInt16}}) pos = block[1] blk = block[2] len = ccall(:wcslen, UInt, (Ptr{UInt16},), pos)+1 diff --git a/base/inference.jl b/base/inference.jl index f645054b88a75..28ba7ff10550b 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -10,7 +10,7 @@ end const NF = NotFound() type StaticVarInfo - sp::Tuple # static parameters tuple + sp::SimpleVector # static parameters cenv::ObjectIdDict # types of closed vars vars::Array{Any,1} # names of args and locals gensym_types::Array{Any,1} # types of the GenSym's in this function @@ -30,7 +30,7 @@ end type CallStack ast mod::Module - types::Tuple + types::Type recurred::Bool cycleid::Int result @@ -101,10 +101,7 @@ cmp_tfunc = (x,y)->Bool isType(t::ANY) = isa(t,DataType) && is((t::DataType).name,Type.name) -isvarargtype(t::ANY) = isa(t,DataType)&&is((t::DataType).name,Vararg.name) - const t_func = ObjectIdDict() -#t_func[tuple] = (0, Inf, (args...)->limit_tuple_depth(args)) t_func[throw] = (1, 1, x->Bottom) t_func[box] = (2, 2, (t,v)->(isType(t) ? t.parameters[1] : Any)) t_func[eq_int] = (2, 2, cmp_tfunc) @@ -136,8 +133,7 @@ t_func[eval(Core.Intrinsics,:ccall)] = return t end) t_func[eval(Core.Intrinsics,:llvmcall)] = - (3, Inf, (fptr, rt, at, a...)->(isType(rt) ? rt.parameters[1] : - isa(rt,Tuple) ? map(x->x.parameters[1],rt) : Any)) + (3, Inf, (fptr, rt, at, a...)->(isType(rt) ? rt.parameters[1] : Any)) t_func[eval(Core.Intrinsics,:cglobal)] = (1, 2, (fptr, t...)->(isempty(t) ? Ptr{Void} : isType(t[1]) ? Ptr{t[1].parameters[1]} : Ptr)) @@ -158,24 +154,11 @@ t_func[Union] = (0, Inf, t_func[_expr] = (1, Inf, (args...)->Expr) t_func[method_exists] = (2, 2, cmp_tfunc) t_func[applicable] = (1, Inf, (f, args...)->Bool) -t_func[tuplelen] = (1, 1, x->Int) t_func[arraylen] = (1, 1, x->Int) #t_func[arrayref] = (2,Inf,(a,i...)->(isa(a,DataType) && a<:Array ? # a.parameters[1] : Any)) #t_func[arrayset] = (3, Inf, (a,v,i...)->a) -#arraysize_tfunc(a, d) = Int -arraysize_tfunc = function (a, d...) - if !is(d,()) - return Int - end - if isa(a,DataType) && a<:Array - N = a.parameters[2] - return isa(N,Int) ? NTuple{N,Int} : (Int...) - else - return (Int...) - end -end -t_func[arraysize] = (1, 2, arraysize_tfunc) +t_func[arraysize] = (2, 2, (a,d)->Int) t_func[pointerref] = (2,2,(a,i)->(isa(a,DataType) && a<:Ptr ? a.parameters[1] : Any)) t_func[pointerset] = (3, 3, (a,v,i)->a) @@ -187,8 +170,6 @@ const typeof_tfunc = function (t) else Type{typeof(t)} end - elseif isvarargtype(t) - Vararg{typeof_tfunc(t.parameters[1])} elseif isa(t,DataType) if isleaftype(t) Type{t} @@ -197,8 +178,6 @@ const typeof_tfunc = function (t) end elseif isa(t,UnionType) Union(map(typeof_tfunc, t.types)...) - elseif isa(t,Tuple) - map(typeof_tfunc, t) elseif isa(t,TypeVar) Type{t} else @@ -206,106 +185,26 @@ const typeof_tfunc = function (t) end end t_func[typeof] = (1, 1, typeof_tfunc) -# involving constants: typeassert, tupleref, getfield, fieldtype, apply_type +# involving constants: typeassert, getfield, fieldtype, apply_type # therefore they get their arguments unevaluated t_func[typeassert] = - (2, 2, (A, v, t)->(isType(t) ? typeintersect(v,t.parameters[1]) : - isa(t,Tuple) && all(isType,t) ? - typeintersect(v,map(t->t.parameters[1],t)) : - Any)) - -const tupleref_tfunc = function (A, t, i) - wrapType = false - if isType(t) - t = t.parameters[1] - wrapType = true - end - if isa(t,DataType) && is(t.name,NTuple.name) - T = t.parameters[2] - return wrapType ? Type{T} : T - end - if !isa(t,Tuple) - return Any - end - if is(t,()) - return Bottom - end - n = length(t) - last = tupleref(t,n) - vararg = isvarargtype(last) - if A !== () && isa(A[2],Integer) - # index is a constant - i = A[2] - if i > n - if vararg - T = last.parameters[1] - else - return Bottom - end - elseif i == n && vararg - T = last.parameters[1] - elseif i <= 0 - return Bottom - else - T = tupleref(t,i) - end - else - # index unknown, could be anything from the tuple - if vararg - types = tuple(t[1:(n-1)]..., last.parameters[1]) - else - types = t - end - if !isa(types, Type) - return Any - end - T = reduce(tmerge, Bottom, types) - if wrapType - return isleaftype(T) || isa(T,TypeVar) ? Type{T} : Type{TypeVar(:_,T)} - else - return T - end - end - return wrapType ? (isa(T,Type) ? Type{T} : typeof(T)) : T -end -t_func[tupleref] = (2, 2, tupleref_tfunc) + (2, 2, (A, v, t)->(isType(t) ? typeintersect(v,t.parameters[1]) : Any)) function limit_type_depth(t::ANY, d::Int, cov::Bool, vars) if isa(t,TypeVar) || isa(t,TypeConstructor) return t end inexact = !cov && d > MAX_TYPE_DEPTH - if isa(t,Tuple) - t === () && return t - if d > MAX_TYPE_DEPTH - if isvatuple(t) - R = Tuple - else - R = NTuple{length(t),Any} - end - else - l0 = length(vars) - R = map(x->limit_type_depth(x, d+1, true, vars), t) - if !cov && (length(vars) > l0 || d == MAX_TYPE_DEPTH) - inexact = true - end - end - elseif isa(t,UnionType) + if isa(t,UnionType) t === Bottom && return t if d > MAX_TYPE_DEPTH R = Any else - R = limit_type_depth(t.types, d, cov, vars) - if isa(R,TypeVar) - R = Union(R.ub...) - inexact = true - else - R = Union(R...) - end + R = Union(map(x->limit_type_depth(x, d+1, cov, vars), t.types)...) end elseif isa(t,DataType) P = t.parameters - P === () && return t + length(P) == 0 && return t if d > MAX_TYPE_DEPTH R = t.name.primary else @@ -327,7 +226,6 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars) return R end - const getfield_tfunc = function (A, s0, name) s = s0 if isType(s) @@ -339,9 +237,18 @@ const getfield_tfunc = function (A, s0, name) if isa(s,UnionType) return reduce(tmerge, Bottom, map(t->getfield_tfunc(A, t, name), s.types)) end - if !isa(s,DataType) || s.abstract + if !isa(s,DataType) return Any end + if is(s.name,NTuple.name) + return s.parameters[2] + end + if s.abstract + return Any + end + if s <: Tuple && name === Symbol + return Bottom + end if isa(A[2],QuoteNode) && isa(A[2].value,Symbol) fld = A[2].value A1 = A[1] @@ -354,21 +261,23 @@ const getfield_tfunc = function (A, s0, name) if isType(s0) sp = s0.parameters[1] if isa(sp,DataType) && !any(x->isa(x,TypeVar), sp.parameters) - if fld === :parameters - return Type{sp.parameters} - end - if fld === :types - return Type{sp.types} - end + # TODO + #if fld === :parameters + # return Type{sp.parameters} + #end + #if fld === :types + # return Type{sp.types} + #end if fld === :super return Type{sp.super} end end end + snames = s.name.names for i=1:nfields(s) - if is(s.names[i],fld) + if is(snames[i],fld) R = s.types[i] - if s.parameters === () + if length(s.parameters) == 0 return R else return limit_type_depth(R, 0, true, @@ -382,12 +291,16 @@ const getfield_tfunc = function (A, s0, name) return Bottom end i::Int = A[2] - if i < 1 || i > nfields(s) + nf = nfields(s) + if isvatuple(s) && i >= nf + return s.types[nf].parameters[1] + end + if i < 1 || i > nf return Bottom end return s.types[i] else - return reduce(tmerge, Bottom, s.types)#Union(s.types...) + return reduce(tmerge, Bottom, map(unwrapva,s.types))#Union(s.types...) end end t_func[getfield] = (2, 2, getfield_tfunc) @@ -408,21 +321,17 @@ t_func[fieldtype] = (2, 2, fieldtype_tfunc) t_func[Box] = (1, 1, (a,)->Box) function valid_tparam(x::ANY) - if isa(x,Int) || isa(x,Symbol) || isa(x,Bool) - return true - elseif isa(x,Tuple) + if isa(x,Tuple) for t in x - if !valid_tparam(t) - return false - end + !valid_tparam(t) && return false end return true end - return false + return isa(x,Int) || isa(x,Symbol) || isa(x,Bool) || (!isa(x,Type) && isbits(x)) end function extract_simple_tparam(Ai) - if (isa(Ai,Int) || isa(Ai,Bool)) + if isa(Ai,Int) || isa(Ai,Bool) return Ai elseif isa(Ai,QuoteNode) && valid_tparam(Ai.value) return Ai.value @@ -444,27 +353,26 @@ end # TODO: handle e.g. apply_type(T, R::Union(Type{Int32},Type{Float64})) const apply_type_tfunc = function (A, args...) if !isType(args[1]) - return Any + return Type end headtype = args[1].parameters[1] - if isa(headtype,UnionType) || isa(headtype,Tuple) || isa(headtype,TypeVar) + if isa(headtype,UnionType) || isa(headtype,TypeVar) return args[1] end - tparams = () + istuple = (headtype === Tuple) uncertain = false lA = length(A) + tparams = svec() for i=2:max(lA,length(args)) ai = args[i] if isType(ai) uncertain |= (!isleaftype(ai)) - tparams = tuple(tparams..., ai.parameters[1]) - elseif isa(ai,Tuple) && all(isType,ai) - tparams = tuple(tparams..., map(t->t.parameters[1], ai)) + tparams = svec(tparams..., ai.parameters[1]) else if i<=lA val = extract_simple_tparam(A[i]) if val !== Bottom - tparams = tuple(tparams..., val) + tparams = svec(tparams..., val) continue elseif isa(inference_stack,CallStack) && isa(A[i],Symbol) sp = inference_stack.sv.sp @@ -475,7 +383,7 @@ const apply_type_tfunc = function (A, args...) # static parameter val = sp[j+1] if valid_tparam(val) - tparams = tuple(tparams..., val) + tparams = svec(tparams..., val) found = true break end @@ -486,12 +394,16 @@ const apply_type_tfunc = function (A, args...) end end end - if i-1 > length(headtype.parameters) + if !istuple && i-1 > length(headtype.parameters) # too many parameters for type return Bottom end uncertain = true - tparams = tuple(tparams..., headtype.parameters[i-1]) + if istuple + tparams = svec(tparams..., Any) + else + tparams = svec(tparams..., headtype.parameters[i-1]) + end end end local appl @@ -501,7 +413,7 @@ const apply_type_tfunc = function (A, args...) catch # type instantiation might fail if one of the type parameters # doesn't match, which could happen if a type estimate is too coarse - appl = args[1] + appl = headtype uncertain = true end if type_too_complex(appl,0) @@ -511,22 +423,22 @@ const apply_type_tfunc = function (A, args...) end t_func[apply_type] = (1, Inf, apply_type_tfunc) -function tuple_tfunc(argtypes::ANY, limit) - t = argtypes - if limit - t = limit_tuple_depth(t) +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), + argtype.parameters) + return Tuple{p...} end - # tuple(Type{T...}) should give Type{(T...)} - if t!==() && all(isType, t) && isvarargtype(t[length(t)].parameters[1]) - return Type{map(t->t.parameters[1], t)} - end - return t + argtype end -function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY) - isva = isvatuple(argtypes) +function builtin_tfunction(f::ANY, args::ANY, argtype::ANY) + isva = isvatuple(argtype) + argtypes = argtype.parameters if is(f,tuple) - return tuple_tfunc(argtypes, true) + return tuple_tfunc(limit_tuple_depth(argtype)) + elseif is(f,svec) + return SimpleVector elseif is(f,arrayset) if length(argtypes) < 3 && !isva return Bottom @@ -554,34 +466,23 @@ function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY) # unknown/unhandled builtin return Any end - tf = tf::(Real, Real, Function) + tf = tf::Tuple{Real, Real, Function} if isva - # only some t-funcs can handle varargs - if is(f,apply_type) || is(f,typeof) - else - return Any - end + # only some t-funcs can handle varargs (TODO) + #if !is(f, apply_type) + return Any + #end elseif !(tf[1] <= length(argtypes) <= tf[2]) # wrong # of args return Bottom end - if is(f,typeassert) || is(f,tupleref) || is(f,getfield) || - is(f,apply_type) || is(f,fieldtype) + if is(f,typeassert) || is(f,getfield) || is(f,apply_type) || is(f,fieldtype) # TODO: case of apply(), where we do not have the args return tf[3](args, argtypes...) end return tf[3](argtypes...) end -function a2t(a::AbstractVector) - n = length(a) - if n==2 return (a[1],a[2]) end - if n==1 return (a[1],) end - if n==3 return (a[1],a[2],a[3]) end - if n==0 return () end - return tuple(a...) -end - function isconstantfunc(f::ANY, sv::StaticVarInfo) if isa(f,TopNode) m = _basemod() @@ -625,37 +526,32 @@ end const isconstantref = isconstantfunc -isvatuple(t::Tuple) = (n = length(t); n > 0 && isvarargtype(t[n])) - const limit_tuple_depth = t->limit_tuple_depth_(t,0) const limit_tuple_depth_ = function (t,d::Int) if isa(t,UnionType) # also limit within Union types. # may have to recur into other stuff in the future too. - return Union(limit_tuple_depth_(t.types,d)...) + return Union(map(x->limit_tuple_depth_(x,d+1), t.types)...) end - if !isa(t,Tuple) + if !(isa(t,DataType) && t.name === Tuple.name) return t end if d > MAX_TUPLE_DEPTH return Tuple end - map(x->limit_tuple_depth_(x,d+1), t) + p = map(x->limit_tuple_depth_(x,d+1), t.parameters) + Tuple{p...} end limit_tuple_type = t -> limit_tuple_type_n(t, MAX_TUPLETYPE_LEN) -const limit_tuple_type_n = function (t::Tuple, lim::Int) - n = length(t) +const limit_tuple_type_n = function (t, lim::Int) + p = t.parameters + n = length(p) if n > lim - last = t[n] - if isvarargtype(last) - last = last.parameters[1] - end - tail = tuple(t[lim:(n-1)]..., last) - tail = typeintersect(reduce(tmerge, Bottom, tail), Any) - return tuple(t[1:(lim-1)]..., Vararg{tail}) + tail = reduce(tmerge, Bottom, svec(p[lim:(n-1)]..., unwrapva(p[n]))) + return Tuple{p[1:(lim-1)]..., Vararg{tail}} end return t end @@ -681,19 +577,20 @@ let stagedcache=Dict{Any,Any}() end end -function abstract_call_gf(f, fargs, argtypes, e) +function abstract_call_gf(f, fargs, argtype, e) + argtypes = argtype.parameters if length(argtypes)>1 && (argtypes[1] <: Tuple) && argtypes[2]===Int # allow tuple indexing functions to take advantage of constant # index arguments. if f === Main.Base.getindex isa(e,Expr) && (e.head = :call1) - return tupleref_tfunc(fargs, argtypes[1], argtypes[2]) + return getfield_tfunc(fargs, argtypes[1], argtypes[2]) elseif f === Main.Base.next isa(e,Expr) && (e.head = :call1) - return (tupleref_tfunc(fargs, argtypes[1], argtypes[2]), Int) + return Tuple{getfield_tfunc(fargs, argtypes[1], argtypes[2]), Int} elseif f === Main.Base.indexed_next isa(e,Expr) && (e.head = :call1) - return (tupleref_tfunc(fargs, argtypes[1], argtypes[2]), Int) + return Tuple{getfield_tfunc(fargs, argtypes[1], argtypes[2]), Int} end end if (isdefined(Main.Base,:promote_type) && f === Main.Base.promote_type) || @@ -727,8 +624,9 @@ function abstract_call_gf(f, fargs, argtypes, e) # It is important for N to be >= the number of methods in the error() # function, so we can still know that error() is always Bottom. # here I picked 4. - argtypes = limit_tuple_type(argtypes) - applicable = _methods(f, argtypes, 4) + argtype = limit_tuple_type(argtype) + argtypes = argtype.parameters + applicable = _methods(f, argtype, 4) rettype = Bottom if is(applicable,false) # this means too many methods matched @@ -751,16 +649,16 @@ function abstract_call_gf(f, fargs, argtypes, e) e.head = :call end end - for (m::Tuple) in x + for (m::SimpleVector) in x local linfo try - linfo = func_for_method(m[3],argtypes,m[2]) + linfo = func_for_method(m[3],argtype,m[2]) catch rettype = Any break end sig = m[1] - lsig = length(m[3].sig) + lsig = length(m[3].sig.parameters) # limit argument type tuple based on size of definition signature. # for example, given function f(T, Any...), limit to 3 arguments # instead of the default (MAX_TUPLETYPE_LEN) @@ -768,20 +666,20 @@ function abstract_call_gf(f, fargs, argtypes, e) limit = false # look at the stack to detect recursive calls with growing argument lists while sp !== EmptyCallStack() - if linfo.ast === sp.ast && length(argtypes) > length(sp.types) + if linfo.ast === sp.ast && length(argtypes) > length(sp.types.parameters) limit = true; break end sp = sp.prev end - ls = length(sig) + ls = length(sig.parameters) if limit && ls > lsig+1 && !(isdefined(Main.Base,:promote_typeof) && f === Main.Base.promote_typeof) - fst = sig[lsig+1] + fst = sig.parameters[lsig+1] allsame = true # allow specializing on longer arglists if all the trailing # arguments are the same, since there is no exponential # blowup in this case. for i = lsig+2:ls - if sig[i] != fst + if sig.parameters[i] != fst allsame = false break end @@ -802,16 +700,16 @@ function abstract_call_gf(f, fargs, argtypes, e) return rettype end -function invoke_tfunc(f, types, argtypes) - argtypes = typeintersect(types,limit_tuple_type(argtypes)) - if is(argtypes,Bottom) +function invoke_tfunc(f, types, argtype) + argtype = typeintersect(types,limit_tuple_type(argtype)) + if is(argtype,Bottom) return Bottom end applicable = _methods(f, types, -1) if isempty(applicable) return Any end - for (m::Tuple) in applicable + for (m::SimpleVector) in applicable local linfo try linfo = func_for_method(m[3],types,m[2]) @@ -821,7 +719,7 @@ function invoke_tfunc(f, types, argtypes) if typeseq(m[1],types) tvars = m[2][1:2:end] (ti, env) = ccall(:jl_match_method, Any, (Any,Any,Any), - argtypes, m[1], tvars)::(Any,Any) + argtype, m[1], tvars)::SimpleVector (_tree,rt) = typeinf(linfo, ti, env, linfo) return rt end @@ -829,25 +727,41 @@ function invoke_tfunc(f, types, argtypes) return Any end -function to_tuple_of_Types(t::ANY) - if isType(t) - p1 = t.parameters[1] - if isa(p1,Tuple) && !isvatuple(p1) - return map(t->Type{t}, p1) +# `types` is an array of inferred types for expressions in `args`. +# if an expression constructs a container (e.g. `svec(x,y,z)`), +# refine its type to an array of element types. returns an array of +# arrays of types, or `nothing`. +function precise_container_types(args, types, vtypes, sv) + n = length(args) + assert(n == length(types)) + result = cell(n) + for i = 1:n + ai = args[i]; ti = types[i] + if isa(ai,Expr) && (is_known_call(ai, svec, sv) || is_known_call(ai, tuple, sv)) + aa = ai.args + result[i] = Any[ (isa(aa[j],Expr) ? aa[j].typ : abstract_eval(aa[j],vtypes,sv)) for j=2:length(aa) ] + elseif ti<:Tuple && (i==n || !isvatuple(ti)) + result[i] = ti.parameters + else + return nothing end end - return t + return result end # do apply(af, fargs...), where af is a function value -function abstract_apply(af, aargtypes, vtypes, sv, e) - if all(x->isa(x,Tuple), aargtypes) && - !any(isvatuple, aargtypes[1:(length(aargtypes)-1)]) +function abstract_apply(af, fargs, aargtypes::Vector{Any}, vtypes, sv, e) + ctypes = precise_container_types(fargs, aargtypes, vtypes, sv) + if ctypes !== nothing e.head = :call1 # apply with known func with known tuple types # can be collapsed to a call to the applied func - at = length(aargtypes) > 0 ? - limit_tuple_type(tuple(append_any(aargtypes...)...)) : () + at = append_any(ctypes...) + n = length(at) + if n > MAX_TUPLETYPE_LEN + tail = foldl((a,b)->tmerge(a,unwrapva(b)), Bottom, at[MAX_TUPLETYPE_LEN:n]) + at = vcat(at[1:MAX_TUPLETYPE_LEN-1], Any[Vararg{tail}]) + end return abstract_call(af, (), at, vtypes, sv, ()) end if is(af,tuple) && length(aargtypes)==1 @@ -861,7 +775,7 @@ function abstract_apply(af, aargtypes, vtypes, sv, e) if is(aat.name, tn) et = aat.parameters[1] if !isa(et,TypeVar) - return (et...) + return Tuple{et, ...} end end if is(aat, Any) @@ -872,47 +786,44 @@ function abstract_apply(af, aargtypes, vtypes, sv, e) end return Tuple end - if is(af,kwcall) - return Any - end + is(af,kwcall) && return Any # apply known function with unknown args => f(Any...) - return abstract_call(af, (), Tuple, vtypes, sv, ()) + return abstract_call(af, (), Any[Vararg{Any}], vtypes, sv, ()) end -function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e) +function abstract_call(f, fargs, argtypes::Vector{Any}, vtypes, sv::StaticVarInfo, e) if is(f,_apply) && length(fargs)>1 - a2type = argtypes[2] af = isconstantfunc(fargs[2], sv) - if !is(af,false) af = _ieval(af) if isa(af,Function) - aargtypes = map(to_tuple_of_Types, argtypes[3:end]) - return abstract_apply(af, aargtypes, vtypes, sv, e) + return abstract_apply(af, fargs[3:end], argtypes[3:end], vtypes, sv, e) end end # TODO: this slows down inference a lot - if !(a2type===Function) && isleaftype(a2type) + a2type = argtypes[2] + if a2type !== Function && isleaftype(a2type) # would definitely use call() call_func = _ieval(isconstantfunc(fargs[1], sv)) if isa(call_func,Function) - aargtypes = Any[ to_tuple_of_Types(argtypes[i]) for i=2:length(argtypes) ] - aargtypes[1] = (aargtypes[1],) # don't splat "function" - return abstract_apply(call_func, tuple(aargtypes...), vtypes, sv, e) + aargtypes = Any[ argtypes[i] for i=2:length(argtypes) ] + aargtypes[1] = Tuple{aargtypes[1]} # don't splat "function" + fa = fargs[2:end] + fa[1] = Expr(:call, top_tuple, fa[1]) + return abstract_apply(call_func, fa, aargtypes, vtypes, sv, e) end end return Any end if isgeneric(f) - return abstract_call_gf(f, fargs, argtypes, e) + return abstract_call_gf(f, fargs, Tuple{argtypes...}, e) end if is(f,invoke) && length(fargs)>1 af = isconstantfunc(fargs[1], sv) if !is(af,false) && (af=_ieval(af);isgeneric(af)) sig = argtypes[2] - if isa(sig,Tuple) && all(isType, sig) - sig = map(t->t.parameters[1], sig) - return invoke_tfunc(af, sig, argtypes[3:end]) + if isType(sig) && sig.parameters[1] <: Tuple + return invoke_tfunc(af, sig.parameters[1], Tuple{argtypes[3:end]...}) end end end @@ -940,7 +851,7 @@ function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e) # use the fact that kwcall(...) calls ff.env.kwsorter posargt = argtypes[(5+2*kwcount):end] return abstract_call_gf(ff.env.kwsorter, (), - tuple(Array{Any,1}, posargt...), e) + Tuple{Array{Any,1}, posargt...}, e) end end # TODO: call() case @@ -949,27 +860,21 @@ function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e) if !isa(f,Function) && !isa(f,IntrinsicFunction) && _iisdefined(:call) call_func = _ieval(:call) if isa(call_func,Function) - return abstract_call(call_func, e.args, tuple(Any[abstract_eval_constant(f),argtypes...]...), vtypes, sv, e) + return abstract_call(call_func, e.args, + Any[abstract_eval_constant(f),argtypes...], + vtypes, sv, e) else return Any end end - rt = builtin_tfunction(f, fargs, argtypes) + rt = builtin_tfunction(f, fargs, Tuple{argtypes...}) #print("=> ", rt, "\n") return rt end -function abstract_eval_arg(a::ANY, vtypes::ANY, sv::StaticVarInfo) - t = abstract_eval(a, vtypes, sv) - if isa(t,TypeVar) && t.lb == Bottom && isleaftype(t.ub) - t = t.ub - end - return t -end - function abstract_eval_call(e, vtypes, sv::StaticVarInfo) fargs = e.args[2:end] - argtypes = tuple([abstract_eval_arg(a, vtypes, sv) for a in fargs]...) + argtypes = Any[abstract_eval(a, vtypes, sv) for a in fargs] if any(x->is(x,Bottom), argtypes) return Bottom end @@ -978,14 +883,14 @@ function abstract_eval_call(e, vtypes, sv::StaticVarInfo) if is(func,false) if isa(called, LambdaStaticData) # called lambda expression (let) - (_, result) = typeinf(called, argtypes, called.sparams, called) + (_, result) = typeinf(called, Tuple{argtypes...}, called.sparams, called) return result end ft = abstract_eval(called, vtypes, sv) if !(Function <: ft) && _iisdefined(:call) call_func = _ieval(:call) if isa(call_func,Function) - return abstract_call(call_func, e.args, tuple(Any[ft,argtypes...]...), vtypes, sv, e) + return abstract_call(call_func, e.args, Any[ft,argtypes...], vtypes, sv, e) end end return Any @@ -1093,9 +998,6 @@ function abstract_eval_constant(x::ANY) end return Type{x} end - #if isa(x,Tuple) && all(e->isa(e,Type), x) - # return Type{x} - #end return typeof(x) end @@ -1199,14 +1101,12 @@ function type_too_complex(t::ANY, d) p = t.types elseif isa(t,DataType) p = t.parameters - elseif isa(t,Tuple) - p = t elseif isa(t,TypeVar) return type_too_complex(t.lb,d+1) || type_too_complex(t.ub,d+1) else return false end - for x in (p::Tuple) + for x in (p::SimpleVector) if type_too_complex(x, d+1) return true end @@ -1219,8 +1119,8 @@ function tmerge(typea::ANY, typeb::ANY) is(typeb, NF) && return typea typea <: typeb && return typeb typeb <: typea && return typea - if isa(typea, Tuple) && isa(typeb, Tuple) - if length(typea) == length(typeb) && !isvatuple(typea) && !isvatuple(typeb) + if (typea <: Tuple) && (typeb <: Tuple) + if length(typea.parameters) == length(typeb.parameters) && !isvatuple(typea) && !isvatuple(typeb) return typejoin(typea, typeb) end return Tuple @@ -1247,8 +1147,8 @@ end tchanged(n::ANY, o::ANY) = is(o,NF) || (!is(n,NF) && !(n <: o)) schanged(n::ANY, o::ANY) = is(o,NF) || (!is(n,NF) && !issubstate(n, o)) -stupdate(state::(), changes::VarTable, vars) = copy(changes) -stupdate(state::(), changes::StateUpdate, vars) = stupdate(ObjectIdDict(), changes, vars) +stupdate(state::Tuple{}, changes::VarTable, vars) = copy(changes) +stupdate(state::Tuple{}, changes::StateUpdate, vars) = stupdate(ObjectIdDict(), changes, vars) function stupdate(state::ObjectIdDict, changes::Union(StateUpdate,VarTable), vars) for i = 1:length(vars) @@ -1359,7 +1259,7 @@ CYCLE_ID = 1 # def is the original unspecialized version of a method. we aggregate all # saved type inference data there. -function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop, needtree) +function typeinf(linfo::LambdaStaticData,atypes::ANY,sparams::SimpleVector, def, cop, needtree) if linfo.module === Core atypes = Tuple end @@ -1370,7 +1270,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop, redo = false # check cached t-functions tf = def.tfunc - if !is(tf,()) + if !is(tf,nothing) tfarr = tf::Array{Any,1} for i = 1:3:length(tfarr) if typeseq(tfarr[i],atypes) @@ -1406,8 +1306,8 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop, end if !redo - if is(def.tfunc,()) - def.tfunc = [] + if is(def.tfunc,nothing) + def.tfunc = Any[] end tfarr = def.tfunc::Array{Any,1} idx = -1 @@ -1437,15 +1337,15 @@ end typeinf_uncached(linfo, atypes::ANY, sparams::ANY; optimize=true) = typeinf_uncached(linfo, atypes, sparams, linfo, Bottom, true, optimize) +# t[n:end] +tupletype_tail(t::ANY, n) = Tuple{t.parameters[n:end]...} + # compute an inferred (optionally optimized) AST without global effects (i.e. updating the cache) -function typeinf_uncached(linfo::LambdaStaticData, atypes::Tuple, sparams::Tuple, def, curtype, cop, optimize) +function typeinf_uncached(linfo::LambdaStaticData, atypes::ANY, sparams::SimpleVector, def, curtype, cop, optimize) ast0 = def.ast #if dbg # print("typeinf ", linfo.name, " ", object_id(ast0), "\n") #end - #if trace_inf - # print("typeinf ", linfo.name, " ", atypes, " ", linfo.file,":",linfo.line,"\n") - #end # if isdefined(:STDOUT) # write(STDOUT, "typeinf ") # write(STDOUT, string(linfo.name)) @@ -1476,10 +1376,14 @@ function typeinf_uncached(linfo::LambdaStaticData, atypes::Tuple, sparams::Tuple f = f.prev end + #if trace_inf + # print("typeinf ", linfo.name, " ", atypes, " ", linfo.file,":",linfo.line,"\n") + #end + #if dbg print("typeinf ", linfo.name, " ", atypes, "\n") end if cop - sparams = tuple(sparams..., linfo.sparams...) + sparams = svec(sparams..., linfo.sparams...) ast = ccall(:jl_prepare_ast, Any, (Any,Any), linfo, sparams)::Expr else ast = linfo.ast @@ -1520,23 +1424,23 @@ function typeinf_uncached(linfo::LambdaStaticData, atypes::Tuple, sparams::Tuple if is_rest_arg(lastarg) if atypes === Tuple if la > 1 - atypes = tuple(NTuple{la-1,Any}..., Tuple[1]) + atypes = Tuple{Any[Any for i=1:la-1]..., Tuple.parameters[1]} end s[1][args[la]] = VarState(Tuple,false) else - s[1][args[la]] = VarState(limit_tuple_depth(atypes[la:end]),false) + s[1][args[la]] = VarState(limit_tuple_depth(tupletype_tail(atypes,la)),false) end la -= 1 else if atypes === Tuple - atypes = tuple(NTuple{la,Any}..., Tuple[1]) + atypes = Tuple{Any[Any for i=1:la]..., Tuple.parameters[1]} end end end - laty = length(atypes) + laty = length(atypes.parameters) if laty > 0 - lastatype = atypes[laty] + lastatype = atypes.parameters[laty] if isvarargtype(lastatype) lastatype = lastatype.parameters[1] laty -= 1 @@ -1545,7 +1449,7 @@ function typeinf_uncached(linfo::LambdaStaticData, atypes::Tuple, sparams::Tuple laty = la end for i=1:laty - s[1][args[i]] = VarState(atypes[i],false) + s[1][args[i]] = VarState(atypes.parameters[i],false) end for i=laty+1:la s[1][args[i]] = VarState(lastatype,false) @@ -1680,7 +1584,7 @@ function typeinf_uncached(linfo::LambdaStaticData, atypes::Tuple, sparams::Tuple end elseif is(hd,:return) pc´ = n+1 - rt = abstract_eval_arg(stmt.args[1], s[pc], sv) + rt = abstract_eval(stmt.args[1], s[pc], sv) if frame.recurred rec = true if !(isa(frame.prev,CallStack) && frame.prev.cycleid == frame.cycleid) @@ -1764,7 +1668,7 @@ function typeinf_uncached(linfo::LambdaStaticData, atypes::Tuple, sparams::Tuple sv.vars = append_any(f_argnames(fulltree), fulltree.args[2][1]) end tuple_elim_pass(fulltree, sv) - tupleref_elim_pass(fulltree.args[3], sv) + getfield_elim_pass(fulltree.args[3], sv) else call1_to_call(fulltree) end @@ -1876,7 +1780,7 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::StaticVarInfo, decls, clo, undef if (head === :call || head === :call1) && isa(e.args[1],LambdaStaticData) called = e.args[1] fargs = e.args[2:end] - argtypes = tuple([abstract_eval_arg(a, vtypes, sv) for a in fargs]...) + argtypes = Tuple{[abstract_eval(a, vtypes, sv) for a in fargs]...} # recur inside inner functions once we have all types tr,ty = typeinf(called, argtypes, called.sparams, called, false, true) called.ast = tr @@ -1885,8 +1789,7 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::StaticVarInfo, decls, clo, undef end # annotate types of all symbols in AST -function type_annotate(ast::Expr, states::Array{Any,1}, sv::ANY, rettype::ANY, - args) +function type_annotate(ast::Expr, states::Array{Any,1}, sv::ANY, rettype::ANY, args) decls = ObjectIdDict() undefs = ObjectIdDict() # initialize decls with argument types @@ -2132,7 +2035,7 @@ function without_linenums(a::Array{Any,1}) end # known affect-free calls (also effect-free) -const _pure_builtins = Any[tuple, tupleref, tuplelen, fieldtype, apply_type, is, isa, typeof, typeassert] +const _pure_builtins = Any[tuple, svec, fieldtype, apply_type, is, isa, typeof, typeassert] # known effect-free calls (might not be affect-free) const _pure_builtins_volatile = Any[getfield, arrayref] @@ -2205,18 +2108,14 @@ function effect_free(e::ANY, sv, allow_volatile::Bool) end if isa(a,SymbolNode) typ = (a::SymbolNode).typ - if !isa(typ,Tuple) - if !isa(typ,DataType) || typ.mutable - return false - end + if !isa(typ,DataType) || typ.mutable + return false end end if isa(a,GenSym) typ = exprtype(a,sv) - if !isa(typ,Tuple) - if !isa(typ,DataType) || typ.mutable - return false - end + if !isa(typ,DataType) || typ.mutable + return false end end if !effect_free(a,sv,allow_volatile) @@ -2259,10 +2158,11 @@ end # functions with closure environments or varargs are also excluded. # static parameters are ok if all the static parameter values are leaf types, # meaning they are fully known. -function inlineable(f::ANY, e::Expr, atypes::Tuple, sv::StaticVarInfo, enclosing_ast::Expr) +function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_ast::Expr) if !(isa(f,Function) || isa(f,IntrinsicFunction)) return NF end + atypes = atype.parameters argexprs = e.args[2:end] if is(f, typeassert) && length(atypes)==2 @@ -2296,22 +2196,19 @@ function inlineable(f::ANY, e::Expr, atypes::Tuple, sv::StaticVarInfo, enclosing end end end - if is(f,tuple) && isa(e.typ,Tuple) && all(isType,e.typ) && isleaftype(e.typ) && effect_free(e,sv,true) - return (map(t->t.parameters[1], e.typ), ()) - end if isa(f,IntrinsicFunction) return NF end - meth = _methods(f, atypes, 1) + meth = _methods(f, atype, 1) if meth === false || length(meth) != 1 return NF end - meth = meth[1]::Tuple + meth = meth[1]::SimpleVector local linfo try - linfo = func_for_method(meth[3],atypes,meth[2]) + linfo = func_for_method(meth[3],atype,meth[2]) catch return NF end @@ -2342,12 +2239,12 @@ function inlineable(f::ANY, e::Expr, atypes::Tuple, sv::StaticVarInfo, enclosing # end # end - if !isa(linfo,LambdaStaticData) || meth[3].func.env !== () + if !isa(linfo,LambdaStaticData) || length(meth[3].func.env) > 0 return NF end - sp = meth[2]::Tuple - sp = tuple(sp..., linfo.sparams...) + sp = meth[2]::SimpleVector + sp = svec(sp..., linfo.sparams...) spvals = Any[ sp[i] for i in 2:2:length(sp) ] for i=1:length(spvals) si = spvals[i] @@ -2359,9 +2256,10 @@ function inlineable(f::ANY, e::Expr, atypes::Tuple, sv::StaticVarInfo, enclosing end end - methargs = meth[1]::Tuple + metharg = meth[1]::Type + methargs = metharg.parameters nm = length(methargs) - if !(atypes <: methargs) + if !(atype <: metharg) incompletematch = true if !inline_incompletematch_allowed return NF @@ -2370,7 +2268,7 @@ function inlineable(f::ANY, e::Expr, atypes::Tuple, sv::StaticVarInfo, enclosing incompletematch = false end - (ast, ty) = typeinf(linfo, methargs, meth[2]::Tuple, linfo, true, true) + (ast, ty) = typeinf(linfo, metharg, meth[2], linfo, true, true) if is(ast,()) return NF end @@ -2407,7 +2305,7 @@ function inlineable(f::ANY, e::Expr, atypes::Tuple, sv::StaticVarInfo, enclosing newnames = unique_names(ast,numarg) sp = () spvals = [] - meth = (methargs, sp) + meth = svec(metharg, sp) locals = [] newcall = Expr(:call, e.args[1]) newcall.typ = ty @@ -2439,7 +2337,7 @@ function inlineable(f::ANY, e::Expr, atypes::Tuple, sv::StaticVarInfo, enclosing vaname = args[na] len_argexprs = length(argexprs) valen = len_argexprs-na+1 - if valen>0 && !occurs_outside_tupleref(body, vaname, sv, valen) + if valen>0 && !occurs_outside_getfield(body, vaname, sv, valen) # argument tuple is not used as a whole, so convert function body # to one accepting the exact number of arguments we have. newnames = unique_names(ast,valen) @@ -2447,7 +2345,7 @@ function inlineable(f::ANY, e::Expr, atypes::Tuple, sv::StaticVarInfo, enclosing body = astcopy(body) needcopy = false end - replace_tupleref!(ast, body, vaname, newnames, sv, 1) + replace_getfield!(ast, body, vaname, newnames, sv, 1) args = vcat(args[1:na-1], newnames) na = length(args) @@ -2546,16 +2444,16 @@ function inlineable(f::ANY, e::Expr, atypes::Tuple, sv::StaticVarInfo, enclosing if incompletematch if isva if nm == 0 - methitype = () + methitype = Tuple{} elseif i > nm methitype = methargs[end] if isvarargtype(methitype) - methitype = (methitype,) + methitype = Tuple{methitype} else - methitype = () + methitype = Tuple{} end else - methitype = tuple(methargs[i:end]...) + methitype = tupletype_tail(metharg,i) end isva = false else @@ -2792,18 +2690,18 @@ function gensym_increment(body::Expr, incr) end const top_setfield = TopNode(:setfield) -const top_tupleref = TopNode(:tupleref) +const top_getfield = TopNode(:getfield) const top_tuple = TopNode(:tuple) -function mk_tupleref(texpr, i, T) - e = :(($top_tupleref)($texpr, $i)) +function mk_getfield(texpr, i, T) + e = :(($top_getfield)($texpr, $i)) e.typ = T e end function mk_tuplecall(args, sv::StaticVarInfo) e = Expr(:call1, top_tuple, args...) - e.typ = tuple_tfunc(tuple(Any[exprtype(x,sv) for x in args]...), false) + e.typ = tuple_tfunc(Tuple{Any[exprtype(x,sv) for x in args]...}) e end @@ -2926,11 +2824,11 @@ function inlining_pass(e::Expr, sv, ast) end for ninline = 1:100 - atypes = tuple(Any[exprtype(x,sv) for x in e.args[2:end]]...) - if length(atypes) > MAX_TUPLETYPE_LEN - atypes = limit_tuple_type(atypes) + atype = Tuple{Any[exprtype(x,sv) for x in e.args[2:end]]...} + if length(atype.parameters) > MAX_TUPLETYPE_LEN + atype = limit_tuple_type(atype) end - res = inlineable(f, e, atypes, sv, ast) + res = inlineable(f, e, atype, sv, ast) if isa(res,Tuple) if isa(res[2],Array) append!(stmts,res[2]) @@ -2954,15 +2852,16 @@ function inlining_pass(e::Expr, sv, ast) newargs = cell(na-3) for i = 4:na aarg = e.args[i] - t = to_tuple_of_Types(exprtype(aarg,sv)) - if isa(aarg,Expr) && is_known_call(aarg, tuple, sv) + t = exprtype(aarg,sv) + if isa(aarg,Expr) && (is_known_call(aarg, tuple, sv) || is_known_call(aarg, svec, sv)) # apply(f,tuple(x,y,...)) => f(x,y,...) newargs[i-3] = aarg.args[2:end] elseif isa(aarg, Tuple) newargs[i-3] = Any[ QuoteNode(x) for x in aarg ] - elseif isa(t,Tuple) && !isvatuple(t) && effect_free(aarg,sv,true) + elseif (t<:Tuple) && !isvatuple(t) && effect_free(aarg,sv,true) # apply(f,t::(x,y)) => f(t[1],t[2]) - newargs[i-3] = Any[ mk_tupleref(aarg,j,t[j]) for j=1:length(t) ] + tp = t.parameters + newargs[i-3] = Any[ mk_getfield(aarg,j,tp[j]) for j=1:length(tp) ] else # not all args expandable return (e,stmts) @@ -3185,13 +3084,13 @@ symequal(x::Symbol , y::SymbolNode) = is(x,y.name) symequal(x::GenSym , y::GenSym) = is(x.id,y.id) symequal(x::ANY , y::ANY) = is(x,y) -function occurs_outside_tupleref(e::ANY, sym::ANY, sv::StaticVarInfo, tuplen::Int) +function occurs_outside_getfield(e::ANY, sym::ANY, sv::StaticVarInfo, tuplen::Int) if is(e, sym) || (isa(e, SymbolNode) && is(e.name, sym)) return true end if isa(e,Expr) e = e::Expr - if is_known_call(e, tupleref, sv) && symequal(e.args[2],sym) + if is_known_call(e, getfield, sv) && symequal(e.args[2],sym) targ = e.args[2] if !(exprtype(targ,sv) <: Tuple) return true @@ -3203,10 +3102,10 @@ function occurs_outside_tupleref(e::ANY, sym::ANY, sv::StaticVarInfo, tuplen::In return false end if is(e.head,:(=)) - return occurs_outside_tupleref(e.args[2], sym, sv, tuplen) + return occurs_outside_getfield(e.args[2], sym, sv, tuplen) else for a in e.args - if occurs_outside_tupleref(a, sym, sv, tuplen) + if occurs_outside_getfield(a, sym, sv, tuplen) return true end end @@ -3215,13 +3114,13 @@ function occurs_outside_tupleref(e::ANY, sym::ANY, sv::StaticVarInfo, tuplen::In return false end -# replace tupleref(tuple(exprs...), i) with exprs[i] -function tupleref_elim_pass(e::Expr, sv) +# replace getfield(tuple(exprs...), i) with exprs[i] +function getfield_elim_pass(e::Expr, sv) for i = 1:length(e.args) ei = e.args[i] if isa(ei,Expr) - tupleref_elim_pass(ei, sv) - if is_known_call(ei, tupleref, sv) && length(ei.args)==3 && + getfield_elim_pass(ei, sv) + if is_known_call(ei, getfield, sv) && length(ei.args)==3 && isa(ei.args[3],Int) e1 = ei.args[2] j = ei.args[3] @@ -3271,7 +3170,7 @@ function tuple_elim_pass(ast::Expr, sv::StaticVarInfo) if isa(rhs,Expr) && is_known_call(rhs, tuple, sv) tup = rhs.args nv = length(tup)-1 - if occurs_outside_tupleref(bexpr, var, sv, nv) || !is_local(sv, var) + if occurs_outside_getfield(bexpr, var, sv, nv) || !is_local(sv, var) i += 1 continue end @@ -3294,20 +3193,20 @@ function tuple_elim_pass(ast::Expr, sv::StaticVarInfo) end end i += n_ins - replace_tupleref!(ast, bexpr, var, vals, sv, i) + replace_getfield!(ast, bexpr, var, vals, sv, i) else i += 1 end end end -function replace_tupleref!(ast, e::ANY, tupname, vals, sv, i0) +function replace_getfield!(ast, e::ANY, tupname, vals, sv, i0) if !isa(e,Expr) return end for i = i0:length(e.args) a = e.args[i] - if isa(a,Expr) && is_known_call(a, tupleref, sv) && + if isa(a,Expr) && is_known_call(a, getfield, sv) && symequal(a.args[2],tupname) val = vals[a.args[3]] # original expression might have better type info than @@ -3332,13 +3231,13 @@ function replace_tupleref!(ast, e::ANY, tupname, vals, sv, i0) end e.args[i] = val else - replace_tupleref!(ast, a, tupname, vals, sv, 1) + replace_getfield!(ast, a, tupname, vals, sv, 1) end end end code_typed(f, types::ANY; optimize=true) = - code_typed(call, tuple(isa(f,Type)?Type{f}:typeof(f), types...), optimize=optimize) + code_typed(call, Tuple{isa(f,Type)?Type{f}:typeof(f), types.parameters...}, optimize=optimize) function code_typed(f::Function, types::ANY; optimize=true) asts = [] for x in _methods(f,types,-1) @@ -3357,7 +3256,7 @@ function code_typed(f::Function, types::ANY; optimize=true) asts end -return_types(f, types::ANY) = return_types(call, tuple(isa(f,Type)?Type{f}:typeof(f), types...)) +return_types(f, types::ANY) = return_types(call, Tuple{isa(f,Type)?Type{f}:typeof(f), types.parameters...}) function return_types(f::Function, types::ANY) rt = [] for x in _methods(f,types,-1) diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index b2870a39697cc..2fbc3879b2134 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -52,8 +52,8 @@ function edit( m::Method ) end edit(file::AbstractString) = edit(file, 1) -edit(f::Callable) = edit(functionloc(f)...) -edit(f::Callable, t::(Type...)) = edit(functionloc(f,t)...) +edit(f::Callable) = edit(functionloc(f)...) +edit(f::Callable, t::ANY) = edit(functionloc(f,t)...) # terminal pager @@ -63,8 +63,8 @@ function less(file::AbstractString, line::Integer) end less(file::AbstractString) = less(file, 1) -less(f::Callable) = less(functionloc(f)...) -less(f::Callable, t::(Type...)) = less(functionloc(f,t)...) +less(f::Callable) = less(functionloc(f)...) +less(f::Callable, t::ANY) = less(functionloc(f,t)...) # clipboard copy and paste @@ -197,7 +197,7 @@ versioninfo(verbose::Bool) = versioninfo(STDOUT,verbose) # displaying type-ambiguity warnings -function code_warntype(io::IO, f, t::(Type...)) +function code_warntype(io::IO, f, t::ANY) global show_expr_type_emphasize state = show_expr_type_emphasize::Bool ct = code_typed(f, t) @@ -217,9 +217,9 @@ function code_warntype(io::IO, f, t::(Type...)) show_expr_type_emphasize::Bool = false nothing end -code_warntype(f, t::(Type...)) = code_warntype(STDOUT, f, t) +code_warntype(f, t::ANY) = code_warntype(STDOUT, f, t) -typesof(args...) = map(a->(isa(a,Type) ? Type{a} : typeof(a)), args) +typesof(args...) = Tuple{map(a->(isa(a,Type) ? Type{a} : typeof(a)), args)...} function gen_call_with_extracted_types(fcn, ex0) if isa(ex0, Expr) && diff --git a/base/io.jl b/base/io.jl index 144a80ed326f1..028634e5e2327 100644 --- a/base/io.jl +++ b/base/io.jl @@ -120,7 +120,7 @@ read(s::IO, ::Type{Float64}) = box(Float64,unbox(Int64,read(s,Int64))) read{T}(s::IO, t::Type{T}, d1::Int, dims::Int...) = read(s, t, tuple(d1,dims...)) read{T}(s::IO, t::Type{T}, d1::Integer, dims::Integer...) = - read(s, t, convert((Int...),tuple(d1,dims...))) + read(s, t, convert(Tuple{Int,...},tuple(d1,dims...))) read{T}(s::IO, ::Type{T}, dims::Dims) = read!(s, Array(T, dims)) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 2a662a63e144a..bee1ebae6c947 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -11,7 +11,7 @@ convert{T}(::Type{AbstractMatrix{T}}, D::Diagonal) = convert(Diagonal{T}, D) convert{T}(::Type{UpperTriangular}, A::Diagonal{T}) = UpperTriangular(A) convert{T}(::Type{LowerTriangular}, A::Diagonal{T}) = LowerTriangular(A) -function similar{T}(D::Diagonal, ::Type{T}, d::(Int,Int)) +function similar{T}(D::Diagonal, ::Type{T}, d::Tuple{Int,Int}) d[1] == d[2] || throw(ArgumentError("Diagonal matrix must be square")) return Diagonal{T}(Array(T,d[1])) end diff --git a/base/methodshow.jl b/base/methodshow.jl index d340713746a31..e101deea92f84 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -12,22 +12,26 @@ function argtype_decl(n, t) # -> (argname, argtype) if t === Any && !isempty(s) return s, "" end - if t <: Vararg && t !== Union() && t.parameters[1] === Any - return string(s, "..."), "" + if isvarargtype(t) + if t.parameters[1] === Any + return string(s, "..."), "" + else + return s, string(t.parameters[1], "...") + end end return s, string(t) end function arg_decl_parts(m::Method) tv = m.tvars - if !isa(tv,Tuple) - tv = (tv,) + if !isa(tv,SimpleVector) + tv = svec(tv) end li = m.func.code e = uncompressed_ast(li) argnames = e.args[1] s = symbol("?") - decls = [argtype_decl(get(argnames,i,s), m.sig[i]) for i=1:length(m.sig)] + decls = [argtype_decl(get(argnames,i,s), m.sig.parameters[i]) for i=1:length(m.sig.parameters)] return tv, decls, li.file, li.line end @@ -55,8 +59,8 @@ function show_method_table(io::IO, mt::MethodTable, max::Int=-1, header::Bool=tr end d = mt.defs n = rest = 0 - while !is(d,()) - if max==-1 || n$name: