ruby2ruby 1.1.9 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.autotest CHANGED
@@ -1,15 +1,21 @@
1
1
  # -*- ruby -*-
2
2
 
3
+ require 'autotest/restart'
4
+
3
5
  Autotest.add_hook :initialize do |at|
4
6
  at.extra_files << "../../ParseTree/dev/test/pt_testcase.rb"
5
7
  at.extra_files << "../../ParseTree/dev/lib/unified_ruby.rb"
6
- at.libs << ":../../ParseTree/dev/lib:../../ParseTree/dev/test"
8
+ at.libs << ":../../sexp_processor/dev/lib:../../ParseTree/dev/lib:../../ParseTree/dev/test"
7
9
 
8
10
  (1..4).each do |n|
9
11
  at.extra_class_map["TestRuby2Ruby#{n}"] = "test/test_ruby2ruby.rb"
10
12
  end
11
13
 
12
14
  at.add_mapping(/unified|pt_testcase/) do |f, _|
13
- at.files_matching(/^test.*rb$/)
15
+ at.files_matching(/test.*rb$/)
14
16
  end
15
17
  end
18
+
19
+ require 'autotest/rcov'
20
+ Autotest::RCov.command = 'rcov_info'
21
+ Autotest::RCov.pattern = 'test/test_ruby2ruby.rb'
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ === 1.2.0 / 2008-10-22
2
+
3
+ * 2 minor enhancements:
4
+
5
+ * Removed all PT dependent code to PT project (see parse_tree_extensions.rb).
6
+ * Revamped. Got working with new unified ruby output. Much much cleaner.
7
+
1
8
  === 1.1.9 / 2008-06-09
2
9
 
3
10
  * 5 minor enhancements:
data/Rakefile CHANGED
@@ -1,24 +1,39 @@
1
1
  # -*- ruby -*-
2
2
 
3
- dirs = (%w(lib ../../ParseTree/dev/test) +
4
- %w(ParseTree RubyInline ruby_parser).map { |p| "../../#{p}/dev/lib" })
5
- $:.push(*dirs)
6
- ENV['RUBY_FLAGS'] = "-I" + dirs.join(":")
7
-
8
3
  require 'rubygems'
9
4
  require 'hoe'
5
+
6
+ Hoe.add_include_dirs("lib",
7
+ "../../ZenTest/dev/lib",
8
+ "../../ParseTree/dev/test",
9
+ "../../ParseTree/dev/lib",
10
+ "../../RubyInline/dev/lib",
11
+ "../../ruby_parser/dev/lib",
12
+ "../../sexp_processor/dev/lib")
13
+
10
14
  require './lib/ruby2ruby.rb'
11
15
 
12
- Hoe.new('ruby2ruby', RubyToRuby::VERSION) do |r2r|
16
+ Hoe.new('ruby2ruby', Ruby2Ruby::VERSION) do |r2r|
13
17
  r2r.rubyforge_name = 'seattlerb'
14
18
  r2r.developer('Ryan Davis', 'ryand-ruby@zenspider.com')
15
19
 
16
20
  r2r.clean_globs << File.expand_path("~/.ruby_inline")
17
- r2r.extra_deps << "ParseTree"
18
-
19
- r2r.multiruby_skip << "rubinius"
21
+ r2r.extra_deps << ["ParseTree", "~> 3.0"]
20
22
  end
21
23
 
22
24
  task :test => :clean
23
25
 
26
+ task :rcov_info do
27
+ pat = ENV['PATTERN'] || "test/test_*.rb"
28
+ ruby "#{Hoe::RUBY_FLAGS} -S rcov --text-report --save coverage.info #{pat}"
29
+ end
30
+
31
+ task :rcov_overlay do
32
+ rcov, eol = Marshal.load(File.read("coverage.info")).last[ENV["FILE"]], 1
33
+ puts rcov[:lines].zip(rcov[:coverage]).map { |line, coverage|
34
+ bol, eol = eol, eol + line.length
35
+ [bol, eol, "#ffcccc"] unless coverage
36
+ }.compact.inspect
37
+ end
38
+
24
39
  # vim: syntax=Ruby
data/lib/ruby2ruby.rb CHANGED
@@ -5,9 +5,7 @@ require 'sexp_processor'
5
5
  require 'unified_ruby'
6
6
 
7
7
  class Ruby2Ruby < SexpProcessor
8
- include UnifiedRuby
9
-
10
- VERSION = '1.1.9'
8
+ VERSION = '1.2.0'
11
9
  LINE_LENGTH = 78
12
10
 
13
11
  ##
@@ -19,6 +17,7 @@ class Ruby2Ruby < SexpProcessor
19
17
  :flip3,
20
18
  :lasgn,
21
19
  :masgn,
