RuTu 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+