From 1a1d6b6d1c636a822cf2da371dc41a5752e8c848 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 22 Dec 2017 13:37:18 +0100 Subject: [PATCH 1/2] Change iteration protocol This changes the iteration protocol from `start`/`next`/`done` to `iterate`. The new lowering of a for loop is as follows: ``` for x in itr ... end ``` becomes ``` next = iterate(itr) while next !== nothing x, state = next::Tuple{Any, Any} ... next = iterate(itr, state) end ``` The semantics are as apparent from the above lowering. `iterate` returns either `nothing` or a tuple of value and state. The state is passed to any subsequent operation. The first iteration is indicated, by not passing the second, state argument to the `iterate` method. Adaptors in both directions are provided to keep the legacy iteration protocol working for now. However, performance of the legacy iteration protocol will be severely pessimized. As an optional add-on for mutable iterators, a new `isdone` function is provided. This function is intended as an O(1) approximate query for iterator completion, where such a calculation is possible without mutation and/or is significantly faster than attempting to obtain the element itself. The function makes use of 3-value logic. `missing` is always an acceptable answer, in which case the caller should go ahead and attempt the iteration to obtain a definite result. If the result is not `missing`, it must be exact (i.e. if true, the next call to iterate must return `nothing`, if false it must not return nothing). --- base/abstractarray.jl | 104 ++-- base/abstractdict.jl | 31 +- base/array.jl | 119 ++-- base/asyncmap.jl | 61 ++- base/bitarray.jl | 53 +- base/bitset.jl | 12 +- base/broadcast.jl | 27 +- base/cartesian.jl | 4 +- base/channels.jl | 18 +- base/char.jl | 4 +- base/compiler/abstractinterpretation.jl | 27 +- base/compiler/compiler.jl | 1 + base/compiler/optimize.jl | 2 +- base/compiler/ssair/domtree.jl | 7 +- base/compiler/ssair/inlining2.jl | 13 +- base/compiler/ssair/ir.jl | 52 +- base/compiler/typeinfer.jl | 8 +- base/deprecated.jl | 5 + base/dict.jl | 60 +- base/env.jl | 18 +- base/error.jl | 16 +- base/essentials.jl | 134 ++++- base/exports.jl | 1 + base/generator.jl | 9 +- base/indices.jl | 13 +- base/io.jl | 9 +- base/iterators.jl | 463 ++++++++-------- base/loading.jl | 10 - base/logging.jl | 2 +- base/math.jl | 8 + base/meta.jl | 2 +- base/missing.jl | 61 +-- base/multidimensional.jl | 96 ++-- base/namedtuple.jl | 6 +- base/number.jl | 4 +- base/pair.jl | 7 +- base/parse.jl | 26 +- base/path.jl | 12 +- base/precompile.jl | 578 -------------------- base/process.jl | 6 +- base/range.jl | 61 ++- base/reduce.jl | 40 +- base/reducedim.jl | 8 +- base/reflection.jl | 4 +- base/regex.jl | 34 +- base/reshapedarray.jl | 6 +- base/set.jl | 48 +- base/show.jl | 13 +- base/some.jl | 2 +- base/sort.jl | 12 +- base/stacktraces.jl | 2 +- base/statistics.jl | 29 +- base/strings/basic.jl | 35 +- base/strings/string.jl | 3 +- base/strings/substring.jl | 7 +- base/strings/unicode.jl | 22 +- base/strings/util.jl | 2 +- base/sysimg.jl | 6 +- base/task.jl | 4 +- base/tuple.jl | 35 +- base/version.jl | 10 +- base/weakkeydict.jl | 18 +- doc/src/base/collections.md | 15 +- doc/src/manual/interfaces.md | 45 +- doc/src/manual/strings.md | 5 - src/julia-syntax.scm | 18 +- stdlib/Dates/src/io.jl | 14 +- stdlib/Dates/src/parse.jl | 16 +- stdlib/Dates/src/ranges.jl | 4 +- stdlib/Dates/test/ranges.jl | 8 +- stdlib/DelimitedFiles/src/DelimitedFiles.jl | 13 +- stdlib/Distributed/src/pmap.jl | 18 +- stdlib/Distributed/src/precompile.jl | 60 -- stdlib/LibGit2/src/config.jl | 24 +- stdlib/LibGit2/src/deprecated.jl | 1 - stdlib/LibGit2/src/reference.jl | 37 +- stdlib/LibGit2/src/walker.jl | 38 +- stdlib/LibGit2/test/libgit2.jl | 4 +- stdlib/LinearAlgebra/src/generic.jl | 102 ++-- stdlib/Pkg3/src/resolve/MaxSum.jl | 4 +- stdlib/REPL/src/LineEdit.jl | 33 +- stdlib/REPL/src/REPL.jl | 2 +- stdlib/REPL/src/REPLCompletions.jl | 18 +- stdlib/REPL/test/repl.jl | 12 +- stdlib/Serialization/src/Serialization.jl | 2 +- stdlib/Test/src/Test.jl | 9 +- test/ambiguous.jl | 8 +- test/arrayops.jl | 35 +- test/channels.jl | 20 +- test/char.jl | 19 +- test/compiler/compiler.jl | 11 +- test/copy.jl | 10 +- test/core.jl | 17 + test/dict.jl | 20 +- test/functional.jl | 2 +- test/generic_map_tests.jl | 4 +- test/hashing.jl | 3 + test/iterators.jl | 11 +- test/ranges.jl | 1 - test/strings/basic.jl | 106 ++-- test/strings/io.jl | 10 - test/strings/types.jl | 8 +- test/tuple.jl | 17 +- test/unicode/utf8.jl | 2 +- 104 files changed, 1295 insertions(+), 2001 deletions(-) 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/julia-syntax.scm b/src/julia-syntax.scm index b339a0e7b6614..367a296cbc892 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,14 @@ ,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)))))))) + (call (|.| (core Intrinsics) 'not_int) (call (core ===) ,next (null))) + (block ,body + (= ,next (call (top iterate) ,coll ,state))))))))))) ;; wrap `expr` in a function appropriate for consuming values from given ranges (define (func-for-generator-ranges expr range-exprs flat outervars) @@ -1978,13 +1979,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)))))) 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) From 62fbad29f271b8a51521418d3b2e3eaf15919160 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 17 May 2018 17:14:11 -0400 Subject: [PATCH 2/2] Use loop inverted loop lowering The primary idea of the new iteration protocol is that for a function like: ``` function iterate(itr) done(itr) ? nothing : next(itr) end ``` we can fuse the `done` comparison into the loop condition and recover the same loop structure we had before (while retaining the flexibility of not requiring the done function to be separate), i.e. for ``` y = iterate(itr) y === nothing && break ``` we want to have after inlining and early optimization: ``` done(itr) && break y = next(itr) ``` LLVM performs this optimization in jump threading. However, we run into a problem. At the top of the loop we have: ``` y = iterate top: %cond = y === nothing br i1 %cond, %exit, %loop .... ``` We'd want to thread over the `top` block (this makes sense, since by the discussion above, we need to merge our condition into the loop exit condition). However, LLVM (quite sensibly) refuses to thread over loop headers and since `top` is both a loop header and a loop exit, we fail to perform the appropriate transformation. However, there's a simple fix. Instead of emitting a foor loop as ``` y = iterate(itr) while y !== nothing x, state = y ... y = iterate(itr, state) end ``` we can emit it as ``` y = iterate(itr) if y !== nothing while true x, state = y ... y = iterate(itr, state) y === nothing && break end end ``` This transformation is known as `loop inversion` (or a special case of `loop rotation`. In our case the primary benefit is that we can fuse the condition contained in the initial `iterate` call into the bypass if, which then lets LLVM understand our loop structure. Co-authored-by: Jeff Bezanson --- src/codegen.cpp | 9 +++++---- src/julia-syntax.scm | 17 +++++++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) 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 367a296cbc892..5e75bc10bca1c 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1606,10 +1606,11 @@ ;; TODO avoid `local declared twice` error from this ;;,@(if outer `((local ,lhs)) '()) ,@(if outer `((require-existing-local ,lhs)) '()) - (_while - (call (|.| (core Intrinsics) 'not_int) (call (core ===) ,next (null))) - (block ,body - (= ,next (call (top iterate) ,coll ,state))))))))))) + (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) @@ -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)