20
+ :attrasgn,
22
21
  :op_asgn1,
23
22
  :op_asgn2,
24
23
  :op_asgn_and,
@@ -28,7 +27,9 @@ class Ruby2Ruby < SexpProcessor
28
27
 
29
28
  def self.translate(klass_or_str, method = nil)
30
29
  require 'parse_tree'
31
- self.new.process(ParseTree.translate(klass_or_str, method))
30
+ sexp = ParseTree.translate(klass_or_str, method)
31
+ sexp = Unifier.new.process(sexp)
32
+ self.new.process(sexp)
32
33
  end
33
34
 
34
35
  def initialize
@@ -41,11 +42,6 @@ class Ruby2Ruby < SexpProcessor
41
42
  # self.debug[:defn] = /zsuper/
42
43
  end
43
44
 
44
- def process exp
45
- exp = Sexp.from_array(exp) if Array === exp unless Sexp === exp
46
- super exp
47
- end
48
-
49
45
  ############################################################
50
46
  # Processors
51
47
 
@@ -57,6 +53,14 @@ class Ruby2Ruby < SexpProcessor
57
53
  "(#{process exp.shift} and #{process exp.shift})"
58
54
  end
59
55
 
56
+ def process_arglist(exp) # custom made node
57
+ code = []
58
+ until exp.empty? do
59
+ code << process(exp.shift)
60
+ end
61
+ code.join ', '
62
+ end
63
+
60
64
  def process_args(exp)
61
65
  args = []
62
66
 
@@ -76,8 +80,6 @@ class Ruby2Ruby < SexpProcessor
76
80
  args.each_with_index do |name, index|
77
81
  args[index] = asgns[name] if asgns.has_key? name
78
82
  end
79
- when :block_arg then
80
- args << "&#{arg.last}"
81
83
  else
82
84
  raise "unknown arg type #{arg.first.inspect}"
83
85
  end
@@ -89,33 +91,6 @@ class Ruby2Ruby < SexpProcessor
89
91
  return "(#{args.join ', '})"
90
92
  end
91
93
 
92
- def process_arglist(exp) # custom made node
93
- code = []
94
- until exp.empty? do
95
- code << process(exp.shift)
96
- end
97
- code.join ', '
98
- end
99
-
100
- def process_argscat(exp)
101
- args = []
102
-
103
- ary = exp.shift
104
- ary.shift # :array
105
- until ary.empty? do
106
- args << process(ary.shift)
107
- end
108
-
109
- args << "*#{process(exp.shift)}"
110
- args << process(exp.shift) unless exp.empty? # optional block arg
111
-
112
- args.join ', '
113
- end
114
-
115
- def process_argspush(exp)
116
- process_arglist(exp)
117
- end
118
-
119
94
  def process_array(exp)
120
95
  "[#{process_arglist(exp)}]"
121
96
  end
@@ -128,13 +103,11 @@ class Ruby2Ruby < SexpProcessor
128
103
  case name
129
104
  when :[]= then
130
105
  rhs = process args.pop
131
- args[0] = :arglist if args[0] == :array
132
106
  "#{receiver}[#{process(args)}] = #{rhs}"
133
107
  else
134
- if args then
135
- "#{receiver}.#{name.to_s[0..-2]} = #{process(args)[1..-2]}"
136
- else
137
- "#{receiver}.#{name.to_s[0..-2]}"
108
+ name = name.to_s.sub(/=$/, '')
109
+ if args && args != s(:arglist) then
110
+ "#{receiver}.#{name} = #{process(args)}"
138
111
  end
139
112
  end
140
113
  end
@@ -143,16 +116,16 @@ class Ruby2Ruby < SexpProcessor
143
116
  "$#{exp.shift}"
144
117
  end
145
118
 
119
+ # TODO: figure out how to do rescue and ensure ENTIRELY w/o begin
146
120
  def process_begin(exp)
147
- is_rescue = exp.first.first == :rescue rescue false
148
121
  code = []
149
122
  code << "begin"
150
123
  until exp.empty?
151
124
  src = process(exp.shift)
152
- src = indent(src) unless src =~ /(^|\n)rescue/ # ensures no level 0 rescues
125
+ src = indent(src) unless src =~ /(^|\n)rescue/ # ensure no level 0 rescues
153
126
  code << src
154
127
  end
155
- code << "end" unless is_rescue
128
+ code << "end"
156
129
  return code.join("\n")
157
130
  end
158
131
 
@@ -181,30 +154,10 @@ class Ruby2Ruby < SexpProcessor
181
154
  return result
182
155
  end
183
156
 
