ruby2ruby 1.1.6 → 1.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,22 @@
1
+ === 1.1.7 / 2007-08-21
2
+
3
+ * 2 major enhancements:
4
+ * Switched to ParseTree's UnifiedRuby... much much cleaner now!
5
+ * Made test_ruby2ruby MUCH more rigorous with circular testing.
6
+ * 5 minor enhancements:
7
+ * Add r2r_show command like parse_tree_show.
8
+ * Add parens for :block nodes as appropriate. May be overzealous.
9
+ * Make SexpAny work with #==.
10
+ * Removed calls to processor_stack / caller in favor of self.context.
11
+ * Some style differences, eschew rescue.
12
+ * 6 bug fixes:
13
+ * Fix R2R bug with masgn/argscat.
14
+ * Fixed a bug with new resbody unification.
15
+ * Fixes for changes to pt_testcase.
16
+ * Fixes the rest of the tests under strict sexp checking.
17
+ * Fixed some circular bugs, mostly by hacking them out, wrt operator precidence.
18
+ * Fixed trinary operator.
19
+
1
20
  === 1.1.6 / 2007-06-05
2
21
 
3
22
  * 2 minor enhancements:
data/Manifest.txt CHANGED
@@ -2,5 +2,6 @@ History.txt
2
2
  Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
+ bin/r2r_show
5
6
  lib/ruby2ruby.rb
6
7
  test/test_ruby2ruby.rb
data/bin/r2r_show ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/local/bin/ruby -ws
2
+
3
+ begin require 'rubygems' rescue LoadError end
4
+ require 'ruby2ruby'
5
+
6
+ def discover_new_classes_from
7
+ old_classes = []
8
+ ObjectSpace.each_object(Module) do |klass|
9
+ old_classes << klass
10
+ end
11
+
12
+ yield
13
+
14
+ new_classes = []
15
+ ObjectSpace.each_object(Module) do |klass|
16
+ new_classes << klass
17
+ end
18
+
19
+ new_classes -= old_classes
20
+ new_classes = [ eval($c) ] if defined? $c
21
+ new_classes
22
+ end
23
+
24
+ $f = true unless defined? $f
25
+
26
+ new_classes = discover_new_classes_from do
27
+ ARGV.unshift "-" if ARGV.empty?
28
+ ARGV.each do |name|
29
+ if name == "-" then
30
+ code = $stdin.read
31
+ code = "class Example; def example; #{code}; end; end" if $f
32
+ eval code unless code.nil?
33
+ else
34
+ require name
35
+ end
36
+ end
37
+ end
38
+
39
+ result = ParseTree.new.parse_tree(*new_classes)
40
+
41
+ result = result[0][3][2][1][2..-1] if $f
42
+
43
+ puts RubyToRuby.new.process(result.first)
44
+
data/lib/ruby2ruby.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  begin require 'rubygems'; rescue LoadError; end
4
4
  require 'parse_tree'
5
5
  require 'sexp_processor'
6
+ require 'unified_ruby'
6
7
 
7
8
  class NilClass # Objective-C trick
8
9
  def method_missing(msg, *args, &block)
@@ -11,9 +12,27 @@ class NilClass # Objective-C trick
11
12
  end
12
13
 
13
14
  class RubyToRuby < SexpProcessor
14
- VERSION = '1.1.6'
15
+ include UnifiedRuby
16
+
17
+ VERSION = '1.1.7'
15
18
  LINE_LENGTH = 78
16
19
 
20
+ ##
21
+ # Nodes that represent assignment and probably need () around them.
22
+
23
+ ASSIGN_NODES = [
24
+ :dasgn,
25
+ :flip2,
26
+ :flip3,
27
+ :lasgn,
28
+ :masgn,
29
+ :op_asgn1,
30
+ :op_asgn2,
31
+ :op_asgn_and,
32
+ :op_asgn_or,
33
+ :return,
34
+ ]
35
+
17
36
  def self.translate(klass_or_str, method = nil)
