class Ruby2Ruby

Generate ruby code from a sexp.

Constants

ASSIGN_NODES

Nodes that represent assignment and probably need () around them.

TODO: this should be replaced with full precedence support :/

BINARY

binary operation messages

HASH_VAL_NO_PAREN

Some sexp types are OK without parens when appearing as hash values. This list can include `:call`s because they're always printed with parens around their arguments. For example:

{ :foo => (bar("baz")) } # The outer parens are unnecessary
{ :foo => bar("baz") }   # This is the normal code style
LINE_LENGTH

cutoff for one-liners

Public Instance Methods

cond_loop(exp, name) click to toggle source

Generate a post-or-pre conditional loop.

# File lib/ruby2ruby.rb, line 1123
def cond_loop(exp, name)
  _, cond, body, head_controlled = exp

  cond = process cond
  body = process body

  body = indent(body).chomp if body

  code = []
  if head_controlled then
    code << "#{name} #{cond} do"
    code << body if body
    code << "end"
  else
    code << "begin"
    code << body if body
    code << "end #{name} #{cond}"
  end

  code.join("\n")
end
dthing_escape(type, lit) click to toggle source

Utility method to escape something interpolated.

# File lib/ruby2ruby.rb, line 1148
def dthing_escape type, lit
  # TODO: this needs more testing
  case type
  when :dregx then
    lit.gsub(/(\A|[^\])\//, '\1\/')
  when :dstr, :dsym then
    lit.dump[1..-2]
  when :dxstr then
    lit.gsub(/`/, '\`')
  else
    raise "unsupported type #{type.inspect}"
  end
end
indent(s) click to toggle source

Indent all lines of s to the current indent level.

# File lib/ruby2ruby.rb, line 1165
def indent s
  s.to_s.split(/\n/).map{|line| @indent + line}.join("\n")
end
parenthesize(exp) click to toggle source

Wrap appropriate expressions in matching parens.

# File lib/ruby2ruby.rb, line 1172
def parenthesize exp
  case self.context[1]
  when nil, :defn, :defs, :class, :sclass, :if, :iter, :resbody, :when, :while then
    exp
  else
    "(#{exp})"
  end
end
process_kwsplat(exp) click to toggle source
# File lib/ruby2ruby.rb, line 651
def process_kwsplat(exp)
  _, kw = exp
  "**#{process kw}"
end
re_opt(options) click to toggle source

Return the appropriate regexp flags for a given numeric code.

# File lib/ruby2ruby.rb, line 1184
def re_opt options
  bits = (0..8).map { |n| options[n] * 2**n }
  bits.delete 0
  bits.map { |n| Regexp::CODES[n] }.join
end
splat(sym) click to toggle source

Return a splatted symbol for sym.

# File lib/ruby2ruby.rb, line 1193
def splat(sym)
  :"*#{sym}"
end
util_dthing(type, exp) click to toggle source

Utility method to generate something interpolated.

# File lib/ruby2ruby.rb, line 1200
def util_dthing(type, exp)
  _, str, *rest = exp

  # 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
    else
      raise "unhandled value in d-thing: #{pt.inspect}"
    end
  }

  [str, rest].join
end
util_module_or_class(exp, is_class=false) click to toggle source

Utility method to generate ether a module or class.

# File lib/ruby2ruby.rb, line 1228
def util_module_or_class(exp, is_class=false)
  result = []

  _, name, *body = exp
  superk = body.shift if is_class

  name = process name if Sexp === name

  result << name

  if superk then
    superk = process superk
    result << " < #{superk}" if superk
  end

  result << "\n"

  body = body.map { |sexp|
    process(sexp).chomp
  }

  unless body.empty? then
    body = indent(body.join("\n\n")) + "\n"
  else
    body = ""
  end

  result << body
  result << "end"

  result.join
end