lib/ruby2ruby.rb in ruby2ruby-2.4.2 vs lib/ruby2ruby.rb in ruby2ruby-2.4.3
- old
+ new
@@ -1,9 +1,9 @@
#!/usr/bin/env ruby -w
-require 'rubygems'
-require 'sexp_processor'
+require "rubygems"
+require "sexp_processor"
# :stopdoc:
# REFACTOR: stolen from ruby_parser
class Regexp
unless defined? ENC_NONE then
@@ -13,33 +13,33 @@
ENC_UTF8 = /x/u.options
end
unless defined? CODES then
CODES = {
- EXTENDED => 'x',
- IGNORECASE => 'i',
- MULTILINE => 'm',
- ENC_NONE => 'n',
- ENC_EUC => 'e',
- ENC_SJIS => 's',
- ENC_UTF8 => 'u',
+ EXTENDED => "x",
+ IGNORECASE => "i",
+ MULTILINE => "m",
+ ENC_NONE => "n",
+ ENC_EUC => "e",
+ ENC_SJIS => "s",
+ ENC_UTF8 => "u",
}
end
end
# :startdoc:
##
# Generate ruby code from a sexp.
class Ruby2Ruby < SexpProcessor
- VERSION = "2.4.2" # :nodoc:
+ VERSION = "2.4.3" # :nodoc:
# cutoff for one-liners
LINE_LENGTH = 78
# binary operation messages
- BINARY = [:<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :%, :<<, :>>, :**, :'!=', :^, :|, :&]
+ BINARY = [:<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :%, :<<, :>>, :**, :"!=", :^, :|, :&]
##
# Nodes that represent assignment and probably need () around them.
#
# TODO: this should be replaced with full precedence support :/
@@ -74,11 +74,11 @@
:false,
:lit,
:lvar,
:nil,
:str,
- :true
+ :true,
]
def initialize # :nodoc:
super
@indent = " "
@@ -116,10 +116,12 @@
end
def process_args exp # :nodoc:
_, *args = exp
+ shadow = []
+
args = args.map { |arg|
case arg
when Symbol then
arg
when Sexp then
@@ -129,19 +131,28 @@
when :masgn then
process(arg)
when :kwarg then
_, k, v = arg
"#{k}: #{process v}"
+ when :shadow then
+ shadow << arg[1]
+ next
else
raise "unknown arg type #{arg.first.inspect}"
end
+ when nil then
+ ""
else
raise "unknown arg type #{arg.inspect}"
end
- }
+ }.compact
- "(#{args.join ', '})"
+ args = args.join(", ").strip
+ shadow = shadow.join(", ").strip
+ shadow = "; #{shadow}" unless shadow.empty?
+
+ "(%s%s)" % [args, shadow]
end
def process_array exp # :nodoc:
"[#{process_arglist exp}]"
end
@@ -178,11 +189,11 @@
def process_begin exp # :nodoc:
_, *rest = exp
code = rest.map { |sexp|
src = process sexp
- src = indent src unless src =~ /(^|\n)(rescue|ensure)/ # ensure no level 0 rescues
+ src = indent src unless src =~ /(^|\n)(rescue|ensure)/ # ensure no level 0 rescues
src
}
code.unshift "begin"
code.push "end"
@@ -236,22 +247,22 @@
# exp.push(*exp.pop[1..-1]) if exp.size == 1 && exp.first.first == :arglist
@calls.push name
in_context :arglist do
- max = args.size-1
+ max = args.size - 1
args = args.map.with_index { |arg, i|
arg_type = arg.sexp_type
is_empty_hash = arg == s(:hash)
arg = process arg
next if arg.empty?
strip_hash = (arg_type == :hash and
not BINARY.include? name and
not is_empty_hash and
- (i == max or args[i+1].sexp_type == :splat))
+ (i == max or args[i + 1].sexp_type == :splat))
wrap_arg = Ruby2Ruby::ASSIGN_NODES.include? arg_type
arg = arg[2..-3] if strip_hash
arg = "(#{arg})" if wrap_arg
@@ -260,32 +271,32 @@
end
case name
when *BINARY then
if safe_call
- "#{receiver}&.#{name}(#{args.join(', ')})"
+ "#{receiver}&.#{name}(#{args.join(", ")})"
elsif args.length > 1
- "#{receiver}.#{name}(#{args.join(', ')})"
+ "#{receiver}.#{name}(#{args.join(", ")})"
else
- "(#{receiver} #{name} #{args.join(', ')})"
+ "(#{receiver} #{name} #{args.join(", ")})"
end
when :[] then
receiver ||= "self"
- "#{receiver}[#{args.join(', ')}]"
+ "#{receiver}[#{args.join(", ")}]"
when :[]= then
receiver ||= "self"
rhs = args.pop
- "#{receiver}[#{args.join(', ')}] = #{rhs}"
+ "#{receiver}[#{args.join(", ")}] = #{rhs}"
when :"!" then
"(not #{receiver})"
when :"-@" then
"-#{receiver}"
when :"+@" then
"+#{receiver}"
else
args = nil if args.empty?
- args = "(#{args.join(', ')})" if args
+ args = "(#{args.join(", ")})" if args
receiver = "#{receiver}." if receiver and not safe_call
receiver = "#{receiver}&." if receiver and safe_call
"#{receiver}#{name}#{args}"
end
@@ -302,15 +313,15 @@
result = []
expr = process expr
- if expr then
- result << "case #{expr}"
- else
- result << "case"
- end
+ result << if expr then
+ "case #{expr}"
+ else
+ "case"
+ end
result.concat rest.map { |pt|
if pt and pt.sexp_type == :when
"#{process pt}"
else
@@ -414,11 +425,11 @@
body = body.join("\n")
body = body.lines.to_a[1..-2].join("\n") if
simple && body =~ /^\Abegin/ && body =~ /^end\z/
body = indent(body) unless simple && body =~ /(^|\n)rescue/
- return "#{comm}def #{name}#{args}\n#{body}\nend".gsub(/\n\s*\n+/, "\n")
+ "#{comm}def #{name}#{args}\n#{body}\nend".gsub(/\n\s*\n+/, "\n")
end
def process_defs exp # :nodoc:
_, lhs, name, args, *body = exp
var = [:self, :cvar, :dvar, :ivar, :gvar, :lvar].include? lhs.sexp_type
@@ -473,14 +484,14 @@
body = process body
ens = nil if ens == s(:nil)
ens = process(ens) || "# do nothing"
ens = "begin\n#{ens}\nend\n" if ens =~ /(^|\n)rescue/
- body.sub!(/\n\s*end\z/, '')
+ body.sub!(/\n\s*end\z/, "")
body = indent(body) unless body =~ /(^|\n)rescue/
- return "#{body}\nensure\n#{indent ens}"
+ "#{body}\nensure\n#{indent ens}"
end
def process_evstr exp # :nodoc:
_, x = exp
@@ -528,12 +539,10 @@
end
def process_hash(exp) # :nodoc:
_, *pairs = exp
- result = []
-
result = pairs.each_slice(2).map { |k, v|
if k.sexp_type == :kwsplat then
"%s" % process(k)
else
t = v.sexp_type
@@ -544,11 +553,11 @@
"%s => %s" % [lhs, rhs]
end
}
- return result.empty? ? "{}" : "{ #{result.join(', ')} }"
+ result.empty? ? "{}" : "{ #{result.join(", ")} }"
end
def process_iasgn(exp) # :nodoc:
_, lhs, rhs = exp
@@ -575,67 +584,89 @@
r = "#{c} ? (#{t}) : (#{f})"
r = nil if r =~ /return/ # HACK - need contextual awareness or something
else
r = "#{t} if #{c}"
end
- return r if r and (@indent+r).size < LINE_LENGTH and r !~ /\n/
+ return r if r and (@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
elsif f
unless expand then
r = "#{f} unless #{c}"
- return r if (@indent+r).size < LINE_LENGTH and r !~ /\n/
+ return r if (@indent + r).size < LINE_LENGTH and r !~ /\n/
end
"unless #{c} then\n#{indent(f)}\nend"
else
# empty if statement, just do it in case of side effects from condition
- "if #{c} then\n#{indent '# do nothing'}\nend"
+ "if #{c} then\n#{indent "# do nothing"}\nend"
end
end
+ def process_lambda exp # :nodoc:
+ "->"
+ end
+
def process_iter(exp) # :nodoc:
_, iter, args, body = exp
+ is_lambda = iter.sexp_type == :lambda
+
iter = process iter
body = process body if body
- args = case args
- when 0 then
+ args = case
+ when args == 0 then
""
+ when is_lambda then
+ " (#{process(args)[1..-2]})"
else
" |#{process(args)[1..-2]}|"
end
b, e = if iter == "END" then
- [ "{", "}" ]
+ %w[ { } ]
else
- [ "do", "end" ]
+ %w[ do end ]
end
- iter.sub!(/\(\)$/, '')
+ iter.sub!(/\(\)$/, "")
# REFACTOR: ugh
result = []
- result << "#{iter} {"
- result << args
- if body then
- result << " #{body.strip} "
+ if is_lambda then
+ result << iter
+ result << args
+ result << " {"
else
- result << ' '
+ result << "#{iter} {"
+ result << args
end
+ result << if body then
+ " #{body.strip} "
+ else
+ " "
+ end
result << "}"
result = result.join
return result if result !~ /\n/ and result.size < LINE_LENGTH
result = []
- result << "#{iter} #{b}"
- result << args
+
+ if is_lambda then
+ result << iter
+ result << args
+ result << " #{b}"
+ else
+ result << "#{iter} #{b}"
+ result << args
+ end
+
result << "\n"
if body then
result << indent(body.strip)
result << "\n"
end
@@ -675,47 +706,32 @@
_, name = exp
name.to_s
end
def process_masgn(exp) # :nodoc:
- _, (type, *), * = exp # ugly, but STRICT_SEXP=1+ requires this
+ # s(:masgn, s(:array, s(:lasgn, :var), ...), s(:to_ary, <val>, ...))
+ # s(:iter, <call>, s(:args, s(:masgn, :a, :b)), <body>)
+ parenthesize = true
- if type == :array then
- _, lhs, rhs = exp
+ result = exp.sexp_body.map { |sexp|
+ case sexp
+ when Sexp then
+ if sexp.sexp_type == :array then
+ parenthesize = context.grep(:masgn).size > 1
+ res = process sexp
- case exp.length
- when 3 then # a, b = c, d
- lhs = lhs.sexp_body.map { |e|
- process e
- }
-
- rhs = case rhs && rhs.sexp_type
- when :array then # a, b = [c, d]
- process(rhs)[1..-2]
- else # a, b = c
- process rhs
- end
- "%s = %s" % [lhs.join(", "), rhs]
- when 2 then # a, (b, c) = ...
- "(%s)" % [process(lhs)[1..-2]]
- else
- raise "unknown masgn length: %p" % [exp]
- end
- else # a { |(b, c)| ... }
- lhs = exp.sexp_body.map { |e|
- case e
- when Symbol then
- e
- when Sexp then
- process e
+ res[1..-2]
else
- raise "unknown masgn type: %p" % [e]
+ process sexp
end
- }
-
- "(%s)" % [lhs.join(", ")]
- end
+ when Symbol then
+ sexp
+ else
+ raise "unknown masgn: #{sexp.inspect}"
+ end
+ }
+ parenthesize ? "(#{result.join ", "})" : result.join(" = ")
end
def process_match exp # :nodoc:
_, rhs = exp
@@ -809,18 +825,18 @@
def process_op_asgn_and(exp) # :nodoc:
# a &&= 1
# [[:lvar, :a], [:lasgn, :a, [:lit, 1]]]
_, _lhs, rhs = exp
- process(rhs).sub(/\=/, '&&=')
+ process(rhs).sub(/\=/, "&&=")
end
def process_op_asgn_or(exp) # :nodoc:
# a ||= 1
# [[:lvar, :a], [:lasgn, :a, [:lit, 1]]]
_, _lhs, rhs = exp
- process(rhs).sub(/\=/, '||=')
+ process(rhs).sub(/\=/, "||=")
end
def process_or(exp) # :nodoc:
_, lhs, rhs = exp
@@ -854,14 +870,13 @@
"rescue#{args}\n#{indent body.join("\n")}"
end
def process_rescue exp # :nodoc:
_, *rest = exp
- exp = nil
body = process rest.shift unless rest.first.sexp_type == :resbody
- els = process rest.pop unless rest.last && rest.last.sexp_type == :resbody
+ els = process rest.pop unless rest.last && rest.last.sexp_type == :resbody
body ||= "# do nothing"
# TODO: I don't like this using method_missing, but I need to ensure tests
simple = rest.size == 1 && rest.first.size <= 3 &&
@@ -876,11 +891,11 @@
}
if els then
"#{indent body}\n#{resbodies.join("\n")}\nelse\n#{indent els}"
elsif simple then
- resbody = resbodies.first.sub(/\n\s*/, ' ')
+ resbody = resbodies.first.sub(/\n\s*/, " ")
"#{body} #{resbody}"
else
"#{indent body}\n#{resbodies.join("\n")}"
end
end
@@ -909,11 +924,11 @@
rhs = rest.pop
args = rest.pop # should be nil
raise "dunno what to do: #{args.inspect}" if args
- name = name.to_s.sub(/=$/, '')
+ name = name.to_s.sub(/=$/, "")
if rhs && rhs != s(:arglist) then
"#{receiver}&.#{name} = #{process rhs}"
else
raise "dunno what to do: #{rhs.inspect}"
@@ -1002,11 +1017,11 @@
"undef #{process name}"
end
def process_until(exp) # :nodoc:
- cond_loop(exp, 'until')
+ cond_loop(exp, "until")
end
def process_valias exp # :nodoc:
_, lhs, rhs = exp
@@ -1046,11 +1061,11 @@
args = args.map { |arg|
process arg
}
unless args.empty? then
- "yield(#{args.join(', ')})"
+ "yield(#{args.join(", ")})"
else
"yield"
end
end
@@ -1207,11 +1222,11 @@
##
# Wrap appropriate expressions in matching parens.
def parenthesize exp
- case self.context[1]
+ case context[1]
when nil, :defn, :defs, :class, :sclass, :if, :iter, :resbody, :when, :while then
exp
else
"(#{exp})"
end
@@ -1241,32 +1256,27 @@
# first item in sexp is a string literal
str = dthing_escape(type, str)
rest = rest.map { |pt|
- case pt
- when Sexp then # TODO: what the fuck? why??
- case pt.sexp_type
- when :str then
- dthing_escape(type, pt.last)
- when :evstr then
- '#{%s}' % [process(pt)]
- else
- raise "unknown type: #{pt.inspect}"
- end
+ case pt.sexp_type
+ when :str then
+ dthing_escape(type, pt.last)
+ when :evstr then
+ '#{%s}' % [process(pt)]
else
- raise "unhandled value in d-thing: #{pt.inspect}"
+ raise "unknown type: #{pt.inspect}"
end
}
[str, rest].join
end
##
# Utility method to generate ether a module or class.
- def util_module_or_class(exp, is_class=false)
+ def util_module_or_class exp, is_class = false
result = []
_, name, *body = exp
superk = body.shift if is_class
@@ -1283,14 +1293,14 @@
body = body.map { |sexp|
process(sexp).chomp
}
- unless body.empty? then
- body = indent(body.join("\n\n")) + "\n"
- else
- body = ""
- end
+ body = unless body.empty? then
+ indent(body.join("\n\n")) + "\n"
+ else
+ ""
+ end
result << body
result << "end"
result.join