ruby2ruby 1.1.3 → 1.1.4
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 +13 -0
- data/Rakefile +5 -0
- data/lib/ruby2ruby.rb +107 -74
- data/test/test_ruby2ruby.rb +43 -1
- metadata +9 -9
data/History.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
== 1.1.4 / 2007-01-15
|
2
|
+
|
3
|
+
* 4 minor enhancements:
|
4
|
+
* Added some extra rewriting code and tests for various bmethods. Ugh.
|
5
|
+
* Added support for splatted block args.
|
6
|
+
* Refactored class/module and dsym/dstr.
|
7
|
+
* Short if/unless statements are now post-conditional expressions.
|
8
|
+
* 4 bug fixes:
|
9
|
+
* Finally fixed eric's nebulous proc code-in-goalposts bug.
|
10
|
+
* Fixed dasgn_curr so block's dasgn vars decl goes away (bug 7420).
|
11
|
+
* Fixed dmethod. I think the tests were bogus before.
|
12
|
+
* Fixed improper end in method rescues (bug 7396).
|
13
|
+
|
1
14
|
== 1.1.3 / 2006-12-20
|
2
15
|
|
3
16
|
* 1 minor enhancement
|
data/Rakefile
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
|
3
|
+
dirs = %w(../../ParseTree/dev/lib ../../ParseTree/dev/test:lib)
|
4
|
+
$:.push(*dirs)
|
5
|
+
ENV['RUBY_FLAGS'] = "-I" + dirs.join(":")
|
6
|
+
|
3
7
|
require 'rubygems'
|
4
8
|
require 'hoe'
|
5
9
|
require './lib/ruby2ruby.rb'
|
@@ -10,6 +14,7 @@ Hoe.new('ruby2ruby', RubyToRuby::VERSION) do |p|
|
|
10
14
|
p.description = p.paragraphs_of('README.txt', 2).join
|
11
15
|
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1].map {|u| u.strip }
|
12
16
|
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
17
|
+
p.clean_globs << File.expand_path("~/.ruby_inline")
|
13
18
|
p.extra_deps << "ParseTree"
|
14
19
|
end
|
15
20
|
|
data/lib/ruby2ruby.rb
CHANGED
@@ -11,7 +11,7 @@ class NilClass # Objective-C trick
|
|
11
11
|
end
|
12
12
|
|
13
13
|
class RubyToRuby < SexpProcessor
|
14
|
-
VERSION = '1.1.
|
14
|
+
VERSION = '1.1.4'
|
15
15
|
|
16
16
|
def self.translate(klass_or_str, method = nil)
|
17
17
|
self.new.process(ParseTree.translate(klass_or_str, method))
|
@@ -148,18 +148,11 @@ class RubyToRuby < SexpProcessor
|
|
148
148
|
result = []
|
149
149
|
|
150
150
|
until exp.empty? do
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
raise "wtf"
|
155
|
-
result[-1] = result[-1][0..-2] + ", #{process(exp.shift)})"
|
151
|
+
code = exp.shift
|
152
|
+
if code.nil? or code.first == :nil then
|
153
|
+
result << "# do nothing"
|
156
154
|
else
|
157
|
-
|
158
|
-
if code.nil? or code.first == :nil then
|
159
|
-
result << "# do nothing"
|
160
|
-
else
|
161
|
-
result << process(code)
|
162
|
-
end
|
155
|
+
result << process(code)
|
163
156
|
end
|
164
157
|
end
|
165
158
|
|
@@ -236,23 +229,7 @@ class RubyToRuby < SexpProcessor
|
|
236
229
|
end
|
237
230
|
|
238
231
|
def process_class(exp)
|
239
|
-
|
240
|
-
superk = process(exp.shift)
|
241
|
-
|
242
|
-
s << " < #{superk}" if superk
|
243
|
-
s << "\n"
|
244
|
-
|
245
|
-
body = []
|
246
|
-
begin
|
247
|
-
code = process(exp.shift).chomp
|
248
|
-
body << code unless code.nil? or code.empty?
|
249
|
-
end until exp.empty?
|
250
|
-
unless body.empty? then
|
251
|
-
body = indent(body.join("\n\n")) + "\n"
|
252
|
-
else
|
253
|
-
body = ""
|
254
|
-
end
|
255
|
-
s + body + "end"
|
232
|
+
"class #{util_module_or_class(exp, true)}"
|
256
233
|
end
|
257
234
|
|
258
235
|
def process_colon2(exp)
|
@@ -279,10 +256,23 @@ class RubyToRuby < SexpProcessor
|
|
279
256
|
"#{exp.shift} = #{process(exp.shift)}"
|
280
257
|
end
|
281
258
|
|
259
|
+
# (a, lit1) => "a = 1"
|
260
|
+
# (a, (b, lit2)) => "a = b = 2"
|
261
|
+
# (a, (b)) => ""
|
262
|
+
|
282
263
|
def process_dasgn_curr(exp)
|
283
|
-
|
284
|
-
|
285
|
-
|
264
|
+
lhs = exp.shift.to_s
|
265
|
+
rhs = exp.shift
|
266
|
+
return lhs if rhs.nil?
|
267
|
+
return "#{lhs} = #{process rhs}" unless rhs.first == :dasgn_curr
|
268
|
+
|
269
|
+
# keep recursing. ensure that the leaf node assigns to _something_
|
270
|
+
rhs = process rhs
|
271
|
+
if rhs =~ /=/ then
|
272
|
+
"#{lhs} = #{rhs}"
|
273
|
+
else
|
274
|
+
""
|
275
|
+
end
|
286
276
|
end
|
287
277
|
|
288
278
|
def process_dasgn(exp)
|
@@ -374,16 +364,7 @@ class RubyToRuby < SexpProcessor
|
|
374
364
|
end
|
375
365
|
|
376
366
|
def process_dsym(exp)
|
377
|
-
|
378
|
-
until exp.empty?
|
379
|
-
pt = exp.shift
|
380
|
-
if pt.first == :str
|
381
|
-
s << process(pt)[1..-2]
|
382
|
-
else
|
383
|
-
s << '#{' + process(pt) + '}'
|
384
|
-
end
|
385
|
-
end
|
386
|
-
s + '"'
|
367
|
+
":" + process_dstr(exp)
|
387
368
|
end
|
388
369
|
|
389
370
|
def process_dvar(exp)
|
@@ -466,11 +447,17 @@ class RubyToRuby < SexpProcessor
|
|
466
447
|
f = process exp.shift
|
467
448
|
|
468
449
|
if t then
|
450
|
+
unless f then
|
451
|
+
r = "#{t} if #{c}"
|
452
|
+
return r if (@indent+r).size < 78 and r !~ /\n/
|
453
|
+
end
|
469
454
|
r = "if #{c} then\n#{indent(t)}\n"
|
470
455
|
r << "else\n#{indent(f)}\n" if f
|
471
456
|
r << "end"
|
472
457
|
r
|
473
458
|
else
|
459
|
+
r = "#{f} unless #{c}"
|
460
|
+
return r if (@indent+r).size < 78 and r !~ /\n/
|
474
461
|
"unless #{c} then\n#{indent(f)}\nend"
|
475
462
|
end
|
476
463
|
end
|
@@ -493,7 +480,7 @@ class RubyToRuby < SexpProcessor
|
|
493
480
|
result << " |#{args}|" if args
|
494
481
|
if body then
|
495
482
|
result << "\n"
|
496
|
-
result << indent(body)
|
483
|
+
result << indent(body.strip)
|
497
484
|
result << "\n"
|
498
485
|
else
|
499
486
|
result << ' '
|
@@ -561,18 +548,7 @@ class RubyToRuby < SexpProcessor
|
|
561
548
|
end
|
562
549
|
|
563
550
|
def process_module(exp)
|
564
|
-
|
565
|
-
body = []
|
566
|
-
begin
|
567
|
-
code = process exp.shift
|
568
|
-
body << code unless code.nil? or code.empty?
|
569
|
-
end until exp.empty?
|
570
|
-
unless body.empty? then
|
571
|
-
body = indent(body.join("\n\n")) + "\n"
|
572
|
-
else
|
573
|
-
body = ""
|
574
|
-
end
|
575
|
-
s + body + "end"
|
551
|
+
"module #{util_module_or_class(exp)}"
|
576
552
|
end
|
577
553
|
|
578
554
|
def process_next(exp)
|
@@ -697,7 +673,7 @@ class RubyToRuby < SexpProcessor
|
|
697
673
|
code << "else"
|
698
674
|
code << indent(els)
|
699
675
|
else
|
700
|
-
code << "end\n"
|
676
|
+
code << "end\n" unless stack.first == "process_block"
|
701
677
|
end
|
702
678
|
code.join("\n")
|
703
679
|
else # a rescue b and others
|
@@ -845,6 +821,12 @@ class RubyToRuby < SexpProcessor
|
|
845
821
|
rewrite_defn(exp)
|
846
822
|
end
|
847
823
|
|
824
|
+
# s(:defn, :name, s(:scope, s(:block, s(:args, ...), ...)))
|
825
|
+
# s(:defn, :name, s(:bmethod, s(:masgn, s(:dasgn_curr, :args)), s(:block, ...)))
|
826
|
+
# s(:defn, :name, s(:fbody, s(:bmethod, s(:masgn, s(:dasgn_curr, :params)), s(:block, ...))))
|
827
|
+
# =>
|
828
|
+
# s(:defn, :name, s(:args, ...), s(:scope, s:(block, ...)))
|
829
|
+
|
848
830
|
def rewrite_defn(exp)
|
849
831
|
# REFACTOR this needs help now
|
850
832
|
exp.shift # :defn
|
@@ -861,18 +843,38 @@ class RubyToRuby < SexpProcessor
|
|
861
843
|
assert_type body[1], :block
|
862
844
|
when :scope, :fbody then
|
863
845
|
body = body[1] if body.first == :fbody
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
846
|
+
case body.first
|
847
|
+
when :scope then
|
848
|
+
args = body.block.args(true)
|
849
|
+
assert_type body, :scope
|
850
|
+
assert_type body[1], :block
|
851
|
+
|
852
|
+
if body[1][1].first == :block_arg then
|
853
|
+
block_arg = body[1].delete_at 1
|
854
|
+
args << block_arg
|
855
|
+
end
|
856
|
+
when :bmethod then
|
857
|
+
body[0] = :scope
|
858
|
+
body.block.delete_at(1) # nuke the decl # REFACTOR
|
859
|
+
masgn = body.masgn(true)
|
860
|
+
if masgn then
|
861
|
+
splat = :"*#{masgn[-1][-1]}"
|
862
|
+
args.push(splat)
|
863
|
+
else
|
864
|
+
dasgn_curr = body.dasgn_curr(true)
|
865
|
+
if dasgn_curr then
|
866
|
+
arg = :"*#{dasgn_curr[-1]}"
|
867
|
+
args.push(arg)
|
868
|
+
end
|
869
|
+
end
|
870
|
+
body.find_and_replace_all(:dvar, :lvar)
|
871
|
+
else
|
872
|
+
raise "no: #{body.first} / #{body.inspect}"
|
872
873
|
end
|
873
874
|
when :bmethod then
|
874
875
|
body.shift # :bmethod
|
875
|
-
|
876
|
+
case body.first.first
|
877
|
+
when :dasgn_curr then
|
876
878
|
# WARN: there are some implications here of having an empty
|
877
879
|
# :args below namely, "proc { || " does not allow extra args
|
878
880
|
# passed in.
|
@@ -881,7 +883,15 @@ class RubyToRuby < SexpProcessor
|
|
881
883
|
dasgn.shift # type
|
882
884
|
args.push(*dasgn)
|
883
885
|
body.find_and_replace_all(:dvar, :lvar)
|
886
|
+
when :masgn then
|
887
|
+
dasgn = body.masgn(true)
|
888
|
+
# DAMNIT body.block.dasgn_curr(true) - multiple values so can't use
|
889
|
+
body.block.delete_at(1) # nuke the decl
|
890
|
+
splat = :"*#{dasgn[-1][-1]}"
|
891
|
+
args.push(splat)
|
892
|
+
body.find_and_replace_all(:dvar, :lvar)
|
884
893
|
end
|
894
|
+
|
885
895
|
if body.first.first == :block then
|
886
896
|
body = s(:scope, body.shift)
|
887
897
|
else
|
@@ -890,12 +900,9 @@ class RubyToRuby < SexpProcessor
|
|
890
900
|
when :dmethod
|
891
901
|
# BEFORE: [:defn, :dmethod_added, [:dmethod, :bmethod_maker, ...]]
|
892
902
|
# AFTER: [:defn, :dmethod_added, ...]
|
893
|
-
|
894
|
-
|
895
|
-
args =
|
896
|
-
iter.delete_at 1 # args
|
897
|
-
iter[0] = :block
|
898
|
-
body = s(:scope, iter.find_and_replace_all(:dvar, :lvar))
|
903
|
+
body[0] = :scope
|
904
|
+
body.delete_at 1 # method name
|
905
|
+
args = body.scope.block.args(true)
|
899
906
|
when :ivar, :attrset then
|
900
907
|
# do nothing
|
901
908
|
else
|
@@ -943,6 +950,29 @@ class RubyToRuby < SexpProcessor
|
|
943
950
|
############################################################
|
944
951
|
# Utility Methods:
|
945
952
|
|
953
|
+
def util_module_or_class(exp, is_class=false)
|
954
|
+
s = "#{exp.shift}"
|
955
|
+
|
956
|
+
if is_class then
|
957
|
+
superk = process(exp.shift)
|
958
|
+
s << " < #{superk}" if superk
|
959
|
+
end
|
960
|
+
|
961
|
+
s << "\n"
|
962
|
+
|
963
|
+
body = []
|
964
|
+
begin
|
965
|
+
code = process(exp.shift).chomp
|
966
|
+
body << code unless code.nil? or code.empty?
|
967
|
+
end until exp.empty?
|
968
|
+
unless body.empty? then
|
969
|
+
body = indent(body.join("\n\n")) + "\n"
|
970
|
+
else
|
971
|
+
body = ""
|
972
|
+
end
|
973
|
+
s + body + "end"
|
974
|
+
end
|
975
|
+
|
946
976
|
def indent(s)
|
947
977
|
s.to_s.map{|line| @indent + line}.join
|
948
978
|
end
|
@@ -1003,8 +1033,11 @@ class Proc
|
|
1003
1033
|
end
|
1004
1034
|
|
1005
1035
|
def to_ruby
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1036
|
+
ruby = self.to_method.to_ruby
|
1037
|
+
ruby.sub!(/\A(def \S+)\(([^\)]*)\)/, '\1 |\2|') # move args
|
1038
|
+
ruby.sub!(/\Adef[^\n\|]+/, 'proc { ') # strip def name
|
1039
|
+
ruby.sub!(/end\Z/, '}') # strip end
|
1040
|
+
ruby.gsub!(/\s+$/, '') # trailing WS bugs me
|
1041
|
+
ruby
|
1009
1042
|
end
|
1010
1043
|
end
|
data/test/test_ruby2ruby.rb
CHANGED
@@ -10,6 +10,40 @@ class TestRubyToRuby < Test::Unit::TestCase
|
|
10
10
|
@processor = RubyToRuby.new
|
11
11
|
end
|
12
12
|
|
13
|
+
def test_rewrite_defn_define_method
|
14
|
+
inn = s(:defn, :splatted,
|
15
|
+
s(:bmethod,
|
16
|
+
s(:masgn, s(:dasgn_curr, :args)),
|
17
|
+
s(:block,
|
18
|
+
s(:dasgn_curr, :y),
|
19
|
+
s(:dasgn_curr, :y, s(:call, s(:dvar, :args), :first)),
|
20
|
+
s(:call, s(:dvar, :y), :+, s(:array, s(:lit, 42))))))
|
21
|
+
out = s(:defn, :splatted,
|
22
|
+
s(:args, :"*args"),
|
23
|
+
s(:scope,
|
24
|
+
s(:block,
|
25
|
+
s(:dasgn_curr, :y, s(:call, s(:lvar, :args), :first)),
|
26
|
+
s(:call, s(:lvar, :y), :+, s(:array, s(:lit, 42))))))
|
27
|
+
|
28
|
+
assert_equal out, @processor.rewrite_defn(inn)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_rewrite_defn_bmethod
|
32
|
+
inn = s(:defn, :group,
|
33
|
+
s(:fbody,
|
34
|
+
s(:bmethod,
|
35
|
+
s(:masgn, s(:dasgn_curr, :params)),
|
36
|
+
s(:block,
|
37
|
+
s(:dasgn_curr, :force_reload, s(:dasgn_curr, :association, s(:dasgn_curr, :retval))),
|
38
|
+
s(:lit, 42)))))
|
39
|
+
out = s(:defn, :group,
|
40
|
+
s(:args, :"*params"),
|
41
|
+
s(:scope,
|
42
|
+
s(:block, s(:lit, 42))))
|
43
|
+
|
44
|
+
assert_equal out, @processor.rewrite_defn(inn)
|
45
|
+
end
|
46
|
+
|
13
47
|
def test_rewrite_resbody
|
14
48
|
inn = [:resbody,
|
15
49
|
[:array, [:const, :SyntaxError]],
|
@@ -60,7 +94,15 @@ class TestRubyToRuby < Test::Unit::TestCase
|
|
60
94
|
end
|
61
95
|
|
62
96
|
# Self-Translation: 1st Generation
|
63
|
-
|
97
|
+
ruby = RubyToRuby.translate(RubyToRuby).sub("RubyToRuby", "RubyToRuby2")
|
98
|
+
begin
|
99
|
+
eval ruby
|
100
|
+
rescue SyntaxError => e
|
101
|
+
puts "SyntaxError: #{e.message}"
|
102
|
+
puts
|
103
|
+
puts ruby
|
104
|
+
exit 1
|
105
|
+
end
|
64
106
|
|
65
107
|
class TestRubyToRuby2 < TestRubyToRuby
|
66
108
|
def setup
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.0
|
2
|
+
rubygems_version: 0.9.0.9
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby2ruby
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.1.
|
7
|
-
date:
|
6
|
+
version: 1.1.4
|
7
|
+
date: 2007-01-15 00:00:00 -08:00
|
8
8
|
summary: ruby2ruby provides a means of generating pure ruby code easily from ParseTree's Sexps.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -49,20 +49,20 @@ requirements: []
|
|
49
49
|
|
50
50
|
dependencies:
|
51
51
|
- !ruby/object:Gem::Dependency
|
52
|
-
name:
|
52
|
+
name: ParseTree
|
53
53
|
version_requirement:
|
54
54
|
version_requirements: !ruby/object:Gem::Version::Requirement
|
55
55
|
requirements:
|
56
|
-
- - "
|
56
|
+
- - ">"
|
57
57
|
- !ruby/object:Gem::Version
|
58
|
-
version:
|
58
|
+
version: 0.0.0
|
59
59
|
version:
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
|
-
name:
|
61
|
+
name: hoe
|
62
62
|
version_requirement:
|
63
63
|
version_requirements: !ruby/object:Gem::Version::Requirement
|
64
64
|
requirements:
|
65
|
-
- - "
|
65
|
+
- - ">="
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
67
|
+
version: 1.1.7
|
68
68
|
version:
|