ruby2ruby 1.1.6 → 1.1.7

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 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: