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