ZenHacks 1.0.0
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.
- data/History.txt +4 -0
- data/Manifest.txt +29 -0
- data/README.txt +84 -0
- data/bin/macgraph +18 -0
- data/bin/parse_tree_graph +161 -0
- data/bin/test_stats +42 -0
- data/fixloops-demo.sh +3 -0
- data/lib/OrderedHash.rb +37 -0
- data/lib/class-path.rb +20 -0
- data/lib/discover.rb +15 -0
- data/lib/fixloops.rb +79 -0
- data/lib/graph.rb +66 -0
- data/lib/muffdaddy.rb +84 -0
- data/lib/r2c_hacks.rb +36 -0
- data/lib/ruby2ruby.rb +306 -0
- data/lib/timezones.rb +11 -0
- data/lib/zendebug.rb +1037 -0
- data/lib/zenoptimize.rb +149 -0
- data/lib/zenprofile.rb +170 -0
- data/misc/factorial.rb +26 -0
- data/misc/find_c_methods +49 -0
- data/misc/fixloops-bad.rb +62 -0
- data/r2c_hacks-demo.rb +23 -0
- data/test/TestOrderedHash.rb +43 -0
- data/test/r2ctestcase.rb +1076 -0
- data/test/test_parse_tree_graph.rb +47 -0
- data/zendebug-demo.sh +86 -0
- data/zenoptimize-demo.sh +22 -0
- data/zenprofile-demo.sh +29 -0
- metadata +69 -0
data/lib/graph.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
class Graph < Hash
|
4
|
+
|
5
|
+
attr_reader :attribs
|
6
|
+
attr_reader :prefix
|
7
|
+
attr_reader :order
|
8
|
+
def initialize(name="a_graph")
|
9
|
+
super() { |h,k| h[k] = [] }
|
10
|
+
@name = name
|
11
|
+
@prefix = []
|
12
|
+
@attribs = Hash.new { |h,k| h[k] = [] }
|
13
|
+
@order = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(key, val)
|
17
|
+
@order << key unless self.has_key? key
|
18
|
+
super(key, val)
|
19
|
+
end
|
20
|
+
|
21
|
+
def each_pair
|
22
|
+
@order.each do |from|
|
23
|
+
self[from].each do |to|
|
24
|
+
yield(from, to)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def invert
|
30
|
+
result = self.class.new
|
31
|
+
each_pair do |from, to|
|
32
|
+
result[to] << from
|
33
|
+
end
|
34
|
+
result
|
35
|
+
end
|
36
|
+
|
37
|
+
def counts
|
38
|
+
result = Hash.new(0)
|
39
|
+
each_pair do |from, to|
|
40
|
+
result[from] += 1
|
41
|
+
end
|
42
|
+
result
|
43
|
+
end
|
44
|
+
|
45
|
+
def keys_by_count
|
46
|
+
counts.sort_by { |x,y| y }.map {|x| x.first }
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
result = []
|
51
|
+
result << "digraph #{@name}"
|
52
|
+
result << " {"
|
53
|
+
@prefix.each do |line|
|
54
|
+
result << line
|
55
|
+
end
|
56
|
+
@attribs.sort.each do |node, attribs|
|
57
|
+
result << " #{node.inspect} [ #{attribs.join(',')} ]"
|
58
|
+
end
|
59
|
+
each_pair do |from, to|
|
60
|
+
result << " #{from.inspect} -> #{to.inspect};"
|
61
|
+
end
|
62
|
+
result << " }"
|
63
|
+
result.join("\n")
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/lib/muffdaddy.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# the ultimate "rapper"
|
4
|
+
module MuffDaddy
|
5
|
+
def self.__rap_method__(c, m)
|
6
|
+
return if m =~ /^__/
|
7
|
+
c = class << c; self; end unless c.class == Class
|
8
|
+
return if c.instance_methods(false).include? "__#{m}"
|
9
|
+
rapped_method = c.const_get("RAP_METHOD_NAME")
|
10
|
+
c.class_eval "alias __#{m} #{m}"
|
11
|
+
c.class_eval "def #{m}(*args); #{rapped_method} { __#{m}(*args) }; end"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.__rap_class__(c)
|
15
|
+
c.instance_methods(false).each { |m| __rap_method__(c, m) }
|
16
|
+
c.class_eval "def self.method_added(m); MuffDaddy.__rap_method__(self, m.to_s); end"
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.__rap_object__(o)
|
20
|
+
o.public_methods(false).each { |m| __rap_method__(o, m) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.extend_object(o)
|
24
|
+
super(o)
|
25
|
+
MuffDaddy.__rap_object__(o)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.included(c)
|
29
|
+
super(c)
|
30
|
+
if c.class == Module then
|
31
|
+
c.module_eval "def self.included(c); super(c); MuffDaddy.included(c); end"
|
32
|
+
c.module_eval "def self.extend_object(c); super(c); MuffDaddy.extend_object(c); end"
|
33
|
+
end
|
34
|
+
MuffDaddy.__rap_class__(c)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module CheapoTracer
|
39
|
+
|
40
|
+
include MuffDaddy
|
41
|
+
|
42
|
+
RAP_METHOD_NAME = :__trace__
|
43
|
+
|
44
|
+
def __trace__
|
45
|
+
@__trace = 0 unless defined? @__trace
|
46
|
+
print " " * @__trace
|
47
|
+
print "#{@__trace}: "
|
48
|
+
@__trace += 1
|
49
|
+
yield
|
50
|
+
@__trace -= 1
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
class Untraced
|
56
|
+
def something
|
57
|
+
puts "Miiiiisery!"
|
58
|
+
something_else
|
59
|
+
end
|
60
|
+
|
61
|
+
def something_else
|
62
|
+
puts "Decay!"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Traced
|
67
|
+
include CheapoTracer
|
68
|
+
|
69
|
+
def method1
|
70
|
+
puts "I'm dead too!"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
w1 = Untraced.new
|
75
|
+
w1.something
|
76
|
+
|
77
|
+
w1.extend CheapoTracer
|
78
|
+
w1.something
|
79
|
+
|
80
|
+
w2 = Untraced.new
|
81
|
+
w2.something
|
82
|
+
|
83
|
+
w3 = Traced.new
|
84
|
+
w3.method1
|
data/lib/r2c_hacks.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#require 'rubygems'
|
2
|
+
#require_gem 'ParseTree'
|
3
|
+
require 'parse_tree'
|
4
|
+
require 'sexp_processor'
|
5
|
+
require 'ruby_to_c'
|
6
|
+
require 'ruby2ruby'
|
7
|
+
|
8
|
+
class Method
|
9
|
+
def with_class_and_method_name
|
10
|
+
if self.inspect =~ /<Method: (.*)\#(.*)>/ then
|
11
|
+
klass = eval $1
|
12
|
+
method = $2.intern
|
13
|
+
return yield(klass, method)
|
14
|
+
else
|
15
|
+
raise "Can't parse signature: #{self.inspect}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_sexp
|
20
|
+
with_class_and_method_name do |klass, method|
|
21
|
+
ParseTree.new.parse_tree_for_method(klass, method)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_c
|
26
|
+
with_class_and_method_name do |klass, method|
|
27
|
+
RubyToC.translate(klass, method)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_ruby
|
32
|
+
with_class_and_method_name do |klass, method|
|
33
|
+
RubyToRuby.translate(klass, method)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/ruby2ruby.rb
ADDED
@@ -0,0 +1,306 @@
|
|
1
|
+
require 'parse_tree'
|
2
|
+
require 'support'
|
3
|
+
require 'sexp_processor'
|
4
|
+
|
5
|
+
class RubyToRuby < SexpProcessor
|
6
|
+
|
7
|
+
def self.translate(klass, method=nil)
|
8
|
+
unless method.nil? then
|
9
|
+
self.new.process(ParseTree.new.parse_tree_for_method(klass, method))
|
10
|
+
else
|
11
|
+
self.new.process(ParseTree.new.parse_tree(klass).first) # huh? why is the :class node wrapped?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
super
|
17
|
+
@env = Environment.new
|
18
|
+
@indent = " "
|
19
|
+
self.auto_shift_type = true
|
20
|
+
self.strict = true
|
21
|
+
self.expected = String
|
22
|
+
end
|
23
|
+
|
24
|
+
def indent(s)
|
25
|
+
s.to_s.map{|line| @indent + line}.join
|
26
|
+
end
|
27
|
+
|
28
|
+
def process_and(exp)
|
29
|
+
"(#{process exp.shift} and #{process exp.shift})"
|
30
|
+
end
|
31
|
+
|
32
|
+
def process_args(exp)
|
33
|
+
args = []
|
34
|
+
|
35
|
+
until exp.empty? do
|
36
|
+
arg = exp.shift
|
37
|
+
if arg.is_a? Array
|
38
|
+
args[-(arg.size-1)..-1] = arg[1..-1].map{|a| process a}
|
39
|
+
else
|
40
|
+
args << arg
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
return "(#{args.join ', '})"
|
45
|
+
end
|
46
|
+
|
47
|
+
def process_array(exp)
|
48
|
+
code = []
|
49
|
+
until exp.empty? do
|
50
|
+
code << process(exp.shift)
|
51
|
+
end
|
52
|
+
return "[" + code.join(", ") + "]"
|
53
|
+
end
|
54
|
+
|
55
|
+
def process_attrasgn(exp)
|
56
|
+
process_call(exp)
|
57
|
+
end
|
58
|
+
|
59
|
+
def process_block(exp)
|
60
|
+
code = []
|
61
|
+
until exp.empty? do
|
62
|
+
code << process(exp.shift)
|
63
|
+
end
|
64
|
+
|
65
|
+
body = code.join("\n")
|
66
|
+
body += "\n"
|
67
|
+
|
68
|
+
return body
|
69
|
+
end
|
70
|
+
|
71
|
+
def process_call(exp)
|
72
|
+
receiver = process exp.shift
|
73
|
+
name = exp.shift
|
74
|
+
args_exp = exp.shift
|
75
|
+
if args_exp && args_exp.first == :array
|
76
|
+
args = "#{process(args_exp)[1..-2]}"
|
77
|
+
else
|
78
|
+
args = process args_exp
|
79
|
+
end
|
80
|
+
|
81
|
+
case name
|
82
|
+
when :<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :% then #
|
83
|
+
"(#{receiver} #{name} #{args})"
|
84
|
+
when :[] then
|
85
|
+
"#{receiver}[#{args}]"
|
86
|
+
else
|
87
|
+
"#{receiver}.#{name}#{args ? "(#{args})" : args}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def process_case(exp)
|
92
|
+
s = "case #{process exp.shift}\n"
|
93
|
+
until exp.empty?
|
94
|
+
pt = exp.shift
|
95
|
+
if pt.first == :when
|
96
|
+
s << "#{process(pt)}\n"
|
97
|
+
else
|
98
|
+
s << "else\n#{indent(process(pt))}\n"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
s + "\nend"
|
102
|
+
end
|
103
|
+
|
104
|
+
def process_class(exp)
|
105
|
+
s = "class #{exp.shift} < #{exp.shift}\n"
|
106
|
+
body = ""
|
107
|
+
body << "#{process exp.shift}\n\n" until exp.empty?
|
108
|
+
s + indent(body) + "end"
|
109
|
+
end
|
110
|
+
|
111
|
+
def process_const(exp)
|
112
|
+
exp.shift.to_s
|
113
|
+
end
|
114
|
+
|
115
|
+
def process_dasgn_curr(exp)
|
116
|
+
exp.shift.to_s
|
117
|
+
end
|
118
|
+
|
119
|
+
def process_defn(exp)
|
120
|
+
name = exp.shift
|
121
|
+
args = process(exp.shift).to_a
|
122
|
+
args[1..-1] = indent(args[1..-1])
|
123
|
+
args.join
|
124
|
+
body = indent(process(exp.shift))
|
125
|
+
return "def #{name}#{args}#{body}end".gsub(/\n\s*\n+/, "\n")
|
126
|
+
end
|
127
|
+
|
128
|
+
def process_dot2(exp)
|
129
|
+
"(#{process exp.shift}..#{process exp.shift})"
|
130
|
+
end
|
131
|
+
|
132
|
+
def process_dot3(exp)
|
133
|
+
"(#{process exp.shift}...#{process exp.shift})"
|
134
|
+
end
|
135
|
+
|
136
|
+
def process_dstr(exp)
|
137
|
+
s = exp.shift.dump[0..-2]
|
138
|
+
until exp.empty?
|
139
|
+
pt = exp.shift
|
140
|
+
if pt.first == :str
|
141
|
+
s << process(pt)[1..-2]
|
142
|
+
else
|
143
|
+
s << '#{' + process(pt) + '}'
|
144
|
+
end
|
145
|
+
end
|
146
|
+
s + '"'
|
147
|
+
end
|
148
|
+
|
149
|
+
def process_dvar(exp)
|
150
|
+
exp.shift.to_s
|
151
|
+
end
|
152
|
+
|
153
|
+
def process_false(exp)
|
154
|
+
"false"
|
155
|
+
end
|
156
|
+
|
157
|
+
def process_fcall(exp)
|
158
|
+
exp_orig = exp.deep_clone
|
159
|
+
# [:fcall, :puts, [:array, [:str, "This is a weird loop"]]]
|
160
|
+
name = exp.shift.to_s
|
161
|
+
args = exp.shift
|
162
|
+
code = []
|
163
|
+
unless args.nil? then
|
164
|
+
assert_type args, :array
|
165
|
+
args.shift # :array
|
166
|
+
until args.empty? do
|
167
|
+
code << process(args.shift)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
return "#{name}(#{code.join(', ')})"
|
171
|
+
end
|
172
|
+
|
173
|
+
def process_iasgn(exp)
|
174
|
+
"#{exp.shift} = #{process exp.shift}"
|
175
|
+
end
|
176
|
+
|
177
|
+
def process_if(exp)
|
178
|
+
s = ["if (#{process exp.shift})"]
|
179
|
+
s << "#{indent(process(exp.shift))}"
|
180
|
+
s << "else\n#{indent(process(exp.shift))}" until exp.empty?
|
181
|
+
s << "end"
|
182
|
+
s.join("\n")
|
183
|
+
end
|
184
|
+
|
185
|
+
def process_iter(exp)
|
186
|
+
"#{process exp.shift} {|#{process exp.shift}|\n" +
|
187
|
+
indent("#{process exp.shift}\n") +
|
188
|
+
"}"
|
189
|
+
end
|
190
|
+
|
191
|
+
def process_ivar(exp)
|
192
|
+
exp.shift.to_s
|
193
|
+
end
|
194
|
+
|
195
|
+
def process_lasgn(exp)
|
196
|
+
return "#{exp.shift} = #{process exp.shift}"
|
197
|
+
end
|
198
|
+
|
199
|
+
def process_lit(exp)
|
200
|
+
obj = exp.shift
|
201
|
+
if obj.is_a? Range # to get around how parsed ranges turn into lits and lose parens
|
202
|
+
"(" + obj.inspect + ")"
|
203
|
+
else
|
204
|
+
obj.inspect
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def process_lvar(exp)
|
209
|
+
exp.shift.to_s
|
210
|
+
end
|
211
|
+
|
212
|
+
def process_masgn(exp)
|
213
|
+
process(exp.shift)[1..-2]
|
214
|
+
end
|
215
|
+
|
216
|
+
def process_nil(exp)
|
217
|
+
"nil"
|
218
|
+
end
|
219
|
+
|
220
|
+
def process_return(exp)
|
221
|
+
return "return #{process exp.shift}"
|
222
|
+
end
|
223
|
+
|
224
|
+
def process_scope(exp)
|
225
|
+
return process(exp.shift)
|
226
|
+
end
|
227
|
+
|
228
|
+
def process_self(exp)
|
229
|
+
"self"
|
230
|
+
end
|
231
|
+
def process_str(exp)
|
232
|
+
return exp.shift.dump
|
233
|
+
end
|
234
|
+
|
235
|
+
def process_super(exp)
|
236
|
+
"super(#{process(exp.shift)})"
|
237
|
+
end
|
238
|
+
|
239
|
+
def process_true(exp)
|
240
|
+
"true"
|
241
|
+
end
|
242
|
+
|
243
|
+
def process_until(exp)
|
244
|
+
cond_loop(exp, 'until')
|
245
|
+
end
|
246
|
+
|
247
|
+
def process_vcall(exp)
|
248
|
+
return exp.shift.to_s
|
249
|
+
end
|
250
|
+
|
251
|
+
def process_when(exp)
|
252
|
+
"when #{process(exp.shift).to_s[1..-2]}\n#{indent(process(exp.shift))}"
|
253
|
+
end
|
254
|
+
|
255
|
+
def process_while(exp)
|
256
|
+
cond_loop(exp, 'while')
|
257
|
+
end
|
258
|
+
|
259
|
+
def process_zarray(exp)
|
260
|
+
"[]"
|
261
|
+
end
|
262
|
+
|
263
|
+
def process_zsuper(exp)
|
264
|
+
"super"
|
265
|
+
end
|
266
|
+
|
267
|
+
def cond_loop(exp, name)
|
268
|
+
cond = process(exp.shift)
|
269
|
+
body = indent(process(exp.shift))
|
270
|
+
head_controlled = exp.empty? ? false : exp.shift
|
271
|
+
|
272
|
+
code = []
|
273
|
+
if head_controlled then
|
274
|
+
code << "#{name} #{cond} do"
|
275
|
+
code << body
|
276
|
+
code << "end"
|
277
|
+
else
|
278
|
+
code << "begin"
|
279
|
+
code << body
|
280
|
+
code << "end #{name} #{cond}"
|
281
|
+
end
|
282
|
+
code.join("\n")
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
|
287
|
+
if __FILE__ == $0
|
288
|
+
r2r2r = RubyToRuby.translate(RubyToRuby).sub("RubyToRuby","RubyToRubyToRuby")
|
289
|
+
eval r2r2r
|
290
|
+
|
291
|
+
class RubyToRubyToRuby
|
292
|
+
class<<self
|
293
|
+
eval RubyToRuby.translate(class<<RubyToRuby;self;end, :translate)
|
294
|
+
end
|
295
|
+
eval RubyToRuby.translate(RubyToRuby, :initialize)
|
296
|
+
end
|
297
|
+
|
298
|
+
r2r2r2 = RubyToRubyToRuby.translate(RubyToRuby).sub("RubyToRuby","RubyToRubyToRuby")
|
299
|
+
r2r2r2r = RubyToRubyToRuby.translate(RubyToRubyToRuby)
|
300
|
+
# File.open('1','w'){|f| f.write r2r2r}
|
301
|
+
# File.open('2','w'){|f| f.write r2r2r2}
|
302
|
+
# File.open('3','w'){|f| f.write r2r2r2r}
|
303
|
+
raise "Translation failed!" if (r2r2r != r2r2r2) or (r2r2r != r2r2r2r)
|
304
|
+
|
305
|
+
puts("RubyToRubyToRubyToRubyyyyy!!!")
|
306
|
+
end
|