18
37
  self.new.process(ParseTree.translate(klass_or_str, method))
19
38
  end
@@ -24,10 +43,17 @@ class RubyToRuby < SexpProcessor
24
43
  self.auto_shift_type = true
25
44
  self.strict = true
26
45
  self.expected = String
46
+
47
+ # self.debug[:defn] = /zsuper/
48
+ end
49
+
50
+ def process exp
51
+ exp = Sexp.from_array(exp) if Array === exp unless Sexp === exp
52
+ super exp
27
53
  end
28
54
 
29
55
  ############################################################
30
- # Processors (rewriters at bottom)
56
+ # Processors
31
57
 
32
58
  def process_alias(exp)
33
59
  "alias_method #{process(exp.shift)}, #{process(exp.shift)}"
@@ -120,7 +146,7 @@ class RubyToRuby < SexpProcessor
120
146
  def process_attrasgn(exp)
121
147
  receiver = process exp.shift
122
148
  name = exp.shift
123
- args = exp.shift
149
+ args = exp.empty? ? nil : exp.shift
124
150
 
125
151
  case name
126
152
  when :[]= then
@@ -165,7 +191,16 @@ class RubyToRuby < SexpProcessor
165
191
  end
166
192
  end
167
193
 
168
- return result.join("\n") + "\n"
194
+ result = result.join "\n"
195
+
196
+ result = case self.context[1]
197
+ when nil, :scope, :if, :iter, :resbody, :when, :while then
198
+ result + "\n"
199
+ else
200
+ "(#{result})"
201
+ end
202
+
203
+ return result
169
204
  end
170
205
 
171
206
  def process_block_arg(exp)
@@ -195,18 +230,29 @@ class RubyToRuby < SexpProcessor
195
230
  end
196
231
 
197
232
  def process_break(exp)
198
- val = process(exp.shift)
199
- "break" + (val ? " #{val}" : "")
233
+ val = exp.empty? ? nil : process(exp.shift)
234
+ # HACK "break" + (val ? " #{val}" : "")
235
+ if val then
236
+ "break #{val}"
237
+ else
238
+ "break"
239
+ end
200
240
  end
201
241
 
202
242
  def process_call(exp)
243
+ receiver_node_type = exp.first.first
203
244
  receiver = process exp.shift
245
+
246
+ receiver = "(#{receiver})" if
247
+ RubyToRuby::ASSIGN_NODES.include? receiver_node_type
248
+
204
249
  name = exp.shift
205
250
  args_exp = exp.shift rescue nil
206
- if args_exp && args_exp.first == :array
251
+ if args_exp && args_exp.first == :array # FIX
207
252
  args = "#{process(args_exp)[1..-2]}"
208
253
  else
209
254
  args = process args_exp
255
+ args = nil if args.empty?
210
256
  end
211
257
 
212
258
  case name
@@ -287,7 +333,7 @@ class RubyToRuby < SexpProcessor
287
333
 
288
334
  def process_dasgn_curr(exp)
289
335
  lhs = exp.shift.to_s
290
- rhs = exp.shift
336
+ rhs = exp.shift rescue nil
291
337
  return lhs if rhs.nil?
292
338
  return "#{lhs} = #{process rhs}" unless rhs.first == :dasgn_curr
293
339
 
@@ -309,16 +355,19 @@ class RubyToRuby < SexpProcessor
309
355
  end
310
356
 
311
357
  def process_defs(exp)
358
+ receiver = process(exp.shift)
359
+ name = exp.shift
360
+ exp.unshift "#{receiver}.#{name}"
312
361
  process_defn(exp)
313
362
  end
314
363
 
315
364
  def process_defn(exp)
316
- t = exp[1].first
317
- t2 = exp[2].first rescue nil
365
+ type1 = exp[1].first
366
+ type2 = exp[2].first rescue nil
318
367
 
