forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
typetree.jl
126 lines (103 loc) · 3.71 KB
/
typetree.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# This file is a part of Julia. License is MIT: http://julialang.org/license
module TypeTrees
##
# Generate a text graphic of Julia modules type tree
##
# The node type holds the type of the cuurent node and a dict of subtypes
type TTNode
strname::AbstractString
typ::Type
subtypes::Dict{AbstractString, TTNode}
TTNode(sname::AbstractString, t::Type) = new(sname, t, Dict{AbstractString, TTNode}())
end
# Add a node to a dict if not added
function add_ttnode(subtypes::Dict{AbstractString, TTNode}, sname::AbstractString, tnode::TTNode)
ret = get(subtypes, sname, nothing)
(nothing == ret) && (ret = subtypes[sname] = tnode)
ret
end
function add_ttnode(subtypes::Dict{AbstractString, TTNode}, sname::AbstractString, t::Type)
ret = get(subtypes, sname, nothing)
(nothing == ret) && (subtypes[sname] = ret = TTNode(sname, t))
ret
end
# Get a string name for the type
typ_name(t::Union) = 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::AbstractString, t::Union)
suptype = Union
tnode = TTNode(sname, t)
# store unions under Union 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
return tnode.subtypes
end
function store_type(sname::AbstractString, 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::AbstractString, t::DataType)
suptype = supertype(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::AbstractString, t::Tuple)
tnode = add_ttnode(types_tree, sname, t)
return tnode.subtypes
end
function store_type(sname::AbstractString, t)
suptype = supertype(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)
if isdefined(m,expr)
t = getfield(m, expr)
isa(t, Type) && store_type(string(expr), t)
end
end
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{AbstractString, TTNode}, pfx::AbstractString="")
for n in sort!([keys(subtypes)...])
v = subtypes[n]
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
# 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{AbstractString, TTNode}()
for m in (Base, Core, Main)
store_all_from(m)
end
# print_tree(types_tree)
end # module
if !isinteractive()
TypeTrees.print_tree(TypeTrees.types_tree)
end