diff --git a/base/array.jl b/base/array.jl index 75824fe94f994..c76e0a38d4509 100644 --- a/base/array.jl +++ b/base/array.jl @@ -433,7 +433,7 @@ end function setindex!{T}(A::Array{T}, X::Array{T}, I::Range1{Int}) if length(X) != length(I) - error("tried to assign $(length(X)) elements to $(length(I)) destinations"); + throw_setindex_mismatch(X, (I,)) end copy!(A, first(I), X, 1, length(I)) return A @@ -441,7 +441,7 @@ end function setindex!{T<:Real}(A::Array, X::AbstractArray, I::AbstractVector{T}) if length(X) != length(I) - error("tried to assign $(length(X)) elements to $(length(I)) destinations"); + throw_setindex_mismatch(X, (I,)) end count = 1 if is(X,A) @@ -465,7 +465,7 @@ function setindex!{T<:Real}(A::Array, x, i::Real, J::AbstractVector{T}) else X = x if length(X) != length(J) - error("tried to assign $(length(X)) elements to $(length(J)) destinations"); + throw_setindex_mismatch(X, (i,J)) end count = 1 for j in J @@ -489,7 +489,7 @@ function setindex!{T<:Real}(A::Array, x, I::AbstractVector{T}, j::Real) else X = x if length(X) != length(I) - error("tried to assign $(length(X)) elements to $(length(I)) destinations"); + throw_setindex_mismatch(X, (I,j)) end count = 1 for i in I @@ -504,7 +504,7 @@ function setindex!{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, j::Real) j = to_index(j) checkbounds(A, I, j) if length(X) != length(I) - error("tried to assign $(length(X)) elements to $(length(I)) destinations"); + throw_setindex_mismatch(X, (I,j)) end unsafe_copy!(A, first(I) + (j-1)*size(A,1), X, 1, length(I)) return A @@ -512,11 +512,7 @@ end function setindex!{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, J::Range1{Int}) checkbounds(A, I, J) - nel = length(I)*length(J) - if length(X) != nel || - (ndims(X) > 1 && (size(X,1)!=length(I) || size(X,2)!=length(J))) - error("tried to assign $(size(X,1)) x $(size(X,2)) Array to $(length(I)) x $(length(J)) destination"); - end + setindex_shape_check(X, I, J) if length(I) == size(A,1) unsafe_copy!(A, first(I) + (first(J)-1)*size(A,1), X, 1, size(A,1)*length(J)) else @@ -531,11 +527,7 @@ end function setindex!{T}(A::Array{T}, X::Array{T}, I::Range1{Int}, J::AbstractVector{Int}) checkbounds(A, I, J) - nel = length(I)*length(J) - if length(X) != nel || - (ndims(X) > 1 && (size(X,1)!=length(I) || size(X,2)!=length(J))) - error("tried to assign $(size(X)) Array to ($(length(I)),$(length(J))) destination"); - end + setindex_shape_check(X, I, J) refoffset = 1 for j = J unsafe_copy!(A, first(I) + (j-1)*size(A,1), X, refoffset, length(I)) @@ -556,11 +548,7 @@ function setindex!{T<:Real}(A::Array, x, I::AbstractVector{T}, J::AbstractVector end else X = x - nel = length(I)*length(J) - if length(X) != nel || - (ndims(X) > 1 && (size(X,1)!=length(I) || size(X,2)!=length(J))) - error("tried to assign $(size(X,1)) x $(size(X,2)) Array to $(length(I)) x $(length(J)) destination"); - end + setindex_shape_check(X, I, J) count = 1 for j in J offset = (j-1)*m @@ -593,20 +581,7 @@ function setindex!(A::Array, x, I::Union(Real,AbstractArray)...) assign_cache = Dict() end X = x - nel = 1 - for idx in I - nel *= length(idx) - end - if length(X) != nel - throw(DimensionMismatch("")) - end - if ndims(X) > 1 - for i = 1:length(I) - if size(X,i) != length(I[i]) - throw(DimensionMismatch("")) - end - end - end + setindex_shape_check(X, I...) gen_array_index_map(assign_cache, storeind -> quote A[$storeind] = X[refind] refind += 1 diff --git a/base/client.jl b/base/client.jl index 8e986958f4ddf..2b7c55dce17e3 100644 --- a/base/client.jl +++ b/base/client.jl @@ -142,6 +142,8 @@ function repl_callback(ast::ANY, show_value) put(repl_channel, (ast, show_value)) end +_eval_done = Condition() + function run_repl() global const repl_channel = RemoteRef() @@ -155,7 +157,7 @@ function run_repl() read(STDIN, buf) ccall(:jl_read_buffer,Void,(Ptr{Void},Cssize_t),buf,1) if _repl_enough_stdin - yield() + wait(_eval_done) end end put(repl_channel,(nothing,-1)) @@ -175,6 +177,7 @@ function run_repl() break end eval_user_input(ast, show_value!=0) + notify(_eval_done) end if have_color diff --git a/base/operators.jl b/base/operators.jl index cf87ef12781d4..dc38a2d083426 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -205,24 +205,77 @@ end index_shape(I::Real...) = () index_shape(i, I...) = tuple(length(i), index_shape(I...)...) +function throw_setindex_mismatch(X, I) + if length(I) == 1 + e = DimensionMismatch("tried to assign $(length(X)) elements to $(length(I[1])) destinations") + else + e = DimensionMismatch("tried to assign $(dims2string(size(X))) array to $(dims2string(map(length,I))) destination") + end + throw(e) +end + # check for valid sizes in A[I...] = X where X <: AbstractArray +# we want to allow dimensions that are equal up to permutation, but only +# for permutations that leave array elements in the same linear order. +# those are the permutations that preserve the order of the non-singleton +# dimensions. function setindex_shape_check(X::AbstractArray, I...) - nel = 1 - for idx in I - nel *= length(idx) - end - if length(X) != nel - error("dimensions must match") - end - if ndims(X) > 1 - for i = 1:length(I) - if size(X,i) != length(I[i]) - error("dimensions must match") + li = ndims(X) + lj = length(I) + i = j = 1 + while true + ii = size(X,i) + jj = length(I[j])::Int + if i == li || j == lj + while i < li + i += 1 + ii *= size(X,i) + end + while j < lj + j += 1 + jj *= length(I[j])::Int end + if ii != jj + throw_setindex_mismatch(X, I) + end + return + end + if ii == jj + i += 1 + j += 1 + elseif ii == 1 + i += 1 + elseif jj == 1 + j += 1 + else + throw_setindex_mismatch(X, I) end end end +setindex_shape_check(X::AbstractArray) = + (length(X)==1 || throw_setindex_mismatch(X,())) + +setindex_shape_check(X::AbstractArray, i) = + (length(X)==length(i) || throw_setindex_mismatch(X, (i,))) + +setindex_shape_check{T}(X::AbstractArray{T,1}, i) = + (length(X)==length(i) || throw_setindex_mismatch(X, (i,))) + +setindex_shape_check{T}(X::AbstractArray{T,1}, i, j) = + (length(X)==length(i)*length(j) || throw_setindex_mismatch(X, (i,j))) + +function setindex_shape_check{T}(X::AbstractArray{T,2}, i, j) + li, lj = length(i), length(j) + if length(X) != li*lj + throw_setindex_mismatch(X, (i,j)) + end + sx1 = size(X,1) + if !(li == 1 || li == sx1 || sx1 == 1) + throw_setindex_mismatch(X, (i,j)) + end +end + # convert to integer index to_index(i) = i to_index(i::Real) = convert(Int, i) diff --git a/src/ccall.cpp b/src/ccall.cpp index 01ff9d9e76667..5e2711256819f 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -419,7 +419,7 @@ static native_sym_arg_t interpret_symbol_arg(jl_value_t *arg, jl_codectx_t *ctx, "cglobal: first argument not a pointer or valid constant expression", ctx); } - jl_ptr = emit_unbox(T_size, arg1, ptr_ty); + jl_ptr = emit_unbox(T_size, arg1, (jl_value_t*)jl_voidpointer_type); } void *fptr=NULL; diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 3baf864618ece..71d8fa48f8688 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1229,8 +1229,7 @@ static Value *boxed(Value *v, jl_codectx_t *ctx, jl_value_t *jt) Value *tpl = builder.CreateCall(jl_alloc_tuple_func,ConstantInt::get(T_size,n)); int last_depth = ctx->argDepth; make_gcroot(tpl,ctx); - for (size_t i = 0; i < n; ++i) - { + for (size_t i = 0; i < n; ++i) { jl_value_t *jti = jl_tupleref(jt,i); Value *vi = emit_tupleref(v,ConstantInt::get(T_size,i+1),jt,ctx); emit_tupleset(tpl,ConstantInt::get(T_size,i+1),boxed(vi,ctx,jti),jt,ctx);