319
- if t == :args and [:ivar, :attrset].include? t2 then
368
+ if type1 == :args and [:ivar, :attrset].include? type2 then
320
369
  name = exp.shift
321
- case t2
370
+ case type2
322
371
  when :ivar then
323
372
  exp.clear
324
373
  return "attr_reader #{name.inspect}"
@@ -330,7 +379,7 @@ class RubyToRuby < SexpProcessor
330
379
  end
331
380
  end
332
381
 
333
- case t
382
+ case type1
334
383
  when :cfunc then
335
384
  s = "# method '#{exp.shift}' defined in a C function"
336
385
  exp.shift
@@ -348,7 +397,7 @@ class RubyToRuby < SexpProcessor
348
397
  body = process(exp.shift)
349
398
  raise "no"
350
399
  else
351
- raise "Unknown defn type: #{t} for #{exp.inspect}"
400
+ raise "Unknown defn type: #{type1} for #{exp.inspect}"
352
401
  end
353
402
  end
354
403
 
@@ -420,8 +469,9 @@ class RubyToRuby < SexpProcessor
420
469
  "false"
421
470
  end
422
471
 
472
+ # TODO: remove for unified
423
473
  def process_fcall(exp)
424
- exp_orig = exp.deep_clone
474
+ recv = exp.shift unless Symbol === exp.first # HACK conditional - some not getting rewritten?
425
475
  name = exp.shift.to_s
426
476
  args = exp.shift
427
477
  code = []
@@ -429,7 +479,7 @@ class RubyToRuby < SexpProcessor
429
479
  args[0] = :arglist if args.first == :array
430
480
  code << process(args)
431
481
  end
432
- return "#{name}(#{code.join(', ')})"
482
+ return code.empty? ? name : "#{name}(#{code.join(', ')})"
433
483
  end
434
484
 
435
485
  def process_flip2(exp)
@@ -477,22 +527,34 @@ class RubyToRuby < SexpProcessor
477
527
  end
478
528
 
479
529
  def process_if(exp)
480
- c = process exp.shift
481
- t = process exp.shift
482
- f = process exp.shift
530
+ expand = RubyToRuby::ASSIGN_NODES.include? exp.first.first
531
+ c = process exp.shift
532
+ t = process exp.shift
533
+ f = process exp.shift
534
+
535
+ c = "(#{c.chomp})" if c =~ /\n/
483
536
 
484
537
  if t then
485
- unless f then
486
- r = "#{t} if #{c}"
487
- return r if (@indent+r).size < LINE_LENGTH and r !~ /\n/
538
+ unless expand then
539
+ if f then
540
+ r = "#{c} ? (#{t}) : (#{f})"
541
+ r = nil if r =~ /return/ # HACK - need contextual awareness or something
542
+ else
543
+ r = "#{t} if #{c}"
544
+ end
545
+ return r if r and (@indent+r).size < LINE_LENGTH and r !~ /\n/
488
546
  end
547
+
489
548
  r = "if #{c} then\n#{indent(t)}\n"
490
549
  r << "else\n#{indent(f)}\n" if f
491
550
  r << "end"
551
+
492
552
  r
493
553
  else
494
- r = "#{f} unless #{c}"
495
- return r if (@indent+r).size < LINE_LENGTH and r !~ /\n/
554
+ unless expand then
555
+ r = "#{f} unless #{c}"
556
+ return r if (@indent+r).size < LINE_LENGTH and r !~ /\n/
557
+ end
496
558
  "unless #{c} then\n#{indent(f)}\nend"
497
559
  end
498
560
  end
@@ -500,7 +562,7 @@ class RubyToRuby < SexpProcessor
500
562
  def process_iter(exp)
501
563
  iter = process exp.shift
502
564
  args = process exp.shift
503
- body = process exp.shift
565
+ body = exp.empty? ? nil : process(exp.shift)
504
566
 
505
567
  b, e = if iter == "END" then
506
568
  [ "{", "}" ]
