ruby2ruby 1.1.9 → 1.2.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/.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