Skip to content

Commit

Permalink
With examples in Base and bootstrap tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mauro3 committed Sep 19, 2015
1 parent 3c78946 commit 22c16ca
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 38 deletions.
81 changes: 61 additions & 20 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,50 @@ call(::Type{Matrix}) = Array{Any}(0, 0)
function call{P<:Ptr,T<:Ptr}(::Type{Ref{P}}, a::Array{T}) # Ref{P<:Ptr}(a::Array{T<:Ptr})
return RefArray(a) # effectively a no-op
end
function call{P<:Ptr,T}(::Type{Ref{P}}, a::Array{T}) # Ref{P<:Ptr}(a::Array)

## Replacing this if-else with traitfns:
# function call{P<:Ptr,T}(::Type{Ref{P}}, a::Array{T}) # Ref{P<:Ptr}(a::Array)
# if (!isbits(T) && T <: eltype(P))
# # this Array already has the right memory layout for the requested Ref
# return RefArray(a,1,false) # root something, so that this function is type-stable
# else
# ptrs = Array(P, length(a)+1)
# roots = Array(Any, length(a))
# for i = 1:length(a)
# root = cconvert(P, a[i])
# ptrs[i] = unsafe_convert(P, root)::P
# roots[i] = root
# end
# ptrs[length(a)+1] = C_NULL
# return RefArray(ptrs,1,roots)
# end
# end

"Make a trait custom trait (just for illustration)"
@traitdef IsJustRight{P,T}
@generated function trait{P,T}(::Type{IsJustRight{P,T}})
if (!isbits(T) && T <: eltype(P))
# this Array already has the right memory layout for the requested Ref
return RefArray(a,1,false) # root something, so that this function is type-stable
return :(IsJustRight{P,T})
else
ptrs = Array(P, length(a)+1)
roots = Array(Any, length(a))
for i = 1:length(a)
root = cconvert(P, a[i])
ptrs[i] = unsafe_convert(P, root)::P
roots[i] = root
end
ptrs[length(a)+1] = C_NULL
return RefArray(ptrs,1,roots)
return :(Not{IsJustRight{P,T}})
end
end
@traitfn function call{P<:Ptr,T; IsJustRight{P,T}}(::Type{Ref{P}}, a::Array{T}) # Ref{P<:Ptr}(a::Array)
# this Array already has the right memory layout for the requested Ref
return RefArray(a,1,false) # root something, so that this function is type-stable
end
@traitfn function call{P<:Ptr,T; !IsJustRight{P,T}}(::Type{Ref{P}}, a::Array{T}) # Ref{P<:Ptr}(a::Array)
ptrs = Array(P, length(a)+1)
roots = Array(Any, length(a))
for i = 1:length(a)
root = cconvert(P, a[i])
ptrs[i] = unsafe_convert(P, root)::P
roots[i] = root
end
ptrs[length(a)+1] = C_NULL
return RefArray(ptrs,1,roots)
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)

Expand All @@ -54,7 +82,9 @@ 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)
#elsize{T}(a::Array{T}) = isbits(T) ? sizeof(T) : sizeof(Ptr)
@traitfn elsize{T; IsBits{T}}(a::Array{T}) = sizeof(T)
@traitfn elsize{T; !IsBits{T}}(a::Array{T}) = sizeof(Ptr)
sizeof(a::Array) = elsize(a) * length(a)

strides{T}(a::Array{T,1}) = (1,)
Expand All @@ -75,13 +105,24 @@ function unsafe_copy!{T}(dest::Ptr{T}, src::Ptr{T}, n)
return dest
end

function unsafe_copy!{T}(dest::Array{T}, doffs, src::Array{T}, soffs, n)
if isbits(T)
unsafe_copy!(pointer(dest, doffs), pointer(src, soffs), n)
else
for i=0:n-1
@inbounds arrayset(dest, src[i+soffs], i+doffs)
end
# function unsafe_copy!{T}(dest::Array{T}, doffs, src::Array{T}, soffs, n)
# if isbits(T)
# unsafe_copy!(pointer(dest, doffs), pointer(src, soffs), n)
# else
# for i=0:n-1
# @inbounds arrayset(dest, src[i+soffs], i+doffs)
# end
# end
# return dest
# end

