diff --git a/base/array.jl b/base/array.jl index b59f0af1f547d..3a2f938774aa4 100644 --- a/base/array.jl +++ b/base/array.jl @@ -322,7 +322,7 @@ end # sure about the behaviour and use unsafe_getindex; in the general case # we can't and must use getindex, otherwise silent corruption can happen) -stagedfunction getindex_bool_1d(A::Array, I::AbstractArray{Bool}) +@generated function getindex_bool_1d(A::Array, I::AbstractArray{Bool}) idxop = I <: Union(Array{Bool}, BitArray) ? :unsafe_getindex : :getindex quote checkbounds(A, I) @@ -401,7 +401,7 @@ end # sure about the behaviour and use unsafe_getindex; in the general case # we can't and must use getindex, otherwise silent corruption can happen) -stagedfunction assign_bool_scalar_1d!(A::Array, x, I::AbstractArray{Bool}) +@generated function assign_bool_scalar_1d!(A::Array, x, I::AbstractArray{Bool}) idxop = I <: Union(Array{Bool}, BitArray) ? :unsafe_getindex : :getindex quote checkbounds(A, I) @@ -414,7 +414,7 @@ stagedfunction assign_bool_scalar_1d!(A::Array, x, I::AbstractArray{Bool}) end end -stagedfunction assign_bool_vector_1d!(A::Array, X::AbstractArray, I::AbstractArray{Bool}) +@generated function assign_bool_vector_1d!(A::Array, X::AbstractArray, I::AbstractArray{Bool}) idxop = I <: Union(Array{Bool}, BitArray) ? :unsafe_getindex : :getindex quote checkbounds(A, I) diff --git a/base/base.jl b/base/base.jl index f7f5883b0e0da..c7c94077f8dc1 100644 --- a/base/base.jl +++ b/base/base.jl @@ -43,7 +43,17 @@ convert{T}(::Type{Tuple{Vararg{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}) +macro generated(f) + isa(f, Expr) || error("invalid syntax; @generated must be used with a function definition") + if is(f.head, :function) || isdefined(:length) && is(f.head, :(=)) && length(f.args) == 2 && f.args[1].head == :call + f.head = :stagedfunction + return Expr(:escape, f) + else + error("invalid syntax; @generated must be used with a function definition") + end +end + +@generated function tuple_type_head{T<:Tuple}(::Type{T}) T.parameters[1] end @@ -51,7 +61,7 @@ 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}) +@generated function tuple_type_tail{T<:Tuple}(::Type{T}) if isvatuple(T) && length(T.parameters) == 1 return T end diff --git a/base/bitarray.jl b/base/bitarray.jl index 239535fd7cb39..2cb1ccbce06ec 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -380,7 +380,7 @@ end # we can't and must use getindex, otherwise silent corruption can happen) # (multiple signatures for disambiguation) for IT in [AbstractVector{Bool}, AbstractArray{Bool}] - @eval stagedfunction getindex(B::BitArray, I::$IT) + @eval @generated function getindex(B::BitArray, I::$IT) idxop = I <: Union(Array{Bool}, BitArray) ? :unsafe_getindex : :getindex quote checkbounds(B, I) @@ -446,7 +446,7 @@ function setindex!(B::BitArray, x, I::BitArray) return B end -stagedfunction setindex!(B::BitArray, x, I::AbstractArray{Bool}) +@generated function setindex!(B::BitArray, x, I::AbstractArray{Bool}) idxop = I <: Array{Bool} ? :unsafe_getindex : :getindex quote checkbounds(B, I) @@ -493,7 +493,7 @@ function setindex!(B::BitArray, X::AbstractArray, I::BitArray) return B end -stagedfunction setindex!(B::BitArray, X::AbstractArray, I::AbstractArray{Bool}) +@generated function setindex!(B::BitArray, X::AbstractArray, I::AbstractArray{Bool}) idxop = I <: Array{Bool} ? :unsafe_getindex : :getindex quote checkbounds(B, I) diff --git a/base/broadcast.jl b/base/broadcast.jl index 90317d2b76967..fde11662ca037 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -239,7 +239,7 @@ broadcast!_function(f::Function) = (B, As...) -> broadcast!(f, B, As...) broadcast_function(f::Function) = (As...) -> broadcast(f, As...) broadcast_getindex(src::AbstractArray, I::AbstractArray...) = broadcast_getindex!(Array(eltype(src), broadcast_shape(I...)), src, I...) -stagedfunction broadcast_getindex!(dest::AbstractArray, src::AbstractArray, I::AbstractArray...) +@generated function broadcast_getindex!(dest::AbstractArray, src::AbstractArray, I::AbstractArray...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] quote @@ -254,7 +254,7 @@ stagedfunction broadcast_getindex!(dest::AbstractArray, src::AbstractArray, I::A end end -stagedfunction broadcast_setindex!(A::AbstractArray, x, I::AbstractArray...) +@generated function broadcast_setindex!(A::AbstractArray, x, I::AbstractArray...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] quote diff --git a/base/constants.jl b/base/constants.jl index 6e29a837de84d..81bcc7cd161bb 100644 --- a/base/constants.jl +++ b/base/constants.jl @@ -13,7 +13,7 @@ convert(::Type{Float16}, x::MathConst) = Float16(Float32(x)) convert{T<:Real}(::Type{Complex{T}}, x::MathConst) = convert(Complex{T}, convert(T,x)) convert{T<:Integer}(::Type{Rational{T}}, x::MathConst) = convert(Rational{T}, Float64(x)) -stagedfunction call{T<:Union(Float32,Float64),s}(t::Type{T},c::MathConst{s},r::RoundingMode) +@generated function call{T<:Union(Float32,Float64),s}(t::Type{T},c::MathConst{s},r::RoundingMode) f = T(big(c()),r()) :($f) end @@ -43,13 +43,13 @@ end <=(x::FloatingPoint,y::MathConst) = x < y # MathConst vs Rational -stagedfunction <{T}(x::MathConst, y::Rational{T}) +@generated function <{T}(x::MathConst, y::Rational{T}) bx = big(x()) bx < 0 && T <: Unsigned && return true rx = rationalize(T,bx,tol=0) rx < bx ? :($rx < y) : :($rx <= y) end -stagedfunction <{T}(x::Rational{T}, y::MathConst) +@generated function <{T}(x::Rational{T}, y::MathConst) by = big(y()) by < 0 && T <: Unsigned && return false ry = rationalize(T,by,tol=0) diff --git a/base/exports.jl b/base/exports.jl index ea529f5cab1e3..bb92f39f81078 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1385,6 +1385,7 @@ export @parallel, # metaprogramming utilities + @generated, @gensym, @eval, @vectorize_1arg, diff --git a/base/iterator.jl b/base/iterator.jl index 8c3d08078e939..5c577c469db56 100644 --- a/base/iterator.jl +++ b/base/iterator.jl @@ -43,7 +43,7 @@ immutable Zip{I, Z<:AbstractZipIterator} <: AbstractZipIterator end zip(a, b, c...) = Zip(a, zip(b, c...)) length(z::Zip) = min(length(z.a), length(z.z)) -stagedfunction tuple_type_cons{S,T<:Tuple}(::Type{S}, ::Type{T}) +@generated function tuple_type_cons{S,T<:Tuple}(::Type{S}, ::Type{T}) Tuple{S, T.parameters...} end eltype{I,Z}(::Type{Zip{I,Z}}) = tuple_type_cons(eltype(I), eltype(Z)) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 97cf378647367..ce0af0a76199a 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -2,7 +2,7 @@ module IteratorsMD import Base: eltype, length, start, done, next, last, getindex, setindex!, linearindexing, min, max, eachindex -import Base: simd_outer_range, simd_inner_length, simd_index +import Base: simd_outer_range, simd_inner_length, simd_index, @generated import Base: @nref, @ncall, @nif, @nexprs, LinearFast, LinearSlow, to_index export CartesianIndex, CartesianRange @@ -13,11 +13,11 @@ linearindexing{A<:BitArray}(::Type{A}) = LinearFast() # CartesianIndex abstract CartesianIndex{N} -stagedfunction Base.call{N}(::Type{CartesianIndex},index::NTuple{N,Integer}) +@generated function Base.call{N}(::Type{CartesianIndex},index::NTuple{N,Integer}) indextype = gen_cartesian(N) return Expr(:call,indextype,[:(to_index(index[$i])) for i=1:N]...) end -stagedfunction Base.call{N}(::Type{CartesianIndex{N}},index::Integer...) +@generated function Base.call{N}(::Type{CartesianIndex{N}},index::Integer...) length(index) == N && return :(CartesianIndex(index)) length(index) > N && throw(DimensionMismatch("Cannot create CartesianIndex{$N} from $(length(index)) indexes")) args = [i <= length(index) ? :(index[$i]) : 1 for i = 1:N] @@ -53,43 +53,43 @@ length{I<:CartesianIndex}(::Type{I})=length(super(I)) # indexing getindex(index::CartesianIndex, i::Integer) = getfield(index, i)::Int -stagedfunction getindex{N}(A::Array, index::CartesianIndex{N}) +@generated function getindex{N}(A::Array, index::CartesianIndex{N}) :(Base.arrayref(A, $(cartindex_exprs((index,), (:index,))...))) end -stagedfunction getindex{N}(A::Array, i::Integer, index::CartesianIndex{N}) +@generated function getindex{N}(A::Array, i::Integer, index::CartesianIndex{N}) :(Base.arrayref(A, $(cartindex_exprs((i, index), (:i, :index))...))) end -stagedfunction getindex{M,N}(A::Array, index1::CartesianIndex{M}, i::Integer, index2::CartesianIndex{N}) +@generated function getindex{M,N}(A::Array, index1::CartesianIndex{M}, i::Integer, index2::CartesianIndex{N}) :(Base.arrayref(A, $(cartindex_exprs((index1, i, index2), (:index1, :i, :index2))...))) end -stagedfunction setindex!{T,N}(A::Array{T}, v, index::CartesianIndex{N}) +@generated function setindex!{T,N}(A::Array{T}, v, index::CartesianIndex{N}) :(Base.arrayset(A, convert($T,v), $(cartindex_exprs((index,), (:index,))...))) end -stagedfunction setindex!{T,N}(A::Array{T}, v, i::Integer, index::CartesianIndex{N}) +@generated function setindex!{T,N}(A::Array{T}, v, i::Integer, index::CartesianIndex{N}) :(Base.arrayset(A, convert($T,v), $(cartindex_exprs((i, index), (:i, :index))...))) end -stagedfunction setindex!{T,M,N}(A::Array{T}, v, index1::CartesianIndex{M}, i::Integer, index2::CartesianIndex{N}) +@generated function setindex!{T,M,N}(A::Array{T}, v, index1::CartesianIndex{M}, i::Integer, index2::CartesianIndex{N}) :(Base.arrayset(A, convert($T,v), $(cartindex_exprs((index1, i, index2), (:index1, :i, :index2))...))) end -stagedfunction getindex{N}(A::AbstractArray, index::CartesianIndex{N}) +@generated function getindex{N}(A::AbstractArray, index::CartesianIndex{N}) :(getindex(A, $(cartindex_exprs((index,), (:index,))...))) end -stagedfunction getindex{N}(A::AbstractArray, i::Integer, index::CartesianIndex{N}) +@generated function getindex{N}(A::AbstractArray, i::Integer, index::CartesianIndex{N}) :(getindex(A, $(cartindex_exprs((i, index), (:i, :index))...))) end -stagedfunction setindex!{T,N}(A::AbstractArray{T}, v, index::CartesianIndex{N}) +@generated function setindex!{T,N}(A::AbstractArray{T}, v, index::CartesianIndex{N}) :(setindex!(A, v, $(cartindex_exprs((index,), (:index,))...))) end -stagedfunction setindex!{T,N}(A::AbstractArray{T}, v, i::Integer, index::CartesianIndex{N}) +@generated function setindex!{T,N}(A::AbstractArray{T}, v, i::Integer, index::CartesianIndex{N}) :(setindex!(A, v, $(cartindex_exprs((i, index), (:i, :index))...))) end for AT in (AbstractVector, AbstractMatrix, AbstractArray) # nix ambiguity warning @eval begin - stagedfunction getindex{M,N}(A::$AT, index1::CartesianIndex{M}, i::Integer, index2::CartesianIndex{N}) + @generated function getindex{M,N}(A::$AT, index1::CartesianIndex{M}, i::Integer, index2::CartesianIndex{N}) :(getindex(A, $(cartindex_exprs((index1, i, index2), (:index1, :i, :index2))...))) end - stagedfunction setindex!{M,N}(A::$AT, v, index1::CartesianIndex{M}, i::Integer, index2::CartesianIndex{N}) + @generated function setindex!{M,N}(A::$AT, v, index1::CartesianIndex{M}, i::Integer, index2::CartesianIndex{N}) :(setindex!(A, v, $(cartindex_exprs((index1, i, index2), (:index1, :i, :index2))...))) end end @@ -115,7 +115,7 @@ end # arithmetic, min/max for op in (:+, :-, :min, :max) @eval begin - stagedfunction ($op){N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) + @generated function ($op){N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) I = index1 args = [:($($op)(index1[$d],index2[$d])) for d = 1:N] :($I($(args...))) @@ -123,7 +123,7 @@ for op in (:+, :-, :min, :max) end end -stagedfunction *{N}(a::Integer, index::CartesianIndex{N}) +@generated function *{N}(a::Integer, index::CartesianIndex{N}) I = index args = [:(a*index[$d]) for d = 1:N] :($I($(args...))) @@ -136,13 +136,13 @@ immutable CartesianRange{I<:CartesianIndex} stop::I end -stagedfunction CartesianRange{N}(I::CartesianIndex{N}) +@generated function CartesianRange{N}(I::CartesianIndex{N}) startargs = fill(1, N) :(CartesianRange($I($(startargs...)), I)) end CartesianRange{N}(sz::NTuple{N,Int}) = CartesianRange(CartesianIndex(sz)) -stagedfunction eachindex{T,N}(::LinearSlow, A::AbstractArray{T,N}) +@generated function eachindex{T,N}(::LinearSlow, A::AbstractArray{T,N}) startargs = fill(1, N) stopargs = [:(size(A,$i)) for i=1:N] meta = Expr(:meta, :inline) @@ -160,7 +160,7 @@ end eltype{I}(::Type{CartesianRange{I}}) = I eltype{I}(::CartesianRange{I}) = I -stagedfunction start{I<:CartesianIndex}(iter::CartesianRange{I}) +@generated function start{I<:CartesianIndex}(iter::CartesianRange{I}) N = length(I) cmp = [:(iter.start[$d] > iter.stop[$d]) for d = 1:N] extest = Expr(:||, cmp...) @@ -170,7 +170,7 @@ stagedfunction start{I<:CartesianIndex}(iter::CartesianRange{I}) $extest ? $exstop : iter.start end end -stagedfunction next{I<:CartesianIndex}(iter::CartesianRange{I}, state) +@generated function next{I<:CartesianIndex}(iter::CartesianRange{I}, state) N = length(I) meta = Expr(:meta, :inline) quote @@ -181,7 +181,7 @@ stagedfunction next{I<:CartesianIndex}(iter::CartesianRange{I}, state) index, newindex end end -stagedfunction done{I<:CartesianIndex}(iter::CartesianRange{I}, state) +@generated function done{I<:CartesianIndex}(iter::CartesianRange{I}, state) N = length(I) :(state[$N] > iter.stop[$N]) end @@ -191,7 +191,7 @@ start{I<:CartesianIndex{0}}(iter::CartesianRange{I}) = false next{I<:CartesianIndex{0}}(iter::CartesianRange{I}, state) = iter.start, true done{I<:CartesianIndex{0}}(iter::CartesianRange{I}, state) = state -stagedfunction length{I<:CartesianIndex}(iter::CartesianRange{I}) +@generated function length{I<:CartesianIndex}(iter::CartesianRange{I}) N = length(I) N == 0 && return 1 args = [:(iter.stop[$i]-iter.start[$i]+1) for i=1:N] @@ -200,7 +200,7 @@ end last(iter::CartesianRange) = iter.stop -stagedfunction simd_outer_range{I}(iter::CartesianRange{I}) +@generated function simd_outer_range{I}(iter::CartesianRange{I}) N = length(I) N == 0 && return :(CartesianRange(CartesianIndex{0}(),CartesianIndex{0}())) startargs = [:(iter.start[$i]) for i=2:N] @@ -212,7 +212,7 @@ simd_inner_length{I<:CartesianIndex{0}}(iter::CartesianRange{I}, ::CartesianInde simd_inner_length(iter::CartesianRange, I::CartesianIndex) = iter.stop[1]-iter.start[1]+1 simd_index{I<:CartesianIndex{0}}(iter::CartesianRange{I}, ::CartesianIndex, I1::Int) = iter.start -stagedfunction simd_index{N}(iter::CartesianRange, Ilast::CartesianIndex{N}, I1::Int) +@generated function simd_index{N}(iter::CartesianRange, Ilast::CartesianIndex{N}, I1::Int) args = [d == 1 ? :(I1+iter.start[1]) : :(Ilast[$(d-1)]) for d = 1:N+1] meta = Expr(:meta, :inline) :($meta; CartesianIndex{$(N+1)}($(args...))) @@ -225,7 +225,7 @@ using .IteratorsMD ### From array.jl -stagedfunction checksize(A::AbstractArray, I...) +@generated function checksize(A::AbstractArray, I...) N = length(I) quote @nexprs $N d->(size(A, d) == length(I[d]) || throw(DimensionMismatch("index $d has length $(length(I[d])), but size(A, $d) = $(size(A,d))"))) @@ -241,7 +241,7 @@ end @inline unsafe_setindex!{T}(v::AbstractArray{T}, x::T, ind::Real) = unsafe_setindex!(v, x, to_index(ind)) # Version that uses cartesian indexing for src -stagedfunction _getindex!(dest::Array, src::AbstractArray, I::Union(Int,AbstractVector)...) +@generated function _getindex!(dest::Array, src::AbstractArray, I::Union(Int,AbstractVector)...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] quote @@ -256,7 +256,7 @@ stagedfunction _getindex!(dest::Array, src::AbstractArray, I::Union(Int,Abstract end # Version that uses linear indexing for src -stagedfunction _getindex!(dest::Array, src::Array, I::Union(Int,AbstractVector)...) +@generated function _getindex!(dest::Array, src::Array, I::Union(Int,AbstractVector)...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] quote @@ -278,9 +278,9 @@ end _getindex(A, I::Tuple{Vararg{Union(Int,AbstractVector),}}) = _getindex!(similar(A, index_shape(I...)), A, I...) -# The stagedfunction here is just to work around the performance hit +# The @generated function here is just to work around the performance hit # of splatting -stagedfunction getindex(A::Array, I::Union(Real,AbstractVector)...) +@generated function getindex(A::Array, I::Union(Real,AbstractVector)...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] quote @@ -290,7 +290,7 @@ stagedfunction getindex(A::Array, I::Union(Real,AbstractVector)...) end # Also a safe version of getindex! -stagedfunction getindex!(dest, src, I::Union(Real,AbstractVector)...) +@generated function getindex!(dest, src, I::Union(Real,AbstractVector)...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] Jsplat = Expr[:(to_index(I[$d])) for d = 1:N] @@ -301,7 +301,7 @@ stagedfunction getindex!(dest, src, I::Union(Real,AbstractVector)...) end -stagedfunction setindex!(A::Array, x, J::Union(Real,AbstractArray)...) +@generated function setindex!(A::Array, x, J::Union(Real,AbstractArray)...) N = length(J) if x<:AbstractArray ex=quote @@ -333,7 +333,7 @@ stagedfunction setindex!(A::Array, x, J::Union(Real,AbstractArray)...) end -stagedfunction findn{T,N}(A::AbstractArray{T,N}) +@generated function findn{T,N}(A::AbstractArray{T,N}) quote nnzA = countnz(A) @nexprs $N d->(I_d = Array(Int, nnzA)) @@ -395,8 +395,8 @@ end # then test whether the corresponding linear index is in linindex. # One exception occurs when only a small subset of the total # is desired, in which case we fall back to the div-based algorithm. -#stagedfunction merge_indexes{T<:Integer}(V, parentindexes::NTuple, parentdims::Dims, linindex::Union(Colon,Range{T}), lindim) -stagedfunction merge_indexes_in{TT}(V, parentindexes::TT, parentdims::Dims, linindex, lindim) +#@generated function merge_indexes{T<:Integer}(V, parentindexes::NTuple, parentdims::Dims, linindex::Union(Colon,Range{T}), lindim) +@generated function merge_indexes_in{TT}(V, parentindexes::TT, parentdims::Dims, linindex, lindim) N = length(parentindexes.parameters) # number of parent axes we're merging N > 0 || throw(ArgumentError("cannot merge empty indexes")) lengthexpr = linindex == Colon ? (:(prod(size(V)[lindim:end]))) : (:(length(linindex))) @@ -437,7 +437,7 @@ end # This could be written as a regular function, but performance # will be better using Cartesian macros to avoid the heap and # an extra loop. -stagedfunction merge_indexes_div{TT}(V, parentindexes::TT, parentdims::Dims, linindex, lindim) +@generated function merge_indexes_div{TT}(V, parentindexes::TT, parentdims::Dims, linindex, lindim) N = length(parentindexes.parameters) N > 0 || throw(ArgumentError("cannot merge empty indexes")) Istride_N = symbol("Istride_$N") @@ -479,7 +479,7 @@ cumprod!(B, A) = cumprod!(B, A, 1) for (f, op) in ((:cumsum!, :+), (:cumprod!, :*)) @eval begin - stagedfunction ($f){T,N}(B, A::AbstractArray{T,N}, axis::Integer) + @generated function ($f){T,N}(B, A::AbstractArray{T,N}, axis::Integer) quote if size(B, axis) < 1 return B @@ -552,7 +552,7 @@ end # (uses linear indexing, which is defined in bitarray.jl) # (code is duplicated for safe and unsafe versions for performance reasons) -stagedfunction unsafe_getindex(B::BitArray, I_0::Int, I::Int...) +@generated function unsafe_getindex(B::BitArray, I_0::Int, I::Int...) N = length(I) quote stride = 1 @@ -565,7 +565,7 @@ stagedfunction unsafe_getindex(B::BitArray, I_0::Int, I::Int...) end end -stagedfunction getindex(B::BitArray, I_0::Int, I::Int...) +@generated function getindex(B::BitArray, I_0::Int, I::Int...) N = length(I) quote stride = 1 @@ -597,7 +597,7 @@ end getindex{T<:Real}(B::BitArray, I0::UnitRange{T}) = getindex(B, to_index(I0)) -stagedfunction unsafe_getindex(B::BitArray, I0::UnitRange{Int}, I::Union(Int,UnitRange{Int})...) +@generated function unsafe_getindex(B::BitArray, I0::UnitRange{Int}, I::Union(Int,UnitRange{Int})...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] quote @@ -632,7 +632,7 @@ end # general multidimensional non-scalar indexing -stagedfunction unsafe_getindex(B::BitArray, I::Union(Int,AbstractVector{Int})...) +@generated function unsafe_getindex(B::BitArray, I::Union(Int,AbstractVector{Int})...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] quote @@ -656,7 +656,7 @@ end # general version with Real (or logical) indexing which dispatches on the appropriate method -stagedfunction getindex(B::BitArray, I::Union(Real,AbstractVector)...) +@generated function getindex(B::BitArray, I::Union(Real,AbstractVector)...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] Jsplat = Expr[:(to_index(I[$d])) for d = 1:N] @@ -673,7 +673,7 @@ end # bounds check and is defined in bitarray.jl) # (code is duplicated for safe and unsafe versions for performance reasons) -stagedfunction unsafe_setindex!(B::BitArray, x::Bool, I_0::Int, I::Int...) +@generated function unsafe_setindex!(B::BitArray, x::Bool, I_0::Int, I::Int...) N = length(I) quote stride = 1 @@ -687,7 +687,7 @@ stagedfunction unsafe_setindex!(B::BitArray, x::Bool, I_0::Int, I::Int...) end end -stagedfunction setindex!(B::BitArray, x::Bool, I_0::Int, I::Int...) +@generated function setindex!(B::BitArray, x::Bool, I_0::Int, I::Int...) N = length(I) quote stride = 1 @@ -723,7 +723,7 @@ function unsafe_setindex!(B::BitArray, x::Bool, I0::UnitRange{Int}) return B end -stagedfunction unsafe_setindex!(B::BitArray, X::BitArray, I0::UnitRange{Int}, I::Union(Int,UnitRange{Int})...) +@generated function unsafe_setindex!(B::BitArray, X::BitArray, I0::UnitRange{Int}, I::Union(Int,UnitRange{Int})...) N = length(I) quote length(X) == 0 && return B @@ -754,7 +754,7 @@ stagedfunction unsafe_setindex!(B::BitArray, X::BitArray, I0::UnitRange{Int}, I: end end -stagedfunction unsafe_setindex!(B::BitArray, x::Bool, I0::UnitRange{Int}, I::Union(Int,UnitRange{Int})...) +@generated function unsafe_setindex!(B::BitArray, x::Bool, I0::UnitRange{Int}, I::Union(Int,UnitRange{Int})...) N = length(I) quote f0 = first(I0) @@ -786,7 +786,7 @@ end # general multidimensional non-scalar indexing -stagedfunction unsafe_setindex!(B::BitArray, X::AbstractArray, I::Union(Int,AbstractArray{Int})...) +@generated function unsafe_setindex!(B::BitArray, X::AbstractArray, I::Union(Int,AbstractArray{Int})...) N = length(I) quote refind = 1 @@ -799,7 +799,7 @@ stagedfunction unsafe_setindex!(B::BitArray, X::AbstractArray, I::Union(Int,Abst end end -stagedfunction unsafe_setindex!(B::BitArray, x::Bool, I::Union(Int,AbstractArray{Int})...) +@generated function unsafe_setindex!(B::BitArray, x::Bool, I::Union(Int,AbstractArray{Int})...) N = length(I) quote @nexprs $N d->(I_d = I[d]) @@ -818,7 +818,7 @@ function setindex!(B::BitArray, x, i::Real) return unsafe_setindex!(B, convert(Bool,x), to_index(i)) end -stagedfunction setindex!(B::BitArray, x, I::Union(Real,AbstractArray)...) +@generated function setindex!(B::BitArray, x, I::Union(Real,AbstractArray)...) N = length(I) quote checkbounds(B, I...) @@ -837,7 +837,7 @@ function setindex!(B::BitArray, X::AbstractArray, i::Real) return unsafe_setindex!(B, X, j) end -stagedfunction setindex!(B::BitArray, X::AbstractArray, I::Union(Real,AbstractArray)...) +@generated function setindex!(B::BitArray, X::AbstractArray, I::Union(Real,AbstractArray)...) N = length(I) quote checkbounds(B, I...) @@ -851,7 +851,7 @@ end ## findn -stagedfunction findn{N}(B::BitArray{N}) +@generated function findn{N}(B::BitArray{N}) quote nnzB = countnz(B) I = ntuple($N, x->Array(Int, nnzB)) @@ -870,7 +870,7 @@ end ## isassigned -stagedfunction isassigned(B::BitArray, I_0::Int, I::Int...) +@generated function isassigned(B::BitArray, I_0::Int, I::Int...) N = length(I) quote @nexprs $N d->(I_d = I[d]) @@ -889,7 +889,7 @@ end ## permutedims for (V, PT, BT) in [((:N,), BitArray, BitArray), ((:T,:N), Array, StridedArray)] - @eval stagedfunction permutedims!{$(V...)}(P::$PT{$(V...)}, B::$BT{$(V...)}, perm) + @eval @generated function permutedims!{$(V...)}(P::$PT{$(V...)}, B::$BT{$(V...)}, perm) quote dimsB = size(B) length(perm) == N || throw(ArgumentError("expected permutation of size $N, but length(perm)=$(length(perm))")) @@ -936,7 +936,7 @@ immutable Prehashed end hash(x::Prehashed) = x.hash -stagedfunction unique{T,N}(A::AbstractArray{T,N}, dim::Int) +@generated function unique{T,N}(A::AbstractArray{T,N}, dim::Int) quote 1 <= dim <= $N || return copy(A) hashes = zeros(UInt, size(A, dim)) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index 4006fd0b2f97f..717ef79d645cc 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -210,7 +210,7 @@ convert(::Type{Array}, S::SharedArray) = S.s getindex(S::SharedArray) = getindex(S.s) getindex(S::SharedArray, I::Real) = getindex(S.s, I) getindex(S::SharedArray, I::AbstractArray) = getindex(S.s, I) -stagedfunction getindex(S::SharedArray, I::Union(Real,AbstractVector)...) +@generated function getindex(S::SharedArray, I::Union(Real,AbstractVector)...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] quote @@ -221,7 +221,7 @@ end setindex!(S::SharedArray, x) = setindex!(S.s, x) setindex!(S::SharedArray, x, I::Real) = setindex!(S.s, x, I) setindex!(S::SharedArray, x, I::AbstractArray) = setindex!(S.s, x, I) -stagedfunction setindex!(S::SharedArray, x, I::Union(Real,AbstractVector)...) +@generated function setindex!(S::SharedArray, x, I::Union(Real,AbstractVector)...) N = length(I) Isplat = Expr[:(I[$d]) for d = 1:N] quote diff --git a/base/statistics.jl b/base/statistics.jl index 3f59d02a15de5..ae5c8e2da6038 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -98,7 +98,7 @@ centralize_sumabs2(A::AbstractArray, m::Number) = centralize_sumabs2(A::AbstractArray, m::Number, ifirst::Int, ilast::Int) = mapreduce_impl(CentralizedAbs2Fun(m), AddFun(), A, ifirst, ilast) -stagedfunction centralize_sumabs2!{S,T,N}(R::AbstractArray{S}, A::AbstractArray{T,N}, means::AbstractArray) +@generated function centralize_sumabs2!{S,T,N}(R::AbstractArray{S}, A::AbstractArray{T,N}, means::AbstractArray) quote # following the implementation of _mapreducedim! at base/reducedim.jl lsiz = check_reducedims(R,A) diff --git a/base/subarray.jl b/base/subarray.jl index 8e8ad899a8311..4c28b2260e527 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -57,7 +57,7 @@ end # For S4, J[1] corresponds to I[2], because of the slice along # dimension 1 in S2 -stagedfunction slice_unsafe{T,NP,IndTypes}(A::AbstractArray{T,NP}, J::IndTypes) +@generated function slice_unsafe{T,NP,IndTypes}(A::AbstractArray{T,NP}, J::IndTypes) N = 0 sizeexprs = Array(Any, 0) Jp = J.parameters @@ -87,7 +87,7 @@ function _sub(A, I) sub_unsafe(A, I) end -stagedfunction sub_unsafe{T,NP,IndTypes}(A::AbstractArray{T,NP}, J::IndTypes) +@generated function sub_unsafe{T,NP,IndTypes}(A::AbstractArray{T,NP}, J::IndTypes) sizeexprs = Array(Any, 0) Itypes = Array(Any, 0) Iexprs = Array(Any, 0) @@ -123,7 +123,7 @@ end # Constructing from another SubArray # This "pops" the old SubArray and creates a more compact one -stagedfunction slice_unsafe{T,NV,PV,IV,PLD,IndTypes}(V::SubArray{T,NV,PV,IV,PLD}, J::IndTypes) +@generated function slice_unsafe{T,NV,PV,IV,PLD,IndTypes}(V::SubArray{T,NV,PV,IV,PLD}, J::IndTypes) N = 0 sizeexprs = Array(Any, 0) indexexprs = Array(Any, 0) @@ -214,7 +214,7 @@ stagedfunction slice_unsafe{T,NV,PV,IV,PLD,IndTypes}(V::SubArray{T,NV,PV,IV,PLD} end end -stagedfunction sub_unsafe{T,NV,PV,IV,PLD,IndTypes}(V::SubArray{T,NV,PV,IV,PLD}, J::IndTypes) +@generated function sub_unsafe{T,NV,PV,IV,PLD,IndTypes}(V::SubArray{T,NV,PV,IV,PLD}, J::IndTypes) Jp = J.parameters IVp = IV.parameters N = length(Jp) @@ -332,10 +332,10 @@ function tailsize(P, d) s end -stagedfunction linearindexing{T,N,P,I,LD}(A::SubArray{T,N,P,I,LD}) +@generated function linearindexing{T,N,P,I,LD}(A::SubArray{T,N,P,I,LD}) length(I.parameters) == LD ? (:(LinearFast())) : (:(LinearSlow())) end -stagedfunction linearindexing{A<:SubArray}(::Type{A}) +@generated function linearindexing{A<:SubArray}(::Type{A}) T,N,P,I,LD = A.parameters length(I.parameters) == LD ? (:(LinearFast())) : (:(LinearSlow())) end @@ -349,7 +349,7 @@ first(::Colon) = 1 in(::Int, ::Colon) = true ## Strides -stagedfunction strides{T,N,P,I}(V::SubArray{T,N,P,I}) +@generated function strides{T,N,P,I}(V::SubArray{T,N,P,I}) Ip = I.parameters all(map(x->x<:Union(RangeIndex,Colon), Ip)) || throw(ArgumentError("strides valid only for RangeIndex indexing")) strideexprs = Array(Any, N+1) diff --git a/base/subarray2.jl b/base/subarray2.jl index 66b7019d64a38..a9cefb5838f6e 100644 --- a/base/subarray2.jl +++ b/base/subarray2.jl @@ -21,7 +21,7 @@ for i = 1:4 setindex!{T,N,P,IV}(V::SubArray{T,N,P,IV}, v, $(varsOther...)) = setindex!(V, v, $(vars_toindex...)) end @eval begin - stagedfunction getindex{T,N,P,IV,LD}(V::SubArray{T,N,P,IV,LD}, $(varsInt...)) + @generated function getindex{T,N,P,IV,LD}(V::SubArray{T,N,P,IV,LD}, $(varsInt...)) if $i == 1 && length(IV.parameters) == LD # linear indexing meta = Expr(:meta, :inline) if iscontiguous(V) @@ -35,7 +35,7 @@ for i = 1:4 $ex end end - stagedfunction setindex!{T,N,P,IV,LD}(V::SubArray{T,N,P,IV,LD}, v, $(varsInt...)) + @generated function setindex!{T,N,P,IV,LD}(V::SubArray{T,N,P,IV,LD}, v, $(varsInt...)) if $i == 1 && length(IV.parameters) == LD # linear indexing meta = Expr(:meta, :inline) if iscontiguous(V) @@ -53,7 +53,7 @@ for i = 1:4 end end # V[] notation (extracts the first element) -stagedfunction getindex{T,N,P,IV}(V::SubArray{T,N,P,IV}) +@generated function getindex{T,N,P,IV}(V::SubArray{T,N,P,IV}) Isyms = ones(Int, N) exhead, ex = index_generate(ndims(P), IV, :V, Isyms) quote @@ -62,7 +62,7 @@ stagedfunction getindex{T,N,P,IV}(V::SubArray{T,N,P,IV}) end end # Splatting variants -stagedfunction getindex{T,N,P,IV}(V::SubArray{T,N,P,IV}, I::Int...) +@generated function getindex{T,N,P,IV}(V::SubArray{T,N,P,IV}, I::Int...) Isyms = [:(I[$d]) for d = 1:length(I)] exhead, ex = index_generate(ndims(P), IV, :V, Isyms) quote @@ -70,7 +70,7 @@ stagedfunction getindex{T,N,P,IV}(V::SubArray{T,N,P,IV}, I::Int...) $ex end end -stagedfunction setindex!{T,N,P,IV}(V::SubArray{T,N,P,IV}, v, I::Int...) +@generated function setindex!{T,N,P,IV}(V::SubArray{T,N,P,IV}, v, I::Int...) Isyms = [:(I[$d]) for d = 1:length(I)] exhead, ex = index_generate(ndims(P), IV, :V, Isyms) quote @@ -99,7 +99,7 @@ function setindex!{T,N,P,IV}(V::SubArray{T,N,P,IV}, v, I::AbstractArray{Bool,N}) end setindex!{T,N,P,IV}(V::SubArray{T,N,P,IV}, v, I::Union(Real,AbstractVector)...) = setindex!(V, v, to_index(I)...) setindex!{T,N,P,IV}(V::SubArray{T,N,P,IV}, x, J::Union(Int,AbstractVector)...) = _setindex!(V, x, J...) -stagedfunction _setindex!(V::SubArray, x, J::Union(Real,AbstractVector)...) +@generated function _setindex!(V::SubArray, x, J::Union(Real,AbstractVector)...) gen_setindex_body(length(J)) end diff --git a/doc/devdocs/cartesian.rst b/doc/devdocs/cartesian.rst index c9f64c0522074..0e0bfd3608e1f 100644 --- a/doc/devdocs/cartesian.rst +++ b/doc/devdocs/cartesian.rst @@ -81,9 +81,9 @@ you need to work with older julia versions, currently you should use the ``@ngenerate`` macro described in `an older version of this documentation `_. Starting in Julia 0.4-pre, the recommended approach is to use -a ``stagedfunction``. Here's an example:: +a ``@generated function``. Here's an example:: - stagedfunction mysum{T,N}(A::Array{T,N}) + @generated function mysum{T,N}(A::Array{T,N}) quote s = zero(T) @nloops $N i A begin diff --git a/doc/devdocs/subarrays.rst b/doc/devdocs/subarrays.rst index 973d5b2aae360..a7d1ff071f7d0 100644 --- a/doc/devdocs/subarrays.rst +++ b/doc/devdocs/subarrays.rst @@ -148,7 +148,7 @@ The better approach is to dispatch to specific methods to handle each type of input. Note, however, that the number of distinct methods needed grows exponentially in the number of dimensions, and since Julia supports arrays of any dimension the number of methods required -is in fact infinite. Fortunately, ``stagedfunction``\s allow one to +is in fact infinite. Fortunately, ``@generated function``\s allow one to generate the necessary methods quite straightforwardly. The resulting code looks quite a lot like the runtime approach above, but all of the type analysis is performed at the time of method instantiation. For a @@ -270,7 +270,7 @@ A few details about which of these three notions of dimensionality is relevant in each circumstance. -- Because the processing needed to implement all of the stagedfunction +- Because the processing needed to implement all of the ``@generated`` expressions isn't readily available at the time ``subarray.jl`` appears in the bootstrap process, ``SubArray`` functionality is split into two files, the second being ``subarray2.jl``. diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 44011ef55e9f5..b647f8c2fa996 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1120,6 +1120,7 @@ `(const ,expr) expr))) ((stagedfunction function macro) + (if (eq? word 'stagedfunction) (syntax-deprecation-warning s "stagedfunction" "@generated function")) (let* ((paren (eqv? (require-token s) #\()) (sig (parse-call s)) (def (if (or (symbol? sig) diff --git a/test/staged.jl b/test/staged.jl index e1020d4f99504..8ebca449f5fb3 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -1,4 +1,4 @@ -stagedfunction staged_t1(a,b) +@generated function staged_t1(a,b) if a == Int return :(a+b) else @@ -15,14 +15,14 @@ tinline(a,b) = staged_t1(a,b) @test !isa(tinline(1,2),Expr) @test tinline(1,0.5) == 1.5 -stagedfunction splat(a,b...) +@generated function splat(a,b...) :( ($a,$b,a,b) ) end @test splat(1,2,3) == (Int,(Int,Int),1,(2,3)) stagediobuf = IOBuffer() -stagedfunction splat2(a...) +@generated function splat2(a...) print(stagediobuf, a) :(nothing) end @@ -53,8 +53,8 @@ splat2(1:5, 3:3) splat2(3, 3:5) @test takebuf_string(stagediobuf) == "($intstr,UnitRange{$intstr})" -# varargs specialization with parametric stagedfunctions (issue #8944) -stagedfunction splat3{T,N}(A::AbstractArray{T,N}, indx::RangeIndex...) +# varargs specialization with parametric @generated functions (issue #8944) +@generated function splat3{T,N}(A::AbstractArray{T,N}, indx::RangeIndex...) print(stagediobuf, indx) :(nothing) end @@ -65,7 +65,7 @@ splat3(A, 1:2, 1, 1:2) @test takebuf_string(stagediobuf) == "(UnitRange{$intstr},$intstr,UnitRange{$intstr})" B = slice(A, 1:3, 2, 1:3); -stagedfunction mygetindex(S::SubArray, indexes::Real...) +@generated function mygetindex(S::SubArray, indexes::Real...) T, N, A, I = S.parameters if N != length(indexes) error("Wrong number of indexes supplied") @@ -90,7 +90,7 @@ end # issue #8497 module MyTest8497 internalfunction(x) = x+1 -stagedfunction h(x) +@generated function h(x) quote internalfunction(x) end @@ -99,26 +99,30 @@ end @test MyTest8497.h(3) == 4 # static parameters (issue #8505) -stagedfunction foo1{N,T}(a::Array{T,N}) +@generated function foo1{N,T}(a::Array{T,N}) "N = $N, T = $T" end -stagedfunction foo2{T,N}(a::Array{T,N}) +@generated function foo2{T,N}(a::Array{T,N}) "N = $N, T = $T" end @test foo1(randn(3,3)) == "N = 2, T = Float64" @test foo2(randn(3,3)) == "N = 2, T = Float64" # issue #9088 -stagedfunction f9088(x, a=5) +@generated function f9088(x, a=5) :(x+a) end @test f9088(7) == 12 # issue #10502 -stagedfunction f10502(x...) +@generated function f10502(x...) :($x) end f10502() = () @test f10502(1) == (Int,) @test f10502(1,2) == (Int,Int) @test f10502(1,2,3) == (Int,Int,Int) + +# One-line @generated functions +@generated oneliner(x,y) = :($x, x, $y, y) +@test oneliner(1, 2.) == (Int, 1, Float64, 2.)