184
- def process_block_arg(exp)
185
- "&#{exp.shift}"
186
- end
187
-
188
- def process_block_pass(exp)
189
- bname = s(:block_arg, process(exp.shift)) # FIX
190
- call = exp.shift
191
-
192
- if Array === call.last then # HACK - I _really_ need rewrites to happen first
193
- case call.last.first
194
- when :splat then
195
- call << [:array, call.pop]
196
- when :array then
197
- # do nothing
198
- else
199
- has_args = Array === call.last and call.last.first == :array
200
- call << [:array] unless has_args
201
- end
202
- call.last << bname
203
- else
204
- call << [:array, bname]
205
- end
157
+ def process_block_pass exp
158
+ raise "huh?: #{exp.inspect}" if exp.size > 1
206
159
 
207
- process(call)
160
+ "&#{process exp.shift}"
208
161
  end
209
162
 
210
163
  def process_break(exp)
@@ -276,8 +229,12 @@ class Ruby2Ruby < SexpProcessor
276
229
  def process_cdecl(exp)
277
230
  lhs = exp.shift
278
231
  lhs = process lhs if Sexp === lhs
279
- rhs = process exp.shift
280
- "#{lhs} = #{rhs}"
232
+ unless exp.empty? then
233
+ rhs = process(exp.shift)
234
+ "#{lhs} = #{rhs}"
235
+ else
236
+ lhs.to_s
237
+ end
281
238
  end
282
239
 
283
240
  def process_class(exp)
@@ -308,34 +265,6 @@ class Ruby2Ruby < SexpProcessor
308
265
  "#{exp.shift} = #{process(exp.shift)}"
309
266
  end
310
267
 
311
- # (a, lit1) => "a = 1"
312
- # (a, (b, lit2)) => "a = b = 2"
313
- # (a, (b)) => ""
314
-
315
- def process_dasgn_curr(exp)
316
- lhs = exp.shift.to_s
317
- rhs = (exp.empty? ? nil : exp.shift)
318
- if rhs.nil? then
319
- if self.context[1] == :block then
320
- return ''
321
- end
322
-
323
- return lhs
324
- end
325
- return "#{lhs} = #{process rhs}" unless rhs.first == :dasgn_curr
326
-
327
- # keep recursing. ensure that the leaf node assigns to _something_
328
- "#{lhs} = #{process rhs}"
329
- end
330
-
331
- def process_dasgn(exp)
332
- if exp.size == 1 then
333
- exp.shift.to_s
334
- else
335
- "#{exp.shift} = #{process(exp.shift)}"
336
- end
337
- end
338
-
339
268
  def process_defined(exp)
340
269
  "defined? #{process(exp.shift)}"
341
270
  end
@@ -371,7 +300,14 @@ class Ruby2Ruby < SexpProcessor
371
300
  end
372
301
 
373
302
  def process_defs(exp)
374
- exp.unshift "#{process(exp.shift)}.#{exp.shift}"
303
+ lhs = exp.shift
304
+ var = [:self, :cvar, :dvar, :ivar, :gvar, :lvar].include? lhs.first
305
+ name = exp.shift
306
+
307
+ lhs = process(lhs)
308
+ lhs = "(#{lhs})" unless var
309
+
310
+ exp.unshift "#{lhs}.#{name}"
375
311
  process_defn(exp)
376
312
  end
377
313
 
@@ -399,41 +335,29 @@ class Ruby2Ruby < SexpProcessor
399
335
  ":#{process_dstr(exp)}"
400
336
  end
401
337
 
402
- def process_dvar(exp)
403
- exp.shift.to_s
404
- end
405
-
406
338
  def process_dxstr(exp)
407
339
  "`#{process_dstr(exp)[1..-2]}`"
408
340
  end
409
341
 
410
342
  def process_ensure(exp)
411
343
  body = process exp.shift
412
- ens = process exp.shift
344
+ ens = exp.shift
345
+ ens = nil if ens == s(:nil)
346
+ ens = process(ens) || "# do nothing"
347
+
348
+ body.sub!(/\n\s*end\z/, '')
349
+
413
350
  return "#{body}\nensure\n#{indent ens}"
414
351
  end
415
352
 
416
353
  def process_evstr(exp)
417
- process exp.shift
354
+ exp.empty? ? '' : process(exp.shift)
418
355
  end
419
356
 
420
357
  def process_false(exp)
421
358
  "false"
422
359
  end
423
360
 
424
- # TODO: remove for unified
425
- def process_fcall(exp)
426
- recv = exp.shift unless Symbol === exp.first # HACK conditional - some not getting rewritten?
427
- name = exp.shift.to_s
428
- args = exp.shift
429
- code = []
430
- unless args.nil? then
431
- args[0] = :arglist if args.first == :array
432
- code << process(args)
433
- end
434
- return code.empty? ? name : "#{name}(#{code.join(', ')})"
435
- end
436
-
437
361
  def process_flip2(exp)
