Skip to content

Commit

Permalink
Merge pull request #3162 from tanmaykm/typetree
Browse files Browse the repository at this point in the history
Fixes #3133 : print unexported types also
  • Loading branch information
StefanKarpinski committed May 21, 2013
2 parents b1d38f7 + 7f473f4 commit 2639665
Showing 1 changed file with 97 additions and 103 deletions.
200 changes: 97 additions & 103 deletions examples/typetree.jl
Original file line number Diff line number Diff line change
@@ -1,125 +1,119 @@
##
#
# (spaghetti) Code to create a text graphic of the Julia type tree
# Used to generate https://github.com/JuliaLang/julia/wiki/Types-Hierarchy
#
# Generate a text graphic of Julia modules type tree
##

function list_all(T::Type, modules::Array{Module}, f::Function)
a = Dict{String, T}()
for m = modules
sm = string(m)
for s = names(m,true)
try
t = eval(m,s)
if f(t)
a[string(s)] = t
end
end
end
end
a
# The node type holds the type of the cuurent node and a dict of subtypes
type TTNode
strname::String
typ::Type
subtypes::Dict{String, TTNode}

TTNode(sname::String, t::Type) = new(sname, t, Dict{String, TTNode}())
end

function to_array{T}(s::Set{T})
a = Array(T, length(s))
i = 1
for ele = s
a[i] = ele
i += 1
end
a
# Add a node to a dict if not added
function add_ttnode(subtypes::Dict{String, TTNode}, sname::String, tnode::TTNode)
ret = get(subtypes, sname, nothing)
(nothing == ret) && (ret = subtypes[sname] = tnode)
ret
end

function mk_tree()
for (x,t) in all_types
add_type(x,t,true)
end
function add_ttnode(subtypes::Dict{String, TTNode}, sname::String, t::Type)
ret = get(subtypes, sname, nothing)
(nothing == ret) && (subtypes[sname] = ret = TTNode(sname, t))
ret
end
extra = Dict{String, String}()
function insert_type(m,s,x,ex)
try
ms = m[s]
add!(ms, x)
catch
m[s] = Set{String}(x)

# Get a string name for the type
typ_name(t::UnionType) = string(t)
typ_name(t::TypeConstructor) = string(t)
typ_name(t) = string(t.name)

# Store a type and its type hierarchy chain
# Recurse till we reach the top level type
function store_type(sname::String, t::UnionType)
suptype = UnionType
tnode = TTNode(sname, t)

# store unions under UnionType type
subtypes = store_type(typ_name(suptype), suptype)
add_ttnode(subtypes, sname, tnode)

# unions are also in a sense related to the types of their components
for suptype = t.types
subtypes = store_type(typ_name(suptype), suptype)
add_ttnode(subtypes, sname, tnode)
end
extra[x] = ex

return tnode.subtypes
end

function add_type(x,t,sup)
if isa(t, DataType)
s = sup ? super(t) : t
s_param = ""
if x != string(t.name)
s_param *= " = " * string(t.name)
elseif length(s.parameters) != 0
s_param *= " (=" * string(s.name) * "{" * join(s.parameters, ", ") * "})"
end
insert_type(children_map, string(s.name), x, s_param)
elseif isa(t, UnionType)
for c in t.types
add_type(x, c, false)
end
insert_type(children_map, "UnionType", x, " = " * string(t))
elseif isa(t, TypeConstructor)
add_type(x, t.body, false)
#println(typeof(t.body))
insert_type(children_map, "TypeConstructor", x, " = " * string(t))
else
function store_type(sname::String, t::TypeConstructor)
suptype = t.body
subtypes = store_type(typ_name(suptype), suptype)
tnode = add_ttnode(subtypes, sname, t)
return tnode.subtypes
end

function store_type(sname::String, t::DataType)
suptype = super(t)
subtypes = (suptype != t) ? store_type(typ_name(suptype), suptype) : types_tree
tnode = add_ttnode(subtypes, sname, t)
return tnode.subtypes
end

function store_type(sname::String, t::Tuple)
tnode = add_ttnode(types_tree, sname, t)
return tnode.subtypes
end

function store_type(sname::String, t)
suptype = super(t)
subtypes = (suptype != t) ? store_type(typ_name(suptype), suptype) : types_tree
tnode = add_ttnode(subtypes, sname, t)
return tnode.subtypes
end

# examine all symbols in module and store those that are types
function store_all_from(m::Module)
for expr = names(m,true)
try
print("unknown -> ")
print(x)
print(" ")
print(typeof(t))
print(" ")
print(t.name)
t = eval(m,expr)
isa(t, Type) && store_type(string(expr), t)
#catch ex
# println("Error adding ", string(expr), " ", t, " ", m, " (", ex, ")")
end
println(t)
end
end

function show_tree(root, prefix, norm_ex)
r = root
t = all_types[root]
try
if length(t.parameters) != 0
root *= "{" * join(t.parameters, ", ") * "}"
end
end
ex = extra[r]
if ex != norm_ex
root *= ex
end
println(prefix[1:end-1] * "+- " * root)
norm_ex = ""
try
norm_ex = " (=" * r * "{" * join(t.parameters, ", ") * "})"
end
children = get(children_map, r, None)
if children != None
ch = to_array(children)
sort!(ch)
delete!(children_map, r)
iter = start(ch)
cpre = prefix * " +"
dpre = prefix * " "
while !done(ch, iter)
c,iter = next(ch, iter)
if c != root
show_tree(c, done(ch, iter) ? dpre : cpre, norm_ex)
end

type_props(typ) = ""
type_props(typ::DataType) = string("<<",
typ.abstract ? " abstract" : " concrete",
typ.mutable ? " mutable" : " immutable",
typ.pointerfree ? " pointerfree" : "",
" size:", typ.size,
" >>")

function print_tree(subtypes::Dict{String, TTNode}, pfx::String="")
for (n,v) in subtypes
if(n == string(v.typ))
println(pfx, "+- ", n, " ", type_props(v.typ))
else
println(pfx, "+- ", n, " = ", v.typ, " ", type_props(v.typ))
end
print_tree(v.subtypes, pfx * ". ")
end
end

show_tree(root) = show_tree(root, "", "")

## main ##
all_types = list_all(Type, [Core, Base, Main], (x)->isa(x, Type))
children_map = Dict{String, Set{String}}()
mk_tree()
println("\n\nType Tree:")
show_tree("Any") #todo: generalize this to be every item without a parent in all_types
# TODO: optionally take module names in command line
# TODO: sort output
# TODO: option to list subtrees of type tree, or other symbol types
const types_tree = Dict{String, TTNode}()

for m = [Base, Core, Main]
store_all_from(m)
end

print_tree(types_tree)

0 comments on commit 2639665

Please sign in to comment.