@@ -578,7 +640,14 @@ class RubyToRuby < SexpProcessor
578
640
  case lhs.first
579
641
  when :array then
580
642
  lhs.shift
581
- lhs = lhs.map { |l| process(l) }
643
+ lhs = lhs.map do |l|
644
+ case l.first
645
+ when :masgn then
646
+ "(#{process(l)})"
647
+ else
648
+ process(l)
649
+ end
650
+ end
582
651
  when :dasgn_curr then
583
652
  lhs = [ splat(lhs.last) ]
584
653
  else
@@ -587,8 +656,11 @@ class RubyToRuby < SexpProcessor
587
656
 
588
657
  unless rhs.nil? then
589
658
  # HACK - but seems to work (see to_ary test) assert_type rhs, :array
590
- rhs.shift
591
- rhs = rhs.map { |r| process(r) }
659
+ rhs = if rhs.shift == :argscat then
660
+ [process_argscat(rhs)]
661
+ else
662
+ rhs.map { |r| process(r) }
663
+ end
592
664
  return "#{lhs.join(", ")} = #{rhs.join(", ")}"
593
665
  else
594
666
  return lhs.join(", ")
@@ -687,18 +759,19 @@ class RubyToRuby < SexpProcessor
687
759
  list = sexp.shift
688
760
  body = sexp.shift
689
761
 
690
- var = if list and list.last.first == :lasgn then
762
+ var = if list and list.size > 1 and list.last.first == :lasgn then
691
763
  list.pop[1]
692
764
  else
693
765
  nil
694
766
  end
695
767
 
696
- if list then
768
+ if list and list.size > 1 then
697
769
  list[0] = :arglist
698
770
  code << "rescue #{process(list)}"
699
771
  else
700
772
  code << "rescue"
701
773
  end
774
+
702
775
  code.last << " => #{var}" if var
703
776
 
704
777
  if body then
@@ -707,8 +780,8 @@ class RubyToRuby < SexpProcessor
707
780
  code << indent("# do nothing")
708
781
  end
709
782
 
710
- sexp = exp.shift
711
- if sexp then
783
+ unless exp.empty? then
784
+ sexp = exp.shift
712
785
  assert_type sexp, :resbody
713
786
  sexp.shift
714
787
  end
@@ -719,17 +792,16 @@ class RubyToRuby < SexpProcessor
719
792
 
720
793
  def process_rescue(exp)
721
794
  # TODO: rewrite this
722
- # TODO: proper formatting depends on knowing the context
723
795
  #
724
796
  # a = b rescue c => [lasgn a [rescue b c]]
725
797
  # begin; a = b; rescue c => [begin [rescue [lasgn a b] c]]
726
- stack = caller.map { |s| s[/process_\w+/] }.compact
727
798
 
728
- case stack.first
729
- when "process_begin", "process_ensure", "process_block" then
799
+ current = self.context[1]
800
+ case current
801
+ when :begin, :ensure, :block then
730
802
  body = process exp.shift
731
- resbody = process exp.shift
732
- els = process exp.shift
803
+ resbody = exp.empty? ? nil : process(exp.shift)
804
+ els = exp.empty? ? nil : process(exp.shift)
733
805
 
734
806
  code = []
735
807
  code << indent(body)
@@ -738,8 +810,7 @@ class RubyToRuby < SexpProcessor
738
810
  code << "else"
739
811
  code << indent(els)
740
812
  else
741
- unless stack.first == "process_block" ||
742
- stack.first == "process_ensure" then
813
+ unless [:block, :ensure].include? current then
743
814
  code << "end\n"
744
815
  else
745
816
  r = [body, resbody.gsub(/rescue\n\s+/, 'rescue ')].join(' ')
@@ -756,7 +827,13 @@ class RubyToRuby < SexpProcessor
756
827
  resbody = resbody.shift # actual code
757
828
 
758
829
  resbody = process resbody