438
362
  "#{process(exp.shift)}..#{process(exp.shift)}"
439
363
  end
@@ -465,7 +389,13 @@ class Ruby2Ruby < SexpProcessor
465
389
  def process_hash(exp)
466
390
  result = []
467
391
  until exp.empty?
468
- result << "#{process(exp.shift)} => #{process(exp.shift)}"
392
+ lhs = process(exp.shift)
393
+ rhs = exp.shift
394
+ t = rhs.first
395
+ rhs = process rhs
396
+ rhs = "(#{rhs})" unless [:lit, :str].include? t # TODO: verify better!
397
+
398
+ result << "#{lhs} => #{rhs}"
469
399
  end
470
400
 
471
401
  case self.context[1]
@@ -588,7 +518,7 @@ class Ruby2Ruby < SexpProcessor
588
518
  rhs = exp.empty? ? nil : exp.shift
589
519
 
590
520
  unless exp.empty? then
591
- rhs[-1] = splat(rhs[-1]) unless rhs == s(:splat)
521
+ rhs[1] = splat(rhs[1]) unless rhs == s(:splat)
592
522
  lhs << rhs
593
523
  rhs = exp.shift
594
524
  end
@@ -604,7 +534,7 @@ class Ruby2Ruby < SexpProcessor
604
534
  process(l)
605
535
  end
606
536
  end
607
- when :dasgn_curr then
537
+ when :lasgn then
608
538
  lhs = [ splat(lhs.last) ]
609
539
  when :splat then
610
540
  lhs = [ :"*" ]
@@ -613,20 +543,14 @@ class Ruby2Ruby < SexpProcessor
613
543
  end
614
544
 
615
545
  if context[1] == :iter and rhs then
616
- lhs << splat(rhs.last)
546
+ lhs << splat(rhs[1])
617
547
  rhs = nil
618
548
  end
619
549
 
620
550
  unless rhs.nil? then
621
551
  t = rhs.first
622
- rhs = if t == :argscat then
623
- rhs.shift
624
- process_argscat(rhs)
625
- else
626
- r = process(rhs)
627
- r = r[1..-2] if t != :to_ary
628
- r
629
- end
552
+ rhs = process rhs
553
+ rhs = rhs[1..-2] if t != :to_ary
630
554
  return "#{lhs.join(", ")} = #{rhs}"
631
555
  else
632
556
  return lhs.join(", ")
@@ -676,13 +600,13 @@ class Ruby2Ruby < SexpProcessor
676
600
  end
677
601
 
678
602
  def process_op_asgn1(exp)
679
- # [[:lvar, :b], [:array, [:lit, 1]], :"||", [:lit, 10]]
603
+ # [[:lvar, :b], [:arglist, [:lit, 1]], :"||", [:lit, 10]]
680
604
  lhs = process(exp.shift)
681
605
  index = process(exp.shift)
682
606
  msg = exp.shift
683
607
  rhs = process(exp.shift)
684
608
 
685
- "#{lhs}#{index} #{msg}= #{rhs}"
609
+ "#{lhs}[#{index}] #{msg}= #{rhs}"
686
610
  end
687
611
 
688
612
  def process_op_asgn2(exp)
@@ -696,18 +620,18 @@ class Ruby2Ruby < SexpProcessor
696
620
  "#{lhs}.#{index} #{msg}= #{rhs}"
697
621
  end
698
622
 
699
- def process_op_asgn_or(exp)
700
- # a ||= 1
623
+ def process_op_asgn_and(exp)
624
+ # a &&= 1
701
625
  # [[:lvar, :a], [:lasgn, :a, [:lit, 1]]]
702
626
  exp.shift
703
- process(exp.shift).sub(/=/, '||=')
627
+ process(exp.shift).sub(/\=/, '&&=')
704
628
  end
705
629
 
706
- def process_op_asgn_and(exp)
707
- # a &&= 1
630
+ def process_op_asgn_or(exp)
631
+ # a ||= 1
708
632
  # [[:lvar, :a], [:lasgn, :a, [:lit, 1]]]
709
633
  exp.shift
710
- process(exp.shift).sub(/=/, '&&=')
634
+ process(exp.shift).sub(/\=/, '||=')
711
635
  end
712
636
 
713
637
  def process_or(exp)
@@ -722,97 +646,40 @@ class Ruby2Ruby < SexpProcessor
722
646
  "redo"
723
647
  end
724
648
 
