RuTu 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/README +1 -0
  2. data/ext/RuTuExt.c +144 -0
  3. data/ext/extconf.rb +3 -0
  4. data/lib/RuTu.rb +205 -0
  5. data/sample.rb +12 -0
  6. metadata +50 -0
data/README ADDED
@@ -0,0 +1 @@
1
+ ruby sample.rb | dot -Tgif > sample.gif
@@ -0,0 +1,144 @@
1
+ #include "ruby.h"
2
+ #include "st.h"
3
+
4
+ #include <assert.h>
5
+ /*
6
+ struct RBasic {
7
+ unsigned long flags;
8
+ VALUE klass;
9
+ };
10
+ struct RObject {
11
+ struct RBasic basic;
12
+ struct st_table *iv_tbl;
13
+ };
14
+ struct RClass {
15
+ struct RBasic basic;
16
+ struct st_table *iv_tbl;
17
+ struct st_table *m_tbl;
18
+ VALUE super;
19
+ };
20
+ */
21
+
22
+
23
+
24
+ VALUE RuTuExt__obj_id(VALUE dummy, VALUE v)
25
+ {
26
+ return rb_obj_id(v);
27
+ }
28
+ VALUE RuTuExt__equal(VALUE dummy, VALUE v1, VALUE v2) // rb_obj_equal
29
+ {
30
+ if (v1 == v2) return Qtrue;
31
+ return Qfalse;
32
+ }
33
+ VALUE RuTuExt__klass(VALUE dummy, VALUE self)
34
+ {
35
+ return RBASIC(self)->klass;
36
+ }
37
+ VALUE RuTuExt__iv_tbl(VALUE dummy, VALUE obj)
38
+ {
39
+ //return rb_fix_new(RCLASS(klass)->m_tbl);
40
+ //assert((RCLASS(klass)->m_tbl & 1) == 0); // doesn't matter......
41
+ return (VALUE) ROBJECT(obj)->iv_tbl; // note: can't be inspected
42
+ }
43
+ VALUE RuTuExt__m_tbl(VALUE dummy, VALUE klass)
44
+ {
45
+ //return rb_fix_new(RCLASS(klass)->m_tbl);
46
+ //assert((RCLASS(klass)->m_tbl & 1) == 0); // doesn't matter......
47
+ return (VALUE) RCLASS(klass)->m_tbl; // note: can't be inspected
48
+ }
49
+ VALUE RuTuExt__super(VALUE dummy, VALUE klass)
50
+ {
51
+ return RCLASS(klass)->super;
52
+ }
53
+ VALUE RuTuExt__singleton_class(VALUE dummy, VALUE klass)
54
+ {
55
+ if (FL_TEST(klass, FL_SINGLETON)) return Qtrue;
56
+ return Qfalse;
57
+ }
58
+
59
+
60
+
61
+ VALUE RuTuExt__class_path(VALUE obj, VALUE klass)
62
+ {
63
+ return rb_class_path(klass);
64
+ }
65
+ //VALUE RuTuExt_class2name(VALUE klass)
66
+ //{
67
+ // return rb_class2name(klass);
68
+ //}
69
+
70
+ //int myprint(ID id, VALUE value, st_data_t dummy)
71
+ //{
72
+ // printf("myprint: %d %s\n", id, rb_id2name(id));
73
+ // return ST_CONTINUE;
74
+ //}
75
+ //
76
+ //int myprint_m_tbl_entry(ID id, VALUE value, st_data_t dummy)
77
+ //{
78
+ // printf("myprint_m_tbl_entry: %d %s %s\n", id, rb_id2name(id), rb_obj_classname(value));
79
+ // return ST_CONTINUE;
80
+ //}
81
+
82
+ /*
83
+ VALUE RuTuExt_foo(VALUE obj, VALUE x)
84
+ {
85
+ //printf("rb_obj_classname of obj: %s\n", rb_obj_classname(obj));
86
+ printf("x: %ld\n", x);
87
+ printf("klass: %ld\n", RBASIC(x)->klass);
88
+ printf("iv_tbl: %ld\n", ROBJECT(x)->iv_tbl);
89
+ printf("m_tbl: %ld\n", RCLASS(x)->m_tbl);
90
+ printf("===== each iv_tbl\n");
91
+ st_foreach(ROBJECT(x)->iv_tbl, myprint, (st_data_t) NULL);
92
+ printf("===== each m_tbl\n");
93
+ st_foreach(RCLASS(x)->m_tbl, myprint_m_tbl_entry, (st_data_t) NULL);
94
+ return x;
95
+ }
96
+ */
97
+
98
+ //VALUE RuTuExt_class_show_methods(VALUE module, VALUE klass)
99
+ //{
100
+ // while (klass)
101
+ // {
102
+ // //printf("klass: %ld %s======\n", klass, RSTRING(rb_class_name(klass))->ptr);
103
+ // //printf("klass: %ld %s======\n", klass, rb_class2name(klass));
104
+ // printf("klass: %ld %s======\n", klass, RSTRING(rb_class_path(klass))->ptr);
105
+ // //st_foreach(ROBJECT(klass)->iv_tbl, myprint, (st_data_t) NULL);
106
+ // printf("--\n");
107
+ // st_foreach(RCLASS(klass)->m_tbl, myprint_m_tbl_entry, (st_data_t) NULL);
108
+ // klass = RCLASS(klass)->super;
109
+ // }
110
+ // return klass;
111
+ //}
112
+ //
113
+ //
114
+ //VALUE RuTuExt_obj_show_methods(VALUE module, VALUE obj)
115
+ //{
116
+ // return RuTuExt_class_show_methods(module, CLASS_OF(obj));
117
+ //}
118
+ //
119
+ //VALUE RuTuExt_class_instance_methods(VALUE dummy, VALUE klass)
120
+ //{
121
+ // return rb_class_instance_methods(0, NULL, klass);
122
+ //}
123
+
124
+
125
+ void Init_RuTuExt()
126
+ {
127
+ VALUE mRuTuExt;
128
+ mRuTuExt = rb_define_module("RuTuExt");
129
+ // printf("hihi\n");
130
+ rb_define_module_function(mRuTuExt, "_obj_id", RuTuExt__obj_id, 1);
131
+ rb_define_module_function(mRuTuExt, "_equal?", RuTuExt__equal, 2);
132
+ rb_define_module_function(mRuTuExt, "_klass", RuTuExt__klass, 1);
133
+ rb_define_module_function(mRuTuExt, "_iv_tbl", RuTuExt__iv_tbl, 1);
134
+ rb_define_module_function(mRuTuExt, "_m_tbl", RuTuExt__m_tbl, 1);
135
+ rb_define_module_function(mRuTuExt, "_super", RuTuExt__super, 1);
136
+ rb_define_module_function(mRuTuExt, "_class_path", RuTuExt__class_path, 1);
137
+ //rb_define_module_function(mRuTuExt, "_instance_methods", RuTuExt_class_instance_methods, 1);
138
+ rb_define_module_function(mRuTuExt, "_singleton_class?", RuTuExt__singleton_class, 1);
139
+ /*
140
+ rb_define_module_function(mRuTuExt, "foo", RuTuExt_foo, 1);
141
+ rb_define_module_function(mRuTuExt, "RuTuExt_obj_show_methods", RuTuExt_obj_show_methods, 1);
142
+ rb_define_module_function(mRuTuExt, "RuTuExt_class_show_methods", RuTuExt_class_show_methods, 1);
143
+ */
144
+ }
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile("RuTuExt")
@@ -0,0 +1,205 @@
1
+ require "set"
2
+ require "RuTuExt"
3
+ require "cgi"
4
+
5
+ module RuTu
6
+
7
+ class ValueNode
8
+ def initialize(g, v)
9
+ @graph = g
10
+ @value = v
11
+ end
12
+ def same_value?(v)
13
+ RuTuExt._equal?(@value, v)
14
+ end
15
+ def _obj_id
16
+ RuTuExt._obj_id(@value)
17
+ end
18
+ def walk(new_value, node_class, relation)
19
+ n = @graph.add(new_value, node_class)
20
+ @graph.add_edge(self, n, relation)
21
+ n
22
+ end
23
+
24
+ def node_id
25
+ "node#{ _obj_id() }"
26
+ end
27
+ def fields
28
+ [ :header ]
29
+ end
30
+ def header_value
31
+ [ self.class.name.gsub(/.*::/, ''), _obj_id() ]
32
+ end
33
+ def color
34
+ "black"
35
+ end
36
+ def to_dot
37
+ label = fields().map do |f|
38
+ v = self.respond_to?("#{f}_value") ? self.send("#{f}_value") : f
39
+ v = [ v ].flatten.map { |x| CGI.escapeHTML(x.to_s()) }.join("<br/>")
40
+ %Q! <tr><td port="#{f}">#{v}</td></tr> !
41
+ end.join(" ")
42
+ label = "<table>#{label}</table>"
43
+ node_id() + " [ shape=plaintext, color=#{color()}, label=<#{label}> ]"
44
+ end
45
+ end
46
+
47
+ class RBasicNode < ValueNode
48
+ def flags; end
49
+ def _klass
50
+ RuTuExt._klass(@value)
51
+ end
52
+ def klass
53
+ walk(_klass(), RClassNode, "klass")
54
+ end
55
+ def fields
56
+ super() + [ :flags, :klass ]
57
+ end
58
+ end
59
+
60
+ class RObjectNode < RBasicNode
61
+ def _iv_tbl
62
+ RuTuExt._iv_tbl(@value)
63
+ end
64
+ def iv_tbl
65
+ walk(_iv_tbl(), St_TableNode, "iv_tbl")
66
+ end
67
+ def fields
68
+ super() + [ :iv_tbl ]
69
+ end
70
+ def color
71
+ "yellow"
72
+ end
73
+ end
74
+
75
+ class RClassNode < RObjectNode
76
+ def header_value
77
+ [ super(), RuTuExt._class_path(@value) ]
78
+ end
79
+ def _m_tbl
80
+ RuTuExt._m_tbl(@value)
81
+ end
82
+ def m_tbl
83
+ walk(_m_tbl(), St_TableNode, "m_tbl")
84
+ end
85
+ def _super
86
+ RuTuExt._super(@value)
87
+ end
88
+ def super
89
+ walk(_super(), RClassNode, "super")
90
+ end
91
+ alias :zuper :super
92
+ def fields
93
+ super() + [ :m_tbl, :super ]
94
+ end
95
+ def color
96
+ "red"
97
+ end
98
+ end
99
+
100
+ class NotValueNode < ValueNode
101
+ def inspect
102
+ "i was never here"
103
+ end
104
+ end
105
+
106
+ class St_TableNode < NotValueNode
107
+ end
108
+
109
+
110
+ class NullNode < ValueNode
111
+ end
112
+
113
+
114
+
115
+
116
+ class Edge
117
+ def initialize(from, to, relation, options = {})
118
+ @from, @to, @relation, @options = from, to, relation, options
119
+ end
120
+ def same?(from, to, relation)
121
+ @from == from && @to == to && @relation == relation
122
+ end
123
+ def to_dot(to_set)
124
+ "#{@from.node_id}:#{@relation} -> #{@to.node_id}:header [ label = #{@relation} ]" +
125
+ ((@relation == "klass" && to_set.add?(@to)) ? "{ rank = same; #{@from.node_id}; #{@to.node_id}; }" : "")
126
+ end
127
+ end
128
+
129
+ class Graph
130
+ def initialize
131
+ @nodes = [] #Set.new
132
+ @edges = [] #Set.new
133
+ end
134
+
135
+ def add(value, node_class)
136
+ rtn = @nodes.find { |n| n.same_value?(value) }
137
+ if not rtn
138
+ node_class = NullNode if false == value
139
+ rtn = node_class.new(self, value)
140
+ @nodes << rtn
141
+ end
142
+ rtn
143
+ end
144
+ def add_edge(from, to, relation)
145
+ rtn = @edges.find { |e| e.same?(from, to, relation) }
146
+ if not rtn
147
+ rtn = Edge.new(from, to, relation)
148
+ @edges << rtn
149
+ end
150
+ rtn
151
+ end
152
+
153
+ # depth = 0 => no-op
154
+ # depth = -1 => no limit
155
+ def closure(init_nodes, relations, depth = -1)
156
+ nodes = Array.new init_nodes
157
+ s = 0
158
+ e = nodes.size
159
+ while s < e && depth != 0
160
+ for i in (s ... e) do
161
+ relations.each do |r|
162
+ nodes |= [ nodes[i].send(r) ] if nodes[i].respond_to?(r)
163
+ end
164
+ end
165
+ depth = depth - 1
166
+ s = e
167
+ e = nodes.size
168
+ end
169
+ nodes
170
+ end
171
+
172
+ def to_dot
173
+ to_set = Set.new
174
+ return <<-"EOG"
175
+ digraph G {
176
+ # rankdir=LR
177
+ node [fontname=Luxi]
178
+ edge [fontname=Luxi]
179
+ #{ @nodes.map { |n| n.to_dot + "\n" } }
180
+ #{ @edges.map { |e| e.to_dot(to_set) + "\n" } }
181
+ }
182
+ EOG
183
+ end
184
+ end
185
+
186
+ end
187
+ __END__
188
+
189
+ #module M; end
190
+ #class A
191
+ # include M
192
+ #end
193
+ #a = A.new
194
+ #def a.foo; end
195
+ #
196
+ class A
197
+ end
198
+ a = A.new
199
+
200
+
201
+
202
+ g = Graph.new
203
+ a_ = g.add(a, RObjectNode)
204
+ g.closure([ a_.klass ], [:klass, :super])
205
+ puts g.to_dot
@@ -0,0 +1,12 @@
1
+ require "rubygems"
2
+ require "RuTu"
3
+
4
+ class A
5
+ end
6
+ a = A.new
7
+
8
+
9
+ g = RuTu::Graph.new
10
+ a_ = g.add(a, RuTu::RObjectNode)
11
+ g.closure([ a_.klass ], [:klass, :super])
12
+ puts g.to_dot
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: RuTu
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2007-06-03 00:00:00 +00:00
8
+ summary: a tool for visualizing object graphs
9
+ require_paths:
10
+ - lib
11
+ email:
12
+ homepage: lcamel@gmail.com
13
+ rubyforge_project: rutu
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Luoh Ren-Shan
31
+ files:
32
+ - lib/RuTu.rb
33
+ - ext/RuTuExt.c
34
+ - ext/extconf.rb
35
+ - sample.rb
36
+ - README
37
+ test_files: []
38
+
39
+ rdoc_options: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ executables: []
44
+
45
+ extensions:
46
+ - ext/extconf.rb
47
+ requirements:
48
+ - "\"dot\" in the GraphViz package"
49
+ dependencies: []
50
+