lib/ruby2ruby.rb in ruby2ruby-1.1.4 vs lib/ruby2ruby.rb in ruby2ruby-1.1.5
- old
+ new
@@ -9,11 +9,12 @@
nil
end
end
class RubyToRuby < SexpProcessor
- VERSION = '1.1.4'
+ VERSION = '1.1.5'
+ LINE_LENGTH = 78
def self.translate(klass_or_str, method = nil)
self.new.process(ParseTree.translate(klass_or_str, method))
end
@@ -117,15 +118,19 @@
name = exp.shift
args = exp.shift
case name
when :[]= then
- lhs = process args.delete_at(1)
+ rhs = process args.pop
args[0] = :arglist
- "#{receiver}[#{lhs}] = #{process(args)}"
+ "#{receiver}[#{process(args)}] = #{rhs}"
else
- "#{receiver}.#{name.to_s[0..-2]} = #{process(args)[1..-2]}"
+ if args then
+ "#{receiver}.#{name.to_s[0..-2]} = #{process(args)[1..-2]}"
+ else
+ "#{receiver}.#{name.to_s[0..-2]}"
+ end
end
end
def process_back_ref(exp)
"$#{exp.shift}"
@@ -162,16 +167,27 @@
def process_block_arg(exp)
"&#{exp.shift}"
end
def process_block_pass(exp)
- bname = [:lvar, "&" + process(exp.shift)]
+ bname = [:block_arg, process(exp.shift)]
call = exp.shift
- has_args = Array === call.last and call.last.first == :array
- call << [:array] unless has_args
- call.last << bname
+ if Array === call.last then # HACK - I _really_ need rewrites to happen first
+ case call.last.first
+ when :splat then
+ call << [:array, call.pop]
+ when :array then
+ # do nothing
+ else
+ call << [:array] unless has_args
+ end
+ call.last << bname
+ else
+ call << [:array, bname]
+ end
+
process(call)
end
def process_break(exp)
val = process(exp.shift)
@@ -191,10 +207,14 @@
case name
when :<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :%, :<<, :>> then #
"(#{receiver} #{name} #{args})"
when :[] then
"#{receiver}[#{args}]"
+ when :"-@" then
+ "-#{receiver}"
+ when :"+@" then
+ "+#{receiver}"
else
unless receiver.nil? then
"#{receiver}.#{name}#{args ? "(#{args})" : args}"
else
"#{name}#{args ? "(#{args})" : args}"
@@ -447,19 +467,19 @@
f = process exp.shift
if t then
unless f then
r = "#{t} if #{c}"
- return r if (@indent+r).size < 78 and r !~ /\n/
+ return r if (@indent+r).size < LINE_LENGTH and r !~ /\n/
end
r = "if #{c} then\n#{indent(t)}\n"
r << "else\n#{indent(f)}\n" if f
r << "end"
r
else
r = "#{f} unless #{c}"
- return r if (@indent+r).size < 78 and r !~ /\n/
+ return r if (@indent+r).size < LINE_LENGTH and r !~ /\n/
"unless #{c} then\n#{indent(f)}\nend"
end
end
def process_iter(exp)
@@ -473,11 +493,24 @@
[ "do", "end" ]
end
iter.sub!(/\(\)$/, '')
+ # REFACTOR: ugh
result = []
+ result << "#{iter} {"
+ result << " |#{args}|" if args
+ if body then
+ result << " #{body.strip} "
+ else
+ result << ' '
+ end
+ result << "}"
+ result = result.join
+ return result if result !~ /\n/ and result.size < LINE_LENGTH
+
+ result = []
result << "#{iter} #{b}"
result << " |#{args}|" if args
if body then
result << "\n"
result << indent(body.strip)
@@ -510,18 +543,34 @@
def process_lvar(exp)
exp.shift.to_s
end
+ def splat(sym)
+ :"*#{sym}"
+ end
+
def process_masgn(exp)
lhs = exp.shift
- rhs = exp.shift rescue nil
+ rhs = exp.empty? ? nil : exp.shift
- assert_type lhs, :array
- lhs.shift
- lhs = lhs.map { |l| process(l) }
+ unless exp.empty? then
+ rhs[-1] = splat(rhs[-1])
+ lhs << rhs
+ rhs = exp.shift
+ end
+ case lhs.first
+ when :array then
+ lhs.shift
+ lhs = lhs.map { |l| process(l) }
+ when :dasgn_curr then
+ lhs = [ splat(lhs.last) ]
+ else
+ raise "no clue: #{lhs.inspect}"
+ end
+
unless rhs.nil? then
# HACK - but seems to work (see to_ary test) assert_type rhs, :array
rhs.shift
rhs = rhs.map { |r| process(r) }
return "#{lhs.join(", ")} = #{rhs.join(", ")}"
@@ -620,19 +669,18 @@
sexp = exp
until exp.empty? and (sexp.nil? or sexp.empty?)
list = sexp.shift
body = sexp.shift
- var = if list.last.first == :lasgn then
+ var = if list and list.last.first == :lasgn then
list.pop[1]
else
nil
end
- list[0] = :arglist
-
if list then
+ list[0] = :arglist
code << "rescue #{process(list)}"
else
code << "rescue"
end
code.last << " => #{var}" if var
@@ -652,10 +700,11 @@
code.join("\n")
end
def process_rescue(exp)
+ # TODO: rewrite this
# TODO: proper formatting depends on knowing the context
#
# a = b rescue c => [lasgn a [rescue b c]]
# begin; a = b; rescue c => [begin [rescue [lasgn a b] c]]
stack = caller.map { |s| s[/process_\w+/] }.compact
@@ -671,13 +720,18 @@
code << resbody
if els then
code << "else"
code << indent(els)
else
- code << "end\n" unless stack.first == "process_block"
+ unless stack.first == "process_block" then
+ code << "end\n"
+ else
+ r = [body, resbody.gsub(/rescue\n\s+/, 'rescue ')].join(' ')
+ code = [r] if (@indent+r).size < LINE_LENGTH and r !~ /\n/
+ end
end
- code.join("\n")
+ code.join("\n").chomp
else # a rescue b and others
body = process exp.shift
assert_type exp.first, :resbody
resbody = exp.shift
resbody.shift # resbody
@@ -840,11 +894,11 @@
body = exp.shift
assert_type args, :args
assert_type body, :scope
assert_type body[1], :block
when :scope, :fbody then
- body = body[1] if body.first == :fbody
+ body = body.pop if body.first == :fbody
case body.first
when :scope then
args = body.block.args(true)
assert_type body, :scope
assert_type body[1], :block
@@ -856,16 +910,16 @@
when :bmethod then
body[0] = :scope
body.block.delete_at(1) # nuke the decl # REFACTOR
masgn = body.masgn(true)
if masgn then
- splat = :"*#{masgn[-1][-1]}"
+ splat = self.splat(masgn[-1][-1])
args.push(splat)
else
dasgn_curr = body.dasgn_curr(true)
if dasgn_curr then
- arg = :"*#{dasgn_curr[-1]}"
+ arg = self.splat(dasgn_curr[-1])
args.push(arg)
end
end
body.find_and_replace_all(:dvar, :lvar)
else
@@ -885,10 +939,10 @@
body.find_and_replace_all(:dvar, :lvar)
when :masgn then
dasgn = body.masgn(true)
# DAMNIT body.block.dasgn_curr(true) - multiple values so can't use
body.block.delete_at(1) # nuke the decl
- splat = :"*#{dasgn[-1][-1]}"
+ splat = self.splat(dasgn[-1][-1])
args.push(splat)
body.find_and_replace_all(:dvar, :lvar)
end
if body.first.first == :block then