ruby2ruby 1.1.3 → 1.1.4

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