From e120bbe309012ebfc1005e5b98abb8859af9c40b Mon Sep 17 00:00:00 2001 From: Mike Nolta Date: Sat, 6 Dec 2014 23:29:14 -0500 Subject: [PATCH] split next into nextval & nextstate For example, for x in xs ... now transforms into iter = start(xs) while !done(xs,iter) x = nextval(xs,iter) ... iter = nextstate(xs,iter) --- base/abstractarray.jl | 3 +- base/bitarray.jl | 3 +- base/char.jl | 3 +- base/collections.jl | 9 +++-- base/combinatorics.jl | 73 ++++++++++++++++++------------------- base/dates/ranges.jl | 3 +- base/dict.jl | 31 ++++++++-------- base/env.jl | 31 ++++++++++------ base/exports.jl | 2 + base/inference.jl | 2 +- base/intset.jl | 9 +++-- base/io.jl | 3 +- base/iterator.jl | 47 ++++++++---------------- base/multidimensional.jl | 21 +++++++---- base/number.jl | 3 +- base/operators.jl | 3 +- base/precompile.jl | 5 --- base/range.jl | 9 +++-- base/reflection.jl | 3 +- base/regex.jl | 9 +++-- base/set.jl | 3 +- base/sparse/sparsematrix.jl | 7 ++-- base/string.jl | 11 +++++- base/sysimg.jl | 2 + base/task.jl | 10 ++--- base/tuple.jl | 2 + base/utf8.jl | 2 + src/julia-syntax.scm | 35 ++++++++++++------ 28 files changed, 189 insertions(+), 155 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 0c7c031eda094..5d1ac467af757 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -271,7 +271,8 @@ zero{T}(x::AbstractArray{T}) = fill!(similar(x), zero(T)) start(A::AbstractArray) = _start(A,linearindexing(A)) _start(::AbstractArray,::LinearFast) = 1 -next(a::AbstractArray,i) = (a[i],i+1) +nextval(a::AbstractArray,i) = a[i] +nextstate(a::AbstractArray,i) = i+1 done(a::AbstractArray,i) = (i > length(a)) isempty(a::AbstractArray) = (length(a) == 0) diff --git a/base/bitarray.jl b/base/bitarray.jl index fab21587ec633..8d9b199b28e1d 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -197,7 +197,8 @@ end ## custom iterator ## start(B::BitArray) = 0 -next(B::BitArray, i::Int) = (B.chunks[@_div64(i)+1] & (uint64(1)<<@_mod64(i)) != 0, i+1) +nextval(B::BitArray, i::Int) = B.chunks[@_div64(i)+1] & (uint64(1)<<@_mod64(i)) != 0 +nextstate(B::BitArray, i::Int) = i+1 done(B::BitArray, i::Int) = i >= length(B) ## similar, fill!, copy! etc ## diff --git a/base/char.jl b/base/char.jl index 778a1db06dd40..11d9389ef373b 100644 --- a/base/char.jl +++ b/base/char.jl @@ -26,7 +26,8 @@ last(c::Char) = c eltype(c::Char) = Char start(c::Char) = false -next(c::Char, state) = (c, true) +nextval(c::Char, state) = c +nextstate(c::Char, state) = true done(c::Char, state) = state isempty(c::Char) = false in(x::Char, y::Char) = x == y diff --git a/base/collections.jl b/base/collections.jl index 43e37f820c209..32453a07a04bf 100644 --- a/base/collections.jl +++ b/base/collections.jl @@ -1,6 +1,6 @@ module Collections -import Base: setindex!, done, get, hash, haskey, isempty, length, next, getindex, start +import Base: setindex!, done, get, hash, haskey, isempty, length, nextstate, nextval, getindex, start import ..Order: Forward, Ordering, lt export @@ -282,10 +282,11 @@ start(pq::PriorityQueue) = start(pq.index) done(pq::PriorityQueue, i) = done(pq.index, i) -function next(pq::PriorityQueue, i) - (k, idx), i = next(pq.index, i) - return ((k, pq.xs[idx].second), i) +function nextval(pq::PriorityQueue, i) + (k, idx) = nextval(pq.index, i) + (k, pq.xs[idx].second) end +nextstate(pq::PriorityQueue, i) = nextstate(pq.index, i) end # module Collections diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 5ff9159b1b73d..6de1beafedda9 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -257,11 +257,11 @@ function combinations(a, t::Integer) end start(c::Combinations) = [1:c.t] -function next(c::Combinations, s) - comb = c.a[s] +nextval(c::Combinations, s) = c.a[s] +function nextstate(c::Combinations, s) if c.t == 0 # special case to generate 1 result for t==0 - return (comb,[length(c.a)+2]) + return [length(c.a)+2] end s = copy(s) for i = length(s):-1:1 @@ -274,7 +274,7 @@ function next(c::Combinations, s) end break end - (comb,s) + s end done(c::Combinations, s) = !isempty(s) && s[1] > length(c.a)-c.t+1 @@ -291,11 +291,11 @@ length(c::Permutations) = factorial(length(c.a)) permutations(a) = Permutations(a) start(p::Permutations) = [1:length(p.a)] -function next(p::Permutations, s) - perm = p.a[s] +nextval(p::Permutations, s) = p.a[s] +function nextstate(p::Permutations, s) if length(p.a) == 0 # special case to generate 1 result for len==0 - return (perm,[1]) + return [1] end s = copy(s) k = length(s)-1 @@ -308,7 +308,7 @@ function next(p::Permutations, s) s[k],s[l] = s[l],s[k] reverse!(s,k+1) end - (perm,s) + s end done(p::Permutations, s) = !isempty(s) && s[1] > length(p.a) @@ -325,7 +325,8 @@ partitions(n::Integer) = IntegerPartitions(n) start(p::IntegerPartitions) = Int[] done(p::IntegerPartitions, xs) = length(xs) == p.n -next(p::IntegerPartitions, xs) = (xs = nextpartition(p.n,xs); (xs,xs)) +nextval(p::IntegerPartitions, xs) = nextpartition(p.n,xs) +nextstate(p::IntegerPartitions, xs) = nextpartition(p.n,xs) function nextpartition(n, as) if isempty(as); return Int[n]; end @@ -395,7 +396,8 @@ function done(f::FixedPartitions, s::Vector{Int}) isempty(s) && return false return f.m == 1 || s[1]-1 <= s[end] end -next(f::FixedPartitions, s::Vector{Int}) = (xs = nextfixedpartition(f.n,f.m,s); (xs,xs)) +nextval(f::FixedPartitions, s::Vector{Int}) = nextfixedpartition(f.n,f.m,s) +nextstate(f::FixedPartitions, s::Vector{Int}) = nextfixedpartition(f.n,f.m,s) function nextfixedpartition(n, m, bs) as = copy(bs) @@ -453,21 +455,19 @@ partitions(s::AbstractVector) = SetPartitions(s) start(p::SetPartitions) = (n = length(p.s); (zeros(Int32, n), ones(Int32, n-1), n, 1)) done(p::SetPartitions, s) = s[1][1] > 0 -next(p::SetPartitions, s) = nextsetpartition(p.s, s...) -function nextsetpartition(s::AbstractVector, a, b, n, m) - function makeparts(s, a, m) - temp = [ similar(s,0) for k = 0:m ] - for i = 1:n - push!(temp[a[i]+1], s[i]) - end - filter!(x->!isempty(x), temp) +function nextval(p::SetPartitions, s) + a, _, n, m = s + temp = [ similar(p.s,0) for k = 0:m ] + for i = 1:n + push!(temp[a[i]+1], p.s[i]) end + filter!(x->!isempty(x), temp) +end - if isempty(s); return ([s], ([1], Int[], n, 1)); end - - part = makeparts(s,a,m) - +function nextstate(p::SetPartitions, s) + a, b, n, m = s + isempty(p.s) && return ([1], Int[], n, 1) if a[end] != m a[end] += 1 else @@ -485,9 +485,7 @@ function nextsetpartition(s::AbstractVector, a, b, n, m) end a[end] = 0 end - - return (part, (a,b,n,m)) - + (a,b,n,m) end let _nsetpartitions = Dict{Int,Int}() @@ -529,22 +527,22 @@ end # integer n done(p::FixedSetPartitions, s) = length(s[1]) == 0 || s[1][1] > 1 -next(p::FixedSetPartitions, s) = nextfixedsetpartition(p.s,p.m, s...) -function nextfixedsetpartition(s::AbstractVector, m, a, b, n) - function makeparts(s, a) - part = [ similar(s,0) for k = 1:m ] - for i = 1:n - push!(part[a[i]], s[i]) - end - return part +function nextval(p::FixedSetPartitions, s) + a, _, n = s + part = [ similar(p.s,0) for k = 1:p.m ] + for i = 1:n + push!(part[a[i]], p.s[i]) end + part +end - part = makeparts(s,a) - +function nextstate(p::FixedSetPartitions, s) + m = p.m + a, b, n = s if m == 1 a[1] = 2 - return (part, (a, b, n)) + return (a, b, n) end if a[end] != m @@ -575,8 +573,7 @@ function nextfixedsetpartition(s::AbstractVector, m, a, b, n) a[b]=1:m end end - - return (part, (a,b,n)) + (a,b,n) end function nfixedsetpartitions(n::Int,m::Int) diff --git a/base/dates/ranges.jl b/base/dates/ranges.jl index 6bdd09a639407..50f5605b7b069 100644 --- a/base/dates/ranges.jl +++ b/base/dates/ranges.jl @@ -29,7 +29,8 @@ function in{T<:TimeType}(x::T, r::StepRange{T}) end Base.start{T<:TimeType}(r::StepRange{T}) = 0 -Base.next{T<:TimeType}(r::StepRange{T}, i::Int) = (r.start+r.step*i,i+1) +Base.nextval{T<:TimeType}(r::StepRange{T}, i::Int) = r.start+r.step*i +Base.nextstate{T<:TimeType}(r::StepRange{T}, i::Int) = i+1 Base.done{T<:TimeType,S<:Period}(r::StepRange{T,S}, i::Integer) = length(r) <= i .+{T<:TimeType}(x::Period, r::Range{T}) = (x+first(r)):step(r):(x+last(r)) diff --git a/base/dict.jl b/base/dict.jl index b5c5153cebc6c..83a70d81b6ace 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -149,15 +149,11 @@ eltype(v::ValueIterator) = eltype(v.dict)[2] start(v::Union(KeyIterator,ValueIterator)) = start(v.dict) done(v::Union(KeyIterator,ValueIterator), state) = done(v.dict, state) -function next(v::KeyIterator, state) - n = next(v.dict, state) - n[1][1], n[2] -end +nextval(v::KeyIterator, state) = nextval(v.dict, state)[1] +nextstate(v::KeyIterator, state) = nextstate(v.dict, state) -function next(v::ValueIterator, state) - n = next(v.dict, state) - n[1][2], n[2] -end +nextval(v::ValueIterator, state) = nextval(v.dict, state)[2] +nextstate(v::ValueIterator, state) = nextstate(v.dict, state) in(k, v::KeyIterator) = !is(get(v.dict, k, secret_table_token), secret_table_token) @@ -304,7 +300,8 @@ _oidd_nextind(a, i) = reinterpret(Int,ccall(:jl_eqtable_nextind, Csize_t, (Any, start(t::ObjectIdDict) = _oidd_nextind(t.ht, 0) done(t::ObjectIdDict, i) = (i == -1) -next(t::ObjectIdDict, i) = ((t.ht[i+1],t.ht[i+2]), _oidd_nextind(t.ht, i+2)) +nextval(t::ObjectIdDict, i) = (t.ht[i+1],t.ht[i+2]) +nextstate(t::ObjectIdDict, i) = _oidd_nextind(t.ht, i+2) function length(d::ObjectIdDict) n = 0 @@ -703,13 +700,17 @@ end start(t::Dict) = skip_deleted(t, 1) done(t::Dict, i) = done(t.vals, i) -next(t::Dict, i) = ((t.keys[i],t.vals[i]), skip_deleted(t,i+1)) +nextval(t::Dict, i) = (t.keys[i],t.vals[i]) +nextstate(t::Dict, i) = skip_deleted(t,i+1) isempty(t::Dict) = (t.count == 0) length(t::Dict) = t.count -next{T<:Dict}(v::KeyIterator{T}, i) = (v.dict.keys[i], skip_deleted(v.dict,i+1)) -next{T<:Dict}(v::ValueIterator{T}, i) = (v.dict.vals[i], skip_deleted(v.dict,i+1)) +nextval{T<:Dict}(v::KeyIterator{T}, i) = v.dict.keys[i] +nextstate{T<:Dict}(v::KeyIterator{T}, i) = skip_deleted(v.dict,i+1) + +nextval{T<:Dict}(v::ValueIterator{T}, i) = v.dict.vals[i] +nextstate{T<:Dict}(v::ValueIterator{T}, i) = skip_deleted(v.dict,i+1) # weak key dictionaries @@ -778,8 +779,6 @@ isempty(wkh::WeakKeyDict) = isempty(wkh.ht) start(t::WeakKeyDict) = start(t.ht) done(t::WeakKeyDict, i) = done(t.ht, i) -function next{K}(t::WeakKeyDict{K}, i) - kv, i = next(t.ht, i) - ((kv[1].value::K,kv[2]), i) -end +nextval{K}(t::WeakKeyDict{K}, i) = (kv = nextval(t.ht,i); (kv[1].value::K,kv[2])) +nextstate(t::WeakKeyDict, i) = nextstate(t.ht, i) length(t::WeakKeyDict) = length(t.ht) diff --git a/base/env.jl b/base/env.jl index ebc40a10fa137..fd145a9c65ec3 100644 --- a/base/env.jl +++ b/base/env.jl @@ -117,7 +117,7 @@ push!(::EnvHash, k::AbstractString, v) = setindex!(ENV, v, k) start(::EnvHash) = 0 done(::EnvHash, i) = (ccall(:jl_environ, Any, (Int32,), i) == nothing) -function next(::EnvHash, i) +function nextval(::EnvHash, i) env = ccall(:jl_environ, Any, (Int32,), i) if env == nothing error(BoundsError) @@ -127,23 +127,26 @@ function next(::EnvHash, i) if m == nothing error("malformed environment entry: $env") end - (ByteString[convert(typeof(env),x) for x in m.captures], i+1) + ByteString[convert(typeof(env),x) for x in m.captures] end +nextstate(::EnvHash, i) = i+1 end @windows_only begin -start(hash::EnvHash) = (pos = ccall(:GetEnvironmentStringsW,stdcall,Ptr{UInt16},()); (pos,pos)) -function done(hash::EnvHash, block::(Ptr{UInt16},Ptr{UInt16})) - if unsafe_load(block[1])==0 - ccall(:FreeEnvironmentStringsW,stdcall,Int32,(Ptr{UInt16},),block[2]) +function start(hash::EnvHash) + pos = ccall(:GetEnvironmentStringsW, stdcall, Ptr{UInt16}, ()) + nextstate(hash, (0,pos,pos)) +end +function done(hash::EnvHash, state::(UInt,Ptr{UInt16},Ptr{UInt16})) + if unsafe_load(state[2]) == 0 + ccall(:FreeEnvironmentStringsW,stdcall,Int32,(Ptr{UInt16},),state[3]) return true end false end -function next(hash::EnvHash, block::(Ptr{UInt16},Ptr{UInt16})) - pos = block[1] - blk = block[2] - len = ccall(:wcslen, UInt, (Ptr{UInt16},), pos)+1 +function nextval(hash::EnvHash, state::(UInt,Ptr{UInt16},Ptr{UInt16})) + len = state[1] + pos = state[2] buf = Array(UInt16, len) unsafe_copy!(pointer(buf), pos, len) env = utf8(UTF16String(buf)) @@ -151,7 +154,13 @@ function next(hash::EnvHash, block::(Ptr{UInt16},Ptr{UInt16})) if m == nothing error("malformed environment entry: $env") end - (ByteString[convert(typeof(env),x) for x in m.captures], (pos+len*2, blk)) + ByteString[convert(typeof(env),x) for x in m.captures] +end +function nextstate(hash::EnvHash, state::(UInt,Ptr{UInt16},Ptr{UInt16})) + len,pos,blk = state + pos += 2len + len = ccall(:wcslen, UInt, (Ptr{UInt16},), pos) + 1 + (len, pos, blk) end end diff --git a/base/exports.jl b/base/exports.jl index f9cad968ff2b0..4a999549630c3 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -983,6 +983,8 @@ export done, enumerate, next, + nextstate, + nextval, start, zip, diff --git a/base/inference.jl b/base/inference.jl index 55a1199ff1228..0e7eabb9080d6 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2160,7 +2160,7 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) if incompletematch cost *= 4 end - if is(f, next) || is(f, done) + if is(f, next) || is(f, nextstate) || is(f, nextval) || is(f, done) cost /= 4 end if !inline_worthy(body, cost) diff --git a/base/intset.jl b/base/intset.jl index fe4bc43fe6437..160bc9f04747f 100644 --- a/base/intset.jl +++ b/base/intset.jl @@ -134,21 +134,22 @@ function in(n::Integer, s::IntSet) end start(s::IntSet) = int64(0) -done(s::IntSet, i) = (!s.fill1s && next(s,i)[1] >= s.limit) || i == typemax(Int) -function next(s::IntSet, i) +done(s::IntSet, i) = (!s.fill1s && nextval(s,i) >= s.limit) || i == typemax(Int) +function nextval(s::IntSet, i) if i >= s.limit n = int64(i) else n = int64(ccall(:bitvector_next, UInt64, (Ptr{UInt32}, UInt64, UInt64), s.bits, i, s.limit)) end - (n, n+1) + n end +nextstate(s::IntSet, i) = nextval(s,i)+1 isempty(s::IntSet) = !s.fill1s && ccall(:bitvector_any1, UInt32, (Ptr{UInt32}, UInt64, UInt64), s.bits, 0, s.limit)==0 function first(s::IntSet) - n = next(s,0)[1] + n = nextval(s,0) if n >= s.limit error("set must be non-empty") end diff --git a/base/io.jl b/base/io.jl index 2edd4265d3ed3..670d4d6844c6b 100644 --- a/base/io.jl +++ b/base/io.jl @@ -267,7 +267,8 @@ function done(itr::EachLine, nada) itr.ondone() true end -next(itr::EachLine, nada) = (readline(itr.stream), nothing) +nextval(itr::EachLine, nada) = readline(itr.stream) +nextstate(itr::EachLine, nada) = nothing eltype(itr::EachLine) = ByteString readlines(s=STDIN) = collect(eachline(s)) diff --git a/base/iterator.jl b/base/iterator.jl index 60af28fdb97f5..f7e74d234fd25 100644 --- a/base/iterator.jl +++ b/base/iterator.jl @@ -9,10 +9,8 @@ enumerate(itr) = Enumerate(itr) length(e::Enumerate) = length(e.itr) start(e::Enumerate) = (1, start(e.itr)) -function next(e::Enumerate, state) - n = next(e.itr,state[2]) - (state[1],n[1]), (state[1]+1,n[2]) -end +nextval(e::Enumerate, state) = (state[1], nextval(e.itr,state[2])) +nextstate(e::Enumerate, state) = (state[1]+1, nextstate(e.itr,state[2])) done(e::Enumerate, state) = done(e.itr, state[2]) eltype(e::Enumerate) = (Int, eltype(e.itr)) @@ -29,10 +27,8 @@ zip(itrs...) = _mkZip(itrs) length(z::Zip) = minimum(length, z.itrs) start(z::Zip) = map(start, z.itrs) -function next(z::Zip, state) - n = map(next, z.itrs, state) - map(x->x[1], n), map(x->x[2], n) -end +nextval(z::Zip, state) = map(nextval, z.itrs, state) +nextstate(z::Zip, state) = map(nextstate, z.itrs, state) done(z::Zip, state::()) = true function done(z::Zip, state) for i = 1:length(z.itrs) @@ -53,11 +49,8 @@ zip(a, b) = Zip2(a, b) length(z::Zip2) = min(length(z.a), length(z.b)) start(z::Zip2) = (start(z.a), start(z.b)) -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])) -end +nextval(z::Zip2, st) = (nextval(z.a,st[1]), nextval(z.b,st[2])) +nextstate(z::Zip2, st) = (nextstate(z.a,st[1]), nextstate(z.b,st[2])) done(z::Zip2, st) = done(z.a,st[1]) | done(z.b,st[2]) eltype(z::Zip2) = (eltype(z.a), eltype(z.b)) @@ -70,11 +63,10 @@ immutable Filter{I} end filter(flt::Function, itr) = Filter(flt, itr) -start(f::Filter) = start_filter(f.flt, f.itr) -function start_filter(pred, itr) - s = start(itr) +function filter_state(pred, itr, s) while !done(itr,s) - v,t = next(itr,s) + v = nextval(itr,s) + t = nextstate(itr,s) if pred(v) return (false, v, t) end @@ -83,20 +75,10 @@ function start_filter(pred, itr) (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) - end - s=t - end - v, (true,) -end - -done(f::Filter, s) = s[1] +start(f::Filter) = filter_state(f.flt, f.itr, start(f.itr)) +done(f::Filter, s) = s[1]::Bool +nextval(f::Filter, s) = s[2] +nextstate(f::Filter, s) = filter_state(f.flt, f.itr, s[3]) eltype(f::Filter) = eltype(f.itr) @@ -108,7 +90,8 @@ end rest(itr,state) = Rest(itr,state) start(i::Rest) = i.st -next(i::Rest, st) = next(i.itr, st) +nextval(i::Rest, st) = nextval(i.itr, st) +nextstate(i::Rest, st) = nextstate(i.itr, st) done(i::Rest, st) = done(i.itr, st) eltype(r::Rest) = eltype(r.itr) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 94b1615531f05..0f3510e122db6 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -3,6 +3,9 @@ module IteratorsMD import Base: start, _start, done, next, getindex, setindex!, linearindexing import Base: @nref, @ncall, @nif, @nexprs, LinearFast, LinearSlow +import Base: + nextstate, + nextval export eachindex @@ -64,8 +67,10 @@ end # Prevent an ambiguity warning gen_cartesian(1) # to make sure the next two lines are valid -next(R::StepRange, state::(Bool, CartesianIndex{1})) = R[state[2].I_1], (state[2].I_1==length(R), CartesianIndex_1(state[2].I_1+1)) -next{T}(R::UnitRange{T}, state::(Bool, CartesianIndex{1})) = R[state[2].I_1], (state[2].I_1==length(R), CartesianIndex_1(state[2].I_1+1)) +nextval(R::StepRange, state::(Bool, CartesianIndex{1})) = R[state[2].I_1] +nextstate(R::StepRange, state::(Bool, CartesianIndex{1})) = (state[2].I_1==length(R), CartesianIndex_1(state[2].I_1+1)) +nextval{T}(R::UnitRange{T}, state::(Bool, CartesianIndex{1})) = R[state[2].I_1] +nextstate{T}(R::UnitRange{T}, state::(Bool, CartesianIndex{1})) = (state[2].I_1==length(R), CartesianIndex_1(state[2].I_1+1)) # iteration eachindex(A::AbstractArray) = IndexIterator(size(A)) @@ -90,20 +95,22 @@ stagedfunction _start{T,N}(A::AbstractArray{T,N}, ::LinearSlow) end end -stagedfunction next{T,N}(A::AbstractArray{T,N}, state::(Bool, CartesianIndex{N})) +@inline nextval{T,N}(A::AbstractArray{T,N}, state::(Bool, CartesianIndex{N})) = ((@inbounds v = A[state[2]]); v) +stagedfunction nextstate{T,N}(A::AbstractArray{T,N}, state::(Bool, CartesianIndex{N})) indextype, _ = gen_cartesian(N) finishedex = (N==0 ? true : :(getfield(newindex, $N) > size(A, $N))) meta = Expr(:meta, :inline) quote $meta index=state[2] - @inbounds v = A[index] newindex=@nif $N d->(getfield(index,d) < size(A, d)) d->@ncall($N, $indextype, k->(k>d ? getfield(index,k) : k==d ? getfield(index,k)+1 : 1)) finished=$finishedex - v, (finished,newindex) + (finished,newindex) end end -stagedfunction next{N}(iter::IndexIterator{N}, state::(Bool, CartesianIndex{N})) + +@inline nextval{N}(iter::IndexIterator{N}, state::(Bool, CartesianIndex{N})) = state[2] +stagedfunction nextstate{N}(iter::IndexIterator{N}, state::(Bool, CartesianIndex{N})) indextype, _ = gen_cartesian(N) finishedex = (N==0 ? true : :(getfield(newindex, $N) > getfield(iter.dims, $N))) meta = Expr(:meta, :inline) @@ -112,7 +119,7 @@ stagedfunction next{N}(iter::IndexIterator{N}, state::(Bool, CartesianIndex{N})) index=state[2] newindex=@nif $N d->(getfield(index,d) < getfield(iter.dims, d)) d->@ncall($N, $indextype, k->(k>d ? getfield(index,k) : k==d ? getfield(index,k)+1 : 1)) finished=$finishedex - index, (finished,newindex) + (finished,newindex) end end diff --git a/base/number.jl b/base/number.jl index c6295a8e59682..a42fbad9571a7 100644 --- a/base/number.jl +++ b/base/number.jl @@ -35,7 +35,8 @@ angle(z::Real) = atan2(zero(z), z) widemul(x::Number, y::Number) = widen(x)*widen(y) start(x::Number) = false -next(x::Number, state) = (x, true) +nextval(x::Number, state) = x +nextstate(x::Number, state) = true done(x::Number, state) = state isempty(x::Number) = false in(x::Number, y::Number) = x == y diff --git a/base/operators.jl b/base/operators.jl index 8fca91a010b4c..de8b8f1c06b3a 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -411,7 +411,8 @@ const => = Pair start(p::Pair) = 1 done(p::Pair, i) = i>2 -next(p::Pair, i) = (getfield(p,i), i+1) +nextval(p::Pair, i) = getfield(p,i) +nextstate(p::Pair, i) = i+1 indexed_next(p::Pair, i::Int, state) = (getfield(p,i), i+1) diff --git a/base/precompile.jl b/base/precompile.jl index 277adf6669946..8c24611b45245 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -293,11 +293,6 @@ precompile(Base.length, (Array{UInt8,1},)) precompile(Base.length, (UnitRange{Int},)) precompile(Base.match, (Regex, ASCIIString)) precompile(Base.min, (Int32, Int32)) -precompile(Base.next, (Array{Base.LineEdit.TextInterface, 1}, Int)) -precompile(Base.next, (Dict{Any,Any}, Int)) -precompile(Base.next, (Dict{Symbol,Any},Int)) -precompile(Base.next, (IntSet, Int)) -precompile(Base.next, (UnitRange{Int},Int)) precompile(Base.nextind, (ASCIIString, Int)) precompile(Base.nnz, (BitArray{1},)) precompile(Base.normpath, (ASCIIString,)) diff --git a/base/range.jl b/base/range.jl index 75ed0e2fec1a7..36f972a60ed20 100644 --- a/base/range.jl +++ b/base/range.jl @@ -235,18 +235,21 @@ copy(r::Range) = r ## iteration start(r::FloatRange) = 0 -next{T}(r::FloatRange{T}, i::Int) = (convert(T, (r.start + i*r.step)/r.divisor), i+1) +nextval{T}(r::FloatRange{T}, i::Int) = convert(T, (r.start + i*r.step)/r.divisor) +nextstate(r::FloatRange, i::Int) = i+1 done(r::FloatRange, i::Int) = (length(r) <= i) # NOTE: For ordinal ranges, we assume start+step might be from a # lifted domain (e.g. Int8+Int8 => Int); use that for iterating. start(r::StepRange) = convert(typeof(r.start+r.step), r.start) -next{T}(r::StepRange{T}, i) = (convert(T,i), i+r.step) +nextval{T}(r::StepRange{T}, i) = convert(T,i) +nextstate(r::StepRange, i) = i+r.step done{T,S}(r::StepRange{T,S}, i) = isempty(r) | (i < min(r.start, r.stop)) | (i > max(r.start, r.stop)) done{T,S}(r::StepRange{T,S}, i::Integer) = isempty(r) | (i == r.stop+r.step) start(r::UnitRange) = oftype(r.start+1, r.start) -next{T}(r::UnitRange{T}, i) = (convert(T,i), i+1) +nextval{T}(r::UnitRange{T}, i) = convert(T,i) +nextstate{T}(r::UnitRange{T}, i) = i+1 done(r::UnitRange, i) = i==oftype(i,r.stop)+1 diff --git a/base/reflection.jl b/base/reflection.jl index ecbd86655fe43..a0892ba4fe9f8 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -140,7 +140,8 @@ function length(mt::MethodTable) end start(mt::MethodTable) = mt.defs -next(mt::MethodTable, m::Method) = (m,m.next) +nextval(mt::MethodTable, m::Method) = m +nextstate(mt::MethodTable, m::Method) = m.next done(mt::MethodTable, m::Method) = false done(mt::MethodTable, i::()) = true diff --git a/base/regex.jl b/base/regex.jl index 4d6d4978b7984..3aeb227d5c0ae 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -202,10 +202,11 @@ end compile(itr::RegexMatchIterator) = (compile(itr.regex); itr) eltype(itr::RegexMatchIterator) = RegexMatch start(itr::RegexMatchIterator) = match(itr.regex, itr.string, 1, uint32(0)) -done(itr::RegexMatchIterator, prev_match) = (prev_match == nothing) +done(itr::RegexMatchIterator, prev_match) = (prev_match === nothing) +nextval(itr::RegexMatchIterator, prev_match) = prev_match # Assumes prev_match is not nothing -function next(itr::RegexMatchIterator, prev_match) +function nextstate(itr::RegexMatchIterator, prev_match) prevempty = isempty(prev_match.match) if itr.overlap @@ -232,10 +233,10 @@ function next(itr::RegexMatchIterator, prev_match) break end else - return (prev_match, mat) + return mat end end - (prev_match, nothing) + nothing end function eachmatch(re::Regex, str::AbstractString, ovr::Bool=false) diff --git a/base/set.jl b/base/set.jl index 251c897cddb0f..de3e7b540e5b9 100644 --- a/base/set.jl +++ b/base/set.jl @@ -43,7 +43,8 @@ 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)) +nextval(s::Set, i) = s.dict.keys[i] +nextstate(s::Set, i)= skip_deleted(s.dict,i+1) # TODO: simplify me? pop!(s::Set) = (val = s.dict.keys[start(s.dict)]; delete!(s.dict, val); val) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 5279bf04ab0b8..0f704a190a202 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -2020,14 +2020,15 @@ length(d::SpDiagIterator) = d.n start(d::SpDiagIterator) = 1 done(d::SpDiagIterator, j) = j > d.n -function next{Tv}(d::SpDiagIterator{Tv}, j) +function nextval{Tv}(d::SpDiagIterator{Tv}, j) A = d.A r1 = int(A.colptr[j]) r2 = int(A.colptr[j+1]-1) - (r1 > r2) && (return (zero(Tv), j+1)) + (r1 > r2) && (return zero(Tv)) r1 = searchsortedfirst(A.rowval, j, r1, r2, Forward) - (((r1 > r2) || (A.rowval[r1] != j)) ? zero(Tv) : A.nzval[r1], j+1) + ((r1 > r2) || (A.rowval[r1] != j)) ? zero(Tv) : A.nzval[r1] end +nextstate(d::SpDiagIterator, j) = j+1 function trace{Tv}(A::SparseMatrixCSC{Tv}) if size(A,1) != size(A,2) diff --git a/base/string.jl b/base/string.jl index b16d7ccffeba2..08bfaacd9b67f 100644 --- a/base/string.jl +++ b/base/string.jl @@ -11,8 +11,13 @@ println(xs...) = println(STDOUT, xs...) endof(s::AbstractString) = error("you must implement endof(", typeof(s), ")") next(s::AbstractString, i::Int) = error("you must implement next(", typeof(s), ",Int)") -next(s::DirectIndexString, i::Int) = (s[i],i+1) next(s::AbstractString, i::Integer) = next(s,int(i)) +nextval(s::AbstractString, i::Integer) = next(s,int(i))[1] +nextstate(s::AbstractString, i::Integer) = next(s,int(i))[2] + +next(s::DirectIndexString, i::Int) = (s[i],i+1) +nextval(s::DirectIndexString, i::Int) = s[i] +nextstate(s::DirectIndexString, i::Int) = i+1 ## conversion of general objects to strings ## @@ -608,6 +613,8 @@ function next(s::SubString, i::Int) c, i = next(s.string, i+s.offset) c, i-s.offset end +nextval(s::SubString, i::Int) = nextval(s.string, i+s.offset) +nextstate(s::SubString, i::Int) = nextstate(s.string, i+s.offset)-s.offset function getindex(s::SubString, i::Int) if i < 1 || i > s.endof @@ -742,6 +749,8 @@ function next(s::RevString, i::Int) n = endof(s); j = n-i+1 (s.string[j], n-prevind(s.string,j)+1) end +nextval(s::RevString, i::Int) = s.string[endof(s)-i+1] +nextstate(s::RevString, i::Int) = (n = endof(s); j = n-i+1; n-prevind(s.string,j)+1) reverse(s::AbstractString) = RevString(s) reverse(s::RevString) = s.string diff --git a/base/sysimg.jl b/base/sysimg.jl index a33c5a37a52e6..ac3b0a6d5d4ba 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -215,6 +215,8 @@ using .I18n using .Help push!(I18n.CALLBACKS, Help.clear_cache) +next(a,b) = (nextval(a,b), nextstate(a,b)) + # frontend include("Terminals.jl") include("LineEdit.jl") diff --git a/base/task.jl b/base/task.jl index f732343d1a2ec..20af39d7a96cb 100644 --- a/base/task.jl +++ b/base/task.jl @@ -167,12 +167,10 @@ function consume(P::Task, values...) schedule_and_wait(P) end -start(t::Task) = nothing -function done(t::Task, val) - t.result = consume(t) - istaskdone(t) -end -next(t::Task, val) = (t.result, nothing) +start(t::Task) = consume(t) +done(t::Task, val) = istaskdone(t) +nextval(t::Task, val) = val +nextstate(t::Task, val) = consume(t) isempty(::Task) = error("isempty not defined for Tasks") diff --git a/base/tuple.jl b/base/tuple.jl index 30ce5cbdfe1fb..86cd7cd403dd4 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -13,6 +13,8 @@ getindex(t::Tuple, b::AbstractArray{Bool}) = getindex(t,find(b)) start(t::Tuple) = 1 done(t::Tuple, i::Int) = (length(t) < i) next(t::Tuple, i::Int) = (t[i], i+1) +nextval(t::Tuple, i::Int) = t[i] +nextstate(t::Tuple, i::Int) = i+1 # this allows partial evaluation of bounded sequences of next() calls on tuples, # while reducing to plain next() for arbitrary iterables. diff --git a/base/utf8.jl b/base/utf8.jl index b8d68aa4d3643..9221d83b007fd 100644 --- a/base/utf8.jl +++ b/base/utf8.jl @@ -78,6 +78,8 @@ function next(s::UTF8String, i::Int) c -= utf8_offset[trailing+1] char(c), i end +nextval(s::UTF8String, i::Int) = next(s,i)[1] +nextstate(s::UTF8String, i::Int) = next(s,i)[2] function first_utf8_byte(ch::Char) c = reinterpret(UInt32, ch) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 4448ad853d5ec..defd0f5474e72 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1585,14 +1585,13 @@ (= ,state (call (top start) ,coll)) ,(expand-forms `(,while - (call (top !) (call (top done) ,coll ,state)) - (scope-block + (call (top !) (call (top done) ,coll ,state)) (block ;; NOTE: enable this to force loop-local var #;,@(map (lambda (v) `(local ,v)) (lhs-vars lhs)) - ,(lower-tuple-assignment (list lhs state) - `(call (top next) ,coll ,state)) - ,body)))))))) + (= ,lhs (call (top nextval) ,coll ,state)) + ,body) + (= ,state (call (top nextstate) ,coll ,state)))))))) (define (map-expand-forms e) (map expand-forms e)) @@ -1897,12 +1896,24 @@ (break-block loop-cont ,(expand-forms (caddr e))))))) - 'inner-while + 'for3 + (lambda (e) + `(scope-block + (break-block loop-exit + (_while ,(expand-forms (cadr e)) + (scope-block + (block + (break-block loop-cont ,(expand-forms (caddr e))) + ,(expand-forms (cadddr e)))))))) + + 'inner-for3 (lambda (e) `(scope-block (_while ,(expand-forms (cadr e)) - (break-block loop-cont - ,(expand-forms (caddr e)))))) + (scope-block + (block + (break-block loop-cont ,(expand-forms (caddr e))) + ,(expand-forms (cadddr e))))))) 'break (lambda (e) @@ -1918,7 +1929,7 @@ (cdr (cadr e)) (list (cadr e)))) (first #t)) - (expand-for (if first 'while 'inner-while) + (expand-for (if first 'for3 'inner-for3) (cadr (car ranges)) (caddr (car ranges)) (if (null? (cdr ranges)) @@ -2140,11 +2151,13 @@ (scope-block (block (= ,(car is) (call (top +) ,(car is) 1)) - (= (tuple ,(cadr (car ranges)) ,(car states)) - (call (top next) ,(car rv) ,(car states))) + (= ,(cadr (car ranges)) + (call (top nextval) ,(car rv) ,(car states))) ;; *** either this or force all for loop vars local ,.(map (lambda (r) `(local ,r)) (lhs-vars (cadr (car ranges)))) + (= ,(car states) + (call (top nextstate) ,(car rv) ,(car states))) ,(construct-loops (cdr ranges) (cdr rv) (cdr is) (cdr states) (cdr lengths)))))))) ;; Evaluate the comprehension