759
- "#{body} rescue #{resbody}"
830
+ code = "#{body} rescue #{resbody}"
831
+ case current
832
+ when :hash then # HACK move to process_hash
833
+ "(#{code})"
834
+ else
835
+ code
836
+ end
760
837
  end
761
838
  end
762
839
 
@@ -765,7 +842,13 @@ class RubyToRuby < SexpProcessor
765
842
  end
766
843
 
767
844
  def process_return(exp)
768
- return "return" + (exp.empty? ? "" : " #{process exp.shift}")
845
+ # HACK return "return" + (exp.empty? ? "" : " #{process exp.shift}")
846
+
847
+ if exp.empty? then
848
+ return "return"
849
+ else
850
+ return "return #{process exp.shift}"
851
+ end
769
852
  end
770
853
 
771
854
  def process_sclass(exp)
@@ -773,7 +856,7 @@ class RubyToRuby < SexpProcessor
773
856
  end
774
857
 
775
858
  def process_scope(exp)
776
- return process(exp.shift) || ""
859
+ exp.empty? ? "" : process(exp.shift)
777
860
  end
778
861
 
779
862
  def process_self(exp)
@@ -818,9 +901,12 @@ class RubyToRuby < SexpProcessor
818
901
  "alias #{exp.shift} #{exp.shift}"
819
902
  end
820
903
 
821
- def process_vcall(exp)
822
- return exp.shift.to_s
823
- end
904
+ # def process_vcall(exp)
905
+ # recv = exp.shift # nil
906
+ # name = exp.shift
907
+ # args = exp.shift # nil
908
+ # return name.to_s
909
+ # end
824
910
 
825
911
  def process_when(exp)
826
912
  src = []
@@ -843,13 +929,18 @@ class RubyToRuby < SexpProcessor
843
929
  end
844
930
 
845
931
  def process_yield(exp)
846
- args = exp.shift
932
+ args = exp.empty? ? nil : exp.shift
847
933
  if args then
848
934
  args[0] = :arglist if args.first == :array
849
935
  args = process(args)
850
936
  end
851
937
 
852
- "yield" + (args ? "(#{args})" : "")
938
+ # "yield" + (args ? "(#{args})" : "")
939
+ if args then
940
+ "yield(#{args})"
941
+ else
942
+ "yield"
943
+ end
853
944
  end
854
945
 
855
946
  def process_zarray(exp)
@@ -883,135 +974,10 @@ class RubyToRuby < SexpProcessor
883
974
  ############################################################
884
975
  # Rewriters
885
976
 
886
- ##
887
- # defn: [:defn, :name, [:args...], [:scope, [:block, ...]]]
888
-
889
977
  def rewrite_defs(exp)
