diff --git a/base/abstractarray.jl b/base/abstractarray.jl index f3106e8e7055f..0a4e706bd6ba0 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -284,9 +284,9 @@ julia> first([1; 2; 3; 4]) ``` """ function first(itr) - state = start(itr) - done(itr, state) && throw(ArgumentError("collection must be non-empty")) - next(itr, state)[1] + x = iterate(itr) + x === nothing && throw(ArgumentError("collection must be non-empty")) + x[1] end """ @@ -635,10 +635,12 @@ emptymutable(itr, ::Type{U}) where {U} = Vector{U}() function copyto!(dest::AbstractArray, src) destiter = eachindex(dest) - state = start(destiter) + y = iterate(destiter) for x in src - i, state = next(destiter, state) - dest[i] = x + y === nothing && + throw(ArgumentError(string("source has fewer elements than required"))) + dest[y[1]] = x + y = iterate(destiter, y[2]) end return dest end @@ -657,25 +659,24 @@ function copyto!(dest::AbstractArray, dstart::Integer, src, sstart::Integer) if (sstart < 1) throw(ArgumentError(string("source start offset (",sstart,") is < 1"))) end - st = start(src) + y = iterate(src) for j = 1:(sstart-1) - if done(src, st) + if y === nothing throw(ArgumentError(string("source has fewer elements than required, ", "expected at least ",sstart,", got ",j-1))) end - _, st = next(src, st) + y = iterate(src, y[2]) end - dn = done(src, st) - if dn + if y === nothing throw(ArgumentError(string("source has fewer elements than required, ", "expected at least ",sstart,", got ",sstart-1))) end i = Int(dstart) - while !dn - val, st = next(src, st) + while y != nothing + val, st = y dest[i] = val i += 1 - dn = done(src, st) + y = iterate(src, st) end return dest end @@ -690,18 +691,19 @@ function copyto!(dest::AbstractArray, dstart::Integer, src, sstart::Integer, n:: sstart < 1 && throw(ArgumentError(string("source start offset (",sstart,") is < 1"))) throw(BoundsError(dest, dstart:dmax)) end - st = start(src) + y = iterate(src) for j = 1:(sstart-1) - if done(src, st) + if y === nothing throw(ArgumentError(string("source has fewer elements than required, ", "expected at least ",sstart,", got ",j-1))) end - _, st = next(src, st) + y = iterate(src, y[2]) end i = Int(dstart) - while i <= dmax && !done(src, st) - val, st = next(src, st) + while i <= dmax && y !== nothing + val, st = y @inbounds dest[i] = val + y = iterate(src, st) i += 1 end i <= dmax && throw(BoundsError(dest, i)) @@ -823,9 +825,11 @@ zero(x::AbstractArray{T}) where {T} = fill!(similar(x), zero(T)) # While the definitions for IndexLinear are all simple enough to inline on their # own, IndexCartesian's CartesianIndices is more complicated and requires explicit # inlining. -start(A::AbstractArray) = (@_inline_meta; itr = eachindex(A); (itr, start(itr))) -next(A::AbstractArray, i) = (@_propagate_inbounds_meta; (idx, s) = next(i[1], i[2]); (A[idx], (i[1], s))) -done(A::AbstractArray, i) = (@_propagate_inbounds_meta; done(i[1], i[2])) +function iterate(A::AbstractArray, state=(eachindex(A),)) + y = iterate(state...) + y === nothing && return nothing + A[y[1]], (state[1], tail(y)...) +end isempty(a::AbstractArray) = (_length(a) == 0) @@ -2042,12 +2046,17 @@ function hash(a::AbstractArray{T}, h::UInt) where T h += hashaa_seed h += hash(size(a)) - state = start(a) - done(a, state) && return h - x1, state = next(a, state) - done(a, state) && return hash(x1, h) - x2, state = next(a, state) - done(a, state) && return hash(x2, hash(x1, h)) + y1 = iterate(a) + y1 === nothing && return h + y2 = iterate(a, y1[2]) + y2 === nothing && return hash(y1[1], h) + y = iterate(a, y2[2]) + y === nothing && return hash(y2[1], hash(y1[1], h)) + x1, x2 = y1[1], y2[1] + + # For the rest of the function, we keep three elements worth of state, + # x1, x2, y[1], with `y` potentially being `nothing` if there's only + # two elements remaining # Check whether the array is equal to a range, and hash the elements # at the beginning of the array as such as long as they match this assumption @@ -2056,6 +2065,10 @@ function hash(a::AbstractArray{T}, h::UInt) where T if isa(a, AbstractVector) && applicable(-, x2, x1) n = 1 local step, laststep, laststate + + h = hash(x1, h) + h += hashr_seed + while true # If overflow happens with entries of the same type, a cannot be equal # to a range with more than two elements because more extreme values @@ -2077,37 +2090,38 @@ function hash(a::AbstractArray{T}, h::UInt) where T end n > 1 && !isequal(step, laststep) && break n += 1 - x1 = x2 laststep = step - laststate = state - done(a, state) && break - x2, state = next(a, state) + if y === nothing + # The array matches a range exactly + return hash(x2, hash(n, h)) + end + x1, x2 = x2, y[1] + y = iterate(a, y[2]) end - h = hash(first(a), h) - h += hashr_seed # Always hash at least the two first elements as a range (even in case of overflow) if n < 2 h = hash(2, h) - h = hash(x2, h) - done(a, state) && return h - x1 = x2 - x2, state = next(a, state) + h = hash(y2[1], h) + @assert y !== nothing + x1, x2 = x2, y[1] + y = iterate(a, y[2]) else h = hash(n, h) h = hash(x1, h) - done(a, laststate) && return h end end - # Hash elements which do not correspond to a range (if any) + # Hash elements which do not correspond to a range while true if isequal(x2, x1) # For repeated elements, use run length encoding # This allows efficient hashing of sparse arrays runlength = 2 - while !done(a, state) - x2, state = next(a, state) + while y !== nothing + # No need to update x1 (it's isequal x2) + x2 = y[1] + y = iterate(a, y[2]) isequal(x1, x2) || break runlength += 1 end @@ -2115,9 +2129,9 @@ function hash(a::AbstractArray{T}, h::UInt) where T h = hash(runlength, h) end h = hash(x1, h) - done(a, state) && break - x1 = x2 - x2, state = next(a, state) + y === nothing && break + x1, x2 = x2, y[1] + y = iterate(a, y[2]) end !isequal(x2, x1) && (h = hash(x2, h)) return h diff --git a/base/abstractdict.jl b/base/abstractdict.jl index 040b6e07d5ac4..47af40b6eef96 100644 --- a/base/abstractdict.jl +++ b/base/abstractdict.jl @@ -55,17 +55,10 @@ isempty(v::Union{KeySet,ValueIterator}) = isempty(v.dict) _tt2(::Type{Pair{A,B}}) where {A,B} = B eltype(::Type{ValueIterator{D}}) where {D} = _tt2(eltype(D)) -start(v::Union{KeySet,ValueIterator}) = start(v.dict) -done(v::Union{KeySet,ValueIterator}, state) = done(v.dict, state) - -function next(v::KeySet, state) - n = next(v.dict, state) - n[1][1], n[2] -end - -function next(v::ValueIterator, state) - n = next(v.dict, state) - n[1][2], n[2] +function iterate(v::Union{KeySet,ValueIterator}, state...) + y = iterate(v.dict, state...) + y === nothing && return nothing + return (y[1][isa(v, KeySet) ? 1 : 2], y[2]) end in(k, v::KeySet) = get(v.dict, k, secret_table_token) !== secret_table_token @@ -670,9 +663,11 @@ end _oidd_nextind(a, i) = reinterpret(Int, ccall(:jl_eqtable_nextind, Csize_t, (Any, Csize_t), a, i)) -start(d::IdDict) = _oidd_nextind(d.ht, 0) -done(d::IdDict, i) = (i == -1) -next(d::IdDict{K, V}, i) where {K, V} = (Pair{K, V}(d.ht[i + 1]::K, d.ht[i + 2]::V), _oidd_nextind(d.ht, i + 2)) +function iterate(d::IdDict{K,V}, idx=0) where {K, V} + idx = _oidd_nextind(d.ht, idx) + idx == -1 && return nothing + return (Pair{K, V}(d.ht[idx + 1]::K, d.ht[idx + 2]::V), idx + 2) +end length(d::IdDict) = d.count @@ -711,9 +706,9 @@ empty!(s::IdSet) = (empty!(s.dict); s) filter!(f, d::IdSet) = unsafe_filter!(f, d) -start(s::IdSet) = start(s.dict) -done(s::IdSet, state) = done(s.dict, state) -function next(s::IdSet, state) - ((k, _), i) = next(s.dict, state) +function iterate(s::IdSet, state...) + y = iterate(s.dict, state...) + y === nothing && return nothing + ((k, _), i) = y return (k, i) end diff --git a/base/array.jl b/base/array.jl index 6475bbc914dbe..26d8e54e2f581 100644 --- a/base/array.jl +++ b/base/array.jl @@ -564,11 +564,11 @@ function collect(itr::Generator) if isa(isz, SizeUnknown) return grow_to!(Vector{et}(), itr) else - st = start(itr) - if done(itr,st) + y = iterate(itr) + if y === nothing return _array_for(et, itr.iter, isz) end - v1, st = next(itr, st) + v1, st = y collect_to_with_first!(_array_for(typeof(v1), itr.iter, isz), v1, itr, st) end end @@ -577,11 +577,11 @@ _collect(c, itr, ::EltypeUnknown, isz::SizeUnknown) = grow_to!(_similar_for(c, @default_eltype(itr), itr, isz), itr) function _collect(c, itr, ::EltypeUnknown, isz::Union{HasLength,HasShape}) - st = start(itr) - if done(itr,st) + y = iterate(itr) + if y === nothing return _similar_for(c, @default_eltype(itr), itr, isz) end - v1, st = next(itr, st) + v1, st = y collect_to_with_first!(_similar_for(c, typeof(v1), itr, isz), v1, itr, st) end @@ -600,8 +600,10 @@ function collect_to!(dest::AbstractArray{T}, itr, offs, st) where T # collect to dest array, checking the type of each result. if a result does not # match, widen the result type and re-dispatch. i = offs - while !done(itr, st) - el, st = next(itr, st) + while true + y = iterate(itr, st) + y === nothing && break + el, st = y if el isa T || typeof(el) === T @inbounds dest[i] = el::T i += 1 @@ -617,21 +619,18 @@ function collect_to!(dest::AbstractArray{T}, itr, offs, st) where T end function grow_to!(dest, itr) - st = start(itr) - if done(itr, st) - return dest - else - v1, st = next(itr, st) - dest2 = empty(dest, typeof(v1)) - push!(dest2, v1) - return grow_to!(dest2, itr, st) - end + y = iterate(itr) + y === nothing && return dest + dest2 = empty(dest, typeof(y[1])) + push!(dest2, y[1]) + grow_to!(dest2, itr, y[2]) end function grow_to!(dest, itr, st) T = eltype(dest) - while !done(itr, st) - el, st = next(itr, st) + y = iterate(itr, st) + while y !== nothing + el, st = y S = typeof(el) if S === T || S <: T push!(dest, el::T) @@ -646,14 +645,16 @@ function grow_to!(dest, itr, st) push!(new, el) return grow_to!(new, itr, st) end + y = iterate(itr, st) end return dest end ## Iteration ## -start(A::Array) = 1 -next(a::Array,i) = (@_propagate_inbounds_meta; (a[i],i+1)) -done(a::Array,i) = (@_inline_meta; i >= length(a)+1) +function iterate(A::Array, i=1) + @_propagate_inbounds_meta + i >= length(A) + 1 ? nothing : (A[i], i+1) +end ## Indexing: getindex ## @@ -1162,12 +1163,14 @@ deleteat!(a::Vector, inds::AbstractVector) = _deleteat!(a, to_indices(a, (inds,) function _deleteat!(a::Vector, inds) n = length(a) - s = start(inds) - done(inds, s) && return a - (p, s) = next(inds, s) + y = iterate(inds) + y === nothing && return a + (p, s) = y q = p+1 - while !done(inds, s) - (i,s) = next(inds, s) + while true + y = iterate(inds, s) + y === nothing && break + (i,s) = y if !(q <= i <= n) if i < q throw(ArgumentError("indices must be unique and sorted")) @@ -2019,16 +2022,18 @@ julia> findmax([1,7,7,NaN]) findmax(a) = _findmax(a, :) function _findmax(a, ::Colon) - if isempty(a) + p = pairs(a) + y = iterate(p) + if y === nothing throw(ArgumentError("collection must be non-empty")) end - p = pairs(a) - s = start(p) - (mi, m), s = next(p, s) + (mi, m), s = y i = mi - while !done(p, s) + while true + y = iterate(p, s) + y === nothing && break m != m && break - (i, ai), s = next(p, s) + (i, ai), s = y if ai != ai || isless(m, ai) m = ai mi = i @@ -2062,16 +2067,18 @@ julia> findmin([7,1,1,NaN]) findmin(a) = _findmin(a, :) function _findmin(a, ::Colon) - if isempty(a) + p = pairs(a) + y = iterate(p) + if y === nothing throw(ArgumentError("collection must be non-empty")) end - p = pairs(a) - s = start(p) - (mi, m), s = next(p, s) + (mi, m), s = y i = mi - while !done(p, s) + while true + y = iterate(p, s) + y === nothing && break m != m && break - (i, ai), s = next(p, s) + (i, ai), s = y if ai != ai || isless(ai, m) m = ai mi = i @@ -2180,35 +2187,38 @@ end function _sortedfindin(v, w) viter, witer = eachindex(v), eachindex(w) out = eltype(viter)[] - i, j = start(viter), start(witer) - if done(viter, i) || done(witer, j) + vy, wy = iterate(viter), iterate(witer) + if vy === nothing || wy === nothing return out end - viteri, i = next(viter, i) - witerj, j = next(witer, j) + viteri, i = vy + witerj, j = wy @inbounds begin vi, wj = v[viteri], w[witerj] while true if isless(vi, wj) - if done(viter, i) + vy = iterate(viter, i) + if vy === nothing break end - viteri, i = next(viter, i) + viteri, i = vy vi = v[viteri] elseif isless(wj, vi) - if done(witer, j) + wy = iterate(witer, j) + if wy === nothing break end - witerj, j = next(witer, j) + witerj, j = wy wj = w[witerj] else push!(out, viteri) - if done(viter, i) + vy = iterate(viter, i) + if vy === nothing break end # We only increment the v iterator because v can have # repeated matches to a single value in w - viteri, i = next(viter, i) + viteri, i = vy vi = v[viteri] end end @@ -2292,16 +2302,17 @@ julia> filter!(isodd, Vector(1:10)) ``` """ function filter!(f, a::AbstractVector) - isempty(a) && return a - idx = eachindex(a) - state = start(idx) - i, state = next(idx, state) + y = iterate(idx) + y === nothing && return a + i, state = y for acurr in a if f(acurr) a[i] = acurr - i, state = next(idx, state) + y = iterate(idx, state) + y === nothing && (i += 1; break) + i, state = y end end diff --git a/base/asyncmap.jl b/base/asyncmap.jl index d2fe557d1c5e6..2456007066033 100644 --- a/base/asyncmap.jl +++ b/base/asyncmap.jl @@ -282,8 +282,8 @@ Keyword args `ntasks` and `batch_size` have the same behavior as in be a function which operates on an array of argument tuples. !!! note - `next(::AsyncCollector, state) -> (nothing, state)`. A successful return - from `next` indicates that the next element from the input collection is + `iterate(::AsyncCollector, state) -> (nothing, state)`. A successful return + from `iterate` indicates that the next element from the input collection is being processed asynchronously. It blocks until a free worker task becomes available. @@ -299,9 +299,11 @@ mutable struct AsyncCollectorState chnl::Channel worker_tasks::Array{Task,1} enum_state # enumerator state + AsyncCollectorState(chnl::Channel, worker_tasks::Vector) = + new(chnl, convert(Vector{Task}, worker_tasks)) end -function start(itr::AsyncCollector) +function iterate(itr::AsyncCollector) itr.ntasks = verify_ntasks(itr.enumerator, itr.ntasks) itr.batch_size = verify_batch_size(itr.batch_size) if itr.batch_size !== nothing @@ -319,29 +321,31 @@ function start(itr::AsyncCollector) exec_func = (i,args) -> (itr.results[i]=itr.f(args...)) end chnl, worker_tasks = setup_chnl_and_tasks((i,args) -> (itr.results[i]=itr.f(args...)), itr.ntasks, itr.batch_size) - return AsyncCollectorState(chnl, worker_tasks, start(itr.enumerator)) + return iterate(itr, AsyncCollectorState(chnl, worker_tasks)) end -function done(itr::AsyncCollector, state::AsyncCollectorState) - if !isopen(state.chnl) || done(itr.enumerator, state.enum_state) - close(state.chnl) +function wait_done(itr::AsyncCollector, state::AsyncCollectorState) + close(state.chnl) - # wait for all tasks to finish - foreach(x->(v=fetch(x); isa(v, Exception) && throw(v)), state.worker_tasks) - empty!(state.worker_tasks) - return true - else - return false - end + # wait for all tasks to finish + foreach(x->(v=fetch(x); isa(v, Exception) && throw(v)), state.worker_tasks) + empty!(state.worker_tasks) end -function next(itr::AsyncCollector, state::AsyncCollectorState) +function iterate(itr::AsyncCollector, state::AsyncCollectorState) if itr.nt_check && (length(state.worker_tasks) < itr.ntasks()) start_worker_task!(state.worker_tasks, itr.f, state.chnl) end # Get index and mapped function arguments from enumeration iterator. - (i, args), state.enum_state = next(itr.enumerator, state.enum_state) + y = isdefined(state, :enum_state) ? + iterate(itr.enumerator, state.enum_state) : + iterate(itr.enumerator) + if y === nothing + wait_done(itr, state) + return nothing + end + (i, args), state.enum_state = y put!(state.chnl, (i, args)) return (nothing, state) @@ -370,29 +374,28 @@ end mutable struct AsyncGeneratorState i::Int + collector_done::Bool collector_state::AsyncCollectorState + AsyncGeneratorState(i::Int) = new(i, false) end -start(itr::AsyncGenerator) = AsyncGeneratorState(0, start(itr.collector)) - -# Done when source async collector is done and all results have been consumed. -function done(itr::AsyncGenerator, state::AsyncGeneratorState) - done(itr.collector, state.collector_state) && isempty(itr.collector.results) -end - -function next(itr::AsyncGenerator, state::AsyncGeneratorState) +function iterate(itr::AsyncGenerator, state::AsyncGeneratorState=AsyncGeneratorState(0)) state.i += 1 results_dict = itr.collector.results - while !haskey(results_dict, state.i) - if done(itr.collector, state.collector_state) - # `done` waits for async tasks to finish. if we do not have the index + while !state.collector_done && !haskey(results_dict, state.i) + y = isdefined(state, :collector_state) ? + iterate(itr.collector, state.collector_state) : + iterate(itr.collector) + if y === nothing + # `check_done` waits for async tasks to finish. if we do not have the index # we are looking for, it is an error. - !haskey(results_dict, state.i) && error("Error processing index ", i) + state.collector_done = true break; end - _, state.collector_state = next(itr.collector, state.collector_state) + _, state.collector_state = y end + state.collector_done && isempty(results_dict) && return nothing r = results_dict[state.i] delete!(results_dict, state.i) diff --git a/base/bitarray.jl b/base/bitarray.jl index d37ce044bdda5..f761496404c4f 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -323,9 +323,10 @@ dumpbitcache(Bc::Vector{UInt64}, bind::Int, C::Vector{Bool}) = ## custom iterator ## -start(B::BitArray) = 0 -next(B::BitArray, i::Int) = (B.chunks[_div64(i)+1] & (UInt64(1)<<_mod64(i)) != 0, i+1) -done(B::BitArray, i::Int) = i >= length(B) +function iterate(B::BitArray, i::Int=0) + i >= length(B) && return nothing + (B.chunks[_div64(i)+1] & (UInt64(1)<<_mod64(i)) != 0, i+1) +end ## similar, fill!, copy! etc ## @@ -540,7 +541,7 @@ convert(T::Type{<:BitArray}, a::AbstractArray) = a isa T ? a : T(a) # generic constructor from an iterable without compile-time info # (we pass start(itr) explicitly to avoid a type-instability with filters) -gen_bitarray(isz::IteratorSize, itr) = gen_bitarray_from_itr(itr, start(itr)) +gen_bitarray(isz::IteratorSize, itr) = gen_bitarray_from_itr(itr) # generic iterable with known shape function gen_bitarray(::HasShape, itr) @@ -554,11 +555,11 @@ end # generator with known shape or length function gen_bitarray(::HasShape, itr::Generator) B = BitArray(undef, size(itr)) - return fill_bitarray_from_itr!(B, itr, start(itr)) + return fill_bitarray_from_itr!(B, itr) end function gen_bitarray(::HasLength, itr) b = BitVector(undef, length(itr)) - return fill_bitarray_from_itr!(b, itr, start(itr)) + return fill_bitarray_from_itr!(b, itr) end gen_bitarray(::IsInfinite, itr) = throw(ArgumentError("infinite-size iterable used in BitArray constructor")) @@ -566,14 +567,15 @@ gen_bitarray(::IsInfinite, itr) = throw(ArgumentError("infinite-size iterable u # The aux functions gen_bitarray_from_itr and fill_bitarray_from_itr! both # use a Vector{Bool} cache for performance reasons -function gen_bitarray_from_itr(itr, st) +function gen_bitarray_from_itr(itr) B = empty!(BitVector(undef, bitcache_size)) C = Vector{Bool}(undef, bitcache_size) Bc = B.chunks ind = 1 cind = 1 - while !done(itr, st) - x, st = next(itr, st) + y = iterate(itr) + while y !== nothing + x, st = y @inbounds C[ind] = x ind += 1 if ind > bitcache_size @@ -582,6 +584,7 @@ function gen_bitarray_from_itr(itr, st) cind += bitcache_chunks ind = 1 end + y = iterate(itr, st) end if ind > 1 @inbounds C[ind:bitcache_size] .= false @@ -591,14 +594,15 @@ function gen_bitarray_from_itr(itr, st) return B end -function fill_bitarray_from_itr!(B::BitArray, itr, st) +function fill_bitarray_from_itr!(B::BitArray, itr) n = length(B) C = Vector{Bool}(undef, bitcache_size) Bc = B.chunks ind = 1 cind = 1 - while !done(itr, st) - x, st = next(itr, st) + y = iterate(itr) + while y !== nothing + x, st = y @inbounds C[ind] = x ind += 1 if ind > bitcache_size @@ -606,6 +610,7 @@ function fill_bitarray_from_itr!(B::BitArray, itr, st) cind += bitcache_chunks ind = 1 end + y = iterate(itr, st) end if ind > 1 @inbounds C[ind:bitcache_size] .= false @@ -926,16 +931,17 @@ end function deleteat!(B::BitVector, inds) n = new_l = length(B) - s = start(inds) - done(inds, s) && return B + y = iterate(inds) + y === nothing && return B Bc = B.chunks - (p, s) = next(inds, s) + (p, s) = y q = p+1 new_l -= 1 - while !done(inds, s) - (i,s) = next(inds, s) + y = iterate(inds, s) + while y !== nothing + (i, s) = y if !(q <= i <= n) i < q && throw(ArgumentError("indices must be unique and sorted")) throw(BoundsError(B, i)) @@ -946,6 +952,7 @@ function deleteat!(B::BitVector, inds) p += i-q end q = i+1 + y = iterate(inds, s) end q <= n && copy_chunks!(Bc, p, Bc, q, n-q+1) @@ -1067,14 +1074,14 @@ end for f in (:+, :-) @eval function ($f)(A::BitArray, B::BitArray) r = Array{Int}(undef, promote_shape(size(A), size(B))) - ai = start(A) - bi = start(B) + ay, by = iterate(A), iterate(B) ri = 1 - while !done(A, ai) - a, ai = next(A, ai) - b, bi = next(B, bi) - @inbounds r[ri] = ($f)(a, b) + # promote_shape guarantees that A and B have the + # same iteration space + while ay !== nothing + @inbounds r[ri] = ($f)(ay[1], by[1]) ri += 1 + ay, by = iterate(A, ay[2]), iterate(B, by[2]) end return r end diff --git a/base/bitset.jl b/base/bitset.jl index 395a61505b85b..25850add41b64 100644 --- a/base/bitset.jl +++ b/base/bitset.jl @@ -290,16 +290,12 @@ filter!(f, s::BitSet) = unsafe_filter!(f, s) @inline in(n::Int, s::BitSet) = _bits_getindex(s.bits, n, s.offset) @inline in(n::Integer, s::BitSet) = _is_convertible_Int(n) ? in(Int(n), s) : false -# Use the next-set index as the state to prevent looking it up again in done -start(s::BitSet) = _bits_findnext(s.bits, 0) - -function next(s::BitSet, i::Int) - nextidx = _bits_findnext(s.bits, i+1) - (i+intoffset(s), nextidx) +function iterate(s::BitSet, idx=0) + idx = _bits_findnext(s.bits, idx) + idx == -1 && return nothing + (idx + intoffset(s), idx+1) end -done(s::BitSet, i) = i == -1 - @noinline _throw_bitset_notempty_error() = throw(ArgumentError("collection must be non-empty")) diff --git a/base/broadcast.jl b/base/broadcast.jl index 226a4cda2c603..284f38007eb10 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -245,13 +245,16 @@ Base.length(bc::Broadcasted) = prod(map(length, axes(bc))) Base.size(bc::Broadcasted) = _size(axes(bc)) _size(::Tuple{Vararg{Base.OneTo}}) = map(length, axes(bc)) -Base.start(bc::Broadcasted) = (iter = eachindex(bc); (iter, start(iter))) -Base.@propagate_inbounds function Base.next(bc::Broadcasted, s) - iter, state = s - i, newstate = next(iter, state) - return (bc[i], (iter, newstate)) +function Base.iterate(bc::Broadcasted) + iter = eachindex(bc) + iterate(bc, (iter,)) +end +Base.@propagate_inbounds function Base.iterate(bc::Broadcasted, s) + y = iterate(s...) + y === nothing && return nothing + i, newstate = y + return (bc[i], (s[1], newstate)) end -Base.done(bc::Broadcasted, s) = done(s[1], s[2]) Base.IteratorSize(::Type{<:Broadcasted{<:Any,<:NTuple{N,Base.OneTo}}}) where {N} = Base.HasShape{N}() Base.IteratorEltype(::Type{<:Broadcasted}) = Base.EltypeUnknown() @@ -758,13 +761,13 @@ const NonleafHandlingStyles = Union{DefaultArrayStyle,ArrayConflict} # will widen `dest` as needed to accommodate later values. bc′ = preprocess(nothing, bc) iter = eachindex(bc′) - state = start(iter) - if done(iter, state) + y = iterate(iter) + if y === nothing # if empty, take the ElType at face value return similar(bc′, ElType) end # Initialize using the first value - I, state = next(iter, state) + I, state = y @inbounds val = bc′[I] dest = similar(bc′, typeof(val)) @inbounds dest[I] = val @@ -907,8 +910,10 @@ end function copyto_nonleaf!(dest, bc::Broadcasted, iter, state, count) T = eltype(dest) - while !done(iter, state) - I, state = next(iter, state) + while true + y = iterate(iter, state) + y === nothing && break + I, state = y @inbounds val = bc[I] S = typeof(val) if S <: T diff --git a/base/cartesian.jl b/base/cartesian.jl index 45515fc4e644f..526cff67bd706 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -275,11 +275,11 @@ function lreplace!(str::AbstractString, r::LReplace) j = firstindex(pat) matching = false local istart::Int - while i <= lastindex(str) + while i <= ncodeunits(str) cstr = str[i] i = nextind(str, i) if !matching - if cstr != '_' || done(str, i) + if cstr != '_' || i > ncodeunits(str) continue end istart = i diff --git a/base/channels.jl b/base/channels.jl index 929f61c7c1de6..82854160fea5b 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -381,28 +381,16 @@ eltype(::Type{Channel{T}}) where {T} = T show(io::IO, c::Channel) = print(io, "$(typeof(c))(sz_max:$(c.sz_max),sz_curr:$(n_avail(c)))") -mutable struct ChannelIterState{T} - hasval::Bool - val::T - ChannelIterState{T}(has::Bool) where {T} = new(has) -end - -start(c::Channel{T}) where {T} = ChannelIterState{T}(false) -function done(c::Channel, state::ChannelIterState) +function iterate(c::Channel, state=nothing) try - # we are waiting either for more data or channel to be closed - state.hasval && return false - state.val = take!(c) - state.hasval = true - return false + return (take!(c), nothing) catch e if isa(e, InvalidStateException) && e.state==:closed - return true + return nothing else rethrow(e) end end end -next(c::Channel, state) = (v=state.val; state.hasval=false; (v, state)) IteratorSize(::Type{<:Channel}) = SizeUnknown() diff --git a/base/char.jl b/base/char.jl index 97e74d2d0758a..359a3013ecfa1 100644 --- a/base/char.jl +++ b/base/char.jl @@ -187,9 +187,7 @@ first(c::AbstractChar) = c last(c::AbstractChar) = c eltype(::Type{T}) where {T<:AbstractChar} = T -start(c::AbstractChar) = false -next(c::AbstractChar, state) = (c, true) -done(c::AbstractChar, state) = state +iterate(c::AbstractChar, done=false) = done ? nothing : (c, true) isempty(c::AbstractChar) = false in(x::AbstractChar, y::AbstractChar) = x == y diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 1acdf48021ebe..ecf4b5d1243fc 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -379,25 +379,28 @@ end # simulate iteration protocol on container type up to fixpoint function abstract_iteration(@nospecialize(itertype), vtypes::VarTable, sv::InferenceState) tm = _topmod(sv) - if !isdefined(tm, :start) || !isdefined(tm, :next) || !isconst(tm, :start) || !isconst(tm, :next) + if !isdefined(tm, :iterate) || !isconst(tm, :iterate) return Vararg{Any} end - startf = getfield(tm, :start) - nextf = getfield(tm, :next) - statetype = abstract_call(startf, (), Any[Const(startf), itertype], vtypes, sv) - statetype === Bottom && return Bottom - valtype = Bottom + iteratef = getfield(tm, :iterate) + stateordonet = abstract_call(iteratef, (), Any[Const(iteratef), itertype], vtypes, sv) + # Return Bottom if this is not an iterator. + # WARNING: Changes to the iteration protocol must be reflected here, + # this is not just an optimization. + stateordonet === Bottom && return Bottom + valtype = statetype = Bottom while valtype !== Any - nt = abstract_call(nextf, (), Any[Const(nextf), itertype, statetype], vtypes, sv) - nt = widenconst(nt) - if !isa(nt, DataType) || !(nt <: Tuple) || isvatuple(nt) || length(nt.parameters) != 2 + stateordonet = widenconst(stateordonet) + nounion = Nothing <: stateordonet ? typesubtract(stateordonet, Nothing) : stateordonet + if !isa(nounion, DataType) || !(nounion <: Tuple) || isvatuple(nounion) || length(nounion.parameters) != 2 return Vararg{Any} end - if nt.parameters[1] <: valtype && nt.parameters[2] <: statetype + if nounion.parameters[1] <: valtype && nounion.parameters[2] <: statetype break end - valtype = tmerge(valtype, nt.parameters[1]) - statetype = tmerge(statetype, nt.parameters[2]) + valtype = tmerge(valtype, nounion.parameters[1]) + statetype = tmerge(statetype, nounion.parameters[2]) + stateordonet = abstract_call(iteratef, (), Any[Const(iteratef), itertype, statetype], vtypes, sv) end return Vararg{valtype} end diff --git a/base/compiler/compiler.jl b/base/compiler/compiler.jl index faf95ce00544a..02c27b30d0937 100644 --- a/base/compiler/compiler.jl +++ b/base/compiler/compiler.jl @@ -24,6 +24,7 @@ include(mod, x) = Core.include(mod, x) # essential files and libraries include("essentials.jl") +include("some.jl") include("ctypes.jl") include("generator.jl") include("reflection.jl") diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 734edef1c15a5..216defaa3b005 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -250,7 +250,7 @@ function isinlineable(m::Method, src::CodeInfo, mod::Module, params::Params, bon isa(sig,DataType) && sig == Tuple{sig.parameters[1],Any,Any,Any,Vararg{Any}}) inlineable = true - elseif (name === :next || name === :done || name === :unsafe_convert || + elseif (name === :iterate || name === :unsafe_convert || name === :cconvert) cost_threshold *= 4 end diff --git a/base/compiler/ssair/domtree.jl b/base/compiler/ssair/domtree.jl index 6a65aac823cf7..8952619c2e224 100644 --- a/base/compiler/ssair/domtree.jl +++ b/base/compiler/ssair/domtree.jl @@ -43,9 +43,8 @@ function dominated(domtree::DomTree, root::Int) doms end -start(doms::DominatedBlocks) = nothing - -function next(doms::DominatedBlocks, state::Nothing) +function iterate(doms::DominatedBlocks, state::Nothing=nothing) + isempty(doms.worklist) && return nothing bb = pop!(doms.worklist) for dominated in doms.domtree.nodes[bb].children push!(doms.worklist, dominated) @@ -53,8 +52,6 @@ function next(doms::DominatedBlocks, state::Nothing) return (bb, nothing) end -done(doms::DominatedBlocks, state::Nothing) = isempty(doms.worklist) - # Construct Dom Tree # Simple algorithm - TODO: Switch to the fast version (e.g. https://tanujkhattar.wordpress.com/2016/01/11/dominator-tree-of-a-directed-graph/) function construct_domtree(cfg::CFG) diff --git a/base/compiler/ssair/inlining2.jl b/base/compiler/ssair/inlining2.jl index 666326cc50973..3873e40450e75 100644 --- a/base/compiler/ssair/inlining2.jl +++ b/base/compiler/ssair/inlining2.jl @@ -640,9 +640,8 @@ end struct SimpleCartesian ranges::Vector{UnitRange{Int}} end -start(s::SimpleCartesian) = Int[1 for _ in 1:length(s.ranges)] -done(s::SimpleCartesian, state) = state[end] > last(s.ranges[end]) -function next(s::SimpleCartesian, state) +function iterate(s::SimpleCartesian, state::Vector{Int}=Int[1 for _ in 1:length(s.ranges)]) + state[end] > last(s.ranges[end]) && return nothing vals = copy(state) any = false for i = 1:length(s.ranges) @@ -673,10 +672,10 @@ function UnionSplitSignature(atypes::Vector{Any}) UnionSplitSignature(SimpleCartesian(ranges), typs) end -start(split::UnionSplitSignature) = start(split.it) -done(split::UnionSplitSignature, state) = done(split.it, state) -function next(split::UnionSplitSignature, state) - idxs, state = next(split.it, state) +function iterate(split::UnionSplitSignature, state::Vector{Int}...) + y = iterate(split.it, state...) + y === nothing && return nothing + idxs, state = y sig = Any[split.typs[i][j] for (i,j) in enumerate(idxs)] sig, state end diff --git a/base/compiler/ssair/ir.jl b/base/compiler/ssair/ir.jl index 0b92e5f0b615f..f5d6240665c72 100644 --- a/base/compiler/ssair/ir.jl +++ b/base/compiler/ssair/ir.jl @@ -29,9 +29,7 @@ struct StmtRange <: AbstractUnitRange{Int} end first(r::StmtRange) = r.first last(r::StmtRange) = r.last -start(r::StmtRange) = 0 -done(r::StmtRange, state) = r.last - r.first < state -next(r::StmtRange, state) = (r.first + state, state + 1) +iterate(r::StmtRange, state=0) = (r.last - r.first < state) ? nothing : (r.first + state, state + 1) StmtRange(range::UnitRange{Int}) = StmtRange(first(range), last(range)) @@ -326,31 +324,17 @@ function userefs(@nospecialize(x)) return UseRefIterator(x, relevant) end -start(it::UseRefIterator) = (it.use[1].op = 0; nothing) -next(it::UseRefIterator, ::Nothing) = it.use -@noinline function done(it::UseRefIterator, ::Nothing) - it.relevant || return true +iterate(it::UseRefIterator) = (it.use[1].op = 0; iterate(it, nothing)) +@noinline function iterate(it::UseRefIterator, ::Nothing) + it.relevant || return nothing use = it.use[1] while true use.op += 1 y = use[] - y === OOBToken() && return true - y === UndefToken() || break + y === OOBToken() && return nothing + y === UndefToken() || return it.use end - return false end -#iterate(it::UseRefIterator) = (it.use[1].op = 0; iterate(it, nothing)) -#@noinline function iterate(it::UseRefIterator, ::Nothing) -# it.relevant || return nothing -# use = it.use[1] -# while true -# use.op += 1 -# y = use[] -# y === OOBToken() && return nothing -# y === UndefToken() || break -# end -# return it.use -#end function scan_ssa_use!(used, @nospecialize(stmt)) if isa(stmt, SSAValue) @@ -639,11 +623,6 @@ function getindex(view::TypesView, idx) end end -start(compact::IncrementalCompact) = (compact.idx, 1) -function done(compact::IncrementalCompact, (idx, _a)::Tuple{Int, Int}) - return idx > length(compact.ir.stmts) && (compact.new_nodes_idx > length(compact.perm)) -end - function getindex(view::TypesView, idx::NewSSAValue) @assert isa(view.ir, IncrementalCompact) compact = view.ir @@ -807,12 +786,15 @@ function process_newnode!(compact, new_idx, new_node_entry, idx, active_bb, do_r active_bb += 1 finish_current_bb!(compact, old_result_idx) end - (old_result_idx == result_idx) && return next(compact, (idx, active_bb)) + (old_result_idx == result_idx) && return iterate(compact, (idx, active_bb)) return Pair{Int, Any}(old_result_idx, compact.result[old_result_idx]), (compact.idx, active_bb) end -function next(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int}) +function iterate(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int}=(compact.idx, 1)) old_result_idx = compact.result_idx + if idx > length(compact.ir.stmts) && (compact.new_nodes_idx > length(compact.perm)) + return nothing + end if length(compact.result) < old_result_idx resize!(compact, old_result_idx) end @@ -845,7 +827,7 @@ function next(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int}) active_bb += 1 finish_current_bb!(compact, old_result_idx) end - (old_result_idx == compact.result_idx) && return next(compact, (idx + 1, active_bb)) + (old_result_idx == compact.result_idx) && return iterate(compact, (idx + 1, active_bb)) compact.idx = idx + 1 if !isassigned(compact.result, old_result_idx) @assert false @@ -972,10 +954,7 @@ end function compact!(code::IRCode) compact = IncrementalCompact(code) # Just run through the iterator without any processing - state = start(compact) - while !done(compact, state) - _, state = next(compact, state) - end + foreach((args...)->nothing, compact) return finish(compact) end @@ -985,9 +964,8 @@ end bbidxiter(ir) = BBIdxIter(ir) -start(x::BBIdxIter) = (1, 1) -done(x::BBIdxIter, (idx, bb)) = (idx > length(x.ir.stmts)) -function next(x::BBIdxIter, (idx, bb)) +function iterate(x::BBIdxIter, (idx, bb)=(1, 1)) + idx > length(x.ir.stmts) && return nothing active_bb = x.ir.cfg.blocks[bb] next_bb = bb if idx == last(active_bb.stmts) diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 534106c79f2b2..f36e718674f96 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -262,12 +262,8 @@ function typeinf_work(frame::InferenceState) local pc´::Int = pc + 1 # next program-counter (after executing instruction) if pc == frame.pc´´ # need to update pc´´ to point at the new lowest instruction in W - min_pc = next(W, pc)[2] - if done(W, min_pc) - frame.pc´´ = max(min_pc, n + 1) - else - frame.pc´´ = min_pc - end + min_pc = _bits_findnext(W.bits, pc + 1) + frame.pc´´ = min_pc == -1 ? n + 1 : min_pc end delete!(W, pc) frame.currpc = pc diff --git a/base/deprecated.jl b/base/deprecated.jl index f0b0b16868631..49decc44e4c3e 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1664,6 +1664,11 @@ end # when this is removed, `isbitstype(typeof(x))` can be replaced with `isbits(x)` @deprecate isbits(@nospecialize(t::Type)) isbitstype(t) +# Special string deprecation +@deprecate start(s::AbstractString) firstindex(s) +@deprecate next(s::AbstractString, i::Integer) iterate(s, i) +@deprecate done(s::AbstractString, i::Integer) i > ncodeunits(s) + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/dict.jl b/base/dict.jl index 61bc06a2f90de..ea793e0c35479 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -136,7 +136,7 @@ function Dict(kv) try dict_with_eltype((K, V) -> Dict{K, V}, kv, eltype(kv)) catch e - if !applicable(start, kv) || !all(x->isa(x,Union{Tuple,Pair}),kv) + if !isiterable(typeof(kv)) || !all(x->isa(x,Union{Tuple,Pair}),kv) throw(ArgumentError("Dict(kv): kv needs to be an iterator of tuples or pairs")) else rethrow(e) @@ -144,16 +144,21 @@ function Dict(kv) end end -# this is a special case due to (1) allowing both Pairs and Tuples as elements, -# and (2) Pair being invariant. a bit annoying. -function grow_to!(dest::AbstractDict, itr) - out = grow_to!(empty(dest, Union{}, Union{}), itr, start(itr)) - return isempty(out) ? dest : out +function grow_to!(dest::AbstractDict{K, V}, itr) where V where K + y = iterate(itr) + y === nothing && return dest + ((k,v), st) = y + dest2 = empty(dest, typeof(k), typeof(v)) + dest2[k] = v + grow_to!(dest2, itr, st) end +# this is a special case due to (1) allowing both Pairs and Tuples as elements, +# and (2) Pair being invariant. a bit annoying. function grow_to!(dest::AbstractDict{K,V}, itr, st) where V where K - while !done(itr, st) - (k,v), st = next(itr, st) + y = iterate(itr, st) + while y !== nothing + (k,v), st = y if isa(k,K) && isa(v,V) dest[k] = v else @@ -162,6 +167,7 @@ function grow_to!(dest::AbstractDict{K,V}, itr, st) where V where K new[k] = v return grow_to!(new, itr, st) end + y = iterate(itr, st) end return dest end @@ -611,7 +617,7 @@ end function pop!(h::Dict) isempty(h) && throw(ArgumentError("dict must be non-empty")) - idx = start(h) + idx = skip_deleted_floor!(h) @inbounds key = h.keys[idx] @inbounds val = h.vals[idx] _delete!(h, idx) @@ -662,25 +668,26 @@ function skip_deleted(h::Dict, i) end return i end - -function start(t::Dict) - i = skip_deleted(t, t.idxfloor) - t.idxfloor = i - return i +function skip_deleted_floor!(h::Dict) + idx = skip_deleted(h, h.idxfloor) + h.idxfloor = idx + idx end -done(t::Dict, i) = i > length(t.vals) -@propagate_inbounds function next(t::Dict{K,V}, i) where {K,V} - return (Pair{K,V}(t.keys[i],t.vals[i]), skip_deleted(t,i+1)) + +@propagate_inbounds _iterate(t::Dict{K,V}, i) where {K,V} = i > length(t.vals) ? nothing : (Pair{K,V}(t.keys[i],t.vals[i]), i+1) +@propagate_inbounds function iterate(t::Dict) + _iterate(t, skip_deleted_floor!(t)) end +@propagate_inbounds iterate(t::Dict, i) = _iterate(t, skip_deleted(t, i)) isempty(t::Dict) = (t.count == 0) length(t::Dict) = t.count -@propagate_inbounds function next(v::KeySet{<:Any, <:Dict}, i) - return (v.dict.keys[i], skip_deleted(v.dict,i+1)) -end -@propagate_inbounds function next(v::ValueIterator{<:Dict}, i) - return (v.dict.vals[i], skip_deleted(v.dict,i+1)) +@propagate_inbounds function iterate(v::Union{KeySet{<:Any, <:Dict}, ValueIterator{<:Dict}}, + i=v.dict.idxfloor) + i = skip_deleted(v.dict, i) + i > length(v.dict.vals) && return nothing + (v isa KeySet ? v.dict.keys[i] : v.dict.vals[i], i+1) end filter!(f, d::Dict) = filter_in_one_pass!(f, d) @@ -749,11 +756,12 @@ function get(dict::ImmutableDict, key, default) end # this actually defines reverse iteration (e.g. it should not be used for merge/copy/filter type operations) -start(t::ImmutableDict) = t -next(::ImmutableDict{K,V}, t) where {K,V} = (Pair{K,V}(t.key, t.value), t.parent) -done(::ImmutableDict, t) = !isdefined(t, :parent) +function iterate(d::ImmutableDict{K,V}, t=d) where {K, V} + !isdefined(t, :parent) && return nothing + (Pair{K,V}(t.key, t.value), t.parent) +end length(t::ImmutableDict) = count(x->true, t) -isempty(t::ImmutableDict) = done(t, start(t)) +isempty(t::ImmutableDict) = !isdefined(t, :parent) empty(::ImmutableDict, ::Type{K}, ::Type{V}) where {K, V} = ImmutableDict{K,V}() _similar_for(c::Dict, ::Type{Pair{K,V}}, itr, isz) where {K, V} = empty(c, K, V) diff --git a/base/env.jl b/base/env.jl index ddcb57bda182d..574b9976cbdb5 100644 --- a/base/env.jl +++ b/base/env.jl @@ -84,15 +84,12 @@ setindex!(::EnvDict, v, k::AbstractString) = _setenv(k,string(v)) push!(::EnvDict, kv::Pair{<:AbstractString}) = setindex!(ENV, kv.second, kv.first) if Sys.iswindows() - start(hash::EnvDict) = (pos = ccall(:GetEnvironmentStringsW,stdcall,Ptr{UInt16},()); (pos,pos)) - function done(hash::EnvDict, block::Tuple{Ptr{UInt16},Ptr{UInt16}}) + GESW() = (pos = ccall(:GetEnvironmentStringsW,stdcall,Ptr{UInt16},()); (pos,pos)) + function iterate(hash::EnvDict, block::Tuple{Ptr{UInt16},Ptr{UInt16}} = GESW()) if unsafe_load(block[1]) == 0 ccall(:FreeEnvironmentStringsW, stdcall, Int32, (Ptr{UInt16},), block[2]) - return true + return nothing end - return false - end - function next(hash::EnvDict, block::Tuple{Ptr{UInt16},Ptr{UInt16}}) pos = block[1] blk = block[2] len = ccall(:wcslen, UInt, (Ptr{UInt16},), pos) @@ -106,14 +103,9 @@ if Sys.iswindows() return (Pair{String,String}(m.captures[1], m.captures[2]), (pos+(len+1)*2, blk)) end else # !windows - start(::EnvDict) = 0 - done(::EnvDict, i) = (ccall(:jl_environ, Any, (Int32,), i) === nothing) - - function next(::EnvDict, i) + function iterate(::EnvDict, i=0) env = ccall(:jl_environ, Any, (Int32,), i) - if env === nothing - throw(BoundsError()) - end + env === nothing && return nothing env = env::String m = match(r"^(.*?)=(.*)$"s, env) if m === nothing diff --git a/base/error.jl b/base/error.jl index fa117f6fc016f..27609460cedc1 100644 --- a/base/error.jl +++ b/base/error.jl @@ -167,14 +167,13 @@ rate in the interval `factor` * (1 ± `jitter`). The first element is """ ExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1) = ExponentialBackOff(n, first_delay, max_delay, factor, jitter) -start(ebo::ExponentialBackOff) = (ebo.n, min(ebo.first_delay, ebo.max_delay)) -function next(ebo::ExponentialBackOff, state) +function iterate(ebo::ExponentialBackOff, state= (ebo.n, min(ebo.first_delay, ebo.max_delay))) + state[1] < 1 && return nothing next_n = state[1]-1 curr_delay = state[2] next_delay = min(ebo.max_delay, state[2] * ebo.factor * (1.0 - ebo.jitter + (rand(Float64) * 2.0 * ebo.jitter))) (curr_delay, (next_n, next_delay)) end -done(ebo::ExponentialBackOff, state) = state[1]<1 length(ebo::ExponentialBackOff) = ebo.n eltype(::Type{ExponentialBackOff}) = Float64 @@ -197,20 +196,23 @@ retry(read, check=(s,e)->isa(e, UVError))(io, 128; all=false) """ function retry(f::Function; delays=ExponentialBackOff(), check=nothing) (args...; kwargs...) -> begin - state = start(delays) - while true + y = iterate(delays) + while y !== nothing + (delay, state) = y try return f(args...; kwargs...) catch e - done(delays, state) && rethrow(e) + y === nothing && rethrow(e) if check !== nothing result = check(state, e) state, retry_or_not = length(result) == 2 ? result : (state, result) retry_or_not || rethrow(e) end end - (delay, state) = next(delays, state) sleep(delay) + y = iterate(delays, state) end + # When delays is out, just run the function without try/catch + return f(args...; kwargs...) end end diff --git a/base/essentials.jl b/base/essentials.jl index 35a2bab7fad22..1ed515cdaa0f5 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -548,9 +548,7 @@ function length(v::SimpleVector) end firstindex(v::SimpleVector) = 1 lastindex(v::SimpleVector) = length(v) -start(v::SimpleVector) = 1 -next(v::SimpleVector,i) = (v[i],i+1) -done(v::SimpleVector,i) = (length(v) < i) +iterate(v::SimpleVector, i=1) = (length(v) < i ? nothing : (v[i], i + 1)) eltype(::Type{SimpleVector}) = Any keys(v::SimpleVector) = OneTo(length(v)) isempty(v::SimpleVector) = (length(v) == 0) @@ -699,25 +697,6 @@ julia> start([4;2;3]) """ function start end -""" - done(iter, state) -> Bool - -Test whether we are done iterating. - -# Examples -```jldoctest -julia> done(1:5, 3) -false - -julia> done(1:5, 5) -false - -julia> done(1:5, 6) -true -``` -""" -function done end - """ isempty(collection) -> Bool @@ -732,7 +711,11 @@ julia> isempty([1 2 3]) false ``` """ -isempty(itr) = done(itr, start(itr)) +function isempty(itr) + d = isdone(itr) + d !== missing && return d + iterate(itr) === nothing +end """ values(iterator) @@ -783,3 +766,108 @@ ismissing(::Missing) = true function popfirst! end function peek end + +""" + @__LINE__ -> Int + +`@__LINE__` expands to the line number of the location of the macrocall. +Returns `0` if the line number could not be determined. +""" +macro __LINE__() + return __source__.line +end + +# Just for bootstrapping purposes below +macro __FILE_SYMBOL__() + return Expr(:quote, __source__.file) +end + +# Iteration +""" + isdone(itr, state...) -> Union{Bool, Missing} + +This function provides a fast-path hint for iterator completion. +This is useful for mutable iterators that want to avoid having elements +consumed, if they are not going to be exposed to the user (e.g. to check +for done-ness in `isempty` or `zip`). Mutable iterators that want to +opt into this feature shoud define an isdone method that returns +true/false depending on whether the iterator is done or not. Stateless +iterators need not implement this function. If the result is `missing`, +callers may go ahead and compute `iterate(x, state...) === nothing` to +compute a definite answer. +""" +isdone(itr, state...) = missing + +""" + iterate(iter [, state]) -> Union{Nothing, Tuple{Any, Any}} + +Advance the iterator to obtain the next element. If no elements +remain, nothing should be returned. Otherwise, a 2-tuple of the +next element and the new iteration state should be returned. +""" +function iterate end + +# Compatibility with old iteration protocol +function iterate(x, state) + @_inline_meta + done(x, state) && return nothing + return next(x, state) +end +const old_iterate_line_prev = (@__LINE__) +iterate(x) = (@_inline_meta; iterate(x, start(x))) + +struct LegacyIterationCompat{I,T,S} + done::Bool + nextval::T + state::S + LegacyIterationCompat{I,T,S}() where {I,T,S} = new{I,T,S}(true) + LegacyIterationCompat{I,T,S}(nextval::T, state::S) where {I,T,S} = new{I,T,S}(false, nextval, state) +end + +function has_non_default_iterate(T) + world = ccall(:jl_get_world_counter, UInt, ()) + mt = Base._methods(iterate, Tuple{T}, -1, world) + # Check if this is the above method + if (mt[1][3].file == @__FILE_SYMBOL__) && (mt[1][3].line == old_iterate_line_prev + 1) + return false + end + return true +end + +const compat_start_line_prev = (@__LINE__) +function start(itr::T) where {T} + has_non_default_iterate(T) || throw(MethodError(iterate, (itr,))) + y = iterate(itr) + y === nothing && return LegacyIterationCompat{T, Union{}, Union{}}() + val, state = y + LegacyIterationCompat{T, typeof(val), typeof(state)}(val, state) +end + +function next(itr::I, state::LegacyIterationCompat{I,T,S}) where {I,T,S} + val, state = state.nextval, state.state + y = iterate(itr, state) + if y === nothing + return (val, LegacyIterationCompat{I,T,S}()) + end + nextval, state = y + val, LegacyIterationCompat{I, typeof(nextval), typeof(state)}(nextval, state) +end + +done(itr::I, state::LegacyIterationCompat{I,T,S}) where {I,T,S} = (@_inline_meta; state.done) +# This is necessary to support the above compatibility layer, +# eventually, this should just check for applicability of `iterate` +function isiterable(T)::Bool + if !has_non_default_iterate(T) + world = ccall(:jl_get_world_counter, UInt, ()) + mt = Base._methods(start, Tuple{T}, -1, world) + # Check if this is the fallback start method + if (mt[1][3].file == @__FILE_SYMBOL__) && (mt[1][3].line == compat_start_line_prev + 2) + return false + end + end + return true +end + +# This is required to avoid massive performance problems +# due to the start(s::AbstractString) deprecation. +iterate(s::AbstractString) = iterate(s, firstindex(s)) diff --git a/base/exports.jl b/base/exports.jl index 18ec3d60d7fb4..1204c0b252e7f 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -651,6 +651,7 @@ export done, next, start, + iterate, enumerate, # re-exported from Iterators zip, diff --git a/base/generator.jl b/base/generator.jl index 7dbe23bc9caf5..0ddeb30f7464c 100644 --- a/base/generator.jl +++ b/base/generator.jl @@ -39,12 +39,11 @@ Generator(::Type{T}, iter::I) where {T,I} = Generator{I,Type{T}}(T, iter) Generator(::Type{T}, I1, I2, Is...) where {T} = Generator(a->T(a...), zip(I1, I2, Is...)) -start(g::Generator) = (@_inline_meta; start(g.iter)) -done(g::Generator, s) = (@_inline_meta; done(g.iter, s)) -function next(g::Generator, s) +function iterate(g::Generator, s...) @_inline_meta - v, s2 = next(g.iter, s) - g.f(v), s2 + y = iterate(g.iter, s...)::Union{Tuple{Any, Any}, Nothing} + y === nothing && return nothing + g.f(y[1]), y[2] end length(g::Generator) = length(g.iter) diff --git a/base/indices.jl b/base/indices.jl index 824ec7ff99365..74dc971ef1c17 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -288,9 +288,7 @@ length(S::Slice) = first(S.indices) == 1 ? length(S.indices) : errmsg(S) unsafe_length(S::Slice) = first(S.indices) == 1 ? unsafe_length(S.indices) : errmsg(S) getindex(S::Slice, i::Int) = (@_inline_meta; @boundscheck checkbounds(S, i); i) show(io::IO, r::Slice) = print(io, "Base.Slice(", r.indices, ")") -start(S::Slice) = start(S.indices) -next(S::Slice, s) = next(S.indices, s) -done(S::Slice, s) = done(S.indices, s) +iterate(S::Slice, s...) = iterate(S.indices, s...) """ LinearIndices(A::AbstractArray) @@ -368,13 +366,8 @@ function getindex(iter::LinearIndices, i::AbstractRange{<:Integer}) end # More efficient iteration — predominantly for non-vector LinearIndices # but one-dimensional LinearIndices must be special-cased to support OffsetArrays -start(iter::LinearIndices{1}) = start(iter.indices[1]) -next(iter::LinearIndices{1}, s) = next(iter.indices[1], s) -done(iter::LinearIndices{1}, s) = done(iter.indices[1], s) -start(::LinearIndices) = 1 -next(::LinearIndices, i) = i, i+1 -done(iter::LinearIndices, i) = i > length(iter) - +iterate(iter::LinearIndices{1}, s...) = iterate(iter.indices[1], s...) +iterate(iter::LinearIndices, i=1) = i > length(iter) ? nothing : (i, i+1) # Needed since firstindex and lastindex are defined in terms of LinearIndices first(iter::LinearIndices) = 1 diff --git a/base/io.jl b/base/io.jl index d9371251f1f08..ada7cb90599a9 100644 --- a/base/io.jl +++ b/base/io.jl @@ -890,13 +890,10 @@ function eachline(filename::AbstractString; chomp=nothing, keep::Bool=false) EachLine(s, ondone=()->close(s), keep=keep)::EachLine end -start(itr::EachLine) = nothing -function done(itr::EachLine, ::Nothing) - eof(itr.stream) || return false - itr.ondone() - true +function iterate(itr::EachLine, state=nothing) + eof(itr.stream) && return (itr.ondone(); nothing) + (readline(itr.stream, keep=itr.keep), nothing) end -next(itr::EachLine, ::Nothing) = (readline(itr.stream, keep=itr.keep), nothing) eltype(::Type{EachLine}) = String diff --git a/base/iterators.jl b/base/iterators.jl index bdb307f2debbe..c7097e3ed424b 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -12,18 +12,21 @@ using .Base: @inline, Pair, AbstractDict, IndexLinear, IndexCartesian, IndexStyle, AbstractVector, Vector, tail, tuple_type_head, tuple_type_tail, tuple_type_cons, SizeUnknown, HasLength, HasShape, IsInfinite, EltypeUnknown, HasEltype, OneTo, @propagate_inbounds, Generator, AbstractRange, - LinearIndices, (:), |, +, -, !==, !, <=, < + LinearIndices, (:), |, +, -, !==, !, <=, <, missing import .Base: - start, done, next, first, last, + first, last, isempty, length, size, axes, ndims, eltype, IteratorSize, IteratorEltype, haskey, keys, values, pairs, - getindex, setindex!, get, popfirst!, - peek + getindex, setindex!, get, iterate, + popfirst!, isdone, peek export enumerate, zip, rest, countfrom, take, drop, cycle, repeated, product, flatten, partition +tail_if_any(::Tuple{}) = () +tail_if_any(x::Tuple) = tail(x) + _min_length(a, b, ::IsInfinite, ::IsInfinite) = min(length(a),length(b)) # inherit behaviour, error _min_length(a, b, A, ::IsInfinite) = length(a) _min_length(a, b, ::IsInfinite, B) = length(b) @@ -43,7 +46,7 @@ and_iteratoreltype(iel::T, ::T) where {T} = iel and_iteratoreltype(a, b) = EltypeUnknown() ## Reverse-order iteration for arrays and other collections. Collections -## should implement start/next/done etcetera if possible/practical. +## should implement iterate etcetera if possible/practical. """ Iterators.reverse(itr) @@ -55,8 +58,8 @@ order to reverse it; see [`Base.reverse`](@ref) for an eager implementation. Not all iterator types `T` support reverse-order iteration. If `T` doesn't, then iterating over `Iterators.reverse(itr::T)` will throw a [`MethodError`](@ref) -because of the missing [`start`](@ref), [`next`](@ref), and [`done`](@ref) -methods for `Iterators.Reverse{T}`. (To implement these methods, the original iterator +because of the missing [`iterate`](@ref) methods for `Iterators.Reverse{T}`. +(To implement these methods, the original iterator `itr::T` can be obtained from `r = Iterators.reverse(itr)` by `r.itr`.) # Examples @@ -83,9 +86,12 @@ last(r::Reverse) = first(r.itr) # the first shall be last first(r::Reverse) = last(r.itr) # and the last shall be first # reverse-order array iterators: assumes more-specialized Reverse for eachindex -@inline start(A::Reverse{<:AbstractArray}) = (itr = reverse(eachindex(A.itr)); (itr, start(itr))) -@propagate_inbounds next(A::Reverse{<:AbstractArray}, i) = ((idx, s) = next(i[1], i[2]); (A.itr[idx], (i[1], s))) -@propagate_inbounds done(A::Reverse{<:AbstractArray}, i) = done(i[1], i[2]) +@propagate_inbounds function iterate(A::Reverse{<:AbstractArray}, state=(reverse(eachindex(A.itr)),)) + y = iterate(state...) + y === nothing && return y + idx, itrs = y + (A.itr[idx], (state[1], itrs)) +end reverse(R::AbstractRange) = Base.reverse(R) # copying ranges is cheap reverse(G::Generator) = Generator(G.f, reverse(G.iter)) @@ -93,10 +99,7 @@ reverse(r::Reverse) = r.itr reverse(x::Union{Number,AbstractChar}) = x reverse(p::Pair) = Base.reverse(p) # copying pairs is cheap -start(r::Reverse{<:Tuple}) = length(r.itr) -done(r::Reverse{<:Tuple}, i::Int) = i < 1 -next(r::Reverse{<:Tuple}, i::Int) = (r.itr[i], i-1) - +iterate(r::Reverse{<:Tuple}, i::Int = length(r.itr)) = i < 1 ? nothing : (r.itr[i], i-1) # enumerate @@ -131,27 +134,28 @@ enumerate(iter) = Enumerate(iter) length(e::Enumerate) = length(e.itr) size(e::Enumerate) = size(e.itr) -@inline start(e::Enumerate) = (1, start(e.itr)) -@propagate_inbounds function next(e::Enumerate, state) - n = next(e.itr,state[2]) - (state[1],n[1]), (state[1]+1,n[2]) +@propagate_inbounds function iterate(e::Enumerate, state=(1,)) + i, rest = state[1], tail(state) + n = iterate(e.itr, rest...) + n === nothing && return n + (i, n[1]), (i+1, n[2]) end -@inline done(e::Enumerate, state) = done(e.itr, state[2]) eltype(::Type{Enumerate{I}}) where {I} = Tuple{Int, eltype(I)} IteratorSize(::Type{Enumerate{I}}) where {I} = IteratorSize(I) IteratorEltype(::Type{Enumerate{I}}) where {I} = IteratorEltype(I) -@inline function start(r::Reverse{<:Enumerate}) +@inline function iterate(r::Reverse{<:Enumerate}) ri = reverse(r.itr.itr) - return (length(ri), ri, start(ri)) + iterate(r, (length(ri), ri)) end -@inline function next(r::Reverse{<:Enumerate}, state) - n = next(state[2],state[3]) - (state[1],n[1]), (state[1]-1,state[2],n[2]) +@inline function iterate(r::Reverse{<:Enumerate}, state) + i, ri, rest = state[1], state[2], tail(tail(state)) + n = iterate(ri, rest...) + n === nothing && return n + (i, n[1]), (i-1, ri, n[2]) end -@inline done(r::Reverse{<:Enumerate}, state) = state[1] < 1 """ Iterators.Pairs(values, keys) <: AbstractDict{eltype(keys), eltype(values)} @@ -222,16 +226,17 @@ pairs(tuple::Tuple) = Pairs(tuple, keys(tuple)) pairs(nt::NamedTuple) = Pairs(nt, keys(nt)) # pairs(v::Pairs) = v # listed for reference, but already defined from being an AbstractDict -length(v::Pairs) = length(v.itr) +length(v::Pairs) = length(v.itr) axes(v::Pairs) = axes(v.itr) -size(v::Pairs) = size(v.itr) -@inline start(v::Pairs) = start(v.itr) -@propagate_inbounds function next(v::Pairs{K, V}, state) where {K, V} - indx, n = next(v.itr, state) +size(v::Pairs) = size(v.itr) +@propagate_inbounds function iterate(v::Pairs{K, V}, state...) where {K, V} + x = iterate(v.itr, state...) + x === nothing && return x + indx, n = x item = v.data[indx] return (Pair{K, V}(indx, item), n) end -@inline done(v::Pairs, state) = done(v.itr, state) +@inline isdone(v::Pairs, state...) = isdone(v.itr, state...) IteratorSize(::Type{<:Pairs{<:Any, <:Any, I}}) where {I} = IteratorSize(I) IteratorSize(::Type{<:Pairs{<:Any, <:Any, <:Base.AbstractUnitRange, <:Tuple}}) = HasLength() @@ -265,12 +270,12 @@ length(z::Zip1) = length(z.a) size(z::Zip1) = size(z.a) axes(z::Zip1) = axes(z.a) eltype(::Type{Zip1{I}}) where {I} = Tuple{eltype(I)} -@inline start(z::Zip1) = start(z.a) -@propagate_inbounds function next(z::Zip1, st) - n = next(z.a,st) +@propagate_inbounds function iterate(z::Zip1, state...) + n = iterate(z.a, state...) + n === nothing && return n return ((n[1],), n[2]) end -@inline done(z::Zip1, st) = done(z.a,st) +@inline isdone(z::Zip1, state...) = isdone(z.a, state...) IteratorSize(::Type{Zip1{I}}) where {I} = IteratorSize(I) IteratorEltype(::Type{Zip1{I}}) where {I} = IteratorEltype(I) @@ -284,13 +289,43 @@ length(z::Zip2) = _min_length(z.a, z.b, IteratorSize(z.a), IteratorSize(z.b)) size(z::Zip2) = promote_shape(size(z.a), size(z.b)) axes(z::Zip2) = promote_shape(axes(z.a), axes(z.b)) eltype(::Type{Zip2{I1,I2}}) where {I1,I2} = Tuple{eltype(I1), eltype(I2)} -@inline start(z::Zip2) = (start(z.a), start(z.b)) -@propagate_inbounds function next(z::Zip2, st) - n1 = next(z.a,st[1]) - n2 = next(z.b,st[2]) - return ((n1[1], n2[1]), (n1[2], n2[2])) +@inline isdone(z::Zip2) = isdone(z.a) | isdone(z.b) +@inline isdone(z::Zip2, (sa, sb)::Tuple{Any, Any}) = isdone(z.a, sa) | isdone(z.b, sb) +function zip_iterate(a, b, sta, stb) # the states are either Tuple{} or Tuple{Any} + da, db = isdone(a), isdone(b) + da === true && return nothing + db === true && return nothing + if da === missing + ya = iterate(a, sta...) + ya === nothing && return nothing + end + if db === missing + yb = iterate(b, stb...) + yb === nothing && return nothing + end + if da === false + ya = iterate(a, sta...) + ya === nothing && return nothing + end + if db === false + yb = iterate(b, stb...) + yb === nothing && return nothing + end + return (ya, yb) +end +let interleave(a, b) = ((a[1], b[1]), (a[2], b[2])) + global iterate + @propagate_inbounds function iterate(z::Zip2) + ys = zip_iterate(z.a, z.b, (), ()) + ys === nothing && return nothing + return interleave(ys...) + end + @propagate_inbounds function iterate(z::Zip2, st::Tuple{Any, Any}) + ys = zip_iterate(z.a, z.b, (st[1],), (st[2],)) + ys === nothing && return nothing + return interleave(ys...) + end end -@inline done(z::Zip2, st) = done(z.a,st[1]) | done(z.b,st[2]) IteratorSize(::Type{Zip2{I1,I2}}) where {I1,I2} = zip_iteratorsize(IteratorSize(I1),IteratorSize(I2)) IteratorEltype(::Type{Zip2{I1,I2}}) where {I1,I2} = and_iteratoreltype(IteratorEltype(I1),IteratorEltype(I2)) @@ -334,13 +369,21 @@ length(z::Zip) = _min_length(z.a, z.z, IteratorSize(z.a), IteratorSize(z.z)) size(z::Zip) = promote_shape(size(z.a), size(z.z)) axes(z::Zip) = promote_shape(axes(z.a), axes(z.z)) eltype(::Type{Zip{I,Z}}) where {I,Z} = tuple_type_cons(eltype(I), eltype(Z)) -@inline start(z::Zip) = tuple(start(z.a), start(z.z)) -@propagate_inbounds function next(z::Zip, st) - n1 = next(z.a, st[1]) - n2 = next(z.z, st[2]) - (tuple(n1[1], n2[1]...), (n1[2], n2[2])) +@inline isdone(z::Zip) = isdone(z.a) | isdone(z.z) +@inline isdone(z::Zip, (sa, sz)) = isdone(z.a, sa) | isdone(z.a, sz) +let interleave(a, b) = ((a[1], b[1]...), (a[2], b[2])) + global iterate + @propagate_inbounds function iterate(z::Zip) + ys = zip_iterate(z.a, z.z, (), ()) + ys === nothing && return nothing + return interleave(ys...) + end + @propagate_inbounds function iterate(z::Zip, st::Tuple{Any, Any}) + ys = zip_iterate(z.a, z.z, (st[1],), (st[2],)) + ys === nothing && return nothing + return interleave(ys...) + end end -@inline done(z::Zip, st) = done(z.a,st[1]) | done(z.z,st[2]) IteratorSize(::Type{Zip{I1,I2}}) where {I1,I2} = zip_iteratorsize(IteratorSize(I1),IteratorSize(I2)) IteratorEltype(::Type{Zip{I1,I2}}) where {I1,I2} = and_iteratoreltype(IteratorEltype(I1),IteratorEltype(I2)) @@ -384,34 +427,17 @@ julia> foreach(println, f) """ filter(flt, itr) = Filter(flt, itr) -start(f::Filter) = start_filter(f.flt, f.itr) -function start_filter(pred, itr) - s = start(itr) - while !done(itr,s) - v,t = next(itr,s) - if pred(v) - return (false, v, t) - end - s=t - end - (true,) -end - -next(f::Filter, s) = advance_filter(f.flt, f.itr, s) -function advance_filter(pred, itr, st) - _, v, s = st - while !done(itr,s) - w,t = next(itr,s) - if pred(w) - return v, (false, w, t) +function iterate(f::Filter, state...) + y = iterate(f.itr, state...) + while y !== nothing + if f.flt(y[1]) + return y end - s=t + y = iterate(f.itr, y[2]) end - v, (true, v, s) + nothing end -done(f::Filter, s) = s[1] - eltype(::Type{Filter{F,I}}) where {F,I} = eltype(I) IteratorEltype(::Type{Filter{F,I}}) where {F,I} = IteratorEltype(I) IteratorSize(::Type{<:Filter}) = SizeUnknown() @@ -440,6 +466,7 @@ julia> collect(Iterators.rest([1,2,3,4], 2)) ``` """ rest(itr,state) = Rest(itr,state) +rest(itr) = itr """ peel(iter) @@ -460,15 +487,14 @@ julia> collect(rest) ``` """ function peel(itr) - s = start(itr) - done(itr, s) && throw(BoundsError()) - val, s = next(itr, s) + y = iterate(itr) + y === nothing && throw(BoundsError()) + val, s = y val, rest(itr, s) end -start(i::Rest) = i.st -@propagate_inbounds next(i::Rest, st) = next(i.itr, st) -done(i::Rest, st) = done(i.itr, st) +@propagate_inbounds iterate(i::Rest, st=i.st) = iterate(i.itr, st) +isdone(i::Rest, st...) = isdone(i.itr, st...) eltype(::Type{<:Rest{I}}) where {I} = eltype(I) IteratorEltype(::Type{<:Rest{I}}) where {I} = IteratorEltype(I) @@ -505,9 +531,7 @@ countfrom() = Count(1, 1) eltype(::Type{Count{S}}) where {S} = S -start(it::Count) = it.start -next(it::Count, state) = (state, state + it.step) -done(it::Count, state) = false +iterate(it::Count, state=it.start) = (state, state + it.step) IteratorSize(::Type{<:Count}) = IsInfinite() @@ -557,18 +581,15 @@ take_iteratorsize(a) = HasLength() take_iteratorsize(::SizeUnknown) = SizeUnknown() IteratorSize(::Type{Take{I}}) where {I} = take_iteratorsize(IteratorSize(I)) length(t::Take) = _min_length(t.xs, 1:t.n, IteratorSize(t.xs), HasLength()) - -start(it::Take) = (it.n, start(it.xs)) - -@propagate_inbounds function next(it::Take, state) - n, xs_state = state - v, xs_state = next(it.xs, xs_state) - return v, (n - 1, xs_state) -end - -function done(it::Take, state) - n, xs_state = state - return n <= 0 || done(it.xs, xs_state) +isdone(t::Take) = isdone(t.xs) +isdone(t::Take, state) = (state[1] <= 0) | isdone(t.xs, tail(state)) + +@propagate_inbounds function iterate(it::Take, state=(it.n,)) + n, rest = state[1], tail(state) + n <= 0 && return nothing + y = iterate(it.xs, rest...) + y === nothing && return nothing + return y[1], (n - 1, y[2]) end # Drop -- iterator through all but the first n elements @@ -619,20 +640,16 @@ drop_iteratorsize(::IsInfinite) = IsInfinite() IteratorSize(::Type{Drop{I}}) where {I} = drop_iteratorsize(IteratorSize(I)) length(d::Drop) = _diff_length(d.xs, 1:d.n, IteratorSize(d.xs), HasLength()) -function start(it::Drop) - xs_state = start(it.xs) +function iterate(it::Drop) + y = iterate(it.xs) for i in 1:it.n - if done(it.xs, xs_state) - break - end - - _, xs_state = next(it.xs, xs_state) + y === nothing && return y + y = iterate(it.xs, y[2]) end - xs_state + y end - -@propagate_inbounds next(it::Drop, state) = next(it.xs, state) -done(it::Drop, state) = done(it.xs, state) +iterate(it::Drop, state) = iterate(it.xs, state) +isdone(it::Drop, state) = isdone(it.xs, state) # Cycle an iterator forever @@ -644,6 +661,7 @@ end cycle(iter) An iterator that cycles through `iter` forever. +N.B. if `iter` is empty, so is `cycle(iter)`. # Examples ```jldoctest @@ -660,22 +678,15 @@ eltype(::Type{Cycle{I}}) where {I} = eltype(I) IteratorEltype(::Type{Cycle{I}}) where {I} = IteratorEltype(I) IteratorSize(::Type{Cycle{I}}) where {I} = IsInfinite() -function start(it::Cycle) - s = start(it.xs) - return s, done(it.xs, s) +iterate(it::Cycle) = iterate(it.xs) +isdone(it::Cycle) = isdone(it.xs) +isdone(it::Cycle, state) = false +function iterate(it::Cycle, state) + y = iterate(it.xs, state) + y === nothing && return iterate(it) + y end -function next(it::Cycle, state) - s, d = state - if done(it.xs, s) - s = start(it.xs) - end - v, s = next(it.xs, s) - return v, (s, false) -end - -done(it::Cycle, state) = state[2] - reverse(it::Cycle) = Cycle(reverse(it.xs)) # Repeated - repeat an object infinitely many times @@ -707,9 +718,7 @@ repeated(x, n::Integer) = take(repeated(x), Int(n)) eltype(::Type{Repeated{O}}) where {O} = O -start(it::Repeated) = nothing -next(it::Repeated, state) = (it.x, nothing) -done(it::Repeated, state) = false +iterate(it::Repeated, state...) = (it.x, nothing) IteratorSize(::Type{<:Repeated}) = IsInfinite() IteratorEltype(::Type{<:Repeated}) = HasEltype() @@ -730,7 +739,7 @@ changes the fastest. # Examples ```jldoctest -julia> collect(Iterators.product(1:2,3:5)) +julia> collect(Iterators.product(1:2, 3:5)) 2×3 Array{Tuple{Int64,Int64},2}: (1, 3) (1, 4) (1, 5) (2, 3) (2, 4) (2, 5) @@ -786,76 +795,54 @@ _prod_eltype(::Type{Tuple{}}) = Tuple{} _prod_eltype(::Type{I}) where {I<:Tuple} = Base.tuple_type_cons(eltype(tuple_type_head(I)),_prod_eltype(tuple_type_tail(I))) -start(::ProductIterator{Tuple{}}) = false -next(::ProductIterator{Tuple{}}, state) = (), true -done(::ProductIterator{Tuple{}}, state) = state - -function start(P::ProductIterator) - iterators = P.iterators - iter1 = first(iterators) - state1 = start(iter1) - d, states, nvalues = _prod_start(tail(iterators)) - d |= done(iter1, state1) - return (d, (state1, states...), nvalues) +iterate(::ProductIterator{Tuple{}}) = (), true +iterate(::ProductIterator{Tuple{}}, state) = nothing + +@inline isdone(P::ProductIterator) = any(isdone, P.iterators) +@inline function _pisdone(iters, states) + iter1 = first(iters) + done1 = isdone(iter1, first(states)) # check step + done1 === true || return done1 # false or missing + done1 = isdone(iter1) # check restart + done1 === true || return done1 # false or missing + return _pisdone(tail(iters), tail(states)) # check tail end -function next(P::ProductIterator, state) - iterators = P.iterators - d, states, nvalues = state - iter1 = first(iterators) - value1, state1 = next(iter1, states[1]) - tailstates = tail(states) - values = (value1, map(get, nvalues)...) # safe if not done(P, state) - if done(iter1, state1) - d, tailstates, nvalues = _prod_next(tail(iterators), tailstates, nvalues) - if !d # only restart iter1 if not completely done - state1 = start(iter1) - end - end - return values, (d, (state1, tailstates...), nvalues) +@inline isdone(P::ProductIterator, states) = _pisdone(P.iterators, states) + +@inline _piterate() = () +@inline function _piterate(iter1, rest...) + next = iterate(iter1) + next === nothing && return nothing + restnext = _piterate(rest...) + restnext === nothing && return nothing + return (next, restnext...) end -done(P::ProductIterator, state) = state[1] - -struct MaybeValue{T} - x::T - MaybeValue{T}() where {T} = new{T}() - MaybeValue{T}(x::T) where {T} = new{T}(x) +@inline function iterate(P::ProductIterator) + isdone(P) === true && return nothing + next = _piterate(P.iterators...) + next === nothing && return nothing + return (map(x -> x[1], next), next) end -get(v::MaybeValue) = v.x - -_prod_start(iterators::Tuple{}) = false, (), () -function _prod_start(iterators) - iter1 = first(iterators) - state1 = start(iter1) - d, tailstates, tailnvalues = _prod_start(tail(iterators)) - if done(iter1, state1) - d = true - nvalue1 = MaybeValue{eltype(iter1)}() - else - value1, state1 = next(iter1, state1) - nvalue1 = MaybeValue{eltype(iter1)}(value1) +@inline _piterate1(::Tuple{}, ::Tuple{}) = nothing +@inline function _piterate1(iters, states) + iter1 = first(iters) + next = iterate(iter1, first(states)[2]) + restnext = tail(states) + if next === nothing + isdone(iter1) === true && return nothing + restnext = _piterate1(tail(iters), restnext) + restnext === nothing && return nothing + next = iterate(iter1) + next === nothing && return nothing end - return (d, (state1, tailstates...), (nvalue1, tailnvalues...)) + return (next, restnext...) end - -_prod_next(iterators::Tuple{}, states, nvalues) = true, (), () -function _prod_next(iterators, states, nvalues) - iter1 = first(iterators) - state1 = first(states) - if !done(iter1, state1) - value1, state1 = next(iter1, state1) - nvalue1 = MaybeValue{eltype(iter1)}(value1) - return false, (state1, tail(states)...), (nvalue1, tail(nvalues)...) - else - d, tailstates, tailnvalues = _prod_next(tail(iterators), tail(states), tail(nvalues)) - if d # all iterators are done - nvalue1 = MaybeValue{eltype(iter1)}() - else - value1, state1 = next(iter1, start(iter1)) # iter cannot be done immediately - nvalue1 = MaybeValue{eltype(iter1)}(value1) - end - return d, (state1, tailstates...), (nvalue1, tailnvalues...) - end +@inline function iterate(P::ProductIterator, states) + isdone(P, states) === true && return nothing + next = _piterate1(P.iterators, states) + next === nothing && return nothing + return (map(x -> x[1], next), next) end reverse(p::ProductIterator) = ProductIterator(map(reverse, p.iterators)) @@ -908,34 +895,14 @@ flatten_length(f, T) = throw(ArgumentError( "Iterates of the argument to Flatten are not known to have constant length")) length(f::Flatten{I}) where {I} = flatten_length(f, eltype(I)) -function start(f::Flatten) - local inner, s2 - s = start(f.it) - d = done(f.it, s) - # this is a simple way to make this function type stable - d && throw(ArgumentError("argument to Flatten must contain at least one iterator")) - while !d - inner, s = next(f.it, s) - s2 = start(inner) - !done(inner, s2) && break - d = done(f.it, s) +@propagate_inbounds function iterate(f::Flatten, state=()) + if state !== () + y = iterate(tail(state)...) + y !== nothing && return (y[1], (state[1], state[2], y[2])) end - return s, inner, s2 -end - -@propagate_inbounds function next(f::Flatten, state) - s, inner, s2 = state - val, s2 = next(inner, s2) - while done(inner, s2) && !done(f.it, s) - inner, s = next(f.it, s) - s2 = start(inner) - end - return val, (s, inner, s2) -end - -@inline function done(f::Flatten, state) - s, inner, s2 = state - return done(f.it, s) && done(inner, s2) + x = (state === () ? iterate(f.it) : iterate(f.it, state[1])) + x === nothing && return nothing + iterate(f, (x[2], x[1])) end reverse(f::Flatten) = Flatten(reverse(itr) for itr in reverse(f.it)) @@ -976,24 +943,33 @@ function length(itr::PartitionIterator) return div(l, itr.n) + ((mod(l, itr.n) > 0) ? 1 : 0) end -start(itr::PartitionIterator) = start(itr.c) - -done(itr::PartitionIterator, state) = done(itr.c, state) - -function next(itr::PartitionIterator{<:Vector}, state) +function iterate(itr::PartitionIterator{<:Vector}, state=1) + iterate(itr.c, state) === nothing && return nothing l = state r = min(state + itr.n-1, length(itr.c)) return view(itr.c, l:r), r + 1 end -function next(itr::PartitionIterator, state) +struct IterationCutShort; end + +function iterate(itr::PartitionIterator, state...) v = Vector{eltype(itr.c)}(undef, itr.n) + # This is necessary to remember whether we cut the + # last element short. In such cases, we do return that + # element, but not the next one + state === (IterationCutShort(),) && return nothing i = 0 - while !done(itr.c, state) && i < itr.n + y = iterate(itr.c, state...) + while y !== nothing i += 1 - v[i], state = next(itr.c, state) + v[i] = y[1] + if i >= itr.n + break + end + y = iterate(itr.c, y[2]) end - return resize!(v, i), state + i === 0 && return nothing + return resize!(v, i), y === nothing ? IterationCutShort() : y[2] end """ @@ -1054,46 +1030,42 @@ mutable struct Stateful{T, VS} nextvalstate::Union{VS, Nothing} taken::Int @inline function Stateful(itr::T) where {T} - state = start(itr) - VS = fixpoint_iter_type(T, Union{}, typeof(state)) - new{T, VS}(itr, done(itr, state) ? nothing : next(itr, state)::VS, 0) + VS = approx_iter_type(T) + new{T, VS}(itr, iterate(itr)::VS, 0) end end function reset!(s::Stateful{T,VS}, itr::T) where {T,VS} s.itr = itr - state = start(itr) - if done(itr, state) - s.nextvalstate = nothing - else - s.nextvalstate = next(itr, state)::VS - end + s.nextvalstate = iterate(itr) s.taken = 0 s end if Base === Core.Compiler - fixpoint_iter_type(a, b, c) = Any + approx_iter_type(a::Type) = Any else # Try to find an appropriate type for the (value, state tuple), # by doing a recursive unrolling of the iteration protocol up to # fixpoint. - function fixpoint_iter_type(itrT::Type, valT::Type, stateT::Type) - nextvalstate = Base._return_type(next, Tuple{itrT, stateT}) - nextvalstate <: Tuple{Any, Any} || return Any - nextvalstate = Tuple{ - typejoin(valT, fieldtype(nextvalstate, 1)), - typejoin(stateT, fieldtype(nextvalstate, 2))} - return (Tuple{valT, stateT} == nextvalstate ? nextvalstate : - fixpoint_iter_type(itrT, - fieldtype(nextvalstate, 1), - fieldtype(nextvalstate, 2))) + approx_iter_type(itrT::Type) = _approx_iter_type(itrT, Base._return_type(iterate, Tuple{itrT})) + # Not actually called, just passed to return type to avoid + # having to typesubtract + function doiterate(itr, valstate::Union{Nothing, Tuple{Any, Any}}) + valstate === nothing && return nothing + iterate(itr, tail(valstate)) + end + function _approx_iter_type(itrT::Type, vstate::Type) + vstate <: Union{Nothing, Tuple{Any, Any}} || return Any + vstate <: Union{} && return Union{} + nextvstate = Base._return_type(doiterate, Tuple{itrT, vstate}) + return (nextvstate <: vstate ? vstate : Any) end end convert(::Type{Stateful}, itr) = Stateful(itr) -@inline isempty(s::Stateful) = s.nextvalstate === nothing +@inline isdone(s::Stateful, st=nothing) = s.nextvalstate === nothing @inline function popfirst!(s::Stateful) vs = s.nextvalstate @@ -1101,17 +1073,14 @@ convert(::Type{Stateful}, itr) = Stateful(itr) throw(EOFError()) else val, state = vs - # Until the optimizer can handle setproperty! better here, use explicit setfield! - setfield!(s, :nextvalstate, done(s.itr, state) ? nothing : next(s.itr, state)) + s.nextvalstate = iterate(s.itr, state) s.taken += 1 return val end end @inline peek(s::Stateful, sentinel=nothing) = s.nextvalstate !== nothing ? s.nextvalstate[1] : sentinel -@inline start(s::Stateful) = nothing -@inline next(s::Stateful, state) = popfirst!(s), nothing -@inline done(s::Stateful, state) = isempty(s) +@inline iterate(s::Stateful, state=nothing) = s.nextvalstate === nothing ? nothing : (popfirst!(s), nothing) IteratorSize(::Type{Stateful{VS,T}} where VS) where {T} = isa(IteratorSize(T), SizeUnknown) ? SizeUnknown() : HasLength() eltype(::Type{Stateful{VS, T}} where VS) where {T} = eltype(T) diff --git a/base/loading.jl b/base/loading.jl index 08a55b8c01405..63bb449bacf69 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1407,16 +1407,6 @@ function stale_cachefile(modpath::String, cachefile::String) end end -""" - @__LINE__ -> Int - -`@__LINE__` expands to the line number of the location of the macrocall. -Returns `0` if the line number could not be determined. -""" -macro __LINE__() - return __source__.line -end - """ @__FILE__ -> AbstractString diff --git a/base/logging.jl b/base/logging.jl index 55726c6c6d4d6..48f7bc9eb07c7 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -203,7 +203,7 @@ end macro _sourceinfo() esc(quote (__module__, - __source__.file == nothing ? "?" : String(__source__.file), + __source__.file === nothing ? "?" : String(__source__.file), __source__.line) end) end diff --git a/base/math.jl b/base/math.jl index 374268cae902b..315229eb1437b 100644 --- a/base/math.jl +++ b/base/math.jl @@ -976,4 +976,12 @@ include("special/gamma.jl") include("special/rem_pio2.jl") include("special/log.jl") +# `missing` definitions for functions in this module +for f in (:(acos), :(acosh), :(asin), :(asinh), :(atan), :(atanh), + :(sin), :(sinh), :(cos), :(cosh), :(tan), :(tanh), + :(exp), :(exp2), :(expm1), :(log), :(log10), :(log1p), + :(log2), :(exponent), :(sqrt), :(gamma), :(lgamma)) + @eval $(f)(::Missing) = missing +end + end # module diff --git a/base/meta.jl b/base/meta.jl index 62b7b89a2dde9..b3dbdf2e5e1e3 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -165,7 +165,7 @@ function parse(str::AbstractString; raise::Bool=true, depwarn::Bool=true) if isa(ex,Expr) && ex.head === :error return ex end - if !done(str, pos) + if pos <= ncodeunits(str) raise && throw(ParseError("extra token after end of expression")) return Expr(:error, "extra token after end of expression") end diff --git a/base/missing.jl b/base/missing.jl index dd6ec8d8f0a7a..8c876f77622e3 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -18,6 +18,8 @@ end showerror(io::IO, ex::MissingException) = print(io, "MissingException: ", ex.msg) + + nonmissingtype(::Type{Union{T, Missing}}) where {T} = T nonmissingtype(::Type{Missing}) = Union{} nonmissingtype(::Type{T}) where {T} = T @@ -66,17 +68,13 @@ isless(::Any, ::Missing) = true # Unary operators/functions for f in (:(!), :(~), :(+), :(-), :(identity), :(zero), :(one), :(oneunit), - :(abs), :(abs2), :(sign), :(real), :(imag), - :(acos), :(acosh), :(asin), :(asinh), :(atan), :(atanh), - :(sin), :(sinh), :(cos), :(cosh), :(tan), :(tanh), - :(exp), :(exp2), :(expm1), :(log), :(log10), :(log1p), - :(log2), :(Math.exponent), :(sqrt), :(Math.gamma), :(Math.lgamma), - :(iseven), :(ispow2), :(isfinite), :(isinf), :(isodd), + :(isfinite), :(isinf), :(isodd), :(isinteger), :(isreal), :(isnan), - :(iszero), :(transpose), :(adjoint), :(float), :(conj)) - @eval $(f)(::Missing) = missing + :(iszero), :(transpose), :(adjoint), :(float), :(conj), + :(abs), :(abs2), :(iseven), :(ispow2), + :(real), :(imag), :(sign)) + @eval ($f)(::Missing) = missing end - for f in (:(Base.zero), :(Base.one), :(Base.oneunit)) @eval function $(f)(::Type{Union{T, Missing}}) where T T === Any && throw(MethodError($f, (Any,))) # To prevent StackOverflowError @@ -178,45 +176,10 @@ end IteratorSize(::Type{<:SkipMissing}) = SizeUnknown() IteratorEltype(::Type{SkipMissing{T}}) where {T} = IteratorEltype(T) eltype(::Type{SkipMissing{T}}) where {T} = nonmissingtype(eltype(T)) -# Fallback implementation for general iterables: we cannot access a value twice, -# so after finding the next non-missing element in start() or next(), we have to -# pass it in the iterator state, which introduces a type instability since the value -# is missing if the input does not contain any non-missing element. -@inline function Base.start(itr::SkipMissing) - s = start(itr.x) - v = missing - @inbounds while !done(itr.x, s) && v isa Missing - v, s = next(itr.x, s) - end - (v, s) -end -@inline Base.done(itr::SkipMissing, state) = ismissing(state[1]) && done(itr.x, state[2]) -@inline function Base.next(itr::SkipMissing, state) - v1, s = state - v2 = missing - @inbounds while !done(itr.x, s) && v2 isa Missing - v2, s = next(itr.x, s) - end - (v1, (v2, s)) -end -# Optimized implementation for AbstractArray, relying on the ability to access x[i] twice: -# once in done() to find the next non-missing entry, and once in next() to return it. -# This works around the type instability problem of the generic fallback. -@inline function _next_nonmissing_ind(x::AbstractArray, s) - idx = eachindex(x) - @inbounds while !done(idx, s) - i, new_s = next(idx, s) - x[i] isa Missing || break - s = new_s +function Base.iterate(itr::SkipMissing, state...) + y = iterate(itr.x, state...) + while y !== nothing && y[1] isa Missing + y = iterate(itr.x, y[2]) end - s -end -@inline Base.start(itr::SkipMissing{<:AbstractArray}) = - _next_nonmissing_ind(itr.x, start(eachindex(itr.x))) -@inline Base.done(itr::SkipMissing{<:AbstractArray}, state) = - done(eachindex(itr.x), state) -@inline function Base.next(itr::SkipMissing{<:AbstractArray}, state) - i, state = next(eachindex(itr.x), state) - @inbounds v = itr.x[i]::eltype(itr) - (v, _next_nonmissing_ind(itr.x, state)) + y end diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 79fa3311c42fa..c768b79d919ad 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -2,9 +2,9 @@ ### Multidimensional iterators module IteratorsMD - import .Base: eltype, length, size, start, done, next, first, last, in, getindex, + import .Base: eltype, length, size, first, last, in, getindex, setindex!, IndexStyle, min, max, zero, one, isless, eachindex, - ndims, IteratorSize, convert, show + ndims, IteratorSize, convert, show, iterate import .Base: +, -, * import .Base: simd_outer_range, simd_inner_length, simd_index @@ -140,17 +140,17 @@ module IteratorsMD # nextind and prevind with CartesianIndex function Base.nextind(a::AbstractArray{<:Any,N}, i::CartesianIndex{N}) where {N} - _, ni = next(CartesianIndices(axes(a)), i) - return ni + iter = CartesianIndices(axes(a)) + return CartesianIndex(inc(i.I, first(iter).I, last(iter).I)) end function Base.prevind(a::AbstractArray{<:Any,N}, i::CartesianIndex{N}) where {N} - _, ni = next(Iterators.reverse(CartesianIndices(axes(a))), i) - return ni + iter = CartesianIndices(axes(a)) + return CartesianIndex(dec(i.I, last(iter).I, first(iter).I)) end # Iteration over the elements of CartesianIndex cannot be supported until its length can be inferred, # see #23719 - Base.start(::CartesianIndex) = + Base.iterate(::CartesianIndex) = error("iteration is deliberately unsupported for CartesianIndex. Use `I` rather than `I...`, or use `Tuple(I)...`") # Iteration @@ -272,16 +272,19 @@ module IteratorsMD eltype(::Type{CartesianIndices{N,TT}}) where {N,TT} = CartesianIndex{N} IteratorSize(::Type{<:CartesianIndices{N}}) where {N} = Base.HasShape{N}() - @inline function start(iter::CartesianIndices) + @inline function iterate(iter::CartesianIndices) iterfirst, iterlast = first(iter), last(iter) if any(map(>, iterfirst.I, iterlast.I)) - return iterlast+one(iterlast) + return nothing end - iterfirst + iterfirst, iterfirst end - @inline function next(iter::CartesianIndices, state) - state, CartesianIndex(inc(state.I, first(iter).I, last(iter).I)) + @inline function iterate(iter::CartesianIndices, state) + nextstate = CartesianIndex(inc(state.I, first(iter).I, last(iter).I)) + nextstate.I[end] > last(iter.indices[end]) && return nothing + nextstate, nextstate end + # increment & carry @inline inc(::Tuple{}, ::Tuple{}, ::Tuple{}) = () @inline inc(state::Tuple{Int}, start::Tuple{Int}, stop::Tuple{Int}) = (state[1]+1,) @@ -292,12 +295,9 @@ module IteratorsMD newtail = inc(tail(state), tail(start), tail(stop)) (start[1], newtail...) end - @inline done(iter::CartesianIndices, state) = state.I[end] > last(iter.indices[end]) # 0-d cartesian ranges are special-cased to iterate once and only once - start(iter::CartesianIndices{0}) = false - next(iter::CartesianIndices{0}, state) = CartesianIndex(), true - done(iter::CartesianIndices{0}, state) = state + iterate(iter::CartesianIndices{0}, done=false) = done ? nothing : (CartesianIndex(), true) size(iter::CartesianIndices) = map(dimlength, first(iter).I, last(iter).I) dimlength(start, stop) = stop-start+1 @@ -351,16 +351,20 @@ module IteratorsMD end # reversed CartesianIndices iteration - @inline function start(r::Reverse{<:CartesianIndices}) + + @inline function iterate(r::Reverse{<:CartesianIndices}) iterfirst, iterlast = last(r.itr), first(r.itr) if any(map(<, iterfirst.I, iterlast.I)) - return iterlast-1 + return nothing end - iterfirst + iterfirst, iterfirst end - @inline function next(r::Reverse{<:CartesianIndices}, state) - state, CartesianIndex(dec(state.I, last(r.itr).I, first(r.itr).I)) + @inline function iterate(r::Reverse{<:CartesianIndices}, state) + nextstate = CartesianIndex(dec(state.I, last(r.itr).I, first(r.itr).I)) + nextstate.I[end] < first(r.itr.indices[end]) && return nothing + nextstate, nextstate end + # decrement & carry @inline dec(::Tuple{}, ::Tuple{}, ::Tuple{}) = () @inline dec(state::Tuple{Int}, start::Tuple{Int}, stop::Tuple{Int}) = (state[1]-1,) @@ -371,11 +375,8 @@ module IteratorsMD newtail = dec(tail(state), tail(start), tail(stop)) (start[1], newtail...) end - @inline done(r::Reverse{<:CartesianIndices}, state) = state.I[end] < first(r.itr.indices[end]) # 0-d cartesian ranges are special-cased to iterate once and only once - start(iter::Reverse{<:CartesianIndices{0}}) = false - next(iter::Reverse{<:CartesianIndices{0}}, state) = CartesianIndex(), true - done(iter::Reverse{<:CartesianIndices{0}}, state) = state + iterate(iter::Reverse{<:CartesianIndices{0}}, state=false) = state ? nothing : (CartesianIndex(), true) Base.LinearIndices(inds::CartesianIndices{N,R}) where {N,R} = LinearIndices{N,R}(inds.indices) end # IteratorsMD @@ -493,28 +494,28 @@ show(io::IO, r::LogicalIndex) = print(io, "Base.LogicalIndex(", r.mask, ")") # Thus the iteration state contains an index iterator and its state. We also # keep track of the count of elements since we already know how many there # should be -- this way we don't need to look at future indices to check done. -@inline function start(L::LogicalIndex{Int}) +@inline function iterate(L::LogicalIndex{Int}) r = LinearIndices(L.mask) - return (r, start(r), 1) + iterate(L, (1, r)) end -@inline function start(L::LogicalIndex{<:CartesianIndex}) +@inline function iterate(L::LogicalIndex{<:CartesianIndex}) r = CartesianIndices(axes(L.mask)) - return (r, start(r), 1) + iterate(L, (1, r)) end -@propagate_inbounds function next(L::LogicalIndex, s) +@propagate_inbounds function iterate(L::LogicalIndex, s) # We're looking for the n-th true element, using iterator r at state i - r, i, n = s + n = s[1] + n > length(L) && return nothing while true - done(r, i) # Call done(r, i) for the iteration protocol, but trust done(L, s) was called - idx, i = next(r, i) - L.mask[idx] && return (idx, (r, i, n+1)) + idx, i = iterate(tail(s)...) + s = (n+1, s[2], i) + L.mask[idx] && return (idx, s) end end -done(L::LogicalIndex, s) = s[3] > length(L) # When wrapping a BitArray, lean heavily upon its internals -- this is a common # case. Just use the Int index and count as its state. -@inline start(L::LogicalIndex{Int,<:BitArray}) = (0, 1) -@inline function next(L::LogicalIndex{Int,<:BitArray}, s) +@inline function iterate(L::LogicalIndex{Int,<:BitArray}, s=(0,1)) + s[2] > length(L) && return nothing i, n = s Bc = L.mask.chunks while true @@ -525,7 +526,6 @@ done(L::LogicalIndex, s) = s[3] > length(L) i += 1 end end -@inline done(L::LogicalIndex{Int,<:BitArray}, s) = s[2] > length(L) @inline checkbounds(::Type{Bool}, A::AbstractArray, I::LogicalIndex{<:Any,<:AbstractArray{Bool,1}}) = eachindex(IndexLinear(), A) == eachindex(IndexLinear(), I.mask) @@ -601,10 +601,14 @@ end quote @_inline_meta D = eachindex(dest) - Ds = start(D) + Dy = iterate(D) @inbounds @nloops $N j d->I[d] begin - d, Ds = next(D, Ds) - dest[d] = @ncall $N getindex src j + # This condition is never hit, but at the moment + # the optimizer is not clever enough to split the union without it + Dy === nothing && return dest + (idx, state) = Dy + dest[idx] = @ncall $N getindex src j + Dy = iterate(D, state) end return dest end @@ -628,10 +632,14 @@ _iterable(X::AbstractArray, I...) = X @nexprs $N d->(I_d = unalias(A, I[d])) idxlens = @ncall $N index_lengths I @ncall $N setindex_shape_check x′ (d->idxlens[d]) - xs = start(x′) + Xy = iterate(x′) @inbounds @nloops $N i d->I_d begin - v, xs = next(x′, xs) - @ncall $N setindex! A v i + # This is never reached, but serves as an assumption for + # the optimizer that it does not need to emit error paths + Xy === nothing && break + (val, state) = Xy + @ncall $N setindex! A val i + Xy = iterate(x′, state) end A end diff --git a/base/namedtuple.jl b/base/namedtuple.jl index 791f174ad9bcb..6224bc93febe9 100644 --- a/base/namedtuple.jl +++ b/base/namedtuple.jl @@ -92,14 +92,12 @@ end end # if Base length(t::NamedTuple) = nfields(t) -start(t::NamedTuple) = 1 -done(t::NamedTuple, iter) = iter > nfields(t) -next(t::NamedTuple, iter) = (getfield(t, iter), iter + 1) +iterate(t::NamedTuple, iter=1) = iter > nfields(t) ? nothing : (getfield(t, iter), iter + 1) firstindex(t::NamedTuple) = 1 lastindex(t::NamedTuple) = nfields(t) getindex(t::NamedTuple, i::Int) = getfield(t, i) getindex(t::NamedTuple, i::Symbol) = getfield(t, i) -indexed_next(t::NamedTuple, i::Int, state) = (getfield(t, i), i+1) +indexed_iterate(t::NamedTuple, i::Int, state=1) = (getfield(t, i), i+1) isempty(::NamedTuple{()}) = true isempty(::NamedTuple) = false diff --git a/base/number.jl b/base/number.jl index 2e42795d36661..b1b20d4102b4c 100644 --- a/base/number.jl +++ b/base/number.jl @@ -214,9 +214,7 @@ julia> widemul(Float32(3.), 4.) """ widemul(x::Number, y::Number) = widen(x)*widen(y) -start(x::Number) = false -next(x::Number, state) = (x, true) -done(x::Number, state) = state +iterate(x::Number, done = false) = done ? nothing : (x, true) isempty(x::Number) = false in(x::Number, y::Number) = x == y diff --git a/base/pair.jl b/base/pair.jl index 62aefd90f5191..83a9745ee7222 100644 --- a/base/pair.jl +++ b/base/pair.jl @@ -45,12 +45,9 @@ foo """ Pair, => -start(p::Pair) = 1 -done(p::Pair, i) = i>2 -next(p::Pair, i) = (getfield(p, i), i+1) eltype(p::Type{Pair{A, B}}) where {A, B} = Union{A, B} - -indexed_next(p::Pair, i::Int, state) = (getfield(p, i), i+1) +iterate(p::Pair, i=1) = i > 2 ? nothing : (getfield(p, i), i + 1) +indexed_iterate(p::Pair, i::Int, state=1) = (getfield(p, i), i + 1) hash(p::Pair, h::UInt) = hash(p.second, hash(p.first, h)) diff --git a/base/parse.jl b/base/parse.jl index 0abb7e623980f..8f7fb70d84fbb 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -43,18 +43,18 @@ function parse(::Type{T}, c::AbstractChar; base::Integer = 10) where T<:Integer convert(T, d) end -function parseint_next(s::AbstractString, startpos::Int, endpos::Int) +function parseint_iterate(s::AbstractString, startpos::Int, endpos::Int) (0 < startpos <= endpos) || (return Char(0), 0, 0) j = startpos - c, startpos = next(s,startpos) + c, startpos = iterate(s,startpos)::Tuple{Char, Int} c, startpos, j end function parseint_preamble(signed::Bool, base::Int, s::AbstractString, startpos::Int, endpos::Int) - c, i, j = parseint_next(s, startpos, endpos) + c, i, j = parseint_iterate(s, startpos, endpos) while isspace(c) - c, i, j = parseint_next(s,i,endpos) + c, i, j = parseint_iterate(s,i,endpos) end (j == 0) && (return 0, 0, 0) @@ -62,21 +62,21 @@ function parseint_preamble(signed::Bool, base::Int, s::AbstractString, startpos: if signed if c == '-' || c == '+' (c == '-') && (sgn = -1) - c, i, j = parseint_next(s,i,endpos) + c, i, j = parseint_iterate(s,i,endpos) end end while isspace(c) - c, i, j = parseint_next(s,i,endpos) + c, i, j = parseint_iterate(s,i,endpos) end (j == 0) && (return 0, 0, 0) if base == 0 - if c == '0' && !done(s,i) - c, i = next(s,i) + if c == '0' && i <= ncodeunits(s) + c, i = iterate(s,i)::Tuple{Char, Int} base = c=='b' ? 2 : c=='o' ? 8 : c=='x' ? 16 : 10 if base != 10 - c, i, j = parseint_next(s,i,endpos) + c, i, j = parseint_iterate(s,i,endpos) end else base = 10 @@ -99,7 +99,7 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: raise && throw(ArgumentError("premature end of integer: $(repr(SubString(s,startpos,endpos)))")) return nothing end - c, i = parseint_next(s,i,endpos) + c, i = parseint_iterate(s,i,endpos) if i == 0 raise && throw(ArgumentError("premature end of integer: $(repr(SubString(s,startpos,endpos)))")) return nothing @@ -123,7 +123,7 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: n *= sgn return n end - c, i = next(s,i) + c, i = iterate(s,i)::Tuple{Char, Int} isspace(c) && break end (T <: Signed) && (n *= sgn) @@ -144,10 +144,10 @@ function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos:: return nothing end (i > endpos) && return n - c, i = next(s,i) + c, i = iterate(s,i)::Tuple{Char, Int} end while i <= endpos - c, i = next(s,i) + c, i = iterate(s,i)::Tuple{Char, Int} if !isspace(c) raise && throw(ArgumentError("extra characters after whitespace in $(repr(SubString(s,startpos,endpos)))")) return nothing diff --git a/base/path.jl b/base/path.jl index bc2a62110239d..5ed7d99957afb 100644 --- a/base/path.jl +++ b/base/path.jl @@ -338,13 +338,13 @@ if Sys.iswindows() expanduser(path::AbstractString) = path # on windows, ~ means "temporary file" else function expanduser(path::AbstractString) - i = start(path) - if done(path,i) return path end - c, i = next(path,i) + y = iterate(path) + y === nothing && return path + c, i = y if c != '~' return path end - if done(path,i) return homedir() end - c, j = next(path,i) - if c == '/' return homedir()*path[i:end] end + y = iterate(path, i) + if y == nothing return homedir() end + if y[1] == '/' return homedir()*path[i:end] end throw(ArgumentError("~user tilde expansion not yet implemented")) end end diff --git a/base/precompile.jl b/base/precompile.jl index 2f69c7f96e118..dd8cf5ee23969 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -36,195 +36,6 @@ precompile(Tuple{Type{Base.InterpreterIP}, Core.CodeInfo, Ptr{Nothing}}) precompile(Tuple{Type{Base.Iterators.Zip{I, Z} where Z<:Base.Iterators.AbstractZipIterator where I}, Array{Symbol, 1}, Base.Iterators.Zip2{Array{Symbol, 1}, Array{DataType, 1}}}) precompile(Tuple{Type{Base.MIME{Symbol("text/plain")}}}) precompile(Tuple{Type{Base.Multimedia.TextDisplay}, Base.TTY}) -precompile(Tuple{Type{Base.NamedEnv}, String}) -precompile(Tuple{Type{Base.Order.Perm{O, V} where V<:(AbstractArray{T, 1} where T) where O<:Base.Order.Ordering}, Base.Order.ForwardOrdering, Array{Tuple{Float64, Int64}, 1}}) -precompile(Tuple{Type{Base.Order.Perm{O, V} where V<:(AbstractArray{T, 1} where T) where O<:Base.Order.Ordering}, Base.Order.ForwardOrdering, Array{Tuple{Int64, Float64}, 1}}) -precompile(Tuple{Type{Base.Pair{A, B} where B where A}, Symbol, UInt8}) -precompile(Tuple{Type{Base.Pair{A, B} where B where A}, UInt8, UInt8}) -precompile(Tuple{Type{Base.Pair{Symbol, Any}}, Symbol, Array{Any, 1}}) -precompile(Tuple{Type{Base.Pair{Symbol, Any}}, Symbol, Base.Docs.Binding}) -precompile(Tuple{Type{Base.Pair{Symbol, Any}}, Symbol, Bool}) -precompile(Tuple{Type{Base.Pair{Symbol, Any}}, Symbol, Int64}) -precompile(Tuple{Type{Base.Pair{Symbol, Any}}, Symbol, Module}) -precompile(Tuple{Type{Base.Pair{Symbol, Any}}, Symbol, Nothing}) -precompile(Tuple{Type{Base.Pair{Symbol, Any}}, Symbol, String}) -precompile(Tuple{Type{Base.Set{T} where T}, Array{String, 1}}) -precompile(Tuple{Type{Base.StackTraces.StackFrame}, Symbol, Symbol, Int64, Core.CodeInfo, Bool, Bool, Int64}) -precompile(Tuple{Type{Base.StackTraces.StackFrame}, Symbol, Symbol, Int64, Core.MethodInstance, Bool, Bool, Ptr{Nothing}}) -precompile(Tuple{Type{Base.StackTraces.StackFrame}, Symbol, Symbol, Int64, Nothing, Bool, Bool, Ptr{Nothing}}) -precompile(Tuple{Type{Base.Val{10}}}) -precompile(Tuple{Type{Base.Val{2}}}) -precompile(Tuple{Type{Base.Val{3}}}) -precompile(Tuple{Type{Base.VersionNumber}, String}) -precompile(Tuple{Type{Base.VersionNumber}, UInt32, UInt32, UInt32, Tuple{String, String, UInt64}, Tuple{}}) -precompile(Tuple{Type{Expr}, Symbol, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr}) -precompile(Tuple{Type{Expr}, Symbol, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr}) -precompile(Tuple{Type{Expr}, Symbol, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr, Expr}) -precompile(Tuple{Type{Expr}, Symbol, Expr, Expr, Expr, Expr}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Bool}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Char, Char}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Char, Core.SSAValue, Char}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, Bool}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Char}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Char}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Char}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, Core.SSAValue, String, Core.SSAValue, String}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, Core.SSAValue, String, Core.SlotNumber}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, Core.SSAValue, String}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, String, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, String, Core.SSAValue, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SSAValue, String, Core.SlotNumber, String, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SlotNumber, Core.SSAValue, Core.SlotNumber}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SlotNumber, Core.SSAValue, Core.TypedSlot}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SlotNumber, Core.SlotNumber, Core.SlotNumber, Core.SlotNumber, Core.SlotNumber}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.SlotNumber, Core.SlotNumber, String}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Core.TypedSlot, String, Core.TypedSlot, String, Core.TypedSlot, String, Core.SlotNumber, String, Core.SlotNumber, String}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Expr, String}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Float64, Float64}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Float64}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, GlobalRef, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, GlobalRef, Core.SlotNumber, String}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, GlobalRef, GlobalRef, GlobalRef}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, GlobalRef, String, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, GlobalRef, String}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Int64, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, Nothing}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, QuoteNode, Core.SSAValue, Core.SlotNumber, Core.SlotNumber, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, QuoteNode, GlobalRef}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, QuoteNode, QuoteNode, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, QuoteNode, QuoteNode, Core.SSAValue, Core.SSAValue, Core.SSAValue, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, String, Core.SSAValue, String, Core.SSAValue, String, Core.SSAValue, String, Core.SSAValue, String, Core.SSAValue, String, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, String, Core.SSAValue, String, Core.SSAValue, String, Core.SSAValue, String, Core.SSAValue, String, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, String, Core.SSAValue, String, Core.SlotNumber}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, String, Core.SlotNumber, String, Expr, String}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, String, Core.TypedSlot, String, Core.TypedSlot}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, String, Expr, String, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, String, GlobalRef, Core.SSAValue, String, Core.SSAValue, String, Core.SSAValue, String}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, String, String, Core.SSAValue, Core.SSAValue}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, String, String, String}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, typeof(Base.getindex), typeof(Base.setindex!)}) -precompile(Tuple{Type{Expr}, Symbol, GlobalRef, typeof(Base.setindex!)}) -precompile(Tuple{Type{Expr}, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}) -precompile(Tuple{Type{Expr}, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}) -precompile(Tuple{Type{Expr}, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}) -precompile(Tuple{Type{Expr}, Symbol, Symbol, Tuple{}, Symbol, Expr, Expr, Expr, Expr, Expr}) -precompile(Tuple{Type{Logging.ConsoleLogger}, Base.IOStream}) -precompile(Tuple{Type{Logging.ConsoleLogger}, Base.TTY}) -precompile(Tuple{Type{Markdown.Header{1}}, Array{Any, 1}}) -precompile(Tuple{Type{Markdown.MD}, Markdown.MD, Markdown.MD}) -precompile(Tuple{Type{NamedTuple{(), T} where T<:Tuple}, Tuple{}}) -precompile(Tuple{Type{NamedTuple{(:bold, :color), Tuple{Bool, Symbol}}}, Tuple{Bool, Symbol}}) -precompile(Tuple{Type{NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}}, Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}) -precompile(Tuple{Type{NamedTuple{(:stderr,), Tuple{Base.IOStream}}}, Tuple{Base.IOStream}}) -precompile(Tuple{Type{Ptr{UInt16}}, Int64}) -precompile(Tuple{Type{Ptr{UInt32}}, Int64}) -precompile(Tuple{Type{REPL.LineEdit.InputAreaState}, Int64, Int64}) -precompile(Tuple{Type{REPL.LineEditREPL}, REPL.Terminals.TTYTerminal, Bool, Bool}) -precompile(Tuple{Type{REPL.LineEditREPL}, REPL.Terminals.TTYTerminal, Bool, String, String, String, String, String, Bool, Bool, Bool, Bool}) -precompile(Tuple{Type{REPL.REPLDisplay{R} where R<:REPL.AbstractREPL}, REPL.LineEditREPL}) -precompile(Tuple{Type{REPL.Terminals.TTYTerminal}, String, Base.PipeEndpoint, Base.TTY, Base.IOStream}) -precompile(Tuple{Type{REPL.Terminals.TTYTerminal}, String, Base.TTY, Base.TTY, Base.IOStream}) -precompile(Tuple{Type{REPL.Terminals.TTYTerminal}, String, Base.TTY, Base.TTY, Base.TTY}) -precompile(Tuple{Type{Symbol}, String, Int64, String}) -precompile(Tuple{Type{Symbol}, String, String, Int64}) -precompile(Tuple{Type{Symbol}, Symbol, Int64}) -precompile(Tuple{getfield(Base, Symbol("#kw##indentation")), NamedTuple{(:tabwidth,), Tuple{Int64}}, typeof(Base.indentation), String}) -precompile(Tuple{getfield(Base, Symbol("#kw##pipeline")), NamedTuple{(:stderr,), Tuple{Base.IOStream}}, typeof(Base.pipeline), Base.Cmd}) -precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:bold, :color), Tuple{Bool, Symbol}}, typeof(Base.printstyled), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) -precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:bold, :color), Tuple{Bool, Symbol}}, typeof(Base.printstyled), REPL.Terminals.TTYTerminal, String}) -precompile(Tuple{getfield(Base, Symbol("#kw##printstyled")), NamedTuple{(:color,), Tuple{Symbol}}, typeof(Base.printstyled), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) -precompile(Tuple{getfield(Base, Symbol("#kw##show_trace_entry")), NamedTuple{(:prefix,), Tuple{String}}, typeof(Base.show_trace_entry), Base.IOContext{REPL.Terminals.TTYTerminal}, Base.StackTraces.StackFrame, Int64}) -precompile(Tuple{getfield(Base, Symbol("#kw##unindent")), NamedTuple{(:tabwidth,), Tuple{Int64}}, typeof(Base.unindent), String, Int64}) -precompile(Tuple{getfield(Base, Symbol("#kw##with_output_color")), NamedTuple{(:bold,), Tuple{Bool}}, typeof(Base.with_output_color), typeof(Base.print), Symbol, Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) -precompile(Tuple{getfield(Base, Symbol("#kw##with_output_color")), NamedTuple{(:bold,), Tuple{Bool}}, typeof(Base.with_output_color), typeof(Base.print), Symbol, REPL.Terminals.TTYTerminal, String}) -precompile(Tuple{getfield(Base.Cartesian, Symbol("#@ncall")), LineNumberNode, Module, Int64, Symbol, Symbol, Expr}) -precompile(Tuple{getfield(Base.CoreLogging, Symbol("#kw##handle_message")), NamedTuple{(:caller, :maxlog), Tuple{Base.StackTraces.StackFrame, Int64}}, typeof(Base.CoreLogging.handle_message), Logging.ConsoleLogger, Base.CoreLogging.LogLevel, String, Module, Symbol, Tuple{Base.InterpreterIP, Symbol}, String, Int64}) -precompile(Tuple{getfield(Base.CoreLogging, Symbol("#kw##handle_message")), NamedTuple{(:caller, :maxlog), Tuple{Base.StackTraces.StackFrame, Int64}}, typeof(Base.CoreLogging.handle_message), Logging.ConsoleLogger, Base.CoreLogging.LogLevel, String, Module, Symbol, Tuple{Ptr{Nothing}, Symbol}, String, Int64}) -precompile(Tuple{getfield(Base.Meta, Symbol("#kw##parse")), NamedTuple{(:raise, :depwarn), Tuple{Bool, Bool}}, typeof(Base.Meta.parse), String, Int64}) -precompile(Tuple{getfield(Core, Symbol("#@doc")), LineNumberNode, Module, Symbol}) -precompile(Tuple{getfield(Core, Symbol("#kw#Type")), NamedTuple{(:prompt_prefix, :prompt_suffix, :repl, :complete, :on_enter), Tuple{String, typeof(Base.input_color), REPL.LineEditREPL, REPL.REPLCompletionProvider, typeof(REPL.return_callback)}}, Type{REPL.LineEdit.Prompt}, String}) -precompile(Tuple{getfield(Markdown, Symbol("#kw##wrapped_lines")), NamedTuple{(:width, :i), Tuple{Int64, Int64}}, typeof(Markdown.wrapped_lines), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) -precompile(Tuple{getfield(REPL, Symbol("#@repl")), LineNumberNode, Module, Base.TTY, Symbol}) -precompile(Tuple{getfield(REPL, Symbol("#kw##print_joined_cols")), NamedTuple{(:cols,), Tuple{Int64}}, typeof(REPL.print_joined_cols), Base.TTY, Array{String, 1}, String, String}) -precompile(Tuple{getfield(REPL, Symbol("#kw##printmatches")), NamedTuple{(:cols,), Tuple{Int64}}, typeof(REPL.printmatches), Base.TTY, String, Array{String, 1}}) -precompile(Tuple{getfield(REPL.LineEdit, Symbol("#kw##refresh_multi_line")), NamedTuple{(:beeping,), Tuple{Bool}}, typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TTYTerminal, REPL.LineEdit.PromptState}) -precompile(Tuple{getfield(REPL.LineEdit, Symbol("#kw##refresh_multi_line")), NamedTuple{(:beeping,), Tuple{Bool}}, typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal, REPL.LineEdit.PromptState}) -precompile(Tuple{getfield(Test, Symbol("#@test")), LineNumberNode, Module, Expr}) -precompile(Tuple{typeof(Base.:(*)), Array{Float64, 2}, Array{Float64, 2}}) -precompile(Tuple{typeof(Base.:(*)), Base.SubString{String}, String}) -precompile(Tuple{typeof(Base.:(==)), typeof(Base.require), typeof(Base.convert)}) -precompile(Tuple{typeof(Base.:(>)), Base.VersionNumber, Base.VersionNumber}) -precompile(Tuple{typeof(Base.:(|)), Type{Function}, Type{Nothing}}) -precompile(Tuple{typeof(Base.:(|)), Type{Integer}, Type{Nothing}}) -precompile(Tuple{typeof(Base.Cartesian._nloops), Int64, Symbol, Expr, Expr}) -precompile(Tuple{typeof(Base.Cartesian.lreplace!), Int64, Base.Cartesian.LReplace{String}}) -precompile(Tuple{typeof(Base.Cartesian.lreplace), Expr, Symbol, Int64}) -precompile(Tuple{typeof(Base.CoreLogging.global_logger), Logging.ConsoleLogger}) -precompile(Tuple{typeof(Base.CoreLogging.handle_message), Logging.ConsoleLogger, Base.CoreLogging.LogLevel, String, Nothing, Symbol, Symbol, String, Int64}) -precompile(Tuple{typeof(Base.CoreLogging.logmsg_shim), Int64, String, Nothing, Symbol, Symbol, Symbol, Int64, Array{Any, 1}}) -precompile(Tuple{typeof(Base.CoreLogging.shouldlog), Logging.ConsoleLogger, Base.CoreLogging.LogLevel, Module, Symbol, Tuple{Base.InterpreterIP, Symbol}}) -precompile(Tuple{typeof(Base.CoreLogging.shouldlog), Logging.ConsoleLogger, Base.CoreLogging.LogLevel, Module, Symbol, Tuple{Ptr{Nothing}, Symbol}}) -precompile(Tuple{typeof(Base.CoreLogging.shouldlog), Logging.ConsoleLogger, Base.CoreLogging.LogLevel, Nothing, Symbol, Symbol}) -precompile(Tuple{typeof(Base.Docs.__doc__!), String, Int64, Bool}) -precompile(Tuple{typeof(Base.Docs.bindingexpr), Expr}) -precompile(Tuple{typeof(Base.Docs.catdoc), Markdown.MD, Markdown.MD}) -precompile(Tuple{typeof(Base.Docs.doc!), Module, Base.Docs.Binding, Base.Docs.DocStr, Type{Tuple{Any}}}) -precompile(Tuple{typeof(Base.Docs.doc!), Module, Base.Docs.Binding, Base.Docs.DocStr, Type{Tuple{Integer}}}) -precompile(Tuple{typeof(Base.Docs.doc!), Module, Base.Docs.Binding, Base.Docs.DocStr, Type{Tuple{UInt8}}}) -precompile(Tuple{typeof(Base.Docs.doc!), Module, Base.Docs.Binding, Base.Docs.DocStr, Type{Tuple{}}}) -precompile(Tuple{typeof(Base.Docs.doc!), Module, Base.Docs.Binding, Base.Docs.DocStr, Type{Union{}}}) -precompile(Tuple{typeof(Base.Docs.doc!), Module, Base.Docs.Binding, Base.Docs.DocStr}) -precompile(Tuple{typeof(Base.Docs.doc), Base.Docs.Binding}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, Expr, Expr}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, Expr, Symbol, Bool}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, Expr}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, String, Expr}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, String, Int64}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, String, Symbol}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, Symbol}) -precompile(Tuple{typeof(Base.Docs.docstr), Base.Docs.DocStr, Base.Dict{Symbol, Any}}) -precompile(Tuple{typeof(Base.Docs.formatdoc), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.Docs.DocStr, String}) -precompile(Tuple{typeof(Base.Docs.isbasicdoc), Int64}) -precompile(Tuple{typeof(Base.Docs.isquotedmacrocall), Int64}) -precompile(Tuple{typeof(Base.Docs.moduledoc), LineNumberNode, Module, String, Expr, Expr}) -precompile(Tuple{typeof(Base.Docs.multidoc), LineNumberNode, Module, String, Expr, Bool}) -precompile(Tuple{typeof(Base.Docs.objectdoc), LineNumberNode, Module, Expr, Expr, Expr, Expr}) -precompile(Tuple{typeof(Base.Docs.objectdoc), LineNumberNode, Module, String, Expr, Expr, Expr}) -precompile(Tuple{typeof(Base.Docs.signature), Expr}) -precompile(Tuple{typeof(Base.Docs.unblock), Int64}) -precompile(Tuple{typeof(Base.GMP.__init__)}) -precompile(Tuple{typeof(Base.Iterators.zip), Array{Symbol, 1}, Array{DataType, 1}}) -precompile(Tuple{typeof(Base.Iterators.zip), Array{Symbol, 1}, Array{Symbol, 1}, Array{DataType, 1}}) -precompile(Tuple{typeof(Base.Math.clamp), Int64, Int64, Int64}) -precompile(Tuple{typeof(Base.Meta.isexpr), Int64, Array{Symbol, 1}}) -precompile(Tuple{typeof(Base.Meta.isexpr), Int64, Symbol}) -precompile(Tuple{typeof(Base.Meta.isexpr), Symbol, Symbol, Int64}) -precompile(Tuple{typeof(Base.Meta.parse), String}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Array{Float64, 1}}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Array{Float64, 2}}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Array{Float64, 3}}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Array{Int64, 1}}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.Dict{String, String}}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Array{Float64, 1}}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Array{Float64, 2}}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Array{Float64, 3}}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Array{Int64, 1}}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Base.Dict{String, String}}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Float64}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Int64}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Markdown.MD}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Module}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, String}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Float64}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Int64}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Markdown.MD}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, Module}) -precompile(Tuple{typeof(Base.Multimedia.display), REPL.REPLDisplay{REPL.LineEditREPL}, String}) -precompile(Tuple{typeof(Base.Multimedia.pushdisplay), REPL.REPLDisplay{REPL.LineEditREPL}}) -precompile(Tuple{typeof(Base.Order.ord), typeof(Base.isless), typeof(Base.identity), Nothing, Base.Order.ForwardOrdering}) -precompile(Tuple{typeof(Base.StackTraces.is_loc_meta), Expr, Symbol}) -precompile(Tuple{typeof(Base.__init__)}) precompile(Tuple{typeof(Base._atexit)}) precompile(Tuple{typeof(Base._compute_eltype), Type{Tuple{Int64, String}}}) precompile(Tuple{typeof(Base._methods), typeof(Base.require), Type{Tuple}, Int64, UInt64}) @@ -330,118 +141,6 @@ precompile(Tuple{typeof(Base.getindex), Tuple{Symbol, String, Expr}, Base.UnitRa precompile(Tuple{typeof(Base.getindex), Tuple{Symbol, String, Symbol}, Base.UnitRange{Int64}}) precompile(Tuple{typeof(Base.getindex), Tuple{Symbol, String}, Base.UnitRange{Int64}}) precompile(Tuple{typeof(Base.getindex), Tuple{Symbol, Symbol, Symbol}, Base.UnitRange{Int64}}) -precompile(Tuple{typeof(Base.getindex), Type{Any}, typeof(Pkg.dir), Array{Base.AbstractEnv, 1}, String, String, String}) -precompile(Tuple{typeof(Base.getindex), Type{Base.AbstractEnv}, Base.CurrentEnv, Base.NamedEnv, Base.NamedEnv, Base.NamedEnv, Base.NamedEnv, Base.NamedEnv}) -precompile(Tuple{typeof(Base.getindex), Type{UInt8}, UInt8, UInt8, Char, Char, Char, Char}) -precompile(Tuple{typeof(Base.getproperty), Base.CoreLogging.LogState, Symbol}) -precompile(Tuple{typeof(Base.getproperty), Base.Pair{Char, Char}, Symbol}) -precompile(Tuple{typeof(Base.getproperty), Markdown.MD, Symbol}) -precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.HistoryPrompt{REPL.REPLHistoryProvider}, Symbol}) -precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.PrefixHistoryPrompt{REPL.REPLHistoryProvider}, Symbol}) -precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.Prompt, Symbol}) -precompile(Tuple{typeof(Base.getproperty), REPL.LineEdit.PromptState, Symbol}) -precompile(Tuple{typeof(Base.getproperty), REPL.LineEditREPL, Symbol}) -precompile(Tuple{typeof(Base.getproperty), REPL.Options, Symbol}) -precompile(Tuple{typeof(Base.getproperty), REPL.Terminals.TTYTerminal, Symbol}) -precompile(Tuple{typeof(Base.grow_to!), Base.Dict{Symbol, Any}, Tuple{Base.Pair{Symbol, String}, Base.Pair{Symbol, Int64}, Base.Pair{Symbol, Module}, Base.Pair{Symbol, Base.Dict{Any, Any}}}, Int64}) -precompile(Tuple{typeof(Base.grow_to!), Base.Dict{Symbol, Any}, Tuple{Base.Pair{Symbol, String}, Base.Pair{Symbol, Int64}, Base.Pair{Symbol, Module}}, Int64}) -precompile(Tuple{typeof(Base.grow_to!), Base.Dict{Symbol, String}, Tuple{Base.Pair{Symbol, String}, Base.Pair{Symbol, Int64}, Base.Pair{Symbol, Module}, Base.Pair{Symbol, Base.Dict{Any, Any}}}, Int64}) -precompile(Tuple{typeof(Base.grow_to!), Base.Dict{Symbol, String}, Tuple{Base.Pair{Symbol, String}, Base.Pair{Symbol, Int64}, Base.Pair{Symbol, Module}}, Int64}) -precompile(Tuple{typeof(Base.hash), Symbol, UInt64}) -precompile(Tuple{typeof(Base.hashindex), Tuple{Module, String, Float64}, Int64}) -precompile(Tuple{typeof(Base.haskey), Base.Dict{Symbol, Any}, Symbol}) -precompile(Tuple{typeof(Base.haskey), Base.IdDict{Any, Any}, Base.Docs.Binding}) -precompile(Tuple{typeof(Base.hasmethod), typeof(Base.require), Type{Tuple{Symbol}}}) -precompile(Tuple{typeof(Base.ident_cmp), Tuple{String, UInt64}, Tuple{String, UInt64}}) -precompile(Tuple{typeof(Base.ident_cmp), Tuple{String}, Tuple{String, UInt64}}) -precompile(Tuple{typeof(Base.in), Char, Tuple{Char, Char, Char}}) -precompile(Tuple{typeof(Base.in), String, Base.Set{Any}}) -precompile(Tuple{typeof(Base.in), Tuple{Module, String, Float64}, Base.Set{Any}}) -precompile(Tuple{typeof(Base.in), typeof(Base.require), Array{Function, 1}}) -precompile(Tuple{typeof(Base.include_ifexists), Module, String}) -precompile(Tuple{typeof(Base.incomplete_tag), Expr}) -precompile(Tuple{typeof(Base.indexed_next), Base.Pair{Symbol, UInt8}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Array{Float64, 1}, Nothing}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Array{Float64, 2}, Nothing}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Array{Float64, 3}, Nothing}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Array{Int64, 1}, Nothing}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Array{String, 1}, String, Bool}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Base.Dict{String, String}, Nothing}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Base.GenericIOBuffer{Array{UInt8, 1}}, Bool, Bool}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Base.StackTraces.StackFrame, Int64}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{DataType, DataType}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{ErrorException, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Float64, Nothing}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Markdown.MD, Nothing}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{MethodError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Module, Nothing}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Nothing, Nothing}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{String, Nothing}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{Symbol, String, String}, Int64, Int64}) -precompile(Tuple{typeof(Base.indexed_next), Tuple{typeof(Base.require), Array{Any, 1}}, Int64, Int64}) -precompile(Tuple{typeof(Base.init_depot_path), String}) -precompile(Tuple{typeof(Base.init_load_path), String}) -precompile(Tuple{typeof(Base.isempty), Array{Base.Docs.DocStr, 1}}) -precompile(Tuple{typeof(Base.isempty), NamedTuple{(), Tuple{}}}) -precompile(Tuple{typeof(Base.isempty), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(Base.isempty), Tuple{String, Expr, Expr}}) -precompile(Tuple{typeof(Base.isempty), Tuple{String, Symbol, Symbol, Expr}}) -precompile(Tuple{typeof(Base.isempty), Tuple{String, Symbol, Symbol, Symbol, Symbol, Expr}}) -precompile(Tuple{typeof(Base.isempty), Tuple{Symbol, String, Expr, Expr, Expr, Expr}}) -precompile(Tuple{typeof(Base.isempty), Tuple{Symbol, String, Expr, Expr}}) -precompile(Tuple{typeof(Base.isempty), Tuple{Symbol, String, Expr, Symbol, Symbol, Expr}}) -precompile(Tuple{typeof(Base.isempty), Tuple{Symbol, String}}) -precompile(Tuple{typeof(Base.isequal), Expr, Symbol}) -precompile(Tuple{typeof(Base.isequal), REPL.LineEdit.Prompt, REPL.LineEdit.Prompt}) -precompile(Tuple{typeof(Base.isequal), String, Symbol}) -precompile(Tuple{typeof(Base.isequal), Tuple{Base.InterpreterIP, Symbol}, Tuple{Ptr{Nothing}, Symbol}}) -precompile(Tuple{typeof(Base.isequal), Tuple{Module, String, Float64}, Tuple{Module, String, Float64}}) -precompile(Tuple{typeof(Base.join), Base.GenericIOBuffer{Array{UInt8, 1}}, Tuple{String, UInt64}, Char}) -precompile(Tuple{typeof(Base.lastindex), Array{AbstractString, 1}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Expr, Expr, Expr, Expr, Expr}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Float32, Float32, Float32, Float32, Float32, Float32}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Float32, Float32, Float32, Float32}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Float64, Float64, Float64, Float64, Float64, Float64, Float64}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Int64}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{String, Expr, Expr}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{String, Symbol, Symbol, Expr}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{String, Symbol, Symbol, Symbol, Symbol, Expr}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Symbol, String, Expr, Expr, Expr, Expr}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Symbol, String, Expr, Expr}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Symbol, String, Expr, Symbol, Symbol, Expr}}) -precompile(Tuple{typeof(Base.lastindex), Tuple{Symbol, String}}) -precompile(Tuple{typeof(Base.leading_ones), UInt8}) -precompile(Tuple{typeof(Base.length), Array{Ptr{Nothing}, 1}}) -precompile(Tuple{typeof(Base.length), Tuple{DataType, DataType}}) -precompile(Tuple{typeof(Base.length), Tuple{Float32, Float32, Float32, Float32, Float32, Float32}}) -precompile(Tuple{typeof(Base.length), Tuple{Float32, Float32, Float32, Float32}}) -precompile(Tuple{typeof(Base.length), Tuple{Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64}}) -precompile(Tuple{typeof(Base.length), Tuple{Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64}}) -precompile(Tuple{typeof(Base.length), Tuple{Float64, Float64, Float64, Float64, Float64, Float64, Float64}}) -precompile(Tuple{typeof(Base.length), Tuple{Symbol, String, Expr, Expr, Expr, Expr}}) -precompile(Tuple{typeof(Base.length), Tuple{Symbol, String, Expr, Expr}}) -precompile(Tuple{typeof(Base.length), Tuple{Symbol, String, Expr, Symbol, Symbol, Expr}}) -precompile(Tuple{typeof(Base.length), Tuple{Symbol, String}}) -precompile(Tuple{typeof(Base.length), Tuple{Symbol}}) -precompile(Tuple{typeof(Base.literal_pow), typeof(Base.:(^)), Int64, Base.Val{10}}) -precompile(Tuple{typeof(Base.merge), NamedTuple{(), Tuple{}}, NamedTuple{(), Tuple{}}}) -precompile(Tuple{typeof(Base.methods), typeof(Base.require), Type{Tuple}}) -precompile(Tuple{typeof(Base.methods), typeof(Base.require)}) -precompile(Tuple{typeof(Base.methods_including_ambiguous), typeof(Base.require), Type{Tuple{Symbol}}}) -precompile(Tuple{typeof(Base.names), Module}) -precompile(Tuple{typeof(Base.next), Array{AbstractString, 1}, Int64}) -precompile(Tuple{typeof(Base.next), Base.Dict{String, String}, Int64}) -precompile(Tuple{typeof(Base.next), Base.Iterators.Zip{Array{Symbol, 1}, Base.Iterators.Zip2{Array{Symbol, 1}, Array{DataType, 1}}}, Tuple{Int64, Tuple{Int64, Int64}}}) -precompile(Tuple{typeof(Base.next), Tuple{Base.Pair{Symbol, Symbol}, Base.Pair{Symbol, Symbol}, Base.Pair{Symbol, Symbol}, Base.Pair{Symbol, Symbol}, Base.Pair{Symbol, Symbol}, Base.Pair{Symbol, Symbol}, Base.Pair{Symbol, Symbol}}, Int64}) -precompile(Tuple{typeof(Base.next), Tuple{Base.Pair{Symbol, UInt8}, Base.Pair{Symbol, UInt8}, Base.Pair{Symbol, UInt8}, Base.Pair{Symbol, UInt8}, Base.Pair{Symbol, UInt8}, Base.Pair{Symbol, UInt8}, Base.Pair{Symbol, UInt8}}, Int64}) -precompile(Tuple{typeof(Base.next), Tuple{DataType, UInt8, UInt8}, Int64}) -precompile(Tuple{typeof(Base.next), Tuple{String, String, String, String, String, String, String, String}, Int64}) -precompile(Tuple{typeof(Base.next), Tuple{Tuple{DataType, DataType}, Tuple{DataType, DataType}, Tuple{DataType, DataType}, Tuple{DataType, DataType}, Tuple{DataType, DataType}}, Int64}) -precompile(Tuple{typeof(Base.next), Tuple{UnionAll, UnionAll, UnionAll, UnionAll}, Int64}) -precompile(Tuple{typeof(Base.next), Tuple{typeof(Base.:(+)), typeof(Base.:(-)), typeof(Base.:(*)), typeof(Base.:(/))}, Int64}) -precompile(Tuple{typeof(Base.next), Tuple{typeof(Base.:(+)), typeof(Base.:(-)), typeof(Base.abs), typeof(Base.abs2)}, Int64}) precompile(Tuple{typeof(Base.open), Base.CmdRedirect, String, Base.TTY}) precompile(Tuple{typeof(Base.position), Base.GenericIOBuffer{Array{UInt8, 1}}}) precompile(Tuple{typeof(Base.precompilableerror), LoadError, Bool}) @@ -610,282 +309,5 @@ precompile(Tuple{typeof(Base.start), Tuple{Markdown.MD, Nothing}}) precompile(Tuple{typeof(Base.start), Tuple{MethodError, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}}}) precompile(Tuple{typeof(Base.start), Tuple{Module, Nothing}}) precompile(Tuple{typeof(Base.start), Tuple{Nothing, Nothing}}) -precompile(Tuple{typeof(Base.start), Tuple{String, Int64}}) -precompile(Tuple{typeof(Base.start), Tuple{String, Nothing}}) -precompile(Tuple{typeof(Base.start), Tuple{String, String, String, String, String, String, String, String}}) -precompile(Tuple{typeof(Base.start), Tuple{String, String}}) -precompile(Tuple{typeof(Base.start), Tuple{Symbol, String, String}}) -precompile(Tuple{typeof(Base.start), Tuple{Tuple{DataType, DataType}, Tuple{DataType, DataType}, Tuple{DataType, DataType}, Tuple{DataType, DataType}, Tuple{DataType, DataType}}}) -precompile(Tuple{typeof(Base.start), Tuple{UnionAll, UnionAll, UnionAll, UnionAll}}) -precompile(Tuple{typeof(Base.start), Tuple{typeof(Base.:(+)), typeof(Base.:(-)), typeof(Base.:(*)), typeof(Base.:(/))}}) -precompile(Tuple{typeof(Base.start), Tuple{typeof(Base.:(+)), typeof(Base.:(-)), typeof(Base.abs), typeof(Base.abs2)}}) -precompile(Tuple{typeof(Base.start), Tuple{typeof(Base.require), Array{Any, 1}}}) -precompile(Tuple{typeof(Base.startswith), Base.SubString{String}, String}) -precompile(Tuple{typeof(Base.string), Base.SubString{String}}) -precompile(Tuple{typeof(Base.string), Expr}) -precompile(Tuple{typeof(Base.string), String, Tuple{UInt64, UInt64}, String}) -precompile(Tuple{typeof(Base.success), Base.Process}) -precompile(Tuple{typeof(Base.take!), Base.Channel{Any}}) -precompile(Tuple{typeof(Base.task_done_hook), Task}) -precompile(Tuple{typeof(Base.task_local_storage)}) -precompile(Tuple{typeof(Base.truncate), Base.GenericIOBuffer{Array{UInt8, 1}}, Int64}) -precompile(Tuple{typeof(Base.trylock), Base.Threads.TatasLock}) -precompile(Tuple{typeof(Base.typed_vcat), Type{Any}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{String, 1}}) -precompile(Tuple{typeof(Base.typeinfo_eltype), Type{Any}}) -precompile(Tuple{typeof(Base.typesof), Symbol}) -precompile(Tuple{typeof(Base.unique), Array{Any, 1}}) -precompile(Tuple{typeof(Base.unlock), Base.Threads.TatasLock}) -precompile(Tuple{typeof(Base.unsafe_write), Base.Pipe, Ptr{UInt8}, UInt64}) -precompile(Tuple{typeof(Base.unsafe_write), Base.TTY, Ptr{UInt8}, UInt64}) -precompile(Tuple{typeof(Base.uv_alloc_buf), Ptr{Nothing}, UInt64, Ptr{Nothing}}) -precompile(Tuple{typeof(Base.uv_readcb), Ptr{Nothing}, Int64, Ptr{Nothing}}) -precompile(Tuple{typeof(Base.uv_return_spawn), Ptr{Nothing}, Int64, Int32}) -precompile(Tuple{typeof(Base.uv_writecb_task), Ptr{Nothing}, Int32}) -precompile(Tuple{typeof(Base.uvfinalize), Base.PipeEndpoint}) -precompile(Tuple{typeof(Base.uvfinalize), Base.Process}) -precompile(Tuple{typeof(Base.uvfinalize), Base.TTY}) -precompile(Tuple{typeof(Base.uvfinalize), Base.Timer}) -precompile(Tuple{typeof(Base.vcat), Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}, Array{Base.StackTraces.StackFrame, 1}}) -precompile(Tuple{typeof(Base.vcat), Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{String, 1}}) -precompile(Tuple{typeof(Base.vect), Expr, Expr}) -precompile(Tuple{typeof(Base.vect), Type{Int64}, Type{Int64}, Type{Int64}, Type{Float64}}) -precompile(Tuple{typeof(Base.vect), typeof(Base.:(+)), typeof(Base.:(-)), typeof(Base.:(*)), typeof(Base.:(/)), typeof(Base.:(&)), typeof(Base.:(|)), typeof(Base.:(<<)), typeof(Base.:(>>)), typeof(Base.:(>>>))}) -precompile(Tuple{typeof(Base.view), Array{Float64, 3}, Base.OneTo{Int64}, Base.OneTo{Int64}, Int64}) -precompile(Tuple{typeof(Base.wait), Base.Timer}) -precompile(Tuple{typeof(Base.write), Base.IOStream, Array{UInt8, 1}}) -precompile(Tuple{typeof(Base.write), Base.Pipe, String}) -precompile(Tuple{typeof(Base.write), Base.Process, String}) -precompile(Tuple{typeof(Base.write), Base.TTY, Char}) -precompile(Tuple{typeof(Base.write), Base.TTY, String}) -precompile(Tuple{typeof(Base.write), Base.TTY, UInt8}) -precompile(Tuple{typeof(Base.write), REPL.Terminals.TTYTerminal, String}) -precompile(Tuple{typeof(Core.Compiler.collect), Type{Symbol}, Tuple{Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}}) -precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{Array{Base.StackTraces.StackFrame, 1}, 1}}}) -precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{QuoteNode, 1}}}) -precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{String, 1}}}) -precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{UInt8, 1}}}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Array{String, 1}}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Colon}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.Multimedia.display)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.__atreplinit)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.display_error)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.show)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(REPL.helpmode)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.open), typeof(Pkg.Reqs.read)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Pkg.Dir.cd), typeof(Pkg.Entry.status)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Bool, Bool}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{DataType, UInt8, UInt8}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Nothing, Nothing}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Symbol, Symbol, QuoteNode}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Tuple{Base.Libc.RawFD, Base.Libc.RawFD, Base.Libc.RawFD}}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{UInt64}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.:(*)), Int64}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.convert), typeof(Base.getindex), typeof(Base.setindex!)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.getindex), typeof(Base.setindex!)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.max), Int64}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Base.setindex!)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Bool, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Char, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Core.SSAValue, Core.SlotNumber, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Core.SlotNumber, Bool, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Core.SlotNumber, Core.SSAValue, Int64, Int64, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Core.SlotNumber, Core.SlotNumber, Core.TypedSlot, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Core.SlotNumber, Int64, Core.SlotNumber, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Core.SlotNumber, Int64, Int64, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Core.TypedSlot, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Expr, Expr, Expr, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Int64, Int64, Int64, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Nothing, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, QuoteNode, Type{Any}, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, String, Core.SSAValue, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, String, Core.SlotNumber, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, Tuple{Bool}, Tuple{}, Core.SSAValue, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, UInt8, Core.SSAValue, Core.SSAValue, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, typeof(Base.Broadcast._broadcast_getindex_eltype), Core.SSAValue, Expr}) -precompile(Tuple{typeof(Core.Compiler.getindex), Type{Any}, GlobalRef, typeof(Base.getindex), Expr}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Array{String, 1}}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Colon}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.Multimedia.display)}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.__atreplinit)}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.display_error)}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(Base.show)}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.invokelatest), typeof(REPL.helpmode)}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Base.open), typeof(Pkg.Reqs.read)}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, typeof(Pkg.Dir.cd), typeof(Pkg.Entry.status)}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Bool, Bool}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{DataType, UInt8, UInt8}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Nothing, Nothing}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Nothing}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Symbol, Symbol, QuoteNode}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Tuple{Base.Libc.RawFD, Base.Libc.RawFD, Base.Libc.RawFD}}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{UInt64}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{typeof(Base.:(*)), Int64}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{typeof(Base.convert), typeof(Base.getindex), typeof(Base.setindex!)}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{typeof(Base.getindex), typeof(Base.setindex!)}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{typeof(Base.max), Int64}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{typeof(Base.setindex!)}}) -precompile(Tuple{typeof(Core.Compiler.replace_use_expr_with!), Core.Compiler.AllocOptContext, Core.Compiler.ValueUse, Tuple{Bool}, Bool, Bool}) -precompile(Tuple{typeof(Core.Compiler.replace_use_expr_with!), Core.Compiler.AllocOptContext, Core.Compiler.ValueUse, Tuple{Int64, Int64, Int64}, Bool, Bool}) -precompile(Tuple{typeof(Distributed.terminate_all_workers)}) -precompile(Tuple{typeof(InteractiveUtils.versioninfo), Base.TTY}) -precompile(Tuple{typeof(InteractiveUtils.versioninfo)}) -precompile(Tuple{typeof(LinearAlgebra.__init__)}) -precompile(Tuple{typeof(Logging.__init__)}) -precompile(Tuple{typeof(Logging.default_metafmt), Base.CoreLogging.LogLevel, Module, Symbol, Symbol, String, Int64}) -precompile(Tuple{typeof(Logging.default_metafmt), Base.CoreLogging.LogLevel, Module, Symbol, Tuple{Base.InterpreterIP, Symbol}, String, Int64}) -precompile(Tuple{typeof(Logging.default_metafmt), Base.CoreLogging.LogLevel, Module, Symbol, Tuple{Ptr{Nothing}, Symbol}, String, Int64}) -precompile(Tuple{typeof(Logging.default_metafmt), Base.CoreLogging.LogLevel, Nothing, Symbol, Symbol, String, Int64}) -precompile(Tuple{typeof(Markdown.admonition), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.ansi_length), Base.SubString{String}}) -precompile(Tuple{typeof(Markdown.ansi_length), String}) -precompile(Tuple{typeof(Markdown.asterisk_bold), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.asterisk_italic), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.blockinterp), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.blockquote), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.blocktex), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.fencedcode), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.footnote), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.footnote_link), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.github_table), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.hashheader), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.horizontalrule), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.indentcode), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.inline_code), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.link), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.list), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.paragraph), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.setextheader), Base.GenericIOBuffer{Array{UInt8, 1}}, Markdown.MD}) -precompile(Tuple{typeof(Markdown.startswith), Base.GenericIOBuffer{Array{UInt8, 1}}, String}) -precompile(Tuple{typeof(Markdown.term), Base.IOContext{REPL.Terminals.TTYTerminal}, Markdown.Code, Int64}) -precompile(Tuple{typeof(Markdown.term), Base.IOContext{REPL.Terminals.TTYTerminal}, Markdown.Header{1}, Int64}) -precompile(Tuple{typeof(Markdown.term), Base.IOContext{REPL.Terminals.TTYTerminal}, Markdown.HorizontalRule, Int64}) -precompile(Tuple{typeof(Markdown.term), Base.IOContext{REPL.Terminals.TTYTerminal}, Markdown.MD, Int64}) -precompile(Tuple{typeof(Markdown.term), Base.IOContext{REPL.Terminals.TTYTerminal}, Markdown.Paragraph, Int64}) -precompile(Tuple{typeof(Markdown.terminline), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Array{Any, 1}}) -precompile(Tuple{typeof(Markdown.terminline), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Markdown.Code}) -precompile(Tuple{typeof(Markdown.terminline), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Markdown.Link}) -precompile(Tuple{typeof(Markdown.terminline), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, String}) -precompile(Tuple{typeof(Markdown.terminline_string), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Array{Any, 1}}) -precompile(Tuple{typeof(Markdown.terminline_string), Base.IOContext{REPL.Terminals.TTYTerminal}, Array{Any, 1}}) -precompile(Tuple{typeof(REPL.LineEdit.accept_result), REPL.LineEdit.MIState, REPL.LineEdit.PrefixHistoryPrompt{REPL.REPLHistoryProvider}}) -precompile(Tuple{typeof(REPL.LineEdit.activate), REPL.LineEdit.HistoryPrompt{REPL.REPLHistoryProvider}, REPL.LineEdit.SearchState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) -precompile(Tuple{typeof(REPL.LineEdit.activate), REPL.LineEdit.PrefixHistoryPrompt{REPL.REPLHistoryProvider}, REPL.LineEdit.PrefixSearchState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) -precompile(Tuple{typeof(REPL.LineEdit.activate), REPL.LineEdit.Prompt, REPL.LineEdit.MIState, REPL.Terminals.TTYTerminal, REPL.Terminals.TTYTerminal}) -precompile(Tuple{typeof(REPL.LineEdit.activate), REPL.LineEdit.Prompt, REPL.LineEdit.PromptState, REPL.Terminals.TTYTerminal, REPL.Terminals.TTYTerminal}) -precompile(Tuple{typeof(REPL.LineEdit.activate), REPL.LineEdit.Prompt, REPL.LineEdit.PromptState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) -precompile(Tuple{typeof(REPL.LineEdit.add_history), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.add_history), REPL.REPLHistoryProvider, REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.buffer), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.cancel_beep), REPL.LineEdit.PrefixSearchState}) -precompile(Tuple{typeof(REPL.LineEdit.cancel_beep), REPL.LineEdit.SearchState}) -precompile(Tuple{typeof(REPL.LineEdit.commit_changes), REPL.Terminals.TTYTerminal, REPL.Terminals.TerminalBuffer}) -precompile(Tuple{typeof(REPL.LineEdit.common_prefix), Array{String, 1}}) -precompile(Tuple{typeof(REPL.LineEdit.complete_line), REPL.LineEdit.PromptState, Int64}) -precompile(Tuple{typeof(REPL.LineEdit.complete_line), REPL.REPLCompletionProvider, REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.copybuf!), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.GenericIOBuffer{Array{UInt8, 1}}}) -precompile(Tuple{typeof(REPL.LineEdit.deactivate), REPL.LineEdit.HistoryPrompt{REPL.REPLHistoryProvider}, REPL.LineEdit.SearchState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) -precompile(Tuple{typeof(REPL.LineEdit.deactivate), REPL.LineEdit.PrefixHistoryPrompt{REPL.REPLHistoryProvider}, REPL.LineEdit.PrefixSearchState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) -precompile(Tuple{typeof(REPL.LineEdit.deactivate), REPL.LineEdit.Prompt, REPL.LineEdit.PromptState, REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal}) -precompile(Tuple{typeof(REPL.LineEdit.deactivate_region), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.default_enter_cb), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.edit_abort), REPL.LineEdit.MIState, Bool}) -precompile(Tuple{typeof(REPL.LineEdit.edit_backspace), REPL.LineEdit.PromptState, Bool, Bool}) -precompile(Tuple{typeof(REPL.LineEdit.edit_backspace), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.edit_insert), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.SubString{String}}) -precompile(Tuple{typeof(REPL.LineEdit.edit_insert), REPL.LineEdit.PromptState, String}) -precompile(Tuple{typeof(REPL.LineEdit.edit_insert_newline), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.edit_move_left), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.edit_move_right), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.edit_move_up), Base.GenericIOBuffer{Array{UInt8, 1}}}) -precompile(Tuple{typeof(REPL.LineEdit.eval), Module, Expr}) -precompile(Tuple{typeof(REPL.LineEdit.history_next_prefix), REPL.LineEdit.PrefixSearchState, REPL.REPLHistoryProvider, String}) -precompile(Tuple{typeof(REPL.LineEdit.history_prev_prefix), REPL.LineEdit.PrefixSearchState, REPL.REPLHistoryProvider, String}) -precompile(Tuple{typeof(REPL.LineEdit.history_search), REPL.REPLHistoryProvider, Base.GenericIOBuffer{Array{UInt8, 1}}, Base.GenericIOBuffer{Array{UInt8, 1}}, Bool, Bool}) -precompile(Tuple{typeof(REPL.LineEdit.init_state), REPL.Terminals.TTYTerminal, REPL.LineEdit.HistoryPrompt{REPL.REPLHistoryProvider}}) -precompile(Tuple{typeof(REPL.LineEdit.init_state), REPL.Terminals.TTYTerminal, REPL.LineEdit.ModalInterface}) -precompile(Tuple{typeof(REPL.LineEdit.init_state), REPL.Terminals.TTYTerminal, REPL.LineEdit.PrefixHistoryPrompt{REPL.REPLHistoryProvider}}) -precompile(Tuple{typeof(REPL.LineEdit.init_state), REPL.Terminals.TTYTerminal, REPL.LineEdit.Prompt}) -precompile(Tuple{typeof(REPL.LineEdit.is_region_active), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.keymap), REPL.LineEdit.PrefixSearchState, REPL.LineEdit.PrefixHistoryPrompt{REPL.REPLHistoryProvider}}) -precompile(Tuple{typeof(REPL.LineEdit.keymap), REPL.LineEdit.PromptState, REPL.LineEdit.Prompt}) -precompile(Tuple{typeof(REPL.LineEdit.keymap), REPL.LineEdit.SearchState, REPL.LineEdit.HistoryPrompt{REPL.REPLHistoryProvider}}) -precompile(Tuple{typeof(REPL.LineEdit.keymap_data), REPL.LineEdit.PrefixSearchState, REPL.LineEdit.PrefixHistoryPrompt{REPL.REPLHistoryProvider}}) -precompile(Tuple{typeof(REPL.LineEdit.keymap_data), REPL.LineEdit.PromptState, REPL.LineEdit.Prompt}) -precompile(Tuple{typeof(REPL.LineEdit.keymap_data), REPL.LineEdit.SearchState, REPL.LineEdit.HistoryPrompt{REPL.REPLHistoryProvider}}) -precompile(Tuple{typeof(REPL.LineEdit.match_input), Base.Dict{Char, Any}, REPL.LineEdit.MIState, Base.GenericIOBuffer{Array{UInt8, 1}}}) -precompile(Tuple{typeof(REPL.LineEdit.match_input), Base.Dict{Char, Any}, REPL.LineEdit.MIState, REPL.Terminals.TTYTerminal, Array{Char, 1}, Base.Dict{Char, Any}}) -precompile(Tuple{typeof(REPL.LineEdit.match_input), Base.Dict{Char, Any}, REPL.LineEdit.MIState}) -precompile(Tuple{typeof(REPL.LineEdit.match_input), REPL.LineEdit.KeyAlias, REPL.LineEdit.MIState, REPL.Terminals.TTYTerminal, Array{Char, 1}, Base.Dict{Char, Any}}) -precompile(Tuple{typeof(REPL.LineEdit.mode), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.move_input_end), Base.GenericIOBuffer{Array{UInt8, 1}}}) -precompile(Tuple{typeof(REPL.LineEdit.on_enter), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.options), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.prompt_string), typeof(Base.input_color)}) -precompile(Tuple{typeof(REPL.LineEdit.push_undo), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TTYTerminal, REPL.LineEdit.PrefixSearchState}) -precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TTYTerminal, REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TTYTerminal, REPL.LineEdit.SearchState}) -precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal, Base.GenericIOBuffer{Array{UInt8, 1}}, REPL.LineEdit.InputAreaState, String}) -precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal, REPL.LineEdit.PrefixSearchState}) -precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal, REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), REPL.Terminals.TerminalBuffer, REPL.Terminals.TTYTerminal, REPL.LineEdit.SearchState}) -precompile(Tuple{typeof(REPL.LineEdit.replace_line), REPL.LineEdit.MIState, Base.SubString{String}, Bool}) -precompile(Tuple{typeof(REPL.LineEdit.replace_line), REPL.LineEdit.MIState, Base.SubString{String}}) -precompile(Tuple{typeof(REPL.LineEdit.replace_line), REPL.LineEdit.MIState, String, Bool}) -precompile(Tuple{typeof(REPL.LineEdit.replace_line), REPL.LineEdit.PromptState, Base.GenericIOBuffer{Array{UInt8, 1}}}) -precompile(Tuple{typeof(REPL.LineEdit.replace_line), REPL.LineEdit.PromptState, Base.SubString{String}}) -precompile(Tuple{typeof(REPL.LineEdit.replace_line), REPL.LineEdit.PromptState, String}) -precompile(Tuple{typeof(REPL.LineEdit.reset_state), REPL.LineEdit.PrefixSearchState}) -precompile(Tuple{typeof(REPL.LineEdit.reset_state), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.reset_state), REPL.LineEdit.SearchState}) -precompile(Tuple{typeof(REPL.LineEdit.reset_state), REPL.REPLHistoryProvider}) -precompile(Tuple{typeof(REPL.LineEdit.run_interface), REPL.Terminals.TTYTerminal, REPL.LineEdit.ModalInterface, REPL.LineEdit.MIState}) -precompile(Tuple{typeof(REPL.LineEdit.show_completions), REPL.LineEdit.PromptState, Array{String, 1}}) -precompile(Tuple{typeof(REPL.LineEdit.terminal), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.LineEdit.update_display_buffer), REPL.LineEdit.SearchState, REPL.LineEdit.SearchState}) -precompile(Tuple{typeof(REPL.REPLCompletions.get_type), Symbol, Module}) -precompile(Tuple{typeof(REPL.REPLCompletions.get_value), Symbol, Module}) -precompile(Tuple{typeof(REPL.Terminals.beep), REPL.LineEdit.PromptState, Float64, Float64, Float64}) -precompile(Tuple{typeof(REPL.Terminals.cmove_col), REPL.Terminals.TTYTerminal, Int64}) -precompile(Tuple{typeof(REPL.Terminals.cmove_down), REPL.Terminals.TTYTerminal, Int64}) -precompile(Tuple{typeof(REPL.Terminals.hascolor), REPL.Terminals.TTYTerminal}) -precompile(Tuple{typeof(REPL.accessible), Module}) -precompile(Tuple{typeof(REPL.banner), REPL.Terminals.TTYTerminal, REPL.Terminals.TTYTerminal}) -precompile(Tuple{typeof(REPL.eval), Module, Expr}) -precompile(Tuple{typeof(REPL.eval), Module, String}) -precompile(Tuple{typeof(REPL.eval_user_input), Expr, REPL.REPLBackend}) -precompile(Tuple{typeof(REPL.filtervalid), Array{Any, 1}}) -precompile(Tuple{typeof(REPL.fuzzysort), String, Array{String, 1}}) -precompile(Tuple{typeof(REPL.helpmode), Base.TTY, String}) -precompile(Tuple{typeof(REPL.hist_from_file), REPL.REPLHistoryProvider, Base.IOStream, String}) -precompile(Tuple{typeof(REPL.insert_hlines), Base.TTY, Markdown.MD}) -precompile(Tuple{typeof(REPL.levsort), String, Array{String, 1}}) -precompile(Tuple{typeof(REPL.lookup_doc), Symbol}) -precompile(Tuple{typeof(REPL.print_response), REPL.LineEditREPL, Array{Float64, 1}, Nothing, Bool, Bool}) -precompile(Tuple{typeof(REPL.print_response), REPL.LineEditREPL, ErrorException, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}, Bool, Bool}) -precompile(Tuple{typeof(REPL.print_response), REPL.Terminals.TTYTerminal, Array{Float64, 1}, Nothing, Bool, Bool, Nothing}) -precompile(Tuple{typeof(REPL.print_response), REPL.Terminals.TTYTerminal, ErrorException, Array{Union{Ptr{Nothing}, Base.InterpreterIP}, 1}, Bool, Bool, Nothing}) -precompile(Tuple{typeof(REPL.repl), Base.TTY, Symbol}) -precompile(Tuple{typeof(REPL.repl_corrections), Base.TTY, String}) -precompile(Tuple{typeof(REPL.repl_latex), Base.TTY, String}) -precompile(Tuple{typeof(REPL.repl_search), Base.TTY, String}) -precompile(Tuple{typeof(REPL.return_callback), REPL.LineEdit.PromptState}) -precompile(Tuple{typeof(REPL.run_repl), REPL.LineEditREPL, typeof(x->nothing)}) -precompile(Tuple{typeof(REPL.send_to_backend), Expr, Base.Channel{Any}, Base.Channel{Any}}) -precompile(Tuple{typeof(REPL.send_to_backend), Expr, REPL.REPLBackendRef}) -precompile(Tuple{typeof(REPL.send_to_backend), String, Base.Channel{Any}, Base.Channel{Any}}) -precompile(Tuple{typeof(REPL.send_to_backend), String, REPL.REPLBackendRef}) -precompile(Tuple{typeof(REPL.setup_interface), REPL.LineEditREPL, Bool, Array{Base.Dict{Any, Any}, 1}}) -precompile(Tuple{typeof(REPL.setup_interface), REPL.LineEditREPL, Bool, Base.Dict{Any, Any}}) -precompile(Tuple{typeof(Random.DSFMT.__init__)}) -precompile(Tuple{typeof(Random.__init__)}) -if Base.USE_GPL_LIBS - precompile(Tuple{typeof(SuiteSparse.CHOLMOD.__init__)}) -end -precompile(Tuple{typeof(Test.get_test_result), Expr, LineNumberNode}) -precompile(Tuple{typeof(Test.get_test_result), Symbol, LineNumberNode}) -precompile(Tuple{typeof(Test.test_expr!), String, Expr}) -precompile(Tuple{typeof(Test.test_expr!), String, Symbol}) end end diff --git a/base/process.jl b/base/process.jl index 5cd44be44aa79..68228df104c0b 100644 --- a/base/process.jl +++ b/base/process.jl @@ -795,7 +795,7 @@ arg_gen(x::AbstractString) = String[cstr(x)] arg_gen(cmd::Cmd) = cmd.exec function arg_gen(head) - if applicable(start, head) + if isiterable(typeof(head)) vals = String[] for x in head push!(vals, cstr(string(x))) @@ -834,10 +834,10 @@ wait(x::ProcessChain) = for p in x.processes; wait(p); end show(io::IO, p::Process) = print(io, "Process(", p.cmd, ", ", process_status(p), ")") # allow the elements of the Cmd to be accessed as an array or iterator -for f in (:length, :firstindex, :lastindex, :start, :keys, :first, :last) +for f in (:length, :firstindex, :lastindex, :keys, :first, :last, :iterate) @eval $f(cmd::Cmd) = $f(cmd.exec) end eltype(::Type{Cmd}) = eltype(fieldtype(Cmd, :exec)) -for f in (:next, :done, :getindex) +for f in (:iterate, :getindex) @eval $f(cmd::Cmd, i) = $f(cmd.exec, i) end diff --git a/base/range.jl b/base/range.jl index 0fc93c5281cc1..5806242dfa11c 100644 --- a/base/range.jl +++ b/base/range.jl @@ -450,40 +450,44 @@ copy(r::AbstractRange) = r ## iteration -start(r::LinRange) = 1 -done(r::LinRange, i::Int) = length(r) < i -function next(r::LinRange, i::Int) +function iterate(r::LinRange, i::Int=1) @_inline_meta + length(r) < i && return nothing unsafe_getindex(r, i), i+1 end -start(r::StepRange) = oftype(r.start + r.step, r.start) -next(r::StepRange{T}, i) where {T} = (convert(T,i), i+r.step) -done(r::StepRange, i) = isempty(r) | (i < min(r.start, r.stop)) | (i > max(r.start, r.stop)) -done(r::StepRange, i::Integer) = - isempty(r) | (i == oftype(i, r.stop) + r.step) - -start(r::StepRangeLen) = 1 -next(r::StepRangeLen{T}, i) where {T} = unsafe_getindex(r, i), i+1 -done(r::StepRangeLen, i) = i > length(r) +function iterate(r::StepRange{T}, i=oftype(r.start + r.step, r.start)) where {T} + if i isa Integer + (isempty(r) | (i == oftype(i, r.stop) + r.step)) && return nothing + else + (isempty(r) | (i < min(r.start, r.stop)) | (i > max(r.start, r.stop))) && return nothing + end + (convert(T,i), i+r.step) +end -start(r::UnitRange{T}) where {T} = oftype(r.start + oneunit(T), r.start) -next(r::AbstractUnitRange{T}, i) where {T} = (convert(T, i), i + oneunit(T)) -done(r::AbstractUnitRange{T}, i) where {T} = i == oftype(i, r.stop) + oneunit(T) +iterate(r::StepRangeLen{T}, i=1) where {T} = i > length(r) ? nothing : (unsafe_getindex(r, i), i+1) -start(r::OneTo{T}) where {T} = oneunit(T) +function iterate(r::AbstractUnitRange{T}, i) where {T} + i == oftype(i, r.stop) + oneunit(T) && return nothing + (convert(T, i), i + oneunit(T)) +end +iterate(r::AbstractUnitRange{T}) where {T} = iterate(r, oftype(r.start + oneunit(T), r.start)) +iterate(r::OneTo{T}) where {T} = iterate(r, oneunit(T)) # some special cases to favor default Int type to avoid overflow let smallint = (Int === Int64 ? Union{Int8,UInt8,Int16,UInt16,Int32,UInt32} : Union{Int8,UInt8,Int16,UInt16}) - global start - global next - start(r::StepRange{<:smallint}) = convert(Int, r.start) - next(r::StepRange{T}, i) where {T<:smallint} = (i % T, i + r.step) - start(r::UnitRange{<:smallint}) = convert(Int, r.start) - next(r::AbstractUnitRange{T}, i) where {T<:smallint} = (i % T, i + 1) - start(r::OneTo{<:smallint}) = 1 + global iterate + function iterate(r::StepRange{T}, i=convert(Int, r.start)) where {T<:smallint} + (isempty(r) | (i == oftype(i, r.stop) + r.step)) && return nothing + (i % T, i + r.step) + end + function iterate(r::AbstractUnitRange{T}, i=convert(Int, r.start)) where {T<:smallint} + i == oftype(i, r.stop) + 1 && return nothing + (i % T, i + 1) + end + iterate(r::OneTo{T}) where {T<:smallint} = iterate(r, 1) end ## indexing @@ -604,13 +608,10 @@ function ==(r::AbstractRange, s::AbstractRange) if lr != length(s) return false end - u, v = start(r), start(s) - while !done(r, u) - x, u = next(r, u) - y, v = next(s, v) - if x != y - return false - end + yr, ys = iterate(r), iterate(s) + while yr !== nothing + yr[1] == ys[1] || return false + yr, ys = iterate(r, yr[2]), iterate(s, ys[2]) end return true end diff --git a/base/reduce.jl b/base/reduce.jl index 73d2b96e589c9..e30e11b85e18e 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -34,20 +34,18 @@ mul_prod(x::SmallUnsigned,y::SmallUnsigned) = UInt(x) * UInt(y) ## foldl && mapfoldl -@noinline function mapfoldl_impl(f, op, v0, itr, i) +@noinline function mapfoldl_impl(f, op, v0, itr, i...) # Unroll the while loop once; if v0 is known, the call to op may # be evaluated at compile time - if done(itr, i) - return v0 - else - (x, i) = next(itr, i) - v = op(v0, f(x)) - while !done(itr, i) - @inbounds (x, i) = next(itr, i) - v = op(v, f(x)) - end - return v + y = iterate(itr, i...) + y === nothing && return v0 + v = op(v0, f(y[1])) + while true + y = iterate(itr, y[2]) + y === nothing && break + v = op(v, f(y[1])) end + return v end """ @@ -56,7 +54,7 @@ end Like [`mapreduce`](@ref), but with guaranteed left associativity, as in [`foldl`](@ref). `v0` will be used exactly once. """ -mapfoldl(f, op, v0, itr) = mapfoldl_impl(f, op, v0, itr, start(itr)) +mapfoldl(f, op, v0, itr) = mapfoldl_impl(f, op, v0, itr) """ mapfoldl(f, op, itr) @@ -67,11 +65,11 @@ Specifically, `mapfoldl(f, op, itr)` produces the same result as In general, this cannot be used with empty collections (see [`reduce(op, itr)`](@ref)). """ function mapfoldl(f, op, itr) - i = start(itr) - if done(itr, i) + y = iterate(itr) + if y === nothing return Base.mapreduce_empty_iter(f, op, itr, IteratorEltype(itr)) end - (x, i) = next(itr, i) + (x, i) = y v0 = mapreduce_first(f, op, x) mapfoldl_impl(f, op, v0, itr, i) end @@ -553,12 +551,14 @@ julia> extrema([9,pi,4.5]) ``` """ function extrema(itr) - s = start(itr) - done(itr, s) && throw(ArgumentError("collection must be non-empty")) - (v, s) = next(itr, s) + y = iterate(itr) + y === nothing && throw(ArgumentError("collection must be non-empty")) + (v, s) = y vmin = vmax = v - while !done(itr, s) - (x, s) = next(itr, s) + while true + y = iterate(itr, s) + y === nothing && break + (x, s) = y vmax = max(x, vmax) vmin = min(x, vmin) end diff --git a/base/reducedim.jl b/base/reducedim.jl index 5ea2547769726..43d9c36f68fca 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -669,7 +669,7 @@ function findminmax!(f, Rval, Rind, A::AbstractArray{T,N}) where {T,N} indsAt, indsRt = safe_tail(axes(A)), safe_tail(axes(Rval)) keep, Idefault = Broadcast.shapeindexer(indsRt) ks = keys(A) - kss = start(ks) + y = iterate(ks) zi = zero(eltype(ks)) if reducedim1(Rval, A) i1 = first(indices1(Rval)) @@ -678,12 +678,13 @@ function findminmax!(f, Rval, Rind, A::AbstractArray{T,N}) where {T,N} tmpRv = Rval[i1,IR] tmpRi = Rind[i1,IR] for i in axes(A,1) - k, kss = next(ks, kss) + k, kss = y::Tuple tmpAv = A[i,IA] if tmpRi == zi || (tmpRv == tmpRv && (tmpAv != tmpAv || f(tmpAv, tmpRv))) tmpRv = tmpAv tmpRi = k end + y = iterate(ks, kss) end Rval[i1,IR] = tmpRv Rind[i1,IR] = tmpRi @@ -692,7 +693,7 @@ function findminmax!(f, Rval, Rind, A::AbstractArray{T,N}) where {T,N} @inbounds for IA in CartesianIndices(indsAt) IR = Broadcast.newindex(IA, keep, Idefault) for i in axes(A, 1) - k, kss = next(ks, kss) + k, kss = y::Tuple tmpAv = A[i,IA] tmpRv = Rval[i,IR] tmpRi = Rind[i,IR] @@ -700,6 +701,7 @@ function findminmax!(f, Rval, Rind, A::AbstractArray{T,N}) where {T,N} Rval[i,IR] = tmpAv Rind[i,IR] = k end + y = iterate(ks, kss) end end end diff --git a/base/reflection.jl b/base/reflection.jl index 8e83052233610..b932e306fa662 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -687,9 +687,7 @@ end length(m::MethodList) = length(m.ms) isempty(m::MethodList) = isempty(m.ms) -start(m::MethodList) = start(m.ms) -done(m::MethodList, s) = done(m.ms, s) -next(m::MethodList, s) = next(m.ms, s) +iterate(m::MethodList, s...) = iterate(m.ms, s...) eltype(::Type{MethodList}) = Method function MethodList(mt::Core.MethodTable) diff --git a/base/regex.jl b/base/regex.jl index 6da10eda0742a..11327e8d6741d 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -176,7 +176,7 @@ julia> m.captures julia> m.match "aba" -julia> match(rx, "cabac", 3) == nothing +julia> match(rx, "cabac", 3) === nothing true ``` """ @@ -229,7 +229,7 @@ ncodeunits(s::SubstitutionString) = ncodeunits(s.string) codeunit(s::SubstitutionString) = codeunit(s.string) codeunit(s::SubstitutionString, i::Integer) = codeunit(s.string, i) isvalid(s::SubstitutionString, i::Integer) = isvalid(s.string, i) -next(s::SubstitutionString, i::Integer) = next(s.string, i) +iterate(s::SubstitutionString, i::Integer...) = iterate(s.string, i...) function show(io::IO, s::SubstitutionString) print(io, "s") @@ -319,24 +319,9 @@ struct RegexMatchIterator end compile(itr::RegexMatchIterator) = (compile(itr.regex); itr) eltype(::Type{RegexMatchIterator}) = RegexMatch -start(itr::RegexMatchIterator) = match(itr.regex, itr.string, 1, UInt32(0)) -done(itr::RegexMatchIterator, prev_match) = (prev_match === nothing) IteratorSize(::Type{RegexMatchIterator}) = SizeUnknown() -# Assumes prev_match is not nothing -function next(itr::RegexMatchIterator, prev_match) - prevempty = isempty(prev_match.match) - - if itr.overlap - if !prevempty - offset = nextind(itr.string, prev_match.offset) - else - offset = prev_match.offset - end - else - offset = prev_match.offset + ncodeunits(prev_match.match) - end - +function iterate(itr::RegexMatchIterator, (offset,prevempty)=(1,false)) opts_nonempty = UInt32(PCRE.ANCHORED | PCRE.NOTEMPTY_ATSTART) while true mat = match(itr.regex, itr.string, offset, @@ -351,10 +336,19 @@ function next(itr::RegexMatchIterator, prev_match) break end else - return (prev_match, mat) + if itr.overlap + if !isempty(mat.match) + offset = nextind(itr.string, mat.offset) + else + offset = mat.offset + end + else + offset = mat.offset + ncodeunits(mat.match) + end + return (mat, (offset, isempty(mat.match))) end end - (prev_match, nothing) + nothing end """ diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index fa87746cc5bc2..bf1603e1693a9 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -28,10 +28,8 @@ struct ReshapedIndex{T} end # eachindex(A::ReshapedArray) = ReshapedArrayIterator(A) # TODO: uncomment this line -start(R::ReshapedArrayIterator) = start(R.iter) -@inline done(R::ReshapedArrayIterator, i) = done(R.iter, i) -@inline function next(R::ReshapedArrayIterator, i) - item, inext = next(R.iter, i) +@inline function iterate(R::ReshapedArrayIterator, i...) + item, inext = iterate(R.iter, i...) ReshapedIndex(item), inext end length(R::ReshapedArrayIterator) = length(R.iter) diff --git a/base/set.jl b/base/set.jl index 4ad6768d1bc3e..b33614b2e4c8f 100644 --- a/base/set.jl +++ b/base/set.jl @@ -51,10 +51,7 @@ pop!(s::Set, x, deflt) = x in s ? pop!(s, x) : deflt function pop!(s::Set) isempty(s) && throw(ArgumentError("set must be non-empty")) - idx = start(s.dict) - val = s.dict.keys[idx] - _delete!(s.dict, idx) - val + pop!(s.dict)[1] end delete!(s::Set, x) = (delete!(s.dict, x); s) @@ -68,10 +65,7 @@ sizehint!(s::Set, newsz) = (sizehint!(s.dict, newsz); s) empty!(s::Set) = (empty!(s.dict); s) rehash!(s::Set) = (rehash!(s.dict); s) -start(s::Set) = start(s.dict) -done(s::Set, state) = done(s.dict, state) -# NOTE: manually optimized to take advantage of Dict representation -next(s::Set, i) = (s.dict.keys[i], skip_deleted(s.dict, i+1)) +iterate(s::Set, i...) = iterate(KeySet(s.dict), i...) """ unique(itr) @@ -99,11 +93,9 @@ function unique(itr) T = @default_eltype(itr) out = Vector{T}() seen = Set{T}() - i = start(itr) - if done(itr, i) - return out - end - x, i = next(itr, i) + y = iterate(itr) + y === nothing && return out + x, i = y if !isconcretetype(T) && IteratorEltype(itr) == EltypeUnknown() S = typeof(x) return _unique_from(itr, S[x], Set{S}((x,)), i) @@ -115,8 +107,10 @@ end _unique_from(itr, out, seen, i) = unique_from(itr, out, seen, i) @inline function unique_from(itr, out::Vector{T}, seen, i) where T - while !done(itr, i) - x, i = next(itr, i) + while true + y = iterate(itr, i) + y === nothing && break + x, i = y S = typeof(x) if !(S === T || S <: T) R = promote_typejoin(S, T) @@ -169,15 +163,17 @@ end function _unique!(A::AbstractVector) seen = Set{eltype(A)}() idxs = eachindex(A) - i = state = start(idxs) + y = iterate(idxs) + count = 0 for x in A if x ∉ seen push!(seen, x) - i, state = next(idxs, state) - A[i] = x + count += 1 + A[y[1]] = x + y = iterate(idxs, y[2]) end end - resize!(A, i - first(idxs) + 1) + resize!(A, count) end # If A is grouped, so that each unique element is in a contiguous group, then we only @@ -188,15 +184,17 @@ function _groupedunique!(A::AbstractVector) isempty(A) && return A idxs = eachindex(A) y = first(A) - state = start(idxs) - i, state = next(idxs, state) - for x in A + # We always keep the first element + it = iterate(idxs, iterate(idxs)[2]) + count = 1 + for x in Iterators.drop(A, 1) if !isequal(x, y) - i, state = next(idxs, state) - y = A[i] = x + y = A[it[1]] = x + count += 1 + it = iterate(idxs, it[2]) end end - resize!(A, i - first(idxs) + 1) + resize!(A, count) end """ diff --git a/base/show.jl b/base/show.jl index d9ea1026d06a7..cf64550060323 100644 --- a/base/show.jl +++ b/base/show.jl @@ -679,22 +679,23 @@ function show_delim_array(io::IO, itr, op, delim, cl, delim_one, i1=1, n=typemax print(io, op) if !show_circular(io, itr) recur_io = IOContext(io, :SHOWN_SET => itr) - state = start(itr) + y = iterate(itr) first = true i0 = i1-1 - while i1 > 1 && !done(itr, state) - _, state = next(itr, state) + while i1 > 2 && y !== nothing + y = iterate(itr, y[2]) i1 -= 1 end - if !done(itr, state) + if y !== nothing typeinfo = get(io, :typeinfo, Any) while true - x, state = next(itr, state) + x = y[1] + y = iterate(itr, y[2]) show(IOContext(recur_io, :typeinfo => typeinfo <: Tuple ? fieldtype(typeinfo, i1+i0) : typeinfo), x) i1 += 1 - if done(itr, state) || i1 > n + if y === nothing || i1 > n delim_one && first && print(io, delim) break end diff --git a/base/some.jl b/base/some.jl index 851ee2a53f254..38a4052ed064e 100644 --- a/base/some.jl +++ b/base/some.jl @@ -73,7 +73,7 @@ coalesce(x::Union{Nothing, Missing}, y...) = coalesce(y...) """ notnothing(x) -Throw an error if `x == nothing`, and return `x` if not. +Throw an error if `x === nothing`, and return `x` if not. """ notnothing(x::Any) = x notnothing(::Nothing) = throw(ArgumentError("nothing passed to notnothing")) diff --git a/base/sort.jl b/base/sort.jl index e8a9c933cdb8c..2980c30acbd03 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -56,13 +56,15 @@ export # not exported by Base ## functions requiring only ordering ## function issorted(itr, order::Ordering) - state = start(itr) - done(itr,state) && return true - prev, state = next(itr, state) - while !done(itr, state) - this, state = next(itr, state) + y = iterate(itr) + y === nothing && return true + prev, state = y + y = iterate(itr, state) + while y !== nothing + this, state = y lt(order, this, prev) && return false prev = this + y = iterate(itr, state) end return true end diff --git a/base/stacktraces.jl b/base/stacktraces.jl index bc8ea3d2c6b30..492b346c7bb73 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -269,7 +269,7 @@ end is_top_level_frame(f::StackFrame) = f.linfo isa Core.CodeInfo || (f.linfo === nothing && f.func === top_level_scope_sym) function show_spec_linfo(io::IO, frame::StackFrame) - if frame.linfo == nothing + if frame.linfo === nothing if frame.func === empty_sym @printf(io, "ip:%#x", frame.pointer) elseif frame.func === top_level_scope_sym diff --git a/base/statistics.jl b/base/statistics.jl index 3a75670d3450d..a5310c3fc5d2c 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -16,18 +16,20 @@ julia> mean([√1, √2, √3]) ``` """ function mean(f::Callable, iterable) - state = start(iterable) - if done(iterable, state) + y = iterate(iterable) + if y == nothing throw(ArgumentError("mean of empty collection undefined: $(repr(iterable))")) end count = 1 - value, state = next(iterable, state) + value, state = y f_value = f(value) total = reduce_first(add_sum, f_value) - while !done(iterable, state) - value, state = next(iterable, state) + y = iterate(iterable, state) + while y !== nothing + value, state = y total += f(value) count += 1 + y = iterate(iterable, state) end return total/count end @@ -86,19 +88,21 @@ realXcY(x::Complex, y::Complex) = real(x)*real(y) + imag(x)*imag(y) var(iterable; corrected::Bool=true, mean=nothing) = _var(iterable, corrected, mean) function _var(iterable, corrected::Bool, mean) - state = start(iterable) - if done(iterable, state) + y = iterate(iterable) + if y === nothing throw(ArgumentError("variance of empty collection undefined: $(repr(iterable))")) end count = 1 - value, state = next(iterable, state) + value, state = y + y = iterate(iterable, state) if mean === nothing # Use Welford algorithm as seen in (among other places) # Knuth's TAOCP, Vol 2, page 232, 3rd edition. M = value / 1 S = real(zero(M)) - while !done(iterable, state) - value, state = next(iterable, state) + while y !== nothing + value, state = y + y = iterate(iterable, state) count += 1 new_M = M + (value - M) / count S = S + realXcY(value - M, value - new_M) @@ -112,8 +116,9 @@ function _var(iterable, corrected::Bool, mean) # Department of Computer Science, Stanford University, # because user can provide mean value that is different to mean(iterable) sum2 = abs2(value - mean::Number) - while !done(iterable, state) - value, state = next(iterable, state) + while y !== nothing + value, state = y + y = iterate(iterable, state) count += 1 sum2 += abs2(value - mean) end diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 0ea89b2921be5..ae669be14fb8b 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -22,7 +22,7 @@ about strings: Some string functions that extract code units, characters or substrings from strings error if you pass them out-of-bounds or invalid string indices. This -includes `codeunit(s, i)`, `s[i]`, and `next(s, i)`. Functions that do string +includes `codeunit(s, i)` and `s[i]`. Functions that do string index arithmetic take a more relaxed approach to indexing and give you the closest valid string index when in-bounds, or when out-of-bounds, behave as if there were an infinite number of characters padding each side of the string. @@ -95,7 +95,7 @@ In order for `isvalid(s, i)` to be an O(1) function, the encoding of `s` must be [self-synchronizing](https://en.wikipedia.org/wiki/Self-synchronizing_code) this is a basic assumption of Julia's generic string support. -See also: [`getindex`](@ref), [`next`](@ref), [`thisind`](@ref), +See also: [`getindex`](@ref), [`iterate`](@ref), [`thisind`](@ref), [`nextind`](@ref), [`prevind`](@ref), [`length`](@ref) # Examples @@ -122,24 +122,21 @@ Stacktrace: throw(MethodError(isvalid, (s, i))) : isvalid(s, Int(i)) """ - next(s::AbstractString, i::Integer) -> Tuple{<:AbstractChar, Int} + iterate(s::AbstractString, i::Integer) -> Union{Tuple{<:AbstractChar, Int}, Nothing} Return a tuple of the character in `s` at index `i` with the index of the start of the following character in `s`. This is the key method that allows strings to be iterated, yielding a sequences of characters. If `i` is out of bounds in `s` -then a bounds error is raised. The `next` function, as part of the iteration +then a bounds error is raised. The `iterate` function, as part of the iteration protocoal may assume that `i` is the start of a character in `s`. -See also: [`getindex`](@ref), [`start`](@ref), [`done`](@ref), -[`checkbounds`](@ref) +See also: [`getindex`](@ref), [`checkbounds`](@ref) """ -@propagate_inbounds next(s::AbstractString, i::Integer) = typeof(i) === Int ? - throw(MethodError(next, (s, i))) : next(s, Int(i)) +@propagate_inbounds iterate(s::AbstractString, i::Integer) = typeof(i) === Int ? + throw(MethodError(iterate, (s, i))) : iterate(s, Int(i)) ## basic generic definitions ## -start(s::AbstractString) = 1 -done(s::AbstractString, i::Integer) = i > ncodeunits(s) eltype(::Type{<:AbstractString}) = Char # some string types may use another AbstractChar sizeof(s::AbstractString) = ncodeunits(s) * sizeof(codeunit(s)) firstindex(s::AbstractString) = 1 @@ -147,7 +144,7 @@ lastindex(s::AbstractString) = thisind(s, ncodeunits(s)) function getindex(s::AbstractString, i::Integer) @boundscheck checkbounds(s, i) - @inbounds return isvalid(s, i) ? next(s, i)[1] : string_index_err(s, i) + @inbounds return isvalid(s, i) ? iterate(s, i)[1] : string_index_err(s, i) end getindex(s::AbstractString, i::Colon) = s @@ -476,9 +473,7 @@ keys(s::AbstractString) = EachStringIndex(s) length(e::EachStringIndex) = length(e.s) first(::EachStringIndex) = 1 last(e::EachStringIndex) = lastindex(e.s) -start(e::EachStringIndex) = start(e.s) -next(e::EachStringIndex, state) = (state, nextind(e.s, state)) -done(e::EachStringIndex, state) = done(e.s, state) +iterate(e::EachStringIndex, state=firstindex(e.s)) = state > ncodeunits(e.s) ? nothing : (state, nextind(e.s, state)) eltype(::Type{<:EachStringIndex}) = Int """ @@ -617,12 +612,8 @@ julia> "Test "^3 (^)(s::Union{AbstractString,AbstractChar}, r::Integer) = repeat(s, r) # reverse-order iteration for strings and indices thereof -start(r::Iterators.Reverse{<:AbstractString}) = lastindex(r.itr) -done(r::Iterators.Reverse{<:AbstractString}, i) = i < start(r.itr) -next(r::Iterators.Reverse{<:AbstractString}, i) = (r.itr[i], prevind(r.itr, i)) -start(r::Iterators.Reverse{<:EachStringIndex}) = lastindex(r.itr.s) -done(r::Iterators.Reverse{<:EachStringIndex}, i) = i < start(r.itr.s) -next(r::Iterators.Reverse{<:EachStringIndex}, i) = (i, prevind(r.itr.s, i)) +iterate(r::Iterators.Reverse{<:AbstractString}, i=lastindex(r.itr)) = i < firstindex(r.itr) ? nothing : (r.itr[i], prevind(r.itr, i)) +iterate(r::Iterators.Reverse{<:EachStringIndex}, i=lastindex(r.itr.s)) = i < firstindex(r.itr.s) ? nothing : (i, prevind(r.itr.s, i)) ## code unit access ## @@ -644,9 +635,7 @@ strides(s::CodeUnits) = (1,) elsize(s::CodeUnits{T}) where {T} = sizeof(T) @propagate_inbounds getindex(s::CodeUnits, i::Int) = codeunit(s.s, i) IndexStyle(::Type{<:CodeUnits}) = IndexLinear() -start(s::CodeUnits) = 1 -next(s::CodeUnits, i) = (@_propagate_inbounds_meta; (s[i], i+1)) -done(s::CodeUnits, i) = (@_inline_meta; i == length(s)+1) +iterate(s::CodeUnits, i=1) = (@_propagate_inbounds_meta; i == length(s)+1 ? nothing : (s[i], i+1)) write(io::IO, s::CodeUnits) = write(io, s.s) diff --git a/base/strings/string.jl b/base/strings/string.jl index f5c17c0a18a65..7ba953790da3d 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -171,7 +171,8 @@ is_valid_continuation(c) = c & 0xc0 == 0x80 ## required core functionality ## -@propagate_inbounds function next(s::String, i::Int) +@propagate_inbounds function iterate(s::String, i::Int=firstindex(s)) + i > ncodeunits(s) && return nothing b = codeunit(s, i) u = UInt32(b) << 24 between(b, 0x80, 0xf7) || return reinterpret(Char, u), i+1 diff --git a/base/strings/substring.jl b/base/strings/substring.jl index 631d191dd678b..c593aaac58f87 100644 --- a/base/strings/substring.jl +++ b/base/strings/substring.jl @@ -62,9 +62,12 @@ function codeunit(s::SubString, i::Integer) @inbounds return codeunit(s.string, s.offset + i) end -function next(s::SubString, i::Integer) +function iterate(s::SubString, i::Integer=firstindex(s)) + i == ncodeunits(s)+1 && return nothing @boundscheck checkbounds(s, i) - @inbounds c, i = next(s.string, s.offset + i) + y = iterate(s.string, s.offset + i) + y === nothing && return nothing + c, i = y return c, i - s.offset end diff --git a/base/strings/unicode.jl b/base/strings/unicode.jl index 98687d93d00e5..39eb6b015ff03 100644 --- a/base/strings/unicode.jl +++ b/base/strings/unicode.jl @@ -3,8 +3,8 @@ # Various Unicode functionality from the utf8proc library module Unicode -import Base: show, ==, hash, string, Symbol, isless, length, eltype, start, - next, done, convert, isvalid, ismalformed, isoverlong +import Base: show, ==, hash, string, Symbol, isless, length, eltype, + convert, isvalid, ismalformed, isoverlong, iterate # whether codepoints are valid Unicode scalar values, i.e. 0-0xd7ff, 0xe000-0x10ffff @@ -649,22 +649,22 @@ function length(g::GraphemeIterator{S}) where {S} return n end -start(g::GraphemeIterator) = (start(g.s), Ref{Int32}(0)) -done(g::GraphemeIterator, i) = done(g.s, i[1]) - -function next(g::GraphemeIterator, i_) +function iterate(g::GraphemeIterator, i_=(Int32(0),firstindex(g.s))) s = g.s - i, state = i_ + statei, i = i_ + state = Ref{Int32}(statei) j = i - c0, k = next(s, i) - while !done(s, k) # loop until next grapheme is s[i:j] - c, ℓ = next(s, k) + y = iterate(s, i) + y === nothing && return nothing + c0, k = y + while k <= ncodeunits(s) # loop until next grapheme is s[i:j] + c, ℓ = iterate(s, k) isgraphemebreak!(state, c0, c) && break j = k k = ℓ c0 = c end - return (SubString(s, i, j), (k, state)) + return (SubString(s, i, j), (state[], k)) end ==(g1::GraphemeIterator, g2::GraphemeIterator) = g1.s == g2.s diff --git a/base/strings/util.jl b/base/strings/util.jl index 5106105f7a8c6..2eb78161d9a40 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -313,7 +313,7 @@ function _split(str::AbstractString, splitter, limit::Integer, keepempty::Bool, j, k = first(r), nextind(str,last(r)) end end - if keepempty || !done(str,i) + if keepempty || i <= ncodeunits(str) push!(strs, SubString(str,i)) end return strs diff --git a/base/sysimg.jl b/base/sysimg.jl index 662f6c217da25..c4fcbd7049eee 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -295,6 +295,9 @@ end end end +# missing values +include("missing.jl") + # version include("version.jl") @@ -419,9 +422,6 @@ include("client.jl") # statistics include("statistics.jl") -# missing values -include("missing.jl") - # worker threads include("threadcall.jl") diff --git a/base/task.jl b/base/task.jl index e46f3426049c0..735b78f3f074f 100644 --- a/base/task.jl +++ b/base/task.jl @@ -34,9 +34,7 @@ end length(c::CompositeException) = length(c.exceptions) push!(c::CompositeException, ex) = push!(c.exceptions, ex) isempty(c::CompositeException) = isempty(c.exceptions) -start(c::CompositeException) = start(c.exceptions) -next(c::CompositeException, state) = next(c.exceptions, state) -done(c::CompositeException, state) = done(c.exceptions, state) +iterate(c::CompositeException, state...) = iterate(c.exceptions, state...) eltype(::Type{CompositeException}) = Any function showerror(io::IO, ex::CompositeException) diff --git a/base/tuple.jl b/base/tuple.jl index 669f6e224e6e6..c6a50da418657 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -35,9 +35,7 @@ _setindex(v, i::Integer) = () ## iterating ## -start(t::Tuple) = 1 -done(t::Tuple, i::Int) = (length(t) < i) -next(t::Tuple, i::Int) = (t[i], i+1) +iterate(t::Tuple, i::Int=1) = length(t) < i ? nothing : (t[i], i+1) keys(t::Tuple) = OneTo(length(t)) @@ -56,9 +54,18 @@ end # this allows partial evaluation of bounded sequences of next() calls on tuples, # while reducing to plain next() for arbitrary iterables. -indexed_next(t::Tuple, i::Int, state) = (t[i], i+1) -indexed_next(a::Array, i::Int, state) = (a[i], i+1) -indexed_next(I, i, state) = done(I,state) ? throw(BoundsError(I, i)) : next(I, state) +indexed_iterate(t::Tuple, i::Int, state=1) = (@_inline_meta; (t[i], i+1)) +indexed_iterate(a::Array, i::Int, state=1) = (@_inline_meta; (a[i], i+1)) +function indexed_iterate(I, i) + x = iterate(I) + x === nothing && throw(BoundsError(I, i)) + x +end +function indexed_iterate(I, i, state) + x = iterate(I, state) + x === nothing && throw(BoundsError(I, i)) + x +end # Use dispatch to avoid a branch in first first(::Tuple{}) = throw(ArgumentError("tuple must be non-empty")) @@ -229,25 +236,25 @@ function (T::All16{E,N})(itr) where {E,N} (elts...,) end -(::Type{T})(itr) where {T<:Tuple} = _totuple(T, itr, start(itr)) +(::Type{T})(itr) where {T<:Tuple} = _totuple(T, itr) -_totuple(::Type{Tuple{}}, itr, s) = () +_totuple(::Type{Tuple{}}, itr, s...) = () function _totuple_err(@nospecialize T) @_noinline_meta throw(ArgumentError("too few elements for tuple type $T")) end -function _totuple(T, itr, s) +function _totuple(T, itr, s...) @_inline_meta - done(itr, s) && _totuple_err(T) - v, s = next(itr, s) - (convert(tuple_type_head(T), v), _totuple(tuple_type_tail(T), itr, s)...) + y = iterate(itr, s...) + y === nothing && _totuple_err(T) + (convert(tuple_type_head(T), y[1]), _totuple(tuple_type_tail(T), itr, y[2])...) end -_totuple(::Type{Tuple{Vararg{E}}}, itr, s) where {E} = (collect(E, Iterators.rest(itr,s))...,) +_totuple(::Type{Tuple{Vararg{E}}}, itr, s...) where {E} = (collect(E, Iterators.rest(itr,s...))...,) -_totuple(::Type{Tuple}, itr, s) = (collect(Iterators.rest(itr,s))...,) +_totuple(::Type{Tuple}, itr, s...) = (collect(Iterators.rest(itr,s...))...,) end diff --git a/base/version.jl b/base/version.jl index d7c09cd958eb0..515986285726f 100644 --- a/base/version.jl +++ b/base/version.jl @@ -153,16 +153,12 @@ function ident_cmp( A::Tuple{Vararg{Union{Integer,String}}}, B::Tuple{Vararg{Union{Integer,String}}}, ) - i = start(A) - j = start(B) - while !done(A,i) && !done(B,i) - a,i = next(A,i) - b,j = next(B,j) + for (a, b) in zip(A, B) c = ident_cmp(a,b) (c != 0) && return c end - done(A,i) && !done(B,j) ? -1 : - !done(A,i) && done(B,j) ? +1 : 0 + length(A) < length(B) ? -1 : + length(B) < length(A) ? +1 : 0 end function ==(a::VersionNumber, b::VersionNumber) diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index fb153d500d96e..32470135045de 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -60,7 +60,7 @@ function WeakKeyDict(kv) try Base.dict_with_eltype((K, V) -> WeakKeyDict{K, V}, kv, eltype(kv)) catch e - if !applicable(start, kv) || !all(x->isa(x,Union{Tuple,Pair}),kv) + if !isiterable(typeof(kv)) || !all(x->isa(x,Union{Tuple,Pair}),kv) throw(ArgumentError("WeakKeyDict(kv): kv needs to be an iterator of tuples or pairs")) else rethrow(e) @@ -104,7 +104,7 @@ getindex(wkh::WeakKeyDict{K}, key) where {K} = lock(() -> getindex(wkh.ht, key), isempty(wkh::WeakKeyDict) = isempty(wkh.ht) length(t::WeakKeyDict) = length(t.ht) -function start(t::WeakKeyDict{K,V}) where V where K +function iterate(t::WeakKeyDict{K,V}) where V where K gc_token = Ref{Bool}(false) # no keys will be deleted via finalizers until this token is gc'd finalizer(gc_token) do r if r[] @@ -113,15 +113,15 @@ function start(t::WeakKeyDict{K,V}) where V where K end end s = lock(t.lock) - gc_token[] = true - return (start(t.ht), gc_token) + iterate(t, (gc_token,)) end -done(t::WeakKeyDict, i) = done(t.ht, i[1]) -function next(t::WeakKeyDict{K,V}, i) where V where K - gc_token = i[2] - wkv, i = next(t.ht, i[1]) +function iterate(t::WeakKeyDict{K,V}, state) where V where K + gc_token = first(state) + y = iterate(t.ht, tail(state)...) + y === nothing && return nothing + wkv, i = y kv = Pair{K,V}(wkv[1].value::K, wkv[2]) - return (kv, (i, gc_token)) + return (kv, (gc_token, i)) end filter!(f, d::WeakKeyDict) = filter_in_one_pass!(f, d) diff --git a/doc/src/base/collections.md b/doc/src/base/collections.md index 63ec4378f7418..4a64aeaa82a2b 100644 --- a/doc/src/base/collections.md +++ b/doc/src/base/collections.md @@ -2,11 +2,11 @@ ## [Iteration](@id lib-collections-iteration) -Sequential iteration is implemented by the methods [`start`](@ref), [`done`](@ref), and [`next`](@ref). +Sequential iteration is implemented by the [`iterate`](@ref) function. The general `for` loop: ```julia -for i = I # or "for i in I" +for i in iter # or "for i = iter" # body end ``` @@ -14,10 +14,11 @@ end is translated into: ```julia -state = start(I) -while !done(I, state) - (i, state) = next(I, state) +next = iterate(iter) +while next !== nothing + (i, state) = next # body + next = iterate(iter, state) end ``` @@ -26,9 +27,7 @@ See the [manual section on the iteration interface](@ref man-interface-iteration iterable type. ```@docs -Base.start -Base.done -Base.next +Base.iterate Base.IteratorSize Base.IteratorEltype ``` diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index 6d72c3dea4e77..9441ae1e9303b 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -9,9 +9,8 @@ to generically build upon those behaviors. | Required methods |   | Brief description | |:------------------------------ |:---------------------- |:------------------------------------------------------------------------------------- | -| `start(iter)` |   | Returns the initial iteration state | -| `next(iter, state)` |   | Returns the current item and the next state | -| `done(iter, state)` |   | Tests if there are any items remaining | +| `iterate(iter)` |   | Returns either a tuple of the first item and initial state or `nothing` if empty | +| `iterate(iter, state)` |   | Returns either a tuple of the next item and next state or `nothing` if no items remain | | **Important optional methods** | **Default definition** | **Brief description** | | `IteratorSize(IterType)` | `HasLength()` | One of `HasLength()`, `HasShape{N}()`, `IsInfinite()`, or `SizeUnknown()` as appropriate | | `IteratorEltype(IterType)` | `HasEltype()` | Either `EltypeUnknown()` or `HasEltype()` as appropriate | @@ -31,15 +30,14 @@ to generically build upon those behaviors. | `HasEltype()` | `eltype(IterType)` | | `EltypeUnknown()` | (*none*) | -Sequential iteration is implemented by the methods [`start`](@ref), [`done`](@ref), and [`next`](@ref). Instead -of mutating objects as they are iterated over, Julia provides these three methods to keep track -of the iteration state externally from the object. The `start(iter)` method returns the initial -state for the iterable object `iter`. That state gets passed along to `done(iter, state)`, which -tests if there are any elements remaining, and `next(iter, state)`, which returns a tuple containing -the current element and an updated `state`. The `state` object can be anything, and is generally -considered to be an implementation detail private to the iterable object. +Sequential iteration is implemented by the [`iterate`](@ref) function. Instead +of mutating objects as they are iterated over, Julia iterators may keep track +of the iteration state externally from the object. The return value from iterate +is always either a tuple of a value and a state, or `nothing` if no elements remain. +The state object will be passed back to the iterate function on the next iteration +and is generally considered an implementation detail private to the iterable object. -Any object that defines these three methods is iterable and can be used in the [many functions that rely upon iteration](@ref lib-collections-iteration). +Any object that defines this function is iterable and can be used in the [many functions that rely upon iteration](@ref lib-collections-iteration). It can also be used directly in a `for` loop since the syntax: ```julia @@ -51,10 +49,11 @@ end is translated into: ```julia -state = start(iter) -while !done(iter, state) - (i, state) = next(iter, state) +next = iterate(iter) +while next !== nothing + (i, state) = next # body + next = iterate(iter, state) end ``` @@ -65,18 +64,14 @@ julia> struct Squares count::Int end -julia> Base.start(::Squares) = 1 - -julia> Base.next(S::Squares, state) = (state*state, state+1) - -julia> Base.done(S::Squares, state) = state > S.count +julia> Base.iterate(S::Squares, state=1) = state > S.count ? nothing : (state*state, state+1) julia> Base.eltype(::Type{Squares}) = Int # Note that this is defined for the type julia> Base.length(S::Squares) = S.count ``` -With only [`start`](@ref), [`next`](@ref), and [`done`](@ref) definitions, the `Squares` type is already pretty powerful. +With only [`iterate`](@ref) definition, the `Squares` type is already pretty powerful. We can iterate over all the elements: ```jldoctest squaretype @@ -142,16 +137,12 @@ be used in their specific case. It is also often useful to allow iteration over a collection in *reverse order* by iterating over [`Iterators.reverse(iterator)`](@ref). To actually support reverse-order iteration, however, an iterator -type `T` needs to implement `start`, `next`, and `done` methods for `Iterators.Reverse{T}`. +type `T` needs to implement `iterate` for `Iterators.Reverse{T}`. (Given `r::Iterators.Reverse{T}`, the underling iterator of type `T` is `r.itr`.) In our `Squares` example, we would implement `Iterators.Reverse{Squares}` methods: ```jldoctest squaretype -julia> Base.start(rS::Iterators.Reverse{Squares}) = rS.itr.count - -julia> Base.next(::Iterators.Reverse{Squares}, state) = (state*state, state-1) - -julia> Base.done(::Iterators.Reverse{Squares}, state) = state < 1 +julia> Base.iterate(rS::Iterators.Reverse{Squares}, state=rS.itr.count) = state < 1 ? nothing : (state*state, state-1) julia> collect(Iterators.reverse(Squares(4))) 4-element Array{Int64,1}: @@ -230,7 +221,7 @@ ourselves, we can officially define it as a subtype of an [`AbstractArray`](@ref | `IndexStyle(::Type)` | `IndexCartesian()` | Returns either `IndexLinear()` or `IndexCartesian()`. See the description below. | | `getindex(A, I...)` | defined in terms of scalar `getindex` | [Multidimensional and nonscalar indexing](@ref man-array-indexing) | | `setindex!(A, I...)` | defined in terms of scalar `setindex!` | [Multidimensional and nonscalar indexed assignment](@ref man-array-indexing) | -| `start`/`next`/`done` | defined in terms of scalar `getindex` | Iteration | +| `iterate` | defined in terms of scalar `getindex` | Iteration | | `length(A)` | `prod(size(A))` | Number of elements | | `similar(A)` | `similar(A, eltype(A), size(A))` | Return a mutable array with the same shape and element type | | `similar(A, ::Type{S})` | `similar(A, S, size(A))` | Return a mutable array with the same shape and the specified element type | diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index e5395d9a7f177..3fc848331e18b 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -602,11 +602,6 @@ Some other useful functions include: * [`length(str, i, j)`](@ref) the number of valid character indices in `str` from `i` to `j`. * [`ncodeunits(str)`](@ref) number of [code units](https://en.wikipedia.org/wiki/Character_encoding#Terminology) in a string. * [`codeunit(str, i)`](@ref) gives the code unit value in the string `str` at index `i`. - * [`i = start(str)`](@ref start) gives the first valid index at which a character can be found in `str` - (typically 1). - * [`c, j = next(str,i)`](@ref next) returns next character at or after the index `i` and the next valid - character index following that. With [`start`](@ref) and [`lastindex`](@ref), can be used to iterate - through the characters in `str`. * [`thisind(str, i)`](@ref) given an arbitrary index into a string find the first index of the character into which the index points. * [`nextind(str, i, n=1)`](@ref) find the start of the `n`th character starting after index `i`. * [`prevind(str, i, n=1)`](@ref) find the start of the `n`th character starting before index `i`. diff --git a/src/codegen.cpp b/src/codegen.cpp index 7759711c3f5ee..8c33740979c5a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6507,7 +6507,7 @@ static std::unique_ptr emit_function( }; // Codegen Phi nodes - std::map BB_rewrite_map; + std::map, BasicBlock*> BB_rewrite_map; std::vector ToDelete; for (auto &tup : ctx.PhiNodes) { jl_cgval_t phi_result; @@ -6526,8 +6526,9 @@ static std::unique_ptr emit_function( Value *V = NULL; BasicBlock *IncomingBB = come_from_bb[edge]; BasicBlock *FromBB = IncomingBB; - if (BB_rewrite_map.count(FromBB)) { - FromBB = BB_rewrite_map[IncomingBB]; + std::pair LookupKey(IncomingBB, PhiBB); + if (BB_rewrite_map.count(LookupKey)) { + FromBB = BB_rewrite_map[LookupKey]; } #ifndef JL_NDEBUG bool found_pred = false; @@ -6681,7 +6682,7 @@ static std::unique_ptr emit_function( // Check any phi nodes in the Phi block to see if by splitting the edges, // we made things inconsistent if (FromBB != ctx.builder.GetInsertBlock()) { - BB_rewrite_map[IncomingBB] = ctx.builder.GetInsertBlock(); + BB_rewrite_map[LookupKey] = ctx.builder.GetInsertBlock(); for (BasicBlock::iterator I = PhiBB->begin(); isa(I); ++I) { PHINode *PN = cast(I); ssize_t BBIdx = PN->getBasicBlockIndex(FromBB); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index b339a0e7b6614..5e75bc10bca1c 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1581,7 +1581,8 @@ (if (null? lhss) body (let* ((coll (make-ssavalue)) - (state (gensy)) + (next (gensy)) + (state (make-ssavalue)) (outer (outer? (car lhss))) (lhs (if outer (cadar lhss) (car lhss))) (body @@ -1591,8 +1592,7 @@ ,@(if (not outer) (map (lambda (v) `(warn-if-existing ,v)) (lhs-vars lhs)) '()) - ,(lower-tuple-assignment (list lhs state) - `(call (top next) ,coll ,state)) + ,(lower-tuple-assignment (list lhs state) next) ,(nest (cdr lhss) (cdr itrs)))) (body (if (null? (cdr lhss)) @@ -1602,13 +1602,15 @@ ,body)) `(scope-block ,body)))) `(block (= ,coll ,(car itrs)) - (= ,state (call (top start) ,coll)) + (= ,next (call (top iterate) ,coll)) ;; TODO avoid `local declared twice` error from this ;;,@(if outer `((local ,lhs)) '()) ,@(if outer `((require-existing-local ,lhs)) '()) - (_while - (call (top not_int) (call (core typeassert) (call (top done) ,coll ,state) (core Bool))) - ,body)))))))) + (if (call (top not_int) (call (core ===) ,next (null))) + (_do_while + (block ,body + (= ,next (call (top iterate) ,coll ,state))) + (call (|.| (core Intrinsics) 'not_int) (call (core ===) ,next (null)))))))))))) ;; wrap `expr` in a function appropriate for consuming values from given ranges (define (func-for-generator-ranges expr range-exprs flat outervars) @@ -1978,13 +1980,12 @@ (st (gensy))) `(block ,@ini - (= ,st (call (top start) ,xx)) ,.(map (lambda (i lhs) (expand-forms (lower-tuple-assignment (list lhs st) - `(call (top indexed_next) - ,xx ,(+ i 1) ,st)))) + `(call (top indexed_iterate) + ,xx ,(+ i 1) ,.(if (eq? i 0) '() `(,st)))))) (iota (length lhss)) lhss) (unnecessary ,xx)))))) @@ -3644,6 +3645,14 @@ f(x) = yt(x) (compile (caddr e) break-labels #f #f) (emit `(goto ,topl)) (mark-label endl))) + ((_do_while) + (let* ((endl (make-label)) + (topl (make&mark-label))) + (compile (cadr e) break-labels #f #f) + (let ((test (compile-cond (caddr e) break-labels))) + (emit `(gotoifnot ,test ,endl))) + (emit `(goto ,topl)) + (mark-label endl))) ((break-block) (let ((endl (make-label))) (begin0 (compile (caddr e) diff --git a/stdlib/Dates/src/io.jl b/stdlib/Dates/src/io.jl index fadab27191714..a3d1d036a34f6 100644 --- a/stdlib/Dates/src/io.jl +++ b/stdlib/Dates/src/io.jl @@ -184,7 +184,9 @@ Delim(d::String) = Delim{String, length(d)}(d) @inline function tryparsenext(d::Delim{<:AbstractChar, N}, str, i::Int, len) where N for j = 1:N i > len && return nothing - c, i = next(str, i) + next = iterate(str, i) + @assert next !== nothing + c, i = next c != d.d && return nothing end return true, i @@ -192,13 +194,17 @@ end @inline function tryparsenext(d::Delim{String, N}, str, i::Int, len) where N i1 = i - i2 = start(d.d) + i2 = firstindex(d.d) for j = 1:N if i1 > len return nothing end - c1, i1 = next(str, i1) - c2, i2 = next(d.d, i2) + next1 = iterate(str, i1) + @assert next1 !== nothing + c1, i1 = next1 + next2 = iterate(d.d, i2) + @assert next2 !== nothing + c2, i2 = next2 if c1 != c2 return nothing end diff --git a/stdlib/Dates/src/parse.jl b/stdlib/Dates/src/parse.jl index 69b3bf2fcfbc5..07a65a73b70c3 100644 --- a/stdlib/Dates/src/parse.jl +++ b/stdlib/Dates/src/parse.jl @@ -162,7 +162,7 @@ end max_pos = max_width <= 0 ? len : min(i + max_width - 1, len) d::Int64 = 0 @inbounds while i <= max_pos - c, ii = next(str, i) + c, ii = iterate(str, i)::Tuple{Char, Int} if '0' <= c <= '9' d = d * 10 + (c - '0') else @@ -181,7 +181,7 @@ end word_start, word_end = i, 0 max_pos = maxchars <= 0 ? len : min(len, nextind(str, i, maxchars-1)) @inbounds while i <= max_pos - c, ii = next(str, i) + c, ii = iterate(str, i)::Tuple{Char, Int} if isletter(c) word_end = i else @@ -209,7 +209,7 @@ function Base.parse(::Type{DateTime}, s::AbstractString, df::typeof(ISODateTimeF i > end_pos && @goto error end - c, i = next(s, i) + c, i = iterate(s, i)::Tuple{Char, Int} c != '-' && @goto error i > end_pos && @goto done @@ -219,7 +219,7 @@ function Base.parse(::Type{DateTime}, s::AbstractString, df::typeof(ISODateTimeF i > end_pos && @goto done end - c, i = next(s, i) + c, i = iterate(s, i)::Tuple{Char, Int} c != '-' && @goto error i > end_pos && @goto done @@ -229,7 +229,7 @@ function Base.parse(::Type{DateTime}, s::AbstractString, df::typeof(ISODateTimeF i > end_pos && @goto done end - c, i = next(s, i) + c, i = iterate(s, i)::Tuple{Char, Int} c != 'T' && @goto error i > end_pos && @goto done @@ -239,7 +239,7 @@ function Base.parse(::Type{DateTime}, s::AbstractString, df::typeof(ISODateTimeF i > end_pos && @goto done end - c, i = next(s, i) + c, i = iterate(s, i)::Tuple{Char, Int} c != ':' && @goto error i > end_pos && @goto done @@ -249,7 +249,7 @@ function Base.parse(::Type{DateTime}, s::AbstractString, df::typeof(ISODateTimeF i > end_pos && @goto done end - c, i = next(s, i) + c, i = iterate(s, i)::Tuple{Char, Int} c != ':' && @goto error i > end_pos && @goto done @@ -259,7 +259,7 @@ function Base.parse(::Type{DateTime}, s::AbstractString, df::typeof(ISODateTimeF i > end_pos && @goto done end - c, i = next(s, i) + c, i = iterate(s, i)::Tuple{Char, Int} c != '.' && @goto error i > end_pos && @goto done diff --git a/stdlib/Dates/src/ranges.jl b/stdlib/Dates/src/ranges.jl index 5fe51b298c0b7..684e42c7f7461 100644 --- a/stdlib/Dates/src/ranges.jl +++ b/stdlib/Dates/src/ranges.jl @@ -31,9 +31,7 @@ function in(x::T, r::StepRange{T}) where T<:TimeType n >= 1 && n <= length(r) && r[n] == x end -Base.start(r::StepRange{<:TimeType}) = 0 -Base.next(r::StepRange{<:TimeType}, i::Int) = (r.start + r.step*i, i + 1) -Base.done(r::StepRange{<:TimeType,<:Period}, i::Integer) = length(r) <= i +Base.iterate(r::StepRange{<:TimeType}, i::Int=0) = length(r) <= i ? nothing : (r.start + r.step*i, i + 1) +(x::Period, r::AbstractRange{<:TimeType}) = (x + first(r)):step(r):(x + last(r)) +(r::AbstractRange{<:TimeType}, x::Period) = x + r diff --git a/stdlib/Dates/test/ranges.jl b/stdlib/Dates/test/ranges.jl index 0a23921a808e0..3d02def61b671 100644 --- a/stdlib/Dates/test/ranges.jl +++ b/stdlib/Dates/test/ranges.jl @@ -55,7 +55,7 @@ let @test maximum(dr) == last(dr) @test dr[1] == f @test dr[end] <= l - @test next(dr, start(dr)) == (first(dr), 1) + @test iterate(dr) == (first(dr), 1) if len < 10000 dr1 = [i for i in dr] @@ -113,7 +113,7 @@ let @test maximum(dr) == first(dr) @test dr[1] == l @test dr[end] >= f - @test next(dr, start(dr)) == (first(dr), 1) + @test iterate(dr) == (first(dr), 1) if len < 10000 dr1 = [i for i in dr] @@ -173,7 +173,7 @@ let @test maximum(dr) == last(dr) @test dr[1] == f @test dr[end] <= l - @test next(dr, start(dr)) == (first(dr), 1) + @test iterate(dr) == (first(dr), 1) if len < 10000 dr1 = [i for i in dr] @@ -231,7 +231,7 @@ let @test maximum(dr) == first(dr) @test dr[1] == l @test dr[end] >= f - @test next(dr, start(dr)) == (first(dr), 1) + @test iterate(dr) == (first(dr), 1) if len < 10000 dr1 = [i for i in dr] diff --git a/stdlib/DelimitedFiles/src/DelimitedFiles.jl b/stdlib/DelimitedFiles/src/DelimitedFiles.jl index 3af9a976c31f0..b7f0dae7ff50b 100644 --- a/stdlib/DelimitedFiles/src/DelimitedFiles.jl +++ b/stdlib/DelimitedFiles/src/DelimitedFiles.jl @@ -562,7 +562,7 @@ function colval(sbuff::String, startpos::Int, endpos::Int, cells::Array{Any,2}, end function colval(sbuff::String, startpos::Int, endpos::Int, cells::Array{<:AbstractChar,2}, row::Int, col::Int) if startpos == endpos - cells[row, col] = next(sbuff, startpos)[1] + cells[row, col] = iterate(sbuff, startpos)[1] return false else return true @@ -587,7 +587,7 @@ function dlm_parse(dbuff::String, eol::D, dlm::D, qchar::D, cchar::D, col_start_idx = 1 was_cr = false while idx <= slen - val,idx = next(dbuff, idx) + val,idx = iterate(dbuff, idx) if (is_eol = (Char(val) == Char(eol))) is_dlm = is_comment = is_cr = is_quote = false elseif (is_dlm = (is_default_dlm ? in(Char(val), _default_delims) : (Char(val) == Char(dlm)))) @@ -759,11 +759,12 @@ writedlm(io::IO, a::AbstractArray{<:Any,0}, dlm; opts...) = writedlm(io, reshape # write an iterable row as dlm-separated items function writedlm_row(io::IO, row, dlm, quotes) - state = start(row) - while !done(row, state) - (x, state) = next(row, state) + y = iterate(row) + while y !== nothing + (x, state) = y + y = iterate(row, state) writedlm_cell(io, x, dlm, quotes) - done(row, state) ? print(io,'\n') : print(io,dlm) + y === nothing ? print(io,'\n') : print(io,dlm) end end diff --git a/stdlib/Distributed/src/pmap.jl b/stdlib/Distributed/src/pmap.jl index dbbaabd43ed65..9eb55dadd035a 100644 --- a/stdlib/Distributed/src/pmap.jl +++ b/stdlib/Distributed/src/pmap.jl @@ -211,7 +211,8 @@ function process_batch_errors!(p, f, results, on_error, retry_delays, retry_chec if length(reprocess) > 0 errors = [x[2] for x in reprocess] exceptions = [x.ex for x in errors] - state = start(retry_delays) + state = iterate(retry_delays) + state != nothing && (state = state[2]) if (length(retry_delays) > 0) && (retry_check==nothing || all([retry_check(state,ex)[2] for ex in exceptions])) # BatchProcessingError.data is a tuple of original args @@ -256,13 +257,18 @@ julia> collect(c) """ function head_and_tail(c, n) head = Vector{eltype(c)}(undef, n) - s = start(c) - i = 0 - while i < n && !done(c, s) + n == 0 && return (head, c) + i = 1 + y = iterate(c) + y == nothing && return (resize!(head, 0), ()) + head[i] = y[1] + while i < n + y = iterate(c, y[2]) + y == nothing && return (resize!(head, i), ()) i += 1 - head[i], s = next(c, s) + head[i] = y[1] end - return resize!(head, i), Iterators.rest(c, s) + return head, Iterators.rest(c, s) end """ diff --git a/stdlib/Distributed/src/precompile.jl b/stdlib/Distributed/src/precompile.jl index fe2b32653fa2f..2842b8991803c 100644 --- a/stdlib/Distributed/src/precompile.jl +++ b/stdlib/Distributed/src/precompile.jl @@ -54,24 +54,6 @@ precompile(Tuple{typeof(Distributed.worker_id_from_socket), Sockets.TCPSocket}) precompile(Tuple{Type{Distributed.ClusterSerializer{Sockets.TCPSocket}}, Sockets.TCPSocket}) precompile(Tuple{typeof(Distributed.send_msg_), Distributed.Worker, Distributed.MsgHeader, Distributed.ResultMsg, Bool}) precompile(Tuple{typeof(Distributed.send_msg_now), Distributed.Worker, Distributed.MsgHeader, Distributed.ResultMsg}) -precompile(Tuple{Type{Core.Compiler.Generator{I, F} where F where I}, Type{Core.Compiler.Const}, Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{Type{Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}}, Type{Core.Compiler.Const}, Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{typeof(Core.Compiler.convert), Type{Tuple{Int64, typeof(Distributed.rmprocs)}}, Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{typeof(Core.Compiler.collect), Type{Any}, Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}}) -precompile(Tuple{typeof(Core.Compiler._collect), Type{Any}, Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}, Core.Compiler.HasLength}) -precompile(Tuple{typeof(Core.Compiler.length), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{typeof(Core.Compiler.copyto!), Array{Any, 1}, Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}}) -precompile(Tuple{typeof(Core.Compiler.start), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}}) -precompile(Tuple{typeof(Core.Compiler.start), Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{typeof(Core.Compiler.done), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}, Int64}) -precompile(Tuple{typeof(Core.Compiler.done), Tuple{Int64, typeof(Distributed.rmprocs)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.next), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}, Int64}) -precompile(Tuple{typeof(Core.Compiler.next), Tuple{Int64, typeof(Distributed.rmprocs)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Int64, typeof(Distributed.rmprocs)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.start), Tuple{typeof(Distributed.rmprocs), Int64}}) -precompile(Tuple{typeof(Core.Compiler.indexed_next), Tuple{typeof(Distributed.rmprocs), Int64}, Int64, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Distributed.rmprocs), Int64}, Int64}) precompile(Tuple{typeof(Distributed.register_worker_streams), Distributed.Worker}) precompile(Tuple{typeof(Distributed.register_worker_streams), Distributed.LocalProcess}) precompile(Tuple{Type{Distributed.ClusterSerializer{Sockets.TCPSocket}}, Sockets.TCPSocket}) @@ -81,15 +63,6 @@ precompile(Tuple{typeof(Base.convert), Type{Distributed.ClusterManager}, Distrib precompile(Tuple{typeof(Base.convert), Type{Distributed.WorkerConfig}, Distributed.WorkerConfig}) precompile(Tuple{typeof(Base.get), Base.Dict{Any, Any}, Distributed.RRID, Bool}) precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Any, Any}, Distributed.RRID}) -precompile(Tuple{typeof(Core.Compiler.isbits), Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{Type{Core.Compiler.Generator{I, F} where F where I}, Type{QuoteNode}, Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{Type{Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}}, Type{QuoteNode}, Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{typeof(Core.Compiler._collect), Type{Any}, Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}, Core.Compiler.HasLength}) -precompile(Tuple{typeof(Core.Compiler.length), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}}) -precompile(Tuple{typeof(Core.Compiler.copyto!), Array{Any, 1}, Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}}) -precompile(Tuple{typeof(Core.Compiler.start), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}}) -precompile(Tuple{typeof(Core.Compiler.done), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}, Int64}) -precompile(Tuple{typeof(Core.Compiler.next), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}, Int64}) precompile(Tuple{typeof(Distributed.local_remotecall_thunk), typeof(Distributed.rmprocs), Tuple{Int64}, Array{Any, 1}}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.Worker, Int64}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.LocalProcess, Int64}) @@ -140,39 +113,6 @@ precompile(Tuple{typeof(Serialization.serialize_cycle_header), Distributed.Clust precompile(Tuple{typeof(Serialization.serialize_any), Distributed.ClusterSerializer{Sockets.TCPSocket}, Type{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}}}) precompile(Tuple{typeof(Distributed.send_msg_), Distributed.Worker, Distributed.MsgHeader, Distributed.ResultMsg, Bool}) precompile(Tuple{typeof(Distributed.send_msg_now), Distributed.Worker, Distributed.MsgHeader, Distributed.ResultMsg}) -precompile(Tuple{Type{Core.Compiler.Generator{I, F} where F where I}, Type{Core.Compiler.Const}, Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{Type{Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}}, Type{Core.Compiler.Const}, Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{typeof(Core.Compiler.convert), Type{Tuple{Int64, typeof(Distributed.rmprocs)}}, Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{typeof(Core.Compiler.collect), Type{Any}, Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}}) -precompile(Tuple{typeof(Core.Compiler._collect), Type{Any}, Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}, Core.Compiler.HasLength}) -precompile(Tuple{typeof(Core.Compiler.length), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}}) -precompile(Tuple{typeof(Core.Compiler.length), Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{typeof(Core.Compiler.copyto!), Array{Any, 1}, Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}}) -precompile(Tuple{typeof(Core.Compiler.start), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}}) -precompile(Tuple{typeof(Core.Compiler.start), Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{typeof(Core.Compiler.done), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}, Int64}) -precompile(Tuple{typeof(Core.Compiler.done), Tuple{Int64, typeof(Distributed.rmprocs)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.next), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{Core.Compiler.Const}}, Int64}) -precompile(Tuple{typeof(Core.Compiler.next), Tuple{Int64, typeof(Distributed.rmprocs)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{Int64, typeof(Distributed.rmprocs)}, Int64}) -precompile(Tuple{typeof(Core.Compiler.start), Tuple{typeof(Distributed.rmprocs), Int64}}) -precompile(Tuple{typeof(Core.Compiler.indexed_next), Tuple{typeof(Distributed.rmprocs), Int64}, Int64, Int64}) -precompile(Tuple{typeof(Core.Compiler.getindex), Tuple{typeof(Distributed.rmprocs), Int64}, Int64}) -precompile(Tuple{typeof(Serialization.deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}}) -precompile(Tuple{typeof(Serialization.deserialize_cycle), Distributed.ClusterSerializer{Sockets.TCPSocket}, Expr}) -precompile(Tuple{typeof(Serialization.handle_deserialize), Distributed.ClusterSerializer{Sockets.TCPSocket}, Int32}) -precompile(Tuple{typeof(Serialization.deserialize_array), Distributed.ClusterSerializer{Sockets.TCPSocket}}) -precompile(Tuple{typeof(Serialization.deserialize_datatype), Distributed.ClusterSerializer{Sockets.TCPSocket}}) -precompile(Tuple{typeof(Serialization.deserialize_expr), Distributed.ClusterSerializer{Sockets.TCPSocket}, Int64}) -precompile(Tuple{typeof(Core.Compiler.isbits), Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{Type{Core.Compiler.Generator{I, F} where F where I}, Type{QuoteNode}, Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{Type{Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}}, Type{QuoteNode}, Tuple{Int64, typeof(Distributed.rmprocs)}}) -precompile(Tuple{typeof(Core.Compiler._collect), Type{Any}, Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}, Core.Compiler.HasLength}) -precompile(Tuple{typeof(Core.Compiler.length), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}}) -precompile(Tuple{typeof(Core.Compiler.copyto!), Array{Any, 1}, Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}}) -precompile(Tuple{typeof(Core.Compiler.start), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}}) -precompile(Tuple{typeof(Core.Compiler.done), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}, Int64}) -precompile(Tuple{typeof(Core.Compiler.next), Core.Compiler.Generator{Tuple{Int64, typeof(Distributed.rmprocs)}, Type{QuoteNode}}, Int64}) precompile(Tuple{typeof(Distributed.local_remotecall_thunk), typeof(Distributed.rmprocs), Tuple{Int64}, Array{Any, 1}}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.Worker, Int64}) precompile(Tuple{typeof(Distributed.remote_do), typeof(Distributed.rmprocs), Distributed.LocalProcess, Int64}) diff --git a/stdlib/LibGit2/src/config.jl b/stdlib/LibGit2/src/config.jl index e33e4ab46f448..46b826d1ae04a 100644 --- a/stdlib/LibGit2/src/config.jl +++ b/stdlib/LibGit2/src/config.jl @@ -192,35 +192,17 @@ function GitConfigIter(cfg::GitConfig, name::Regex) return GitConfigIter(ci_ptr[]) end -function Base.start(ci::GitConfigIter) +function Base.iterate(ci::GitConfigIter, state=nothing) entry_ptr_ptr = Ref{Ptr{ConfigEntry}}(C_NULL) err = ccall((:git_config_next, :libgit2), Cint, (Ptr{Ptr{ConfigEntry}}, Ptr{Cvoid}), entry_ptr_ptr, ci.ptr) if err == Cint(Error.GIT_OK) - state = unsafe_load(entry_ptr_ptr[]) + return (unsafe_load(entry_ptr_ptr[]), nothing) elseif err == Cint(Error.ITEROVER) - state = nothing + return nothing else throw(GitError(err)) end - return state -end - -Base.done(ci::GitConfigIter, state) = state === nothing - -function Base.next(ci::GitConfigIter, state) - entry = notnothing(state) - entry_ptr_ptr = Ref{Ptr{ConfigEntry}}(C_NULL) - err = ccall((:git_config_next, :libgit2), Cint, - (Ptr{Ptr{ConfigEntry}}, Ptr{Cvoid}), entry_ptr_ptr, ci.ptr) - if err == Cint(Error.GIT_OK) - state = unsafe_load(entry_ptr_ptr[]) - elseif err == Cint(Error.ITEROVER) - state = nothing - else - throw(GitError(err)) - end - return (entry, state) end Base.IteratorSize(::Type{GitConfigIter}) = Base.SizeUnknown() diff --git a/stdlib/LibGit2/src/deprecated.jl b/stdlib/LibGit2/src/deprecated.jl index 224afb937685d..8df06ef69dbac 100644 --- a/stdlib/LibGit2/src/deprecated.jl +++ b/stdlib/LibGit2/src/deprecated.jl @@ -44,7 +44,6 @@ end @eval Base @deprecate count(rb::$(GitRebase)) $(LibGit2.count)(rb) @eval Base @deprecate count(tree::$(GitTree)) $(LibGit2.count)(tree) @eval Base @deprecate count(f::Function, walker::$(GitRevWalker); kwargs...) $(LibGit2.count)(f, walker; kwargs...) -@eval Base @deprecate map(f::Function, bi::$(GitBranchIter)) $(LibGit2.map)(f, bi) @eval Base @deprecate map(f::Function, walker::$(GitRevWalker); kwargs...) $(LibGit2.map)(f, walker; kwargs...) # PR #24594 diff --git a/stdlib/LibGit2/src/reference.jl b/stdlib/LibGit2/src/reference.jl index b5728bd50d86e..7ff669e5316e0 100644 --- a/stdlib/LibGit2/src/reference.jl +++ b/stdlib/LibGit2/src/reference.jl @@ -318,40 +318,19 @@ function GitBranchIter(repo::GitRepo, flags::Cint=Cint(Consts.BRANCH_LOCAL)) return GitBranchIter(repo, bi_ptr[]) end -function Base.start(bi::GitBranchIter) +function Base.iterate(bi::GitBranchIter, state=nothing) ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) btype = Ref{Cint}() err = ccall((:git_branch_next, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cint}, Ptr{Cvoid}), ref_ptr_ptr, btype, bi.ptr) - err != Int(Error.GIT_OK) && return (nothing, -1, true) - return (GitReference(bi.owner, ref_ptr_ptr[]), btype[], false) -end - -Base.done(bi::GitBranchIter, state) = Bool(state[3]) - -function Base.next(bi::GitBranchIter, state) - ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) - btype = Ref{Cint}() - err = ccall((:git_branch_next, :libgit2), Cint, - (Ptr{Ptr{Cvoid}}, Ptr{Cint}, Ptr{Cvoid}), - ref_ptr_ptr, btype, bi.ptr) - err != Int(Error.GIT_OK) && return (state[1:2], (nothing, -1, true)) - return (state[1:2], (GitReference(bi.owner, ref_ptr_ptr[]), btype[], false)) + if err == Cint(Error.GIT_OK) + return ((GitReference(bi.owner, ref_ptr_ptr[]), btype[]), nothing) + elseif err == Cint(Error.ITEROVER) + return nothing + else + throw(GitError(err)) + end end Base.IteratorSize(::Type{GitBranchIter}) = Base.SizeUnknown() - -function map(f::Function, bi::GitBranchIter) - res = nothing - s = start(bi) - while !done(bi, s) - val = f(s[1:2]) - if res === nothing - res = Vector{typeof(val)}() - end - Base.push!(res, val) - val, s = next(bi, s) - end - return res -end diff --git a/stdlib/LibGit2/src/walker.jl b/stdlib/LibGit2/src/walker.jl index 1234a0d1d0a96..0546a6f024f77 100644 --- a/stdlib/LibGit2/src/walker.jl +++ b/stdlib/LibGit2/src/walker.jl @@ -25,22 +25,17 @@ function GitRevWalker(repo::GitRepo) return GitRevWalker(repo, w_ptr[]) end -function Base.start(w::GitRevWalker) +function Base.iterate(w::GitRevWalker, state=nothing) id_ptr = Ref(GitHash()) err = ccall((:git_revwalk_next, :libgit2), Cint, (Ptr{GitHash}, Ptr{Cvoid}), id_ptr, w.ptr) - err != Int(Error.GIT_OK) && return (nothing, true) - return (id_ptr[], false) -end - -Base.done(w::GitRevWalker, state) = Bool(state[2]) - -function Base.next(w::GitRevWalker, state) - id_ptr = Ref(GitHash()) - err = ccall((:git_revwalk_next, :libgit2), Cint, - (Ptr{GitHash}, Ptr{Cvoid}), id_ptr, w.ptr) - err != Int(Error.GIT_OK) && return (state[1], (nothing, true)) - return (state[1], (id_ptr[], false)) + if err == Cint(Error.GIT_OK) + return (id_ptr[], nothing) + elseif err == Cint(Error.ITEROVER) + return nothing + else + throw(GitError(err)) + end end Base.IteratorSize(::Type{GitRevWalker}) = Base.SizeUnknown() @@ -120,16 +115,10 @@ function map(f::Function, walker::GitRevWalker; else push_head!(walker) end - s = start(walker) - c = 0 repo = repository(walker) - while !done(walker, s) - val = f(s[1], repo) - Base.push!(res, val) - val, s = next(walker, s) - c +=1 - count == c && break + for val in (count == 0 ? walker : Iterators.take(walker, count)) + Base.push!(res, f(val, repo)) end return res end @@ -169,13 +158,10 @@ function count(f::Function, walker::GitRevWalker; else push_head!(walker) end - s = start(walker) repo = repository(walker) - while !done(walker, s) - val = f(s[1], repo) - _, s = next(walker, s) - c += (val == true) + for val in walker + c += f(val, repo) == true end return c end diff --git a/stdlib/LibGit2/test/libgit2.jl b/stdlib/LibGit2/test/libgit2.jl index 17ec68cfdcf3d..ab9353d1ba46c 100644 --- a/stdlib/LibGit2/test/libgit2.jl +++ b/stdlib/LibGit2/test/libgit2.jl @@ -885,7 +885,7 @@ mktempdir() do dir @test LibGit2.lookup_branch(repo, test_branch2, true) === nothing end end - branches = LibGit2.map(b->LibGit2.shortname(b[1]), LibGit2.GitBranchIter(repo)) + branches = map(b->LibGit2.shortname(b[1]), LibGit2.GitBranchIter(repo)) @test master_branch in branches @test test_branch in branches end @@ -1364,7 +1364,7 @@ mktempdir() do dir @test tag2 in tags # all tag in place - branches = LibGit2.map(b->LibGit2.shortname(b[1]), LibGit2.GitBranchIter(repo)) + branches = map(b->LibGit2.shortname(b[1]), LibGit2.GitBranchIter(repo)) @test master_branch in branches @test test_branch in branches diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index 0409a950497bc..2ecd4220095b4 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -251,11 +251,12 @@ diag(A::AbstractVector) = throw(ArgumentError("use diagm instead of diag to cons # special cases of vecnorm; note that they don't need to handle isempty(x) function generic_vecnormMinusInf(x) - s = start(x) - (v, s) = next(x, s) + (v, s) = iterate(x)::Tuple minabs = norm(v) - while !done(x, s) - (v, s) = next(x, s) + while true + y = iterate(x, s) + y === nothing && break + (v, s) = y vnorm = norm(v) minabs = ifelse(isnan(minabs) | (minabs < vnorm), minabs, vnorm) end @@ -263,11 +264,12 @@ function generic_vecnormMinusInf(x) end function generic_vecnormInf(x) - s = start(x) - (v, s) = next(x, s) + (v, s) = iterate(x)::Tuple maxabs = norm(v) - while !done(x, s) - (v, s) = next(x, s) + while true + y = iterate(x, s) + y === nothing && break + (v, s) = y vnorm = norm(v) maxabs = ifelse(isnan(maxabs) | (maxabs > vnorm), maxabs, vnorm) end @@ -275,13 +277,14 @@ function generic_vecnormInf(x) end function generic_vecnorm1(x) - s = start(x) - (v, s) = next(x, s) + (v, s) = iterate(x)::Tuple av = float(norm(v)) T = typeof(av) sum::promote_type(Float64, T) = av - while !done(x, s) - (v, s) = next(x, s) + while true + y = iterate(x, s) + y === nothing && break + (v, s) = y sum += norm(v) end return convert(T, sum) @@ -295,20 +298,23 @@ norm_sqr(x::Union{T,Complex{T},Rational{T}}) where {T<:Integer} = abs2(float(x)) function generic_vecnorm2(x) maxabs = vecnormInf(x) (maxabs == 0 || isinf(maxabs)) && return maxabs - s = start(x) - (v, s) = next(x, s) + (v, s) = iterate(x)::Tuple T = typeof(maxabs) if isfinite(_length(x)*maxabs*maxabs) && maxabs*maxabs != 0 # Scaling not necessary sum::promote_type(Float64, T) = norm_sqr(v) - while !done(x, s) - (v, s) = next(x, s) + while true + y = iterate(x, s) + y === nothing && break + (v, s) = y sum += norm_sqr(v) end return convert(T, sqrt(sum)) else sum = abs2(norm(v)/maxabs) - while !done(x, s) - (v, s) = next(x, s) + while true + y = iterate(x, s) + y === nothing && break + (v, s) = y sum += (norm(v)/maxabs)^2 end return convert(T, maxabs*sqrt(sum)) @@ -318,8 +324,7 @@ end # Compute L_p norm ‖x‖ₚ = sum(abs(x).^p)^(1/p) # (Not technically a "norm" for p < 1.) function generic_vecnormp(x, p) - s = start(x) - (v, s) = next(x, s) + (v, s) = iterate(x)::Tuple if p > 1 || p < -1 # might need to rescale to avoid overflow maxabs = p > 1 ? vecnormInf(x) : vecnormMinusInf(x) (maxabs == 0 || isinf(maxabs)) && return maxabs @@ -330,15 +335,19 @@ function generic_vecnormp(x, p) spp::promote_type(Float64, T) = p if -1 <= p <= 1 || (isfinite(_length(x)*maxabs^spp) && maxabs^spp != 0) # scaling not necessary sum::promote_type(Float64, T) = norm(v)^spp - while !done(x, s) - (v, s) = next(x, s) + while true + y = iterate(x, s) + y === nothing && break + (v, s) = y sum += norm(v)^spp end return convert(T, sum^inv(spp)) else # rescaling sum = (norm(v)/maxabs)^spp - while !done(x, s) - (v, s) = next(x, s) + while true + y = iterate(x, s) + y == nothing && break + (v, s) = y sum += (norm(v)/maxabs)^spp end return convert(T, maxabs*sum^inv(spp)) @@ -626,29 +635,30 @@ julia> vecdot(x, y) ``` """ function vecdot(x, y) # arbitrary iterables - ix = start(x) - if done(x, ix) - if !isempty(y) + ix = iterate(x) + iy = iterate(y) + if ix === nothing + if iy !== nothing throw(DimensionMismatch("x and y are of different lengths!")) end return dot(zero(eltype(x)), zero(eltype(y))) end - iy = start(y) - if done(y, iy) + if iy === nothing throw(DimensionMismatch("x and y are of different lengths!")) end - (vx, ix) = next(x, ix) - (vy, iy) = next(y, iy) + (vx, xs) = ix + (vy, ys) = iy s = dot(vx, vy) - while !done(x, ix) - if done(y, iy) - throw(DimensionMismatch("x and y are of different lengths!")) + while true + ix = iterate(x, xs) + iy = iterate(y, ys) + if (ix == nothing) || (iy == nothing) + break end - (vx, ix) = next(x, ix) - (vy, iy) = next(y, iy) + (vx, xs), (vy, ys) = ix, iy s += dot(vx, vy) end - if !done(y, iy) + if !(iy == nothing && ix == nothing) throw(DimensionMismatch("x and y are of different lengths!")) end return s @@ -678,18 +688,18 @@ function dot(x::AbstractVector, y::AbstractVector) if length(x) != length(y) throw(DimensionMismatch("dot product arguments have lengths $(length(x)) and $(length(y))")) end - ix = start(x) - if done(x, ix) + ix = iterate(x) + if ix === nothing # we only need to check the first vector, since equal lengths have been asserted return zero(eltype(x))'zero(eltype(y)) end - @inbounds (vx, ix) = next(x, ix) - @inbounds (vy, iy) = next(y, start(y)) - s = vx'vy - while !done(x, ix) - @inbounds (vx, ix) = next(x, ix) - @inbounds (vy, iy) = next(y, iy) - s += vx'vy + iy = iterate(y) + s = ix[1]'iy[1] + ix, iy = iterate(x, ix[2]), iterate(y, iy[2]) + while ix != nothing + s += ix[1]'iy[1] + ix = iterate(x, ix[2]) + iy = iterate(y, iy[2]) end return s end diff --git a/stdlib/Pkg3/src/resolve/MaxSum.jl b/stdlib/Pkg3/src/resolve/MaxSum.jl index 635b002408c46..95906cc7ba09d 100644 --- a/stdlib/Pkg3/src/resolve/MaxSum.jl +++ b/stdlib/Pkg3/src/resolve/MaxSum.jl @@ -235,9 +235,7 @@ function Random.shuffle!(perm::NodePerm) #@assert isperm(p) end -Base.start(perm::NodePerm) = start(perm.p) -Base.next(perm::NodePerm, x) = next(perm.p, x) -Base.done(perm::NodePerm, x) = done(perm.p, x) +Base.iterate(perm::NodePerm, state...) = iterate(perm.p, state...) # Call update for all nodes (i.e. packages) in # random order diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index 15e8c1a3ff347..15ab53c146e98 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -258,7 +258,7 @@ function common_prefix(completions) c1 = completions[1] isempty(c1) && return ret i = 1 - cc, nexti = next(c1, i) + cc, nexti = iterate(c1, i) while true for c in completions (i > lastindex(c) || c[i] != cc) && return ret @@ -266,7 +266,7 @@ function common_prefix(completions) ret = string(ret, cc) i >= lastindex(c1) && return ret i = nexti - cc, nexti = next(c1, i) + cc, nexti = iterate(c1, i) end end @@ -1204,25 +1204,25 @@ normalize_key(key::Integer) = normalize_key(Char(key)) function normalize_key(key::AbstractString) wildcard in key && error("Matching '\U10f7ff' not supported.") buf = IOBuffer() - i = start(key) - while !done(key, i) - c, i = next(key, i) + i = firstindex(key) + while i <= ncodeunits(key) + c, i = iterate(key, i) if c == '*' write(buf, wildcard) elseif c == '^' - c, i = next(key, i) + c, i = iterate(key, i) write(buf, uppercase(c)-64) elseif c == '\\' - c, i = next(key, i) + c, i = iterate(key, i) if c == 'C' - c, i = next(key, i) + c, i = iterate(key, i) @assert c == '-' - c, i = next(key, i) + c, i = iterate(key, i) write(buf, uppercase(c)-64) elseif c == 'M' - c, i = next(key, i) + c, i = iterate(key, i) @assert c == '-' - c, i = next(key, i) + c, i = iterate(key, i) write(buf, '\e') write(buf, c) end @@ -1247,14 +1247,15 @@ function normalize_keys(keymap::Dict) end function add_nested_key!(keymap::Dict, key, value; override = false) - i = start(key) - while !done(key, i) - c, i = next(key, i) - if !override && c in keys(keymap) && (done(key, i) || !isa(keymap[c], Dict)) + y = iterate(key) + while y !== nothing + c, i = y + y = iterate(key, i) + if !override && c in keys(keymap) && (y === nothing || !isa(keymap[c], Dict)) error("Conflicting definitions for keyseq " * escape_string(key) * " within one keymap") end - if done(key, i) + if y === nothing keymap[c] = value break elseif !(c in keys(keymap) && isa(keymap[c], Dict)) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index b3bf04e2f9edc..d2045e678b714 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -937,7 +937,7 @@ function setup_interface( end ast, pos = Meta.parse(input, oldpos, raise=false, depwarn=false) if (isa(ast, Expr) && (ast.head == :error || ast.head == :continue || ast.head == :incomplete)) || - (done(input, pos) && !endswith(input, '\n')) + (pos > ncodeunits(input) && !endswith(input, '\n')) # remaining text is incomplete (an error, or parser ran to the end but didn't stop with a newline): # Insert all the remaining text as one line (might be empty) tail = input[oldpos:end] diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index 3dee24dbb1c58..e8d2386a3e291 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -234,12 +234,12 @@ end function find_start_brace(s::AbstractString; c_start='(', c_end=')') braces = 0 r = reverse(s) - i = start(r) + i = firstindex(r) in_single_quotes = false in_double_quotes = false in_back_ticks = false - while !done(r, i) - c, i = next(r, i) + while i <= ncodeunits(r) + c, i = iterate(r, i) if !in_single_quotes && !in_double_quotes && !in_back_ticks if c == c_start braces += 1 @@ -254,13 +254,13 @@ function find_start_brace(s::AbstractString; c_start='(', c_end=')') end else if !in_back_ticks && !in_double_quotes && - c == '\'' && !done(r, i) && next(r, i)[1] != '\\' + c == '\'' && i <= ncodeunits(r) && iterate(r, i)[1] != '\\' in_single_quotes = !in_single_quotes elseif !in_back_ticks && !in_single_quotes && - c == '"' && !done(r, i) && next(r, i)[1] != '\\' + c == '"' && i <= ncodeunits(r) && iterate(r, i)[1] != '\\' in_double_quotes = !in_double_quotes elseif !in_single_quotes && !in_double_quotes && - c == '`' && !done(r, i) && next(r, i)[1] != '\\' + c == '`' && i <= ncodeunits(r) && iterate(r, i)[1] != '\\' in_back_ticks = !in_back_ticks end end @@ -516,7 +516,7 @@ function completions(string, pos) if inc_tag == :string && length(paths) == 1 && # Only close if there's a single choice, - !isdir(expanduser(replace(string[startpos:prevind(string, start(r))] * paths[1], + !isdir(expanduser(replace(string[startpos:prevind(string, first(r))] * paths[1], r"\\ " => " "))) && # except if it's a directory (length(string) <= pos || string[nextind(string,pos)] != '"') # or there's already a " at the cursor. @@ -537,7 +537,7 @@ function completions(string, pos) frange, method_name_end = find_start_brace(partial) ex = Meta.parse(partial[frange] * ")", raise=false, depwarn=false) if isa(ex, Expr) && ex.head==:call - return complete_methods(ex), start(frange):method_name_end, false + return complete_methods(ex), first(frange):method_name_end, false end elseif inc_tag == :comment return String[], 0:-1, false @@ -605,7 +605,7 @@ function completions(string, pos) c_start='['; c_end=']' end frange, end_of_identifier = find_start_brace(string[1:prevind(string, i)], c_start=c_start, c_end=c_end) - startpos = start(frange) + startpos = first(frange) i = prevind(string, startpos) elseif c in ["\'\"\`"...] s = "$c$c"*string[startpos:pos] diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 61451af53e2d8..30c72c0055ade 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -69,6 +69,14 @@ fake_repl() do stdin_write, stdout_read, repl notify(b) wait(c) + # Give ourselves a generous timer here, just to prevent + # this causing e.g. a CI hang when there's something unexpected + # in the output. + t = Timer(200) do t + isopen(t) || return + error("Stuck waiting for repl test") + end + # Latex completions write(stdin_write, "\x32\\alpha\t") readuntil(stdout_read, "α") @@ -230,10 +238,6 @@ fake_repl() do stdin_write, stdout_read, repl # Test down arrow to go back to history # populate history with a trivial input - t = Timer(10) do t - isopen(t) || return - error("Stuck waiting for history test") - end s1 = "12345678"; s2 = "23456789" write(stdin_write, s1, '\n') readuntil(stdout_read, s1) diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index a3b9e6f5ebbdd..96fb3a62c2451 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -67,7 +67,7 @@ const TAGS = Any[ :(=), :(==), :(===), :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, :a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z, :add_int, :sub_int, :mul_int, :add_float, :sub_float, :new, :mul_float, :bitcast, :start, :done, :next, - :indexed_next, :getfield, :meta, :eq_int, :slt_int, :sle_int, :ne_int, :push_loc, :pop_loc, + :indexed_iterate, :getfield, :meta, :eq_int, :slt_int, :sle_int, :ne_int, :push_loc, :pop_loc, :pop, :arrayset, :arrayref, :apply_type, :inbounds, :getindex, :setindex!, :Core, :!, :+, :Base, :static_parameter, :convert, :colon, Symbol("#self#"), Symbol("#temp#"), :tuple, diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 1b1a49c75c339..bc55fd26bc3cc 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1418,7 +1418,7 @@ function detect_unbound_args(mods...; params = tuple_sig.parameters[1:(end - 1)] tuple_sig = Base.rewrap_unionall(Tuple{params...}, m.sig) mf = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), tuple_sig, typemax(UInt)) - if mf != nothing && mf.func !== m && mf.func.sig <: tuple_sig + if mf !== nothing && mf.func !== m && mf.func.sig <: tuple_sig continue end end @@ -1499,7 +1499,7 @@ Base.ncodeunits(s::GenericString) = ncodeunits(s.string) Base.codeunit(s::GenericString) = codeunit(s.string) Base.codeunit(s::GenericString, i::Integer) = codeunit(s.string, i) Base.isvalid(s::GenericString, i::Integer) = isvalid(s.string, i) -Base.next(s::GenericString, i::Integer) = next(s.string, i) +Base.iterate(s::GenericString, i::Integer=1) = iterate(s.string, i) Base.reverse(s::GenericString) = GenericString(reverse(s.string)) Base.reverse(s::SubString{GenericString}) = GenericString(typeof(s.string)(reverse(String(s)))) @@ -1525,10 +1525,9 @@ end for (G, A) in ((GenericSet, AbstractSet), (GenericDict, AbstractDict)) @eval begin - Base.done(s::$G, state) = done(s.s, state) - Base.next(s::$G, state) = next(s.s, state) + Base.iterate(s::$G, state...) = iterate(s.s, state...) end - for f in (:isempty, :length, :start) + for f in (:isempty, :length) @eval begin Base.$f(s::$G) = $f(s.s) end diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 818eb01815e80..f3396b64ed8d2 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -153,7 +153,11 @@ ambs = detect_ambiguities(Ambig5) # Test that Core and Base are free of ambiguities # not using isempty so this prints more information when it fails -@test detect_ambiguities(Core, Base; imported=true, recursive=true, ambiguous_bottom=false) == [] +@test filter(detect_ambiguities(Core, Base; imported=true, recursive=true, ambiguous_bottom=false)) do meths + # start, next, done fallbacks have ambiguities, but the iteration + # protocol prevents those from arising in practice. + !(meths[1].name in (:start, :next, :done)) +end == [] # some ambiguities involving Union{} type parameters are expected, but not required @test !isempty(detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=true)) @@ -271,6 +275,8 @@ end @test_broken need_to_handle_undef_sparam == Set() pop!(need_to_handle_undef_sparam, which(Core.Compiler.cat, Tuple{Any, AbstractArray})) pop!(need_to_handle_undef_sparam, first(methods(Core.Compiler.same_names))) + pop!(need_to_handle_undef_sparam, which(Core.Compiler.convert, (Type{Union{Core.Compiler.Some{T}, Nothing}} where T, Core.Compiler.Some))) + pop!(need_to_handle_undef_sparam, which(Core.Compiler.convert, (Type{Union{T, Nothing}} where T, Core.Compiler.Some))) @test need_to_handle_undef_sparam == Set() end let need_to_handle_undef_sparam = diff --git a/test/arrayops.jl b/test/arrayops.jl index 53fe39b2ff6ec..8f211f6b679e7 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1739,34 +1739,35 @@ end @test hash(CartesianIndex()) == Base.IteratorsMD.cartindexhash_seed @test hash(CartesianIndex(1, 2)) != hash((1, 2)) -@testset "itr, start, done, next" begin +@testset "itr, iterate" begin r = 2:3 itr = eachindex(r) - state = start(itr) - @test !done(itr, state) - _, state = next(itr, state) - @test !done(itr, state) - val, state = next(itr, state) - @test done(itr, state) + y = iterate(itr) + @test y !== nothing + y = iterate(itr, y[2]) + @test y !== nothing + val, _ = y + y = iterate(itr, y[2]) + @test y === nothing @test r[val] == 3 r = sparse(2:3:8) itr = eachindex(r) - state = start(itr) - @test !done(itr, state) - _, state = next(itr, state) - _, state = next(itr, state) - @test !done(itr, state) - val, state = next(itr, state) + y = iterate(itr) + @test y !== nothing + y = iterate(itr, y[2]) + y = iterate(itr, y[2]) + @test y !== nothing + val, state = y @test r[val] == 8 - @test done(itr, state) + @test iterate(itr, state) == nothing end R = CartesianIndices((1,3)) -@test done(R, start(R)) == false +@test iterate(R) !== nothing R = CartesianIndices((0,3)) -@test done(R, start(R)) == true +@test iterate(R) === nothing R = CartesianIndices((3,0)) -@test done(R, start(R)) == true +@test iterate(R) === nothing @testset "multi-array eachindex" begin local a = zeros(2,2) diff --git a/test/channels.jl b/test/channels.jl index 07033c6cc7c64..02689b2c27217 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -64,25 +64,7 @@ end @test sum(results) == 15 end -@testset "channel iterator with done()" begin -# Test channel iterator with done() being called multiple times -# This needs to be explicitly tested since `take!` is called -# in `done()` and not `next()` - c = Channel(32) - foreach(i -> put!(c, i), 1:10) - close(c) - s = start(c) - @test done(c, s) == false - res = Int[] - while !done(c, s) - local v - @test done(c,s) == false - v, s = next(c, s) - push!(res, v) - end - @test res == Int[1:10...] -end - +# Tests for channels bound to tasks. using Distributed @testset "channels bound to tasks" for N in [0, 10] # Normal exit of task diff --git a/test/char.jl b/test/char.jl index a85573bbc4c9a..e195d3bececd8 100644 --- a/test/char.jl +++ b/test/char.jl @@ -116,23 +116,10 @@ end @test eltype(x) == Char end - #start(c::Char) = false + #iterate(c::Char) for x in testarrays - @test start(x) == false - end - - #next(c::Char, state) = (c, true) - for x in testarrays - for state in [true, false] - @test next(x, state) == (x, true) - end - end - - #done(c::Char, state) = state - for x in testarrays - for state in [true, false] - @test done(x, state) == state - end + @test iterate(x)[1] == x + @test iterate(x, iterate(x)[2]) == nothing end #isless(x::Char, y::Integer) = isless(UInt32(x), y) diff --git a/test/compiler/compiler.jl b/test/compiler/compiler.jl index 425ec1d1b1bfd..a86d3034915d9 100644 --- a/test/compiler/compiler.jl +++ b/test/compiler/compiler.jl @@ -247,13 +247,12 @@ end # issue #12474 @generated function f12474(::Any) - :(for i in 1 - end) + return :(for i in 1 + end) end -let - ast12474 = code_typed(f12474, Tuple{Float64}) +let ast12474 = code_typed(f12474, Tuple{Float64}) @test isdispatchelem(ast12474[1][2]) - @test all(isdispatchelem, ast12474[1][1].slottypes) + @test all(x -> isdispatchelem(Core.Compiler.typesubtract(x, Nothing)), ast12474[1][1].slottypes) end @@ -526,7 +525,7 @@ function g19348(x) a, b = x g = 1 g = 2 - c = Base.indexed_next(x, g, g) + c = Base.indexed_iterate(x, g, g) return a + b + c[1] end diff --git a/test/copy.jl b/test/copy.jl index 80a83ed7b2cab..74650d28d42d4 100644 --- a/test/copy.jl +++ b/test/copy.jl @@ -41,13 +41,13 @@ chnlprod(x) = Channel(c->for i in x; put!(c,i); end) @test_throws ArgumentError copyto!(dest, 1, src(), 1, -1) - @test_throws BoundsError copyto!(dest, bigsrc()) + @test_throws Union{BoundsError, ArgumentError} copyto!(dest, bigsrc()) - @test_throws BoundsError copyto!(dest, 3, src()) - @test_throws BoundsError copyto!(dest, 3, src(), 1) - @test_throws BoundsError copyto!(dest, 3, src(), 1, 2) + @test_throws Union{BoundsError, ArgumentError} copyto!(dest, 3, src()) + @test_throws Union{BoundsError, ArgumentError} copyto!(dest, 3, src(), 1) + @test_throws Union{BoundsError, ArgumentError} copyto!(dest, 3, src(), 1, 2) - @test_throws BoundsError copyto!(dest, 1, src(), 2, 2) + @test_throws Union{BoundsError, ArgumentError} copyto!(dest, 1, src(), 2, 2) end end diff --git a/test/core.jl b/test/core.jl index 07785c99c2b9a..fc13fc54fa79f 100644 --- a/test/core.jl +++ b/test/core.jl @@ -6072,3 +6072,20 @@ end @test !Base.isvatuple(Tuple{Float64,Vararg{Int,1}}) @test !Base.isvatuple(Tuple{T,Vararg{Int,2}} where T) @test !Base.isvatuple(Tuple{Int,Int,Vararg{Int,2}}) + +# The old iteration protocol shims deprecation test +struct DelegateIterator{T} + x::T +end +Base.start(itr::DelegateIterator) = start(itr.x) +Base.next(itr::DelegateIterator, state) = next(itr.x, state) +Base.done(itr::DelegateIterator, state) = done(itr.x, state) +let A = [1], B = [], C = DelegateIterator([1]), D = DelegateIterator([]), E = Any[1,"abc"] + @test next(A, start(A))[1] == 1 + @test done(A, next(A, start(A))[2]) + @test done(B, start(B)) + @test next(C, start(C))[1] == 1 + @test done(C, next(C, start(C))[2]) + @test done(D, start(D)) + @test next(E, next(E, start(E))[2])[1] == "abc" +end diff --git a/test/dict.jl b/test/dict.jl index 7491eee6bc4d0..912209b2efa6c 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -6,15 +6,12 @@ using Random p = Pair(10,20) @test p == (10=>20) @test isequal(p,10=>20) - @test start(p) == 1 - @test next(p, 1) == (10,2) - @test !done(p, 1) - @test !done(p,2) - @test done(p,3) - @test !done(p,0) + @test iterate(p)[1] == 10 + @test iterate(p, iterate(p)[2])[1] == 20 + @test iterate(p, iterate(p, iterate(p)[2])[2]) == nothing @test lastindex(p) == length(p) == 2 - @test Base.indexed_next(p, 1, (1,2)) == (10,2) - @test Base.indexed_next(p, 2, (1,2)) == (20,3) + @test Base.indexed_iterate(p, 1, nothing) == (10,2) + @test Base.indexed_iterate(p, 2, nothing) == (20,3) @test (1=>2) < (2=>3) @test (2=>2) < (2=>3) @test !((2=>3) < (2=>3)) @@ -531,9 +528,6 @@ end @test 1 == @inferred get(d, 1, 1) @test pop!(d, -111, nothing) == nothing @test 1 == @inferred pop!(d, 1) - i = @inferred start(d) - @inferred next(d, i) - @inferred done(d, i) # get! and delete! d = @inferred IdDict(Pair(:a,1), Pair(:b,2), Pair(3,3)) @@ -713,13 +707,13 @@ const global hashoffset = [UInt(190)] Base.hash(s::MyString) = hash(s.str) + hashoffset[] Base.lastindex(s::MyString) = lastindex(s.str) -Base.next(s::MyString, v::Int) = next(s.str, v) +Base.iterate(s::MyString, v::Int=1) = iterate(s.str, v) Base.isequal(a::MyString, b::MyString) = isequal(a.str, b.str) ==(a::MyString, b::MyString) = (a.str == b.str) Base.hash(v::MyInt) = v.val + hashoffset[] Base.lastindex(v::MyInt) = lastindex(v.val) -Base.next(v::MyInt, i::Int) = next(v.val, i) +Base.iterate(v::MyInt, i...) = iterate(v.val, i...) Base.isequal(a::MyInt, b::MyInt) = isequal(a.val, b.val) ==(a::MyInt, b::MyInt) = (a.val == b.val) @testset "issue #15077" begin diff --git a/test/functional.jl b/test/functional.jl index 469d67ffb3678..6d7b64fbead87 100644 --- a/test/functional.jl +++ b/test/functional.jl @@ -107,7 +107,7 @@ end # generators and guards let gen = (x for x in 1:10) @test gen.iter == 1:10 - @test gen.f(first(1:10)) == next(gen, start(gen))[1] + @test gen.f(first(1:10)) == iterate(gen)[1] for (a,b) in zip(1:10,gen) @test a == b end diff --git a/test/generic_map_tests.jl b/test/generic_map_tests.jl index 15c6ca8c6165d..8fde731770bf3 100644 --- a/test/generic_map_tests.jl +++ b/test/generic_map_tests.jl @@ -1,9 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license mutable struct GenericIterator{N} end -Base.start(::GenericIterator{N}) where {N} = 1 -Base.next(::GenericIterator{N}, i) where {N} = (i, i + 1) -Base.done(::GenericIterator{N}, i) where {N} = i > N ? true : false +Base.iterate(::GenericIterator{N}, i=1) where {N} = i > N ? nothing : (i, i + 1) Base.IteratorSize(::Type{GenericIterator{N}}) where {N} = Base.SizeUnknown() function generic_map_tests(mapf, inplace_mapf=nothing) diff --git a/test/hashing.jl b/test/hashing.jl index b9675d9ce8a05..99c3daff46007 100644 --- a/test/hashing.jl +++ b/test/hashing.jl @@ -98,6 +98,9 @@ vals = Any[ for a in vals, b in vals @test isequal(a,b) == (hash(a)==hash(b)) +end + +for a in vals if a isa AbstractArray @test hash(a) == hash(Array(a)) == hash(Array{Any}(a)) end diff --git a/test/iterators.jl b/test/iterators.jl index e97fda5dcfaea..8903421e4d818 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -65,7 +65,7 @@ end # rest # ---- let s = "hello" - _, st = next(s, start(s)) + _, st = iterate(s) c = collect(rest(s, st)) @test c == ['e','l','l','o'] @test c isa Vector{Char} @@ -363,7 +363,7 @@ end @test eltype(flatten(UnitRange{Int8}[1:2, 3:4])) == Int8 @test length(flatten(zip(1:3, 4:6))) == 6 @test length(flatten(1:6)) == 6 -@test_throws ArgumentError collect(flatten(Any[])) +@test collect(flatten(Any[])) == Any[] @test_throws ArgumentError length(flatten(NTuple[(1,), ()])) # #16680 @test_throws ArgumentError length(flatten([[1], [1]])) @@ -528,4 +528,11 @@ end @test Base.peek(a) == 3 @test sum(a) == 7 end + # Interaction of zip/Stateful + let a = Iterators.Stateful("a"), b = "" + @test isempty(collect(zip(a,b))) + @test !isempty(a) + @test isempty(collect(zip(b,a))) + @test !isempty(a) + end end diff --git a/test/ranges.jl b/test/ranges.jl index 9b32428dea766..c29f348ff1524 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -881,7 +881,6 @@ end end @testset "LinRange ops" begin - @test start(LinRange(0,3,4)) == 1 @test 2*LinRange(0,3,4) == LinRange(0,6,4) @test LinRange(0,3,4)*2 == LinRange(0,6,4) @test LinRange(0,3,4)/3 == LinRange(0,1,4) diff --git a/test/strings/basic.jl b/test/strings/basic.jl index ac3326d587920..c64acc45fc3f3 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -187,8 +187,8 @@ let @test lastindex(srep) == 7 - @test next(srep, 3) == ('β',5) - @test next(srep, 7) == ('β',9) + @test iterate(srep, 3) == ('β',5) + @test iterate(srep, 7) == ('β',9) @test srep[7] == 'β' @test_throws BoundsError srep[8] @@ -230,8 +230,8 @@ end @test_throws MethodError codeunit(tstr, true) @test_throws MethodError isvalid(tstr, 1) @test_throws MethodError isvalid(tstr, true) - @test_throws MethodError next(tstr, 1) - @test_throws MethodError next(tstr, true) + @test_throws MethodError iterate(tstr, 1) + @test_throws MethodError iterate(tstr, true) @test_throws MethodError lastindex(tstr) gstr = GenericString("12") @@ -251,7 +251,7 @@ end @test first(eachindex("foobar")) === 1 @test first(eachindex("")) === 1 @test last(eachindex("foobar")) === lastindex("foobar") - @test done(eachindex("foobar"),7) + @test iterate(eachindex("foobar"),7) === nothing @test Int == eltype(Base.EachStringIndex) == eltype(Base.EachStringIndex{String}) == eltype(Base.EachStringIndex{GenericString}) == @@ -490,7 +490,7 @@ end @testset "issue #18280: next/nextind must return past String's underlying data" begin for s in ("Hello", "Σ", "こんにちは", "😊😁") local s - @test next(s, lastindex(s))[2] > sizeof(s) + @test iterate(s, lastindex(s))[2] > sizeof(s) @test nextind(s, lastindex(s)) > sizeof(s) end end @@ -501,9 +501,7 @@ mutable struct CharStr <: AbstractString chars::Vector{Char} CharStr(x) = new(collect(x)) end -Base.start(x::CharStr) = start(x.chars) -Base.next(x::CharStr, i::Int) = next(x.chars, i) -Base.done(x::CharStr, i::Int) = done(x.chars, i) +Base.iterate(x::CharStr, i::Integer=1) = iterate(x.chars, i) Base.lastindex(x::CharStr) = lastindex(x.chars) @testset "cmp without UTF-8 indexing" begin # Simple case, with just ANSI Latin 1 characters @@ -737,100 +735,100 @@ end @test unsafe_wrap(Vector{UInt8},"\xcc\xdd\xee\xff\x80") == [0xcc,0xdd,0xee,0xff,0x80] -@test next("a", 1)[2] == 2 +@test iterate("a", 1)[2] == 2 @test nextind("a", 1) == 2 -@test next("az", 1)[2] == 2 +@test iterate("az", 1)[2] == 2 @test nextind("az", 1) == 2 -@test next("a\xb1", 1)[2] == 2 +@test iterate("a\xb1", 1)[2] == 2 @test nextind("a\xb1", 1) == 2 -@test next("a\xb1z", 1)[2] == 2 +@test iterate("a\xb1z", 1)[2] == 2 @test nextind("a\xb1z", 1) == 2 -@test next("a\xb1\x83", 1)[2] == 2 +@test iterate("a\xb1\x83", 1)[2] == 2 @test nextind("a\xb1\x83", 1) == 2 -@test next("a\xb1\x83\x84", 1)[2] == 2 +@test iterate("a\xb1\x83\x84", 1)[2] == 2 @test nextind("a\xb1\x83\x84", 1) == 2 -@test next("a\xb1\x83\x84z", 1)[2] == 2 +@test iterate("a\xb1\x83\x84z", 1)[2] == 2 @test nextind("a\xb1\x83\x84z", 1) == 2 -@test next("\x81", 1)[2] == 2 +@test iterate("\x81", 1)[2] == 2 @test nextind("\x81", 1) == 2 -@test next("\x81z", 1)[2] == 2 +@test iterate("\x81z", 1)[2] == 2 @test nextind("\x81z", 1) == 2 -@test next("\x81\xb1", 1)[2] == 2 +@test iterate("\x81\xb1", 1)[2] == 2 @test nextind("\x81\xb1", 1) == 2 -@test next("\x81\xb1z", 1)[2] == 2 +@test iterate("\x81\xb1z", 1)[2] == 2 @test nextind("\x81\xb1z", 1) == 2 -@test next("\x81\xb1\x83", 1)[2] == 2 +@test iterate("\x81\xb1\x83", 1)[2] == 2 @test nextind("\x81\xb1\x83", 1) == 2 -@test next("\x81\xb1\x83\x84", 1)[2] == 2 +@test iterate("\x81\xb1\x83\x84", 1)[2] == 2 @test nextind("\x81\xb1\x83\x84", 1) == 2 -@test next("\x81\xb1\x83\x84z", 1)[2] == 2 +@test iterate("\x81\xb1\x83\x84z", 1)[2] == 2 @test nextind("\x81\xb1\x83\x84z", 1) == 2 -@test next("\xce", 1)[2] == 2 +@test iterate("\xce", 1)[2] == 2 @test nextind("\xce", 1) == 2 -@test next("\xcez", 1)[2] == 2 +@test iterate("\xcez", 1)[2] == 2 @test nextind("\xcez", 1) == 2 -@test next("\xce\xb1", 1)[2] == 3 +@test iterate("\xce\xb1", 1)[2] == 3 @test nextind("\xce\xb1", 1) == 3 -@test next("\xce\xb1z", 1)[2] == 3 +@test iterate("\xce\xb1z", 1)[2] == 3 @test nextind("\xce\xb1z", 1) == 3 -@test next("\xce\xb1\x83", 1)[2] == 3 +@test iterate("\xce\xb1\x83", 1)[2] == 3 @test nextind("\xce\xb1\x83", 1) == 3 -@test next("\xce\xb1\x83\x84", 1)[2] == 3 +@test iterate("\xce\xb1\x83\x84", 1)[2] == 3 @test nextind("\xce\xb1\x83\x84", 1) == 3 -@test next("\xce\xb1\x83\x84z", 1)[2] == 3 +@test iterate("\xce\xb1\x83\x84z", 1)[2] == 3 @test nextind("\xce\xb1\x83\x84z", 1) == 3 -@test next("\xe2", 1)[2] == 2 +@test iterate("\xe2", 1)[2] == 2 @test nextind("\xe2", 1) == 2 -@test next("\xe2z", 1)[2] == 2 +@test iterate("\xe2z", 1)[2] == 2 @test nextind("\xe2z", 1) == 2 -@test next("\xe2\x88", 1)[2] == 3 +@test iterate("\xe2\x88", 1)[2] == 3 @test nextind("\xe2\x88", 1) == 3 -@test next("\xe2\x88z", 1)[2] == 3 +@test iterate("\xe2\x88z", 1)[2] == 3 @test nextind("\xe2\x88z", 1) == 3 -@test next("\xe2\x88\x83", 1)[2] == 4 +@test iterate("\xe2\x88\x83", 1)[2] == 4 @test nextind("\xe2\x88\x83", 1) == 4 -@test next("\xe2\x88\x83z", 1)[2] == 4 +@test iterate("\xe2\x88\x83z", 1)[2] == 4 @test nextind("\xe2\x88\x83z", 1) == 4 -@test next("\xe2\x88\x83\x84", 1)[2] == 4 +@test iterate("\xe2\x88\x83\x84", 1)[2] == 4 @test nextind("\xe2\x88\x83\x84", 1) == 4 -@test next("\xe2\x88\x83\x84z", 1)[2] == 4 +@test iterate("\xe2\x88\x83\x84z", 1)[2] == 4 @test nextind("\xe2\x88\x83\x84z", 1) == 4 -@test next("\xf0", 1)[2] == 2 +@test iterate("\xf0", 1)[2] == 2 @test nextind("\xf0", 1) == 2 -@test next("\xf0z", 1)[2] == 2 +@test iterate("\xf0z", 1)[2] == 2 @test nextind("\xf0z", 1) == 2 -@test next("\xf0\x9f", 1)[2] == 3 +@test iterate("\xf0\x9f", 1)[2] == 3 @test nextind("\xf0\x9f", 1) == 3 -@test next("\xf0\x9fz", 1)[2] == 3 +@test iterate("\xf0\x9fz", 1)[2] == 3 @test nextind("\xf0\x9fz", 1) == 3 -@test next("\xf0\x9f\x98", 1)[2] == 4 +@test iterate("\xf0\x9f\x98", 1)[2] == 4 @test nextind("\xf0\x9f\x98", 1) == 4 -@test next("\xf0\x9f\x98z", 1)[2] == 4 +@test iterate("\xf0\x9f\x98z", 1)[2] == 4 @test nextind("\xf0\x9f\x98z", 1) == 4 -@test next("\xf0\x9f\x98\x84", 1)[2] == 5 +@test iterate("\xf0\x9f\x98\x84", 1)[2] == 5 @test nextind("\xf0\x9f\x98\x84", 1) == 5 -@test next("\xf0\x9f\x98\x84z", 1)[2] == 5 +@test iterate("\xf0\x9f\x98\x84z", 1)[2] == 5 @test nextind("\xf0\x9f\x98\x84z", 1) == 5 -@test next("\xf8", 1)[2] == 2 +@test iterate("\xf8", 1)[2] == 2 @test nextind("\xf8", 1) == 2 -@test next("\xf8z", 1)[2] == 2 +@test iterate("\xf8z", 1)[2] == 2 @test nextind("\xf8z", 1) == 2 -@test next("\xf8\x9f", 1)[2] == 2 +@test iterate("\xf8\x9f", 1)[2] == 2 @test nextind("\xf8\x9f", 1) == 2 -@test next("\xf8\x9fz", 1)[2] == 2 +@test iterate("\xf8\x9fz", 1)[2] == 2 @test nextind("\xf8\x9fz", 1) == 2 -@test next("\xf8\x9f\x98", 1)[2] == 2 +@test iterate("\xf8\x9f\x98", 1)[2] == 2 @test nextind("\xf8\x9f\x98", 1) == 2 -@test next("\xf8\x9f\x98z", 1)[2] == 2 +@test iterate("\xf8\x9f\x98z", 1)[2] == 2 @test nextind("\xf8\x9f\x98z", 1) == 2 -@test next("\xf8\x9f\x98\x84", 1)[2] == 2 +@test iterate("\xf8\x9f\x98\x84", 1)[2] == 2 @test nextind("\xf8\x9f\x98\x84", 1) == 2 -@test next("\xf8\x9f\x98\x84z", 1)[2] == 2 +@test iterate("\xf8\x9f\x98\x84z", 1)[2] == 2 @test nextind("\xf8\x9f\x98\x84z", 1) == 2 # codeunit vectors diff --git a/test/strings/io.jl b/test/strings/io.jl index 7ada8e3eaf07c..18f0786025aad 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -156,16 +156,6 @@ end @test join((), ", ", ", and ") == "" end -# issue #9178 `join` calls `done()` twice on the iterables -mutable struct i9178 - nnext::Int64 - ndone::Int64 -end -Base.start(jt::i9178) = (jt.nnext=0 ; jt.ndone=0 ; 0) -Base.done(jt::i9178, n) = (jt.ndone += 1 ; n > 3) -Base.next(jt::i9178, n) = (jt.nnext += 1 ; ("$(jt.nnext),$(jt.ndone)", n+1)) -@test join(i9178(0,0), ";") == "1,1;2,2;3,3;4,4" - # quotes + interpolation (issue #455) @test "$("string")" == "string" arr = ["a","b","c"] diff --git a/test/strings/types.jl b/test/strings/types.jl index d20510ba836df..be67e24029e8c 100644 --- a/test/strings/types.jl +++ b/test/strings/types.jl @@ -95,8 +95,8 @@ let str = "aa\u2200\u2222bb" @test String(take!(b)) == "\u2200\u2222" @test_throws StringIndexError SubString(str, 4, 5) - @test_throws BoundsError next(u, 0) - @test_throws BoundsError next(u, 7) + @test_throws BoundsError iterate(u, 0) + @test_throws BoundsError iterate(u, 8) @test_throws BoundsError getindex(u, 0) @test_throws BoundsError getindex(u, 7) @test_throws BoundsError getindex(u, 0:1) @@ -193,10 +193,10 @@ let rng = MersenneTwister(1), strs = ["∀∃∀"*String(rand(rng, UInt8, 40))*" String(rand(rng, UInt8, 50))] for s in strs a = 0 - while !done(s, a) + while a <= ncodeunits(s) a = nextind(s, a) b = a - 1 - while !done(s, b) + while b <= ncodeunits(s) ss = SubString(s, a:b) s2 = s[a:b] @test ncodeunits(ss) == ncodeunits(s2) diff --git a/test/tuple.jl b/test/tuple.jl index 7704c8c193d74..7024fd125bd15 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -153,16 +153,13 @@ end end @testset "iterating" begin - @test start((1,2,3)) === 1 - - @test done((), 1) - @test !done((1,2,3), 3) - @test done((1,2,3), 4) - - @test next((5,6,7), 1) === (5, 2) - @test next((5,6,7), 3) === (7, 4) - @test_throws BoundsError next((5,6,7), 0) - @test_throws BoundsError next((), 1) + @test iterate(()) === nothing + t = (1,2,3) + y1 = iterate(t) + y2 = iterate(t, y1[2]) + y3 = iterate(t, y2[2]) + @test y3 !== nothing + @test iterate(t, y3[2]) === nothing @test eachindex((2,5,"foo")) === Base.OneTo(3) @test eachindex((2,5,"foo"), (1,2,5,7)) === Base.OneTo(4) diff --git a/test/unicode/utf8.jl b/test/unicode/utf8.jl index 4f5499073e5bf..9b59e0b0455fb 100644 --- a/test/unicode/utf8.jl +++ b/test/unicode/utf8.jl @@ -2,7 +2,7 @@ @testset "string indexing" begin let str = "this is a test\xed\x80" - @test next(str, 15) == (reinterpret(Char, 0xed800000), 17) + @test iterate(str, 15) == (reinterpret(Char, 0xed800000), 17) @test_throws BoundsError getindex(str, 0:3) @test_throws BoundsError getindex(str, 17:18) @test_throws BoundsError getindex(str, 2:17)