class Original
  CONST = :original
  @@class = :original

  def create_proc
    return Proc.new{
      p self
      p CONST
      p @@class

      def new_method_by_proc_at_method
      end
      # 縺薙ｌ縺ｯ讒区枚繧ｨ繝ｩ繝ｼ縺ｫ縺ｪ繧九�縺ｧ繧ｳ繝｡繝ｳ繝亥喧
      # NEW_CONST_BY_PROC_AT_METHOD = :proc_at_method
      @@new_class_by_proc_at_method = :proc_at_method
    }
  end

  CONST = :modified
  @@class = :modified
end

class Other
  CONST = :other
  @@class = :other

  class << self
    CONST = :other_class
    @@class = :other_class

    def call(code, method_name, const_name, classvar_name)
      case code
      when Proc
        self.module_eval(&code)
      else
        self.module_eval(code)
      end
  
      case
      when Original.method_defined?(method_name)
        p :original
      when Other.method_defined?(method_name)
        p :other
      when self.respond_to?(method_name)
        p :singleton
      else
        raise
      end
  
      case
      when Original.const_defined?(const_name)
        p :original
      when Other.const_defined?(const_name)
        p :other
      when (class << self; self end).const_defined?(const_name)
        p :singleton
      else
        p :not_defined
      end
  
      case
      when (Original.__send__(:class_variable_get, classvar_name) rescue false)
        p :original
      when (Other.__send__(:class_variable_get, classvar_name) rescue false)
        p :other
      when ((class << self; self end).__send__(:class_variable_get, classvar_name) rescue false)
        p :singleton
      else
        raise
      end
    end
  end
end

orig = Original.new
proc_by_method = orig.create_proc

proc_by_class = class Original
  Proc.new {
    p self
    p CONST
    p @@class

    def new_method_by_proc_at_class
    end
    NEW_CONST_BY_PROC_AT_CLASS = :proc_at_class
    @@new_class_by_proc_at_class = :proc_at_class
  }
end

program = <<'EOS'
  p self
  p CONST
  p @@class

  def new_method_by_str
  end
  NEW_CONST_BY_STR = :str
  @@new_class_by_str = :str
EOS






Other.call(program, :new_method_by_str, :NEW_CONST_BY_STR, :@@new_class_by_str)
puts
Other.call(proc_by_method, :new_method_by_proc_at_method, :NEW_CONST_BY_PROC_AT_METHOD, :@@new_class_by_proc_at_method)
puts
Other.call(proc_by_class, :new_method_by_proc_at_class, :NEW_CONST_BY_PROC_AT_CLASS, :@@new_class_by_proc_at_class)