890
- target = exp.delete_at 1
891
- exp[1] = :"#{target}.#{exp[1]}"
892
- rewrite_defn(exp)
893
- end
894
-
895
- # s(:defn, :name, s(:scope, s(:block, s(:args, ...), ...)))
896
- # s(:defn, :name, s(:bmethod, s(:masgn, s(:dasgn_curr, :args)), s(:block, ...)))
897
- # s(:defn, :name, s(:fbody, s(:bmethod, s(:masgn, s(:dasgn_curr, :params)), s(:block, ...))))
898
- # =>
899
- # s(:defn, :name, s(:args, ...), s(:scope, s:(block, ...)))
900
-
901
- def rewrite_defn(exp)
902
- # REFACTOR this needs help now
903
- exp.shift # :defn
904
- name = exp.shift
905
- args = s(:args)
906
- body = Sexp.from_array exp.shift
907
-
908
- case body.first
909
- when :args then # already normalized
910
- args = body
911
- body = exp.shift
912
- assert_type args, :args
913
- assert_type body, :scope
914
- assert_type body[1], :block
915
- when :scope, :fbody then
916
- body = body.pop if body.first == :fbody
917
- case body.first
918
- when :scope then
919
- args = body.block.args(true)
920
- assert_type body, :scope
921
- assert_type body[1], :block
922
-
923
- if body[1][1].first == :block_arg then
924
- block_arg = body[1].delete_at 1
925
- args << block_arg
926
- end
927
- when :bmethod then
928
- body[0] = :scope
929
- masgn = body.masgn(true)
930
- if masgn then
931
- splat = self.splat(masgn[-1][-1])
932
- args.push(splat)
933
- else
934
- dasgn_curr = body.dasgn_curr(true)
935
- if dasgn_curr then
936
- arg = self.splat(dasgn_curr[-1])
937
- args.push(arg)
938
- end
939
- end
940
- body.find_and_replace_all(:dvar, :lvar)
941
- else
942
- raise "no: #{body.first} / #{body.inspect}"
943
- end
944
- when :bmethod then
945
- body.shift # :bmethod
946
- case body.first.first
947
- when :dasgn_curr then
948
- # WARN: there are some implications here of having an empty
949
- # :args below namely, "proc { || " does not allow extra args
950
- # passed in.
951
- dasgn = body.shift
952
- assert_type dasgn, :dasgn_curr
953
- dasgn.shift # type
954
- args.push(*dasgn)
955
- body.find_and_replace_all(:dvar, :lvar)
956
- when :masgn then
957
- dasgn = body.masgn(true)
958
- splat = self.splat(dasgn[-1][-1])
959
- args.push(splat)
960
- body.find_and_replace_all(:dvar, :lvar)
961
- end
962
-
963
- if body.first.first == :block then
964
- body = s(:scope, body.shift)
965
- else
966
- body = s(:scope, s(:block, body.shift)) # single statement
967
- end
968
- when :dmethod
969
- # BEFORE: [:defn, :dmethod_added, [:dmethod, :bmethod_maker, ...]]
970
- # AFTER: [:defn, :dmethod_added, ...]
971
- body[0] = :scope
972
- body.delete_at 1 # method name
973
- args = body.scope.block.args(true)
974
- when :ivar, :attrset then
975
- # do nothing
976
- else
977
- raise "Unknown :defn format: #{name.inspect} #{args.inspect} #{body.inspect}"
978
- end
979
-
980
- return s(:defn, name, args, body)
981
- end
982
-
983
- def rewrite_resbody(exp)
984
- result = []
985
-
986
- code = result
987
- while exp and exp.first == :resbody do
988
- code << exp.shift
989
- list = exp.shift
990
- body = exp.shift
991
- exp = exp.shift # either another resbody or nil
992
-
993
- # code may be nil, :lasgn, or :block
994
- case body.first
995
- when nil then
996
- # do nothing
997
- when :lasgn then
998
- # TODO: check that it is assigning $!
999
- list << body
1000
- body = nil
1001
- when :block then
1002
- # TODO: check that it is assigning $!
1003
- list << body.delete_at(1) if body[1].first == :lasgn
1004
- else
1005
- # do nothing (expression form)
1006
- end
1007
-
1008
- code << list << body
1009
- if exp then
1010
- code = []
1011
- result << code
1012
- end
1013
- end
1014
-
978
+ receiver = exp.shift
979
+ result = rewrite_defn(exp)
980
+ result.unshift receiver
1015
981
  result
1016
982
  end
1017
983
 
@@ -1,15 +1,24 @@
1
1
  #!/usr/local/bin/ruby -w
2
2
 
3
+ $TESTING = true
4
+
3
5
  require 'test/unit'
4
6
  begin require 'rubygems'; rescue LoadError; end
5
7
  require 'ruby2ruby'
6
8
  require 'pt_testcase'
7
9
 
10
+ # TODO: rename file so autotest stops bitching
11
+
8
12
  class TestRubyToRuby < Test::Unit::TestCase
9
13
  def setup
10
14
  @processor = RubyToRuby.new
11
15
  end
12
16
 
17
+ def test_proc_to_ruby
18
+ block = proc { puts "something" }
19
+ assert_equal %Q|proc {\n puts("something")\n}|, block.to_ruby
20
+ end
21
+
13
22
  def test_lit_regexp_slash