725
- def process_resbody(exp) # TODO: rewrite this fucker
726
- code = []
727
-
728
- sexp = exp
729
- until exp.empty? and (sexp.nil? or sexp.empty?)
730
- list = sexp.shift
731
- body = sexp.shift
732
-
733
- var = if list and
734
- list.size > 1 and
735
- [:lasgn, :dasgn, :dasgn_curr].include? list.last.first then
736
- list.pop[1]
737
- else
738
- nil
739
- end
740
-
741
- # FIX: omg this is horrid. I should be punished
742
- var = body.delete_at(1)[1] if
743
- [:dasgn_curr, :dasgn].include? body[1][0] unless
744
- var or body.nil? rescue nil
745
-
746
- if list and list.size > 1 then
747
- list[0] = :arglist
748
- code << "rescue #{process(list)}"
749
- else
750
- code << "rescue"
751
- end
752
-
753
- code.last << " => #{var}" if var
754
-
755
- if body then
756
- code << indent(process(body)).chomp
757
- else
758
- code << indent("# do nothing")
759
- end
649
+ def process_resbody exp
650
+ args = exp.shift
651
+ body = process(exp.shift) || "# do nothing"
760
652
 
761
- unless exp.empty? then
762
- sexp = exp.shift
763
- assert_type sexp, :resbody
764
- sexp.shift
765
- end
766
- end
653
+ name = args.lasgn true
654
+ name ||= args.iasgn true
655
+ args = process(args)[1..-2]
656
+ args = " #{args}" unless args.empty?
657
+ args += " => #{name[1]}" if name
767
658
 
768
- code.join("\n")
659
+ "rescue#{args}\n#{indent body}"
769
660
  end
770
661
 
771
- def process_rescue(exp)
772
- # TODO: rewrite this
773
- #
774
- # a = b rescue c => [lasgn a [rescue b c]]
775
- # begin; a = b; rescue c => [begin [rescue [lasgn a b] c]]
776
-
777
- current = self.context[1]
778
- case current
779
- when :begin, :ensure, :block then
780
- body = (exp.first.first == :resbody) ? nil : process(exp.shift)
781
- resbody = exp.empty? ? '' : process(exp.shift)
782
- els = exp.empty? ? nil : process(exp.shift)
783
-
784
- code = []
785
- code << indent(body) if body
786
- code << resbody
787
- if els then
788
- code << "else"
789
- code << indent(els)
790
- else
791
- unless [:block].include? current then
792
- code << "end\n" unless current == :ensure
793
- else
794
- r = [body, resbody.gsub(/rescue\n\s+/, 'rescue ')].compact.join(' ')
795
- code = [r] if (@indent+r).size < LINE_LENGTH and r !~ /\n/
796
- end
797
- end
662
+ def process_rescue exp
663
+ body = process(exp.shift) unless exp.first.first == :resbody
664
+ els = process(exp.pop) unless exp.last.first == :resbody
665
+
666
+ body ||= "# do nothing"
667
+ simple = exp.size == 1
798
668
 
799
- code.join("\n").chomp
800
- else # a rescue b and others
801
- body = process exp.shift
802
- assert_type exp.first, :resbody
669
+ resbodies = []
670
+ until exp.empty? do
803
671
  resbody = exp.shift
804
- resbody.shift # resbody
805
- resbody.shift # nil (no types for expression form)
806
- resbody = resbody.shift # actual code
807
-
808
- resbody = process resbody
809
- code = "#{body} rescue #{resbody}"
810
- case current
811
- when :hash then # HACK move to process_hash
812
- "(#{code})"
813
- else
814
- code
815
- end
672
+ simple &&= resbody[1] == s(:array) && resbody[2] != nil
673
+ resbodies << process(resbody)
674
+ end
675
+
676
+ if els then
677
+ "#{indent body}\n#{resbodies.join("\n")}\nelse\n#{indent els}"
678
+ elsif simple then
679
+ resbody = resbodies.first.sub(/\n\s*/, ' ')
680
+ "#{body} #{resbody}"
681
+ else
682
+ "#{indent body}\n#{resbodies.join("\n")}"
816
683
  end
817
684
  end
818
685
 
@@ -855,13 +722,20 @@ class Ruby2Ruby < SexpProcessor
855
722
  end
856
723
 
857
724
  def process_super(exp)
858
- args = exp.shift
859
- args[0] = :arglist if args[0] == :array
860
- "super(#{process(args)})"
725
+ args = []
726
+ until exp.empty? do
727
+ args << process(exp.shift)
728
+ end
729
+
730
+ "super(#{args.join(', ')})"
861
731
  end
862
732
 
863
733
  def process_svalue(exp)
864
- process(exp.shift)
734
+ code = []
735
+ until exp.empty? do
736
+ code << process(exp.shift)
737
+ end
738
+ code.join(", ")
865
739
  end
866
740
 
867
741
  def process_to_ary(exp)
@@ -912,24 +786,18 @@ class Ruby2Ruby < SexpProcessor
912
786
  end
913
787
 
914
788
  def process_yield(exp)
