https://github.com/JuliaLang/julia
Tip revision: 63b33a2ef51b66d06cc075f9a36efb480515f887 authored by Tony Kelman on 04 November 2016, 23:38:30 UTC
Homebrew changed tap layouts
Homebrew changed tap layouts
Tip revision: 63b33a2
replutil.jl
# This file is a part of Julia. License is MIT: http://julialang.org/license
# fallback text/plain representation of any type:
writemime(io::IO, ::MIME"text/plain", x) = showlimited(io, x)
function writemime(io::IO, ::MIME"text/plain", f::Function)
if isgeneric(f)
n = length(f.env)
m = n==1 ? "method" : "methods"
print(io, "$(f.env.name) (generic function with $n $m)")
else
show(io, f)
end
end
function writemime(io::IO, ::MIME"text/plain", v::AbstractVector)
if isa(v, Range)
show(io, v)
else
print(io, summary(v))
if !isempty(v)
println(io, ":")
with_output_limit(()->print_matrix(io, v))
end
end
end
writemime(io::IO, ::MIME"text/plain", v::AbstractArray) =
with_output_limit(()->showarray(io, v, header=true, repr=false))
function writemime(io::IO, ::MIME"text/plain", v::DataType)
show(io, v)
# TODO: maybe show constructor info?
end
writemime(io::IO, ::MIME"text/plain", t::Associative) =
showdict(io, t, limit=true)
writemime(io::IO, ::MIME"text/plain", t::Union{KeyIterator, ValueIterator}) =
showkv(io, t, limit=true)
# showing exception objects as descriptive error messages
showerror(io::IO, ex) = show(io, ex)
function showerror(io::IO, ex::BoundsError)
print(io, "BoundsError")
if isdefined(ex, :a)
print(io, ": attempt to access ")
writemime(io, MIME"text/plain"(), ex.a)
if isdefined(ex, :i)
print(io, "\n at index [")
if isa(ex.i, Range)
print(io, ex.i)
else
print_joined(io, ex.i, ',')
end
print(io, ']')
end
end
end
function showerror(io::IO, ex::TypeError)
print(io, "TypeError: ")
ctx = isempty(ex.context) ? "" : "in $(ex.context), "
if ex.expected === Bool
print(io, "non-boolean ($(typeof(ex.got))) used in boolean context")
else
if isa(ex.got, Type)
tstr = "Type{$(ex.got)}"
else
tstr = string(typeof(ex.got))
end
print(io, "$(ex.func): $(ctx)expected $(ex.expected), got $tstr")
if ex.func === :apply && ex.expected <: Function && isa(ex.got, AbstractArray)
print(io, "\nUse square brackets [] for indexing.")
end
end
end
function showerror(io::IO, ex, bt; backtrace=true)
try
showerror(io, ex)
finally
backtrace && show_backtrace(io, bt)
end
end
function showerror(io::IO, ex::LoadError, bt; backtrace=true)
print(io, "LoadError: ")
showerror(io, ex.error, bt, backtrace=backtrace)
print(io, "\nwhile loading $(ex.file), in expression starting on line $(ex.line)")
end
showerror(io::IO, ex::LoadError) = showerror(io, ex, [])
function showerror(io::IO, ex::InitError, bt; backtrace=true)
print(io, "InitError: ")
showerror(io, ex.error, bt, backtrace=backtrace)
print(io, "\nduring initialization of module $(ex.mod)")
end
showerror(io::IO, ex::InitError) = showerror(io, ex, [])
function showerror(io::IO, ex::DomainError, bt; backtrace=true)
print(io, "DomainError:")
for b in bt
code = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), b-1, true)
if length(code) == 7 && !code[6] # code[6] == fromC
if code[1] in (:log, :log2, :log10, :sqrt) # TODO add :besselj, :besseli, :bessely, :besselk
print(io,"\n$(code[1]) will only return a complex result if called with a complex argument. Try $(code[1])(complex(x)).")
elseif (code[1] == :^ && code[2] == symbol("intfuncs.jl")) || code[1] == :power_by_squaring #3024
print(io, "\nCannot raise an integer x to a negative power -n. \nMake x a float by adding a zero decimal (e.g. 2.0^-n instead of 2^-n), or write 1/x^n, float(x)^-n, or (x//1)^-n.")
elseif code[1] == :^ && (code[2] == symbol("promotion.jl") || code[2] == symbol("math.jl"))
print(io, "\nExponentiation yielding a complex result requires a complex argument.\nReplace x^y with (x+0im)^y, Complex(x)^y, or similar.")
end
break
end
end
backtrace && show_backtrace(io, bt)
nothing
end
showerror(io::IO, ex::SystemError) = print(io, "SystemError: $(ex.prefix): $(Libc.strerror(ex.errnum))")
showerror(io::IO, ::DivideError) = print(io, "DivideError: integer division error")
showerror(io::IO, ::StackOverflowError) = print(io, "StackOverflowError:")
showerror(io::IO, ::UndefRefError) = print(io, "UndefRefError: access to undefined reference")
showerror(io::IO, ex::UndefVarError) = print(io, "UndefVarError: $(ex.var) not defined")
showerror(io::IO, ::EOFError) = print(io, "EOFError: read end of file")
showerror(io::IO, ex::ErrorException) = print(io, ex.msg)
showerror(io::IO, ex::KeyError) = print(io, "KeyError: $(ex.key) not found")
showerror(io::IO, ex::InterruptException) = print(io, "InterruptException:")
showerror(io::IO, ex::ArgumentError) = print(io, "ArgumentError: $(ex.msg)")
showerror(io::IO, ex::AssertionError) = print(io, "AssertionError: $(ex.msg)")
function showerror(io::IO, ex::MethodError)
# ex.args is a tuple type if it was thrown from `invoke` and is
# a tuple of the arguments otherwise.
is_arg_types = isa(ex.args, DataType)
arg_types = is_arg_types ? ex.args : typesof(ex.args...)
arg_types_param::SimpleVector = arg_types.parameters
print(io, "MethodError: ")
if isa(ex.f, Tuple)
f = ex.f[1]
print(io, "<inline> ")
else
f = ex.f
end
name = isgeneric(f) ? f.env.name : :anonymous
if isa(f, DataType)
print(io, "`$(f)` has no method matching $(f)(")
else
print(io, "`$(name)` has no method matching $(name)(")
end
for (i, typ) in enumerate(arg_types_param)
print(io, "::$typ")
i == length(arg_types_param) || print(io, ", ")
end
print(io, ")")
# Check for local functions that shadow methods in Base
if isdefined(Base, name)
basef = eval(Base, name)
if basef !== ex.f && isgeneric(basef) && method_exists(basef, arg_types)
println(io)
print(io, "you may have intended to import Base.$(name)")
end
end
if !is_arg_types
# Check for row vectors used where a column vector is intended.
vec_args = []
hasrows = false
for arg in ex.args
isrow = isa(arg,Array) && ndims(arg)==2 && size(arg,1)==1
hasrows |= isrow
push!(vec_args, isrow ? vec(arg) : arg)
end
if hasrows && applicable(f, vec_args...)
print(io, "\n\nYou might have used a 2d row vector where a 1d column vector was required.",
"\nNote the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].",
"\nYou can convert to a column vector with the vec() function.")
end
end
# Give a helpful error message if the user likely called a type constructor
# and sees a no method error for convert
if (f == Base.convert && !isempty(arg_types_param) && !is_arg_types &&
isa(arg_types_param[1], DataType) &&
arg_types_param[1].name === Type.name)
construct_type = arg_types_param[1].parameters[1]
println(io)
print(io, "This may have arisen from a call to the constructor $construct_type(...),",
"\nsince type constructors fall back to convert methods.")
end
try
show_method_candidates(io, ex)
catch
warn(io, "Error showing method candidates, aborted")
end
end
#Show an error by directly calling jl_printf.
#Useful in Base submodule __init__ functions where STDERR isn't defined yet.
function showerror_nostdio(err, msg::AbstractString)
stderr_stream = ccall(:jl_stderr_stream, Ptr{Void}, ())
ccall(:jl_printf, Cint, (Ptr{Void},Cstring), stderr_stream, msg)
ccall(:jl_printf, Cint, (Ptr{Void},Cstring), stderr_stream, ":\n")
ccall(:jl_static_show, Csize_t, (Ptr{Void},Any), stderr_stream, err)
ccall(:jl_printf, Cint, (Ptr{Void},Cstring), stderr_stream, "\n")
end
const UNSHOWN_METHODS = ObjectIdDict(
which(call, Tuple{Type, Vararg{Any}}) => true
)
function show_method_candidates(io::IO, ex::MethodError)
is_arg_types = isa(ex.args, DataType)
arg_types = is_arg_types ? ex.args : typesof(ex.args...)
arg_types_param::SimpleVector = arg_types.parameters
# Displays the closest candidates of the given function by looping over the
# functions methods and counting the number of matching arguments.
if isa(ex.f, Tuple)
f = ex.f[1]
else
f = ex.f
end
lines = []
# These functions are special cased to only show if first argument is matched.
special = f in [convert, getindex, setindex!]
funcs = [f]
# An incorrect call method produces a MethodError for convert.
# It also happens that users type convert when they mean call. So
# pool MethodErrors for these two functions.
f === convert && push!(funcs, call)
for func in funcs
name = isgeneric(func) ? func.env.name : :anonymous
for method in methods(func)
haskey(UNSHOWN_METHODS, method) && continue
buf = IOBuffer()
sig = method.sig.parameters
use_constructor_syntax = func == call && !isempty(sig) && isa(sig[1], DataType) &&
!isempty(sig[1].parameters) && isa(sig[1].parameters[1], DataType)
print(buf, " ", use_constructor_syntax ? sig[1].parameters[1].name : name)
right_matches = 0
tv = method.tvars
if !isa(tv,SimpleVector)
tv = svec(tv)
end
if !isempty(tv)
show_delim_array(buf, tv, '{', ',', '}', false)
end
print(buf, "(")
t_i = Any[arg_types_param...]
right_matches = 0
for i = 1 : min(length(t_i), length(sig))
i > (use_constructor_syntax ? 2 : 1) && print(buf, ", ")
# If isvarargtype then it checks wether the rest of the input arguements matches
# the varargtype
if Base.isvarargtype(sig[i])
sigstr = string(sig[i].parameters[1], "...")
j = length(t_i)
else
sigstr = string(sig[i])
j = i
end
# Checks if the type of arg 1:i of the input intersects with the current method
t_in = typeintersect(Tuple{sig[1:i]...}, Tuple{t_i[1:j]...})
# If the function is one of the special cased then it should break the loop if
# the type of the first argument is not matched.
t_in === Union{} && special && i == 1 && break
if use_constructor_syntax && i == 1
right_matches += i
elseif t_in === Union{}
if Base.have_color
Base.with_output_color(:red, buf) do buf
print(buf, "::$sigstr")
end
else
print(buf, "!Matched::$sigstr")
end
# If there is no typeintersect then the type signature from the method is
# inserted in t_i this ensures if the type at the next i matches the type
# signature then there will be a type intersect
t_i[i] = sig[i]
else
right_matches += j==i ? 1 : 0
print(buf, "::$sigstr")
end
end
special && right_matches==0 && continue
if length(t_i) > length(sig) && !isempty(sig) && Base.isvarargtype(sig[end])
# It ensures that methods like f(a::AbstractString...) gets the correct
# number of right_matches
for t in arg_types_param[length(sig):end]
if t <: sig[end].parameters[1]
right_matches += 1
end
end
end
if right_matches > 0
if length(t_i) < length(sig)
# If the methods args is longer than input then the method
# arguments is printed as not a match
for sigtype in sig[length(t_i)+1:end]
if Base.isvarargtype(sigtype)
sigstr = string(sigtype.parameters[1], "...")
else
sigstr = string(sigtype)
end
print(buf, ", ")
if Base.have_color
Base.with_output_color(:red, buf) do buf
print(buf, "::$sigstr")
end
else
print(buf, "!Matched::$sigstr")
end
end
end
print(buf, ")")
push!(lines, (buf, right_matches))
end
end
end
if length(lines) != 0 # Display up to three closest candidates
Base.with_output_color(:normal, io) do io
println(io)
print(io, "Closest candidates are:")
sort!(lines, by = x -> -x[2])
i = 0
for line in lines
println(io)
if i >= 3
print(io, " ...")
break
end
i += 1
print(io, takebuf_string(line[1]))
end
end
end
end
function show_trace_entry(io, fname, file, line, inlinedat_file, inlinedat_line, n)
print(io, "\n")
# if we have inlining information, we print the `file`:`line` first,
# then show the inlining info, because the inlining location
# corresponds to `fname`.
if (inlinedat_file != symbol(""))
# align the location text
print(io, " [inlined code] from ")
else
print(io, " in ", fname, " at ")
end
print(io, file)
if line >= 1
try
print(io, ":", line)
catch
print(io, '?') #for when dec is not yet defined
end
end
if n > 1
print(io, " (repeats ", n, " times)")
end
if (inlinedat_file != symbol(""))
print(io, "\n in ", fname, " at ")
print(io, inlinedat_file, ":", inlinedat_line)
end
end
function show_backtrace(io::IO, t, set=1:typemax(Int))
# we may not declare :eval_user_input
# directly so that we get a compile error
# in case its name changes in the future
show_backtrace(io,
try
eval_user_input.env.name
catch
:(:) #for when client.jl is not yet defined
end, t, set)
end
function show_backtrace(io::IO, top_function::Symbol, t, set)
process_entry(lastname, lastfile, lastline, last_inlinedat_file, last_inlinedat_line, n) =
show_trace_entry(io, lastname, lastfile, lastline, last_inlinedat_file, last_inlinedat_line, n)
process_backtrace(process_entry, top_function, t, set)
end
function show_backtrace(io::IO, top_function::Symbol, t::Vector{Any}, set)
for entry in t
show_trace_entry(io, entry...)
end
end
# process the backtrace, up to (but not including) top_function
function process_backtrace(process_func::Function, top_function::Symbol, t, set)
n = 1
lastfile = ""; lastline = -11; lastname = symbol("#");
last_inlinedat_file = ""; last_inlinedat_line = -1
local fname, file, line
count = 0
for i = 1:length(t)
lkup = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), t[i]-1, true)
if lkup === nothing
continue
end
fname, file, line, inlinedat_file, inlinedat_line, fromC = lkup
if fromC; continue; end
if i == 1 && fname == :error; continue; end
if fname == top_function; break; end
count += 1
if !in(count, set); continue; end
if file != lastfile || line != lastline || fname != lastname
if lastline != -11
process_func(lastname, lastfile, lastline, last_inlinedat_file, last_inlinedat_line, n)
end
n = 1
lastfile = file; lastline = line; lastname = fname;
last_inlinedat_file = inlinedat_file; last_inlinedat_line = inlinedat_line;
else
n += 1
end
end
if n > 1 || lastline != -11
process_func(lastname, lastfile, lastline, last_inlinedat_file, last_inlinedat_line, n)
end
end