@traitfn function unsafe_copy!{T; IsBits{T}}(dest::Array{T}, doffs, src::Array{T}, soffs, n)
unsafe_copy!(pointer(dest, doffs), pointer(src, soffs), n)
return dest
end
@traitfn function unsafe_copy!{T; !IsBits{T}}(dest::Array{T}, doffs, src::Array{T}, soffs, n)
for i=0:n-1
@inbounds arrayset(dest, src[i+soffs], i+doffs)
end
return dest
end
Expand Down
2 changes: 1 addition & 1 deletion base/coreimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ include("pointer.jl")
# traits
getindex(A::Array, i1::Real) = arrayref(A, to_index(i1))
include("traits.jl")
include("traits-bootstrap-tests.jl")
#include("traits-bootstrap-tests.jl")

# core array operations
include("abstractarray.jl")
Expand Down
4 changes: 2 additions & 2 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ eval(m,x) = Core.eval(m,x)

include("exports.jl")

if true
if false
# simple print definitions for debugging. enable these if something
# goes wrong during bootstrap before printing code is available.
show(x::ANY) = ccall(:jl_static_show, Void, (Ptr{Void}, Any),
Expand Down Expand Up @@ -51,7 +51,7 @@ include("functors.jl")

# traits
include("traits.jl")
include("traits-bootstrap-tests.jl")
#include("traits-bootstrap-tests.jl") # also activate the printing above

# array structures
include("abstractarray.jl")
Expand Down
94 changes: 94 additions & 0 deletions base/traits-bootstrap-tests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Tests which can be run during bootstrap. Essentially the same as in test/traits.jl

println("--------------------trait-----------------")
println("Running traits tests:")
### tests
@traitdef Tr{X}
@traitimpl Tr{Int}
@traitfn ff985{X; Tr{X}}(x::X) = x
a = ff985(5)
# println("Running traitfn:")
# println(ff985(5))

## run tests

macro assert_(ex)
:($(esc(ex)) ? $(nothing) : (print("------------- Error in: "); println($(esc(ex)))) )
end

@traitdef Tr1{X}
@assert_ trait(Tr1{Int})==Not{Tr1{Int}}
@assert_ !istrait(Tr1{Int})
@traitimpl Tr1{Integer}
@assert_ trait(Tr1{Int})==Tr1{Int}
@assert_ istrait(Tr1{Int})
@assert_ trait(Tr1{Bool})==Tr1{Bool}

# Logic. trait(Tr) returns the same trait Tr if it is fulfilled and
# Not{Tr} otherwise. This is a bit confusing.
@assert_ trait(Tr1{AbstractString})==Not{Tr1{AbstractString}}
@assert_ istrait(Tr1{AbstractString})==false
@assert_ trait(Not{Tr1{AbstractString}})==Not{Tr1{AbstractString}}
@assert_ istrait(Not{Tr1{AbstractString}})==true
@assert_ trait(Not{Not{Tr1{AbstractString}}})==Not{Tr1{AbstractString}}
@assert_ istrait(Not{Not{Tr1{AbstractString}}})==false
@assert_ trait(Not{Not{Not{Tr1{AbstractString}}}})==Not{Tr1{AbstractString}}
@assert_ istrait(Not{Not{Not{Tr1{AbstractString}}}})==true

@assert_ trait(Not{Tr1{Integer}})==Tr1{Integer}
@assert_ istrait(Not{Tr1{Integer}})==false
@assert_ trait(Not{Not{Tr1{Integer}}})==Tr1{Integer}
@assert_ istrait(Not{Not{Tr1{Integer}}})==true
@assert_ trait(Not{Not{Not{Tr1{Integer}}}})==Tr1{Integer}
@assert_ istrait(Not{Not{Not{Tr1{Integer}}}})==false

@traitdef Tr2{X,Y}
@assert_ trait(Tr2{Int,AbstractFloat})==Not{Tr2{Int,AbstractFloat}}
@traitimpl Tr2{Integer, Float64}
@assert_ trait(Tr2{Int, Float64})==Tr2{Int, Float64}
@assert_ trait(Tr2{Int, Float32})==Not{Tr2{Int, Float32}}

# trait functions
@traitfn f985{X; Tr1{X}}(x::X) = 1 # def 1
@traitfn f985{X; !Tr1{X}}(x::X) = 2
@assert_ f985(5)==1
@assert_ f985(5.)==2


@traitfn f985{X,Y; Tr2{X,Y}}(x::X,y::Y,z) = 1
@assert_ f985(5,5., "a")==1
@traitfn f985{X,Y; !Tr2{X,Y}}(x::X,y::Y,z) = 2
@assert_ f985(5,5, "a")==2
# This will overwrite the definition def1 above
@traitfn f985{X; !Tr2{X,X}}(x::X) = 10
@traitfn f985{X; Tr2{X,X}}(x::X) = 100
@assert_ f985(5)==10
@assert_ f985(5.)==10
@traitimpl Tr2{Integer, Integer}
@assert_ f985(5.)==10
println("This fails on the first round of coreimg.jl:")
@assert_ f985(5)==10
println("end of failure")
# need to update method cache to make above right:
@traitfn f985{X; Tr2{X,X}}(x::X) = 100
@assert_ f985(5)==100
@assert_ f985(5.)==10

# VarArg
@traitfn g{X; Tr1{X}}(x::X, y...) = y
@assert_ g(5, 7, 8)==((7,8),)
### @assert_ g(5.0, 7, 8)==((7,8),) # hangs because of https://github.com/JuliaLang/julia/issues/13183
## With macros
@traitfn @generated ggg{X; Tr1{X}}(x::X) = ( x<:Array ? :(x[1]+1) : :(x))
#@traitfn @generated ggg{X; Tr1{X}}(x::X) = ( println(x); x<:Array ? :(x[1]+1) : :(x))
@assert_ ggg(5)==5
@traitimpl Tr1{AbstractArray}
a = Array(Any,1) # Array(Int,1) does not work yet!?
a[1] = 5
@assert_ ggg(a)==6

# traitfn with Type
@traitfn ggt{X; Tr1{X}}(::Type{X}, y) = (X,y)
@assert_ ggt(Array, 5)==(Array, 5)

println("Traits tests done")
30 changes: 15 additions & 15 deletions base/traits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -278,20 +278,20 @@ typealias IsNothing{X} Not{IsAnything{X}}
end
end

# "Trait of all isbits-types"
# @traitdef IsBits{X}
# @generated function trait{X}(::Type{IsBits{X}})
# isbits(X) ? :(IsBits{X}) : :(Not{IsBits{X}})
# end
"Trait of all isbits-types"
@traitdef IsBits{X}
@generated function trait{X}(::Type{IsBits{X}})
isbits(X) ? :(IsBits{X}) : :(Not{IsBits{X}})
end

# "Trait of all immutable types"
# @traitdef IsImmutable{X}
# @generated function trait{X}(::Type{IsImmutable{X}})
# X.mutable ? :(Not{IsImmutable{X}}) : :(IsImmutable{X})
# end
"Trait of all immutable types"
@traitdef IsImmutable{X}
@generated function trait{X}(::Type{IsImmutable{X}})
X.mutable ? :(Not{IsImmutable{X}}) : :(IsImmutable{X})
end

# "Trait of all leaf types types"
# @traitdef IsLeafType{X}
# @generated function trait{X}(::Type{IsLeafType{X}})
# X.mutable ? :(Not{IsLeafType{X}}) : :(IsLeafType{X})
# end
"Trait of all leaf types types"
@traitdef IsLeafType{X}
@generated function trait{X}(::Type{IsLeafType{X}})
X.mutable ? :(Not{IsLeafType{X}}) : :(IsLeafType{X})
end
13 changes: 13 additions & 0 deletions test/traits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ using Base.Test
@traitfn g{X; !Tr1{X}}(x::X, y...) = 99
@test g(5.0, 7, 8)==99

## With macros
@traitfn @generated ggg{X; Tr1{X}}(x::X) = ( x<:Array ? :(x[1]+1) : :(x))
#@traitfn @generated ggg{X; Tr1{X}}(x::X) = ( println(x); x<:Array ? :(x[1]+1) : :(x))
@test ggg(5)==5
@traitimpl Tr1{AbstractArray}
a = Array(Any,1) # Array(Int,1) does not work yet!?
a[1] = 5
@test ggg(a)==6

# traitfn with Type
@traitfn ggt{X; Tr1{X}}(::Type{X}, y) = (X,y)
@test ggt(Array, 5)==(Array, 5)

######
# Other tests
#####
Expand Down

0 comments on commit 22c16ca

Please sign in to comment.