process_defn (Rewriter)

    # 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