915
- args = exp.empty? ? nil : exp.shift
916
- if args then
917
- args[0] = :arglist if args.first == :array
918
- args = process(args)
789
+ args = []
790
+ until exp.empty? do
791
+ args << process(exp.shift)
919
792
  end
920
793
 
921
- # "yield" + (args ? "(#{args})" : "")
922
- if args then
923
- "yield(#{args})"
794
+ unless args.empty? then
795
+ "yield(#{args.join(', ')})"
924
796
  else
925
797
  "yield"
926
798
  end
927
799
  end
928
800
 
929
- def process_zarray(exp)
930
- "[]"
931
- end
932
-
933
801
  def process_zsuper(exp)
934
802
  "super"
935
803
  end
@@ -957,24 +825,52 @@ class Ruby2Ruby < SexpProcessor
957
825
  ############################################################
958
826
  # Rewriters:
959
827
 
828
+ def rewrite_attrasgn exp
829
+ if context.first(2) == [:array, :masgn] then
830
+ exp[0] = :call
831
+ exp[2] = exp[2].to_s.sub(/=$/, '').to_sym
832
+ end
833
+
834
+ exp
835
+ end
836
+
837
+ def rewrite_ensure exp
838
+ exp = s(:begin, exp) unless context.first == :begin
839
+ exp
840
+ end
841
+
960
842
  def rewrite_rescue exp
961
- exp = s(:begin, exp) if
962
- context[1] == :block unless
963
- context[2] == :scope and [:defn, :defs].include? context[3]
843
+ complex = false
844
+ complex ||= exp.size > 3
845
+ complex ||= exp.block
846
+ complex ||= exp.find_nodes(:resbody).any? { |n| n.array != s(:array) }
847
+ complex ||= exp.find_nodes(:resbody).any? { |n| n.last.nil? }
848
+
849
+ handled = context.first == :ensure
850
+
851
+ exp = s(:begin, exp) if complex unless handled
852
+
964
853
  exp
965
854
  end
966
855
 
856
+ def rewrite_svalue(exp)
857
+ case exp.last.first
858
+ when :array
859
+ s(:svalue, *exp[1][1..-1])
860
+ when :splat
861
+ exp
862
+ else
863
+ raise "huh: #{exp.inspect}"
864
+ end
865
+ end
866
+
967
867
  ############################################################
968
868
  # Utility Methods:
969
869
 
970
870
  def util_dthing(exp, regx = false)
971
871
  s = []
972
872
  suck = true
