ruby-changes:38593
From: ko1 <ko1@a...>
Date: Fri, 29 May 2015 17:40:11 +0900 (JST)
Subject: [ruby-changes:38593] ko1:r50674 (trunk): * tool/make_hgraph.rb: added.
ko1 2015-05-29 17:39:50 +0900 (Fri, 29 May 2015) New Revision: 50674 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50674 Log: * tool/make_hgraph.rb: added. Added files: trunk/tool/make_hgraph.rb Modified files: trunk/ChangeLog Index: ChangeLog =================================================================== --- ChangeLog (revision 50673) +++ ChangeLog (revision 50674) @@ -1,3 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Fri May 29 17:39:14 2015 Koichi Sasada <ko1@a...> + + * tool/make_hgraph.rb: added. + Fri May 29 14:39:00 2015 Nobuyoshi Nakada <nobu@r...> * compile.c (iseq_compile_each): out of range NTH_REF is always Index: tool/make_hgraph.rb =================================================================== --- tool/make_hgraph.rb (revision 0) +++ tool/make_hgraph.rb (revision 50674) @@ -0,0 +1,95 @@ https://github.com/ruby/ruby/blob/trunk/tool/make_hgraph.rb#L1 +# +# Make dot file of internal class/module hierarchy graph. +# + +require 'objspace' + +module ObjectSpace + def self.object_id_of obj + if obj.kind_of?(ObjectSpace::InternalObjectWrapper) + obj.internal_object_id + else + obj.object_id + end + end + + T_ICLASS_NAME = {} + + def self.class_name_of klass + case klass + when Class, Module + # (singleton class).name returns nil + klass.name || klass.inspect + when InternalObjectWrapper # T_ICLASS + if klass.type == :T_ICLASS + "#<I:#{class_name_of(ObjectSpace.internal_class_of(klass))}>" + else + klass.inspect + end + else + klass.inspect + end + end + + def self.module_refenreces klass + h = {} # object_id -> [klass, class_of, super] + stack = [klass] + while klass = stack.pop + obj_id = ObjectSpace.object_id_of(klass) + next if h.has_key?(obj_id) + cls = ObjectSpace.internal_class_of(klass) + sup = ObjectSpace.internal_super_of(klass) + stack << cls if cls + stack << sup if sup + h[obj_id] = [klass, cls, sup].map{|e| ObjectSpace.class_name_of(e)} + end + h.values + end + + def self.module_refenreces_dot klass + result = [] + rank_set = {} + + result << "digraph mod_h {" + # result << " rankdir=LR;" + module_refenreces(klass).each{|(m, k, s)| + # next if /singleton/ =~ m + result << "#{m.dump} -> #{s.dump} [label=\"super\"];" + result << "#{m.dump} -> #{k.dump} [label=\"klass\"];" + + unless rank = rank_set[m] + rank = rank_set[m] = 0 + end + unless rank_set[s] + rank_set[s] = rank + 1 + end + unless rank_set[k] + rank_set[k] = rank + end + } + + rs = [] # [[mods...], ...] + rank_set.each{|m, r| + rs[r] = [] unless rs[r] + rs[r] << m + } + + rs.each{|ms| + result << "{rank = same; #{ms.map{|m| m.dump}.join(", ")}};" + } + result << "}" + result.join("\n") + end + + def self.module_refenreces_image klass, file + dot = module_refenreces_dot(klass) + img = nil + IO.popen("dot -Tpng", 'r+'){|io| + # + io.puts dot + io.close_write + img = io.read + } + open(File.expand_path(file), 'w+'){|f| f.puts img} + end +end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/