Skip to content

Commit

Permalink
split next into nextval & nextstate
Browse files Browse the repository at this point in the history
For example,

    for x in xs
        ...

now transforms into

    iter = start(xs)
    while !done(xs,iter)
        x = nextval(xs,iter)
        ...
        iter = nextstate(xs,iter)
  • Loading branch information
nolta committed Nov 27, 2014
1 parent 40fc56b commit d2a0479
Show file tree
Hide file tree
Showing 28 changed files with 171 additions and 148 deletions.
3 changes: 2 additions & 1 deletion base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,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)

Expand Down
3 changes: 2 additions & 1 deletion base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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 ##
Expand Down
3 changes: 2 additions & 1 deletion base/char.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions base/collections.jl
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down
73 changes: 35 additions & 38 deletions base/combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,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
Expand All @@ -273,7 +273,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

Expand All @@ -290,13 +290,13 @@ length(c::Permutations) = factorial(length(c.a))
permutations(a) = Permutations(a)

start(p::Permutations) = [1:length(p.a)]
function next(p::Permutations, s)
nextval(p::Permutations, s) = length(p.a) == 0 ? p.a : p.a[s]
function nextstate(p::Permutations, s)
if length(p.a) == 0
# special case to generate 1 result for len==0
return (p.a,[1])
return [1]
end
s = copy(s)
perm = p.a[s]
k = length(s)-1
while k > 0 && s[k] > s[k+1]; k -= 1; end
if k == 0
Expand All @@ -307,7 +307,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)

Expand All @@ -324,7 +324,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
Expand Down Expand Up @@ -394,7 +395,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)
Expand Down Expand Up @@ -452,21 +454,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
Expand All @@ -484,9 +484,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}()
Expand Down Expand Up @@ -528,22 +526,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
Expand Down Expand Up @@ -574,8 +572,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)
Expand Down
3 changes: 2 additions & 1 deletion base/dates/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ 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
31 changes: 15 additions & 16 deletions base/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -300,7 +296,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
Expand Down Expand Up @@ -699,13 +696,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

Expand Down Expand Up @@ -774,8 +775,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)
31 changes: 20 additions & 11 deletions base/env.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -127,31 +127,40 @@ 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))
m = match(r"^(=?[^=]+)=(.*)$"s, env)
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

Expand Down
2 changes: 2 additions & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,8 @@ export
done,
enumerate,
next,
nextstate,
nextval,
start,
zip,

Expand Down
2 changes: 1 addition & 1 deletion base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 5 additions & 4 deletions base/intset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion base/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,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))
Expand Down
Loading

0 comments on commit d2a0479

Please sign in to comment.