Skip to content

Commit

Permalink
simplify process of printing UnionAll type-variables
Browse files Browse the repository at this point in the history
Since UnionAll bounds are encountered recursively,
it's easiest to represent this the same way in the IOContext.

Also avoid the performance / allocation overhead of using
`IOContext(io)` as a no-op convert (not a no-op since keyword support was added)
  • Loading branch information
vtjnash committed Feb 7, 2017
1 parent 6cc099c commit 893a65b
Show file tree
Hide file tree
Showing 13 changed files with 54 additions and 64 deletions.
8 changes: 6 additions & 2 deletions base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ end

function arg_decl_parts(m::Method)
tv = m.tvars
if !isa(tv,SimpleVector)
if !isa(tv, SimpleVector)
tv = Any[tv]
else
tv = Any[tv...]
Expand All @@ -59,7 +59,11 @@ function arg_decl_parts(m::Method)
if src !== nothing && src.slotnames !== nothing
argnames = src.slotnames[1:m.nargs]
sig = unwrap_unionall(m.sig)
decls = Any[argtype_decl(:tvar_env => tv, argnames[i], sig, i, m.nargs, m.isva)
show_env = ImmutableDict{Symbol, Any}()
for t in tv
show_env = ImmutableDict(show_env, :unionall_env => t)
end
decls = Any[argtype_decl(show_env, argnames[i], sig, i, m.nargs, m.isva)
for i = 1:m.nargs]
else
decls = Any[("", "") for i = 1:length(unwrap_unionall(m.sig).parameters)]
Expand Down
2 changes: 1 addition & 1 deletion base/multimedia.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ mimewritable{mime}(::MIME{mime}, x) =
show(io::IO, m::AbstractString, x) = show(io, MIME(m), x)
mimewritable(m::AbstractString, x) = mimewritable(MIME(m), x)

verbose_show(io, m, x) = show(IOContext(io,limit=false), m, x)
verbose_show(io, m, x) = show(IOContext(io, :limit => false), m, x)

"""
reprmime(mime, x)
Expand Down
2 changes: 1 addition & 1 deletion base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ function print_range(io::IO, r::Range,
limit = get(io, :limit, false)
sz = displaysize(io)
if !haskey(io, :compact)
io = IOContext(io, compact=true)
io = IOContext(io, :compact => true)
end
screenheight, screenwidth = sz[1] - 4, sz[2]
screenwidth -= length(pre) + length(post)
Expand Down
2 changes: 1 addition & 1 deletion base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function show{K,V}(io::IO, ::MIME"text/plain", t::Associative{K,V})
recur_io = IOContext(io, :SHOWN_SET => t)
limit::Bool = get(io, :limit, false)
if !haskey(io, :compact)
recur_io = IOContext(recur_io, compact=true)
recur_io = IOContext(recur_io, :compact => true)
end

print(io, summary(t))
Expand Down
69 changes: 28 additions & 41 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,24 @@ end
The same as `IOContext(io::IO, KV::Pair)`, but accepting properties as keyword arguments.
"""
IOContext(io::IO; kws...) = IOContext(IOContext(io, ImmutableDict{Symbol,Any}()); kws...)
IOContext(io::IO; kws...) = IOContext(convert(IOContext, io); kws...)
function IOContext(io::IOContext; kws...)
for (k, v) in kws
io = IOContext(io, k, v)
end
io
return io
end

convert(::Type{IOContext}, io::IOContext) = io
convert(::Type{IOContext}, io::IO) = IOContext(io, ImmutableDict{Symbol, Any}())

IOContext(io::IOContext, dict::ImmutableDict) = typeof(io)(io.io, dict)
IOContext(io::IO, dict::ImmutableDict) = IOContext{typeof(io)}(io, dict)

IOContext(io::IOContext, key, value) = IOContext(io.io, ImmutableDict{Symbol, Any}(io.dict, key, value))
IOContext(io::IO, key, value) = IOContext(io, ImmutableDict{Symbol, Any}(key, value))
IOContext(io::IOContext, key, value) = IOContext(io, ImmutableDict{Symbol, Any}(io.dict, key, value))

IOContext(io::IO, context::IO) = IOContext(io)
IOContext(io::IO, context::IO) = convert(IOContext, io)

"""
IOContext(io::IO, context::IOContext)
Expand Down Expand Up @@ -183,32 +186,14 @@ function show(io::IO, x::UnionAll)
if print_without_params(x)
return show(io, unwrap_unionall(x).name)
end
tvar_env = get(io, :tvar_env, false)
if tvar_env !== false && isa(tvar_env, AbstractVector)
tvar_env = Any[tvar_env..., x.var]
else
tvar_env = Any[x.var]
end
show(IOContext(io, tvar_env = tvar_env), x.body)
show(IOContext(io, :unionall_env => x.var), x.body)
print(io, " where ")
show(io, x.var)
end

function show_type_parameter(io::IO, p::ANY, has_tvar_env::Bool)
if has_tvar_env
show(io, p)
else
show(IOContext(io, :tvar_env, true), p)
end
end

show(io::IO, x::DataType) = show_datatype(io, x)

function show_datatype(io::IO, x::DataType)
# tvar_env is a `::Vector{Any}` when we are printing a method signature
# and `true` if we are printing type parameters outside a method signature.
has_tvar_env = get(io, :tvar_env, false) !== false

if (!isempty(x.parameters) || x.name === Tuple.name) && x !== Tuple
n = length(x.parameters)

Expand All @@ -223,7 +208,7 @@ function show_datatype(io::IO, x::DataType)
# since this information is still useful.
print(io, '{')
for (i, p) in enumerate(x.parameters)
show_type_parameter(io, p, has_tvar_env)
show(io, p)
i < n && print(io, ',')
end
print(io, '}')
Expand Down Expand Up @@ -1063,16 +1048,12 @@ function ismodulecall(ex::Expr)
end

function show(io::IO, tv::TypeVar)
# If `tvar_env` exist and we are in it, the type constraint are
# already printed and we don't need to print it again.
# If we are in the `unionall_env`, the type-variable is bound
# and the type constraints are already printed.
# We don't need to print it again.
# Otherwise, the lower bound should be printed if it is not `Bottom`
# and the upper bound should be printed if it is not `Any`.
tvar_env = isa(io, IOContext) && get(io, :tvar_env, false)
if isa(tvar_env, Vector{Any})
in_env = (tv in tvar_env::Vector{Any})
else
in_env = false
end
in_env = (:unionall_env => tv) in io
function show_bound(io::IO, b::ANY)
parens = isa(b,UnionAll) && !print_without_params(b)
parens && print(io, "(")
Expand Down Expand Up @@ -1191,16 +1172,22 @@ function dump(io::IO, x::DataType, n::Int, indent)
if x !== Any
print(io, " <: ", supertype(x))
end
if !(x <: Tuple)
tvar_io = IOContext(io, :tvar_env => Any[x.parameters...])
fields = fieldnames(x)
if n > 0
for idx in 1:length(fields)
println(io)
print(io, indent, " ", fields[idx], "::")
print(tvar_io, fieldtype(x, idx))
if n > 0 && !(x <: Tuple)
tvar_io::IOContext = io
for tparam in x.parameters
# approximately recapture the list of tvar parameterization
# that may be used by the internal fields
if isa(tparam, TypeVar)
tvar_io = IOContext(tvar_io, :unionall_env => tparam)
end
end
fields = fieldnames(x)
fieldtypes = x.types
for idx in 1:length(fields)
println(io)
print(io, indent, " ", fields[idx], "::")
print(tvar_io, fieldtypes[idx])
end
end
nothing
end
Expand Down Expand Up @@ -1634,7 +1621,7 @@ function showarray(io::IO, X::AbstractArray, repr::Bool = true; header = true)
return show_vector(io, X, "[", "]")
end
if !haskey(io, :compact)
io = IOContext(io, compact=true)
io = IOContext(io, :compact => true)
end
if !repr && get(io, :limit, false) && eltype(X) === Method
# override usual show method for Vector{Method}: don't abbreviate long lists
Expand Down
4 changes: 2 additions & 2 deletions base/sparse/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ function Base.show(io::IO, ::MIME"text/plain", S::SparseMatrixCSC)
end
end

function Base.show(io::IO, S::SparseMatrixCSC)
Base.show(io::IO, S::SparseMatrixCSC) = Base.show(convert(IOContext, io), S::SparseMatrixCSC)
function Base.show(io::IOContext, S::SparseMatrixCSC)
if nnz(S) == 0
return show(io, MIME("text/plain"), S)
end
Expand All @@ -139,7 +140,6 @@ function Base.show(io::IO, S::SparseMatrixCSC)
pad = ndigits(max(S.m,S.n))
k = 0
sep = "\n "
io = IOContext(io)
if !haskey(io, :compact)
io = IOContext(io, :compact => true)
end
Expand Down
4 changes: 2 additions & 2 deletions base/sparse/sparsevector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,8 @@ function show(io::IO, ::MIME"text/plain", x::AbstractSparseVector)
show(io, x)
end

function show(io::IO, x::AbstractSparseVector)
show(io::IO, x::AbstractSparseVector) = show(convert(IOContext, io), x)
function show(io::IOContext, x::AbstractSparseVector)
# TODO: make this a one-line form
n = length(x)
nzind = nonzeroinds(x)
Expand All @@ -693,7 +694,6 @@ function show(io::IO, x::AbstractSparseVector)
half_screen_rows = limit ? div(displaysize(io)[1] - 8, 2) : typemax(Int)
pad = ndigits(n)
sep = "\n\t"
io = IOContext(io)
if !haskey(io, :compact)
io = IOContext(io, :compact => true)
end
Expand Down
1 change: 0 additions & 1 deletion doc/src/stdlib/io-network.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ Base.readavailable
Base.IOContext
Base.IOContext(::IO, ::Pair)
Base.IOContext(::IO, ::IOContext)
Base.IOContext(::IO)
```

## Text I/O
Expand Down
6 changes: 3 additions & 3 deletions test/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ for d in (Dict("\n" => "\n", "1" => "\n", "\n" => "2"),
for cols in (12, 40, 80), rows in (2, 10, 24)
# Ensure output is limited as requested
s = IOBuffer()
io = Base.IOContext(s, limit=true, displaysize=(rows, cols))
io = Base.IOContext(Base.IOContext(s, :limit => true), :displaysize => (rows, cols))
Base.show(io, MIME("text/plain"), d)
out = split(String(take!(s)),'\n')
for line in out[2:end]
Expand All @@ -278,7 +278,7 @@ for d in (Dict("\n" => "\n", "1" => "\n", "\n" => "2"),

for f in (keys, values)
s = IOBuffer()
io = Base.IOContext(s, limit=true, displaysize=(rows, cols))
io = Base.IOContext(Base.IOContext(s, :limit => true), :displaysize => (rows, cols))
Base.show(io, MIME("text/plain"), f(d))
out = split(String(take!(s)),'\n')
for line in out[2:end]
Expand Down Expand Up @@ -311,7 +311,7 @@ end
type Alpha end
Base.show(io::IO, ::Alpha) = print(io,"α")
let sbuff = IOBuffer(),
io = Base.IOContext(sbuff, limit=true, displaysize=(10, 20))
io = Base.IOContext(Base.IOContext(sbuff, :limit => true), :displaysize => (10, 20))

Base.show(io, MIME("text/plain"), Dict(Alpha()=>1))
@test !contains(String(sbuff), "")
Expand Down
6 changes: 3 additions & 3 deletions test/nullable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ for (i, T) in enumerate(types)
@test String(take!(io1)) == @sprintf("Nullable{%s}(%s)", T, String(take!(io2)))

a1 = [x2]
show(IOContext(io1, compact=false), a1)
show(IOContext(io2, compact=false), x2)
show(IOContext(io1, :compact => false), a1)
show(IOContext(io2, :compact => false), x2)
@test String(take!(io1)) ==
@sprintf("Nullable{%s}[%s]", string(T), String(take!(io2)))

show(io1, a1)
show(IOContext(io2, compact=true), x2)
show(IOContext(io2, :compact => true), x2)
@test String(take!(io1)) ==
@sprintf("Nullable{%s}[%s]", string(T), String(take!(io2)))
end
Expand Down
6 changes: 3 additions & 3 deletions test/offsetarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ smry = summary(v)
@test contains(smry, "OffsetArray{Float64,1")
@test contains(smry, "with indices -1:1")
function cmp_showf(printfunc, io, A)
ioc = IOContext(io, limit=true, compact=true)
ioc = IOContext(IOContext(io, :limit => true), :compact => true)
printfunc(ioc, A)
str1 = String(take!(io))
printfunc(ioc, parent(A))
Expand All @@ -162,9 +162,9 @@ targets2 = ["(1.0, 1.0)",
"([1.0], [1.0])"]
for n = 0:4
a = OffsetArray(ones(Float64,ntuple(d->1,n)), ntuple(identity,n))
show(IOContext(io, limit=true), MIME("text/plain"), a)
show(IOContext(io, :limit => true), MIME("text/plain"), a)
@test String(take!(io)) == targets1[n+1]
show(IOContext(io, limit=true), MIME("text/plain"), (a,a))
show(IOContext(io, :limit => true), MIME("text/plain"), (a,a))
@test String(take!(io)) == targets2[n+1]
end
P = OffsetArray(rand(8,8), (1,1))
Expand Down
2 changes: 1 addition & 1 deletion test/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ end

# stringmime/show should display the range or linspace nicely
# to test print_range in range.jl
replstrmime(x) = sprint((io,x) -> show(IOContext(io, limit=true), MIME("text/plain"), x), x)
replstrmime(x) = sprint((io,x) -> show(IOContext(io, :limit => true), MIME("text/plain"), x), x)
@test replstrmime(1:4) == "1:4"
@test stringmime("text/plain", 1:4) == "1:4"
@test stringmime("text/plain", linspace(1,5,7)) == "1.0:0.6666666666666666:5.0"
Expand Down
6 changes: 3 additions & 3 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const curmod = current_module()
const curmod_name = fullname(curmod)
const curmod_prefix = "$(["$m." for m in curmod_name]...)"

replstr(x) = sprint((io,x) -> show(IOContext(io, limit=true), MIME("text/plain"), x), x)
replstr(x) = sprint((io,x) -> show(IOContext(io, :limit => true), MIME("text/plain"), x), x)

@test replstr(Array{Any}(2)) == "2-element Array{Any,1}:\n #undef\n #undef"
@test replstr(Array{Any}(2,2)) == "2×2 Array{Any,2}:\n #undef #undef\n #undef #undef"
Expand Down Expand Up @@ -533,14 +533,14 @@ end

# PR #16651
@test !contains(repr(ones(10,10)), "\u2026")
@test contains(sprint((io,x)->show(IOContext(io,:limit=>true), x), ones(30,30)), "\u2026")
@test contains(sprint((io, x) -> show(IOContext(io, :limit => true), x), ones(30, 30)), "\u2026")

# showcompact() also sets :multiline=>false (#16817)
let io = IOBuffer()
x = [1, 2]
showcompact(io, x)
@test String(take!(io)) == "[1, 2]"
showcompact(IOContext(io, :compact=>true), x)
showcompact(IOContext(io, :compact => true), x)
@test String(take!(io)) == "[1, 2]"
end

Expand Down

0 comments on commit 893a65b

Please sign in to comment.