14
23
  inn = s(:lit, /blah\/blah/)
15
24
  out = '/blah\/blah/'
@@ -57,75 +66,9 @@ class TestRubyToRuby < Test::Unit::TestCase
57
66
  assert_equal :"blah2blah\"blah/blah", r
58
67
  end
59
68
 
60
- def test_rewrite_defn_define_method
61
- inn = s(:defn, :splatted,
62
- s(:bmethod,
63
- s(:masgn, s(:dasgn_curr, :args)),
64
- s(:block,
65
- s(:dasgn_curr, :y, s(:call, s(:dvar, :args), :first)),
66
- s(:call, s(:dvar, :y), :+, s(:array, s(:lit, 42))))))
67
- out = s(:defn, :splatted,
68
- s(:args, :"*args"),
69
- s(:scope,
70
- s(:block,
71
- s(:dasgn_curr, :y, s(:call, s(:lvar, :args), :first)),
72
- s(:call, s(:lvar, :y), :+, s(:array, s(:lit, 42))))))
73
-
74
- assert_equal out, @processor.rewrite_defn(inn)
75
- end
76
-
77
- def test_rewrite_defn_bmethod
78
- inn = s(:defn, :group,
79
- s(:fbody,
80
- s(:bmethod,
81
- s(:masgn, s(:dasgn_curr, :params)),
82
- s(:block,
83
- s(:lit, 42)))))
84
- out = s(:defn, :group,
85
- s(:args, :"*params"),
86
- s(:scope,
87
- s(:block, s(:lit, 42))))
88
-
89
- assert_equal out, @processor.rewrite_defn(inn)
90
- end
91
-
92
- def test_rewrite_resbody
93
- inn = [:resbody,
94
- [:array, [:const, :SyntaxError]],
95
- [:block, [:lasgn, :e1, [:gvar, :$!]], [:lit, 2]],
96
- [:resbody,
97
- [:array, [:const, :Exception]],
98
- [:block, [:lasgn, :e2, [:gvar, :$!]], [:lit, 3]]]]
99
-
100
- out = [:resbody,
101
- [:array, [:const, :SyntaxError], [:lasgn, :e1, [:gvar, :$!]]],
102
- [:block, [:lit, 2]],
103
- [:resbody,
104
- [:array, [:const, :Exception], [:lasgn, :e2, [:gvar, :$!]]],
105
- [:block, [:lit, 3]]]]
106
-
107
- assert_equal out, @processor.rewrite_resbody(inn)
108
- end
109
-
110
- def test_rewrite_resbody_lasgn
111
- inn = [:resbody,
112
- [:array, [:const, :SyntaxError]],
113
- [:lasgn, :e1, [:gvar, :$!]],
114
- [:resbody,
115
- [:array, [:const, :Exception]],
116
- [:block, [:lasgn, :e2, [:gvar, :$!]], [:lit, 3]]]]
117
-
118
- out = [:resbody,
119
- [:array, [:const, :SyntaxError], [:lasgn, :e1, [:gvar, :$!]]],
120
- nil,
121
- [:resbody,
122
- [:array, [:const, :Exception], [:lasgn, :e2, [:gvar, :$!]]],
123
- [:block, [:lit, 3]]]]
124
-
125
- assert_equal out, @processor.rewrite_resbody(inn)
126
- end
127
-
128
69
  eval ParseTreeTestCase.testcases.map { |node, data|
70
+ next if node == "vcall" # HACK
71
+
129
72
  "def test_#{node}
130
73
  pt = #{data['ParseTree'].inspect}
131
74
  rb = #{(data['Ruby2Ruby'] || data['Ruby']).inspect}
@@ -138,24 +81,63 @@ class TestRubyToRuby < Test::Unit::TestCase
138
81
  }.join("\n")
139
82
  end
140
83
 