973
- if suck then
974
- x = exp.shift.gsub(/"/, '\"').gsub(/\n/, '\n')
975
- else
976
- x = exp.shift.dump[1..-2]
977
- end
873
+ x = exp.shift.gsub(/"/, '\"').gsub(/\n/, '\n')
978
874
  x.gsub!(/\//, '\/') if regx
979
875
 
980
876
  s << x
@@ -984,18 +880,15 @@ class Ruby2Ruby < SexpProcessor
984
880
  when Sexp then
985
881
  case pt.first
986
882
  when :str then
987
- if suck then
988
- x = pt.last.gsub(/"/, '\"').gsub(/\n/, '\n')
989
- else
990
- x = pt.last.dump[1..-2]
991
- end
883
+ x = pt.last.gsub(/"/, '\"').gsub(/\n/, '\n')
992
884
  x.gsub!(/\//, '\/') if regx
993
885
  s << x
994
886
  else
995
887
  s << '#{' << process(pt) << '}' # do not use interpolation here
996
888
  end
997
889
  else
998
- # do nothing - yet
890
+ # HACK: raise "huh?: #{pt.inspect}"
891
+ # do nothing for now
999
892
  end
1000
893
  end
1001
894
 
@@ -1038,71 +931,3 @@ class Ruby2Ruby < SexpProcessor
1038
931
  s.to_s.split(/\n/).map{|line| @indent + line}.join("\n")
1039
932
  end
1040
933
  end
1041
-
1042
- RubyToRuby = Ruby2Ruby # For backwards compatibilty... TODO: remove 2008-03-28
1043
-
1044
- class Method
1045
- def with_class_and_method_name
1046
- if self.inspect =~ /<Method: (.*)\#(.*)>/ then
1047
- klass = eval $1
1048
- method = $2.intern
1049
- raise "Couldn't determine class from #{self.inspect}" if klass.nil?
1050
- return yield(klass, method)
1051
- else
1052
- raise "Can't parse signature: #{self.inspect}"
1053
- end
1054
- end
1055
-
1056
- def to_sexp
1057
- require 'parse_tree'
1058
- parser = ParseTree.new(false)
1059
- with_class_and_method_name do |klass, method|
1060
- parser.parse_tree_for_method(klass, method)
1061
- end
1062
- end
1063
-
1064
- def to_ruby
1065
- Ruby2Ruby.new.process(self.to_sexp)
1066
- end
1067
- end
1068
-
1069
- class ProcStoreTmp
1070
- @@n = 0
1071
- def self.new_name
1072
- @@n += 1
1073
- return :"myproc#{@@n}"
1074
- end
1075
- end
1076
-
1077
- class UnboundMethod
1078
- def to_ruby
1079
- name = ProcStoreTmp.new_name
1080
- ProcStoreTmp.send(:define_method, name, self)
1081
- m = ProcStoreTmp.new.method(name)
1082
- result = m.to_ruby.sub(/def #{name}(?:\(([^\)]*)\))?/,
1083
- 'proc { |\1|').sub(/end\Z/, '}')
1084
- return result
1085
- end
1086
- end
1087
-
1088
- class Proc
1089
- def to_method
1090
- name = ProcStoreTmp.new_name
1091
- ProcStoreTmp.send(:define_method, name, self)
1092
- ProcStoreTmp.new.method(name)
1093
- end
1094
-
1095
- def to_sexp
1096
- sexp = self.to_method.to_sexp
1097
- body = sexp[2]
1098
- body[0] = :block
1099
- args = body.delete_at 1
1100
- body = body[1] if body.size == 2
1101
-
1102
- [:iter, [:fcall, :proc], args, body]
1103
- end
1104
-
1105
- def to_ruby
1106
- Ruby2Ruby.new.process(self.to_sexp).sub(/^\Aproc do/, 'proc {').sub(/end\Z/, '}')
1107
- end
1108
- end
@@ -14,8 +14,29 @@ require 'tmpdir'
14
14
 
15
15
  FileUtils.rm_rf File.expand_path("~/.ruby_inline") # for self-translation
16
16
 
17
- class TestRuby2Ruby < Test::Unit::TestCase
17
+ class R2RTestCase < ParseTreeTestCase
18
+ def self.previous key
19
+ "ParseTree"
20
+ end
21
+
22
+ def self.generate_test klass, node, data, input_name, output_name
23
+ output_name = data.has_key?('Ruby2Ruby') ? 'Ruby2Ruby' : 'Ruby'
24
+
25
+ klass.class_eval <<-EOM
26
+ def test_#{node}
27
+ pt = #{data[input_name].inspect}
28
+ rb = #{data[output_name].inspect}
29
+
30
+ refute_nil pt, \"ParseTree for #{node} undefined\"
31
+ refute_nil rb, \"Ruby for #{node} undefined\"
32
+
33
+ assert_equal rb, @processor.process(pt)
34
+ end
35
+ EOM
36
+ end
37
+ end
18
38
 
39
+ class TestRuby2Ruby < R2RTestCase
19
40
  alias :refute_nil :assert_not_nil unless defined? Mini
20
41
 
21
42
  def setup
@@ -30,35 +51,6 @@ class TestRuby2Ruby < Test::Unit::TestCase
30
51
  end if defined?(@rootdir) && @rootdir
31
52
  end
32
53
 
33
- def util_setup_inline
34
- @rootdir = File.join(Dir.tmpdir, "test_ruby_to_ruby.#{$$}")
35
- Dir.mkdir @rootdir, 0700 unless test ?d, @rootdir
36
- ENV['INLINEDIR'] = @rootdir
37
- end
38
-
39
- def test_proc_to_ruby
40
- util_setup_inline
41
- block = proc { puts "something" }
42
- assert_equal 'proc { puts("something") }', block.to_ruby
43
- end unless SKIP_PROCS
44
-
45
- def test_lit_regexp_slash
46
- inn = s(:lit, /blah\/blah/)
47
- out = '/blah\/blah/'
48
-
49
- assert_equal out, @processor.process(inn)
50
-
51
- r = eval(out)
52
- assert_equal(/blah\/blah/, r)
53
- end
54
-
55
- def util_thingy(type)
56
- s(type,
57
- 'blah"blah',
58
- s(:call, s(:lit, 1), :+, s(:array, s(:lit, 1))),
59
- s(:str, 'blah"blah/blah'))
60
- end
61
-
62
54
  def test_dregx_slash
63
55
  inn = util_thingy(:dregx)
64
56
  out = "/blah\\\"blah#\{(1 + 1)}blah\\\"blah\\/blah/"
@@ -89,58 +81,59 @@ class TestRuby2Ruby < Test::Unit::TestCase
89
81
  assert_equal :"blah\"blah2blah\"blah/blah", r
90
82
  end
91
83
 
92
- def test_proc_to_sexp
93
- util_setup_inline
94
- p = proc { 1 + 1 }
95
- s = [:iter, [:fcall, :proc], nil, [:call, [:lit, 1], :+, [:array, [:lit, 1]]]]
96
- assert_equal s, p.to_sexp
97
- end unless SKIP_PROCS
98
-
99
- def test_unbound_method_to_ruby
100
- util_setup_inline
101
- r = "proc { ||\n util_setup_inline\n p = proc { (1 + 1) }\n s = [:iter, [:fcall, :proc], nil, [:call, [:lit, 1], :+, [:array, [:lit, 1]]]]\n assert_equal(s, p.to_sexp)\n}"
102
- m = self.class.instance_method(:test_proc_to_sexp)
103
-
104
- assert_equal r, m.to_ruby
105
- end unless SKIP_PROCS
84
+ def test_lit_regexp_slash
85
+ inn = s(:lit, /blah\/blah/)
86
+ out = '/blah\/blah/'
106
87
 
107
- eval ParseTreeTestCase.testcases.map { |node, data|
108
- next if node == "vcall" # HACK
88
+ assert_equal out, @processor.process(inn)
109
89
 
110
- "def test_#{node}
111
- pt = #{data['ParseTree'].inspect}
112
- rb = #{(data['Ruby2Ruby'] || data['Ruby']).inspect}
90
+ r = eval(out)
91
+ assert_equal(/blah\/blah/, r)
92
+ end
113
93
 
114
- refute_nil pt, \"ParseTree for #{node} undefined\"
115
- refute_nil rb, \"Ruby for #{node} undefined\"
94
+ def util_setup_inline
95
+ @rootdir = File.join(Dir.tmpdir, "test_ruby_to_ruby.#{$$}")
96
+ Dir.mkdir @rootdir, 0700 unless test ?d, @rootdir
97
+ ENV['INLINEDIR'] = @rootdir
98
+ end
116
99
 
117
- assert_equal rb, @processor.process(pt)
118
- end"
119
- }.join("\n")
100
+ def util_thingy(type)
101
+ s(type,
102
+ 'blah"blah',
103
+ s(:call, s(:lit, 1), :+, s(:array, s(:lit, 1))),
104
+ s(:str, 'blah"blah/blah'))
105
+ end
120
106
  end
121
107
 
122
108
  ##
123
109
  # Converts a +target+ using a +processor+ and converts +target+ name
124
110
  # in the source adding +gen+ to allow easy renaming.
125
111
 
112
+ $broken = false
126
113
  def morph_and_eval(processor, target, gen, n)
114
+ return if $broken
127
115
  begin
128
116
  processor = Object.const_get processor if Symbol === processor
129
117
  target = Object.const_get target if Symbol === target
130
118
  old_name = target.name
131
119
  new_name = target.name.sub(/\d*$/, gen.to_s)
132
- ruby = processor.translate(target).sub(old_name, new_name)
120
+ ruby = processor.translate(target).sub(old_name, new_name)
133
121
 
122
+ old, $-w = $-w, nil
134
123
  eval ruby
124
+ $-w = old
125
+
135
126
  target.constants.each do |constant|
136
127
  eval "#{new_name}::#{constant} = #{old_name}::#{constant}"
137
128
  end
138
129
  rescue Exception => e
139
130
  warn "Self-Translation Generation #{n} failed:"
140
131
  warn "#{e.class}: #{e.message}"
132
+ warn e.backtrace.join("\n ")
141
133
  warn ""
142
134
  warn ruby
143
135
  warn ""
136
+ $broken = true
144
137
  else
145
138
  begin
146
139
  yield if block_given?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby2ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.9
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Davis
@@ -9,26 +9,28 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-06-09 00:00:00 -07:00
12
+ date: 2008-10-22 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: ParseTree
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
20
- - - ">="
21
+ - - ~>
21
22
  - !ruby/object:Gem::Version
22
- version: "0"
23
+ version: "3.0"
23
24
  version:
24
25
  - !ruby/object:Gem::Dependency
25
26
  name: hoe
27
+ type: :development
26
28
  version_requirement:
27
29
  version_requirements: !ruby/object:Gem::Requirement
28
30
  requirements:
29
31
  - - ">="
30
32
  - !ruby/object:Gem::Version
31
- version: 1.5.3
33
+ version: 1.8.0
32
34
  version:
33
35
  description: ruby2ruby provides a means of generating pure ruby code easily from ParseTree's Sexps. This makes making dynamic language processors much easier in ruby than ever before.
34
36
  email:
@@ -73,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
75
  requirements: []
74
76
 
75
77
  rubyforge_project: seattlerb
76
- rubygems_version: 1.1.1
78
+ rubygems_version: 1.3.0
77
79
  signing_key:
78
80
  specification_version: 2
79
81
  summary: ruby2ruby provides a means of generating pure ruby code easily from ParseTree's Sexps