# File lib/rewriter.rb, line 114
  def process_defn(exp)
    name = exp.shift
    args = s(:args)
    body = process exp.shift

    case body.first
    when :scope, :fbody then
      body = body[1] if body.first == :fbody
      args = body.last[1]
      assert_type args, :args
      assert_type body, :scope
      assert_type body[1], :block
      body.last.delete_at 1
    when :bmethod then
      # BEFORE: [:defn, :bmethod_added, [:bmethod, [:dasgn_curr, :x], ...]]
      # AFTER:  [:defn, :bmethod_added, [:args, :x], [:scope, [:block, ...]]]
      body.shift # :bmethod
      # [:dasgn_curr, :x],
      # [:call, [:dvar, :x], :+, [:arglist, [:lit, 1]]]]]
      dasgn = body.shift
      assert_type dasgn, :dasgn_curr
      dasgn.shift # type
      args.push(*dasgn)
      body.find_and_replace_all(:dvar, :lvar)
      if body.first.first == :block then
        body = s(:scope, body.shift)
      else
        body = s(:scope, s(:block, body.shift)) # single statement
      end
    when :dmethod
      # BEFORE: [:defn, :dmethod_added, [:dmethod, :bmethod_maker, ...]]
      # AFTER:  [:defn, :dmethod_added, ...]
      body = body[2][1][2] # UGH! FIX
      args = body[1]
      body.delete_at 1
      body = s(:scope, body)
    when :ivar then
      body = s(:scope, s(:block, s(:return, body)))
    when :attrset then
      argname = body.last
      args << :arg
      body = s(:scope, s(:block, s(:return, s(:iasgn, argname, s(:lvar, :arg)))))
    else
      raise "Unknown :defn format: #{name.inspect} #{args.inspect} #{body.inspect}"
    end

    if Array === args.last and args.last.first == :block then
      cond = args.pop
      cond.shift # take off :block
      new_code =  cond.map do |t, var, val|
        s(:if, s(:call, s(:lvar, var), :nil?), s(:lasgn, var, val), nil)
      end
      body[1].insert 1, *new_code
    end


    return s(:defn, name, args, body)
  end