141
- # Self-Translation: 1st Generation
142
- ruby = RubyToRuby.translate(RubyToRuby).sub("RubyToRuby", "RubyToRuby2")
143
- begin
144
- eval ruby
145
- rescue SyntaxError => e
146
- puts "SyntaxError: #{e.message}"
147
- puts
148
- puts ruby
149
- exit 1
84
+ ##
85
+ # Converts a +target+ using a +processor+ and converts +target+ name
86
+ # in the source adding +gen+ to allow easy renaming.
87
+
88
+ def morph_and_eval(processor, target, gen)
89
+ begin
90
+ old_name = target.name
91
+ new_name = target.name.sub(/\d*$/, gen.to_s)
92
+ ruby = processor.translate(target).sub(old_name, new_name)
93
+ eval ruby
94
+ target.constants.each do |constant|
95
+ eval "#{new_name}::#{constant} = #{old_name}::#{constant}"
96
+ end
97
+ rescue SyntaxError => e
98
+ puts
99
+ puts ruby
100
+ puts
101
+ raise e
102
+ rescue => e
103
+ puts
104
+ puts ruby
105
+ puts
106
+ raise e
107
+ end
150
108
  end
151
109
 
152
- RubyToRuby2::LINE_LENGTH = RubyToRuby::LINE_LENGTH # HACK
110
+ ####################
111
+ # impl
112
+ # old new
113
+ #
114
+ # t old 0 1
115
+ # e
116
+ # s
117
+ # t new 2 3
118
+
119
+ # Self-Translation: 1st Generation - morph RubyToRuby using RubyToRuby
120
+ morph_and_eval RubyToRuby, RubyToRuby, 2
121
+ class TestRubyToRuby1 < TestRubyToRuby
122
+ def setup
123
+ @processor = RubyToRuby2.new
124
+ end
125
+ end
126
+
127
+ # Self-Translation: 2nd Generation - morph TestRubyToRuby using RubyToRuby
128
+ morph_and_eval RubyToRuby, TestRubyToRuby, 2
153
129
 
154
- class TestRubyToRuby2 < TestRubyToRuby
130
+ # Self-Translation: 3rd Generation - test RubyToRuby2 with TestRubyToRuby1
131
+ class TestRubyToRuby3 < TestRubyToRuby2
155
132
  def setup
156
133
  @processor = RubyToRuby2.new
157
134
  end
158
135
  end
159
136
 
160
- # Self-Translation: 2nd Generation - against the tests this time
161
- eval RubyToRuby2.translate(TestRubyToRuby).sub("TestRubyToRuby", "TestRubyToRuby3")
137
+ # Self-Translation: 4th (and final) Generation - fully circular
138
+ morph_and_eval RubyToRuby2, RubyToRuby2, 3
139
+ class TestRubyToRuby4 < TestRubyToRuby3
140
+ def setup
141
+ @processor = RubyToRuby3.new
142
+ end
143
+ end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: ruby2ruby
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.1.6
7
- date: 2007-06-05 00:00:00 -07:00
6
+ version: 1.1.7
7
+ date: 2007-08-21 00:00:00 -07: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
@@ -33,6 +33,7 @@ files:
33
33
  - Manifest.txt
34
34
  - README.txt
35
35
  - Rakefile
36
+ - bin/r2r_show
36
37
  - lib/ruby2ruby.rb
37
38
  - test/test_ruby2ruby.rb
38
39
  test_files:
@@ -44,8 +45,8 @@ extra_rdoc_files:
44
45
  - History.txt
45
46
  - Manifest.txt
46
47
  - README.txt
47
- executables: []
48
-
48
+ executables:
49
+ - r2r_show
49
50
  extensions: []
50
51
 
51
52
  requirements: []
@@ -67,5 +68,5 @@ dependencies:
67
68
  requirements:
68
69
  - - ">="
69
70
  - !ruby/object:Gem::Version
70
- version: 1.2.1
71
+ version: 1.3.0
71
72
  version: