# ref.rb
#
# For those times you need an extra level of indirection.
#
# Author: Dave Burt <dave at burt.id.au>
#
# Created: 6 May 2005
# Last modified: 7 May 2005
#

unless Object.const_defined? :Ref
  require 'delegate'

  Ref = DelegateClass(Object)
  class Ref
    # Dereference (get the referred-to value)
    alias deref __getobj__
    # Set value (change the reference to point at something else)
    def deref=(val) __setobj__(val) end
    # A way to tell if this is a ref
    def ref?
      true
    end
    # Delegate type query methods
    def class() __getobj__.class end
    def is_a?(mod) __getobj__.is_a?(mod) end
    def kind_of?(mod) __getobj__.kind_of?(mod) end
    def respond_to?(message)
      [:deref, :deref=, :ref=, :'[]', :'[]='].include?(message.to_sym) or
      __getobj__.respond_to?(message)
    end
  end
  class Object
    # Make a reference
    def ref
      Ref.new(self)
    end
    # A way to tell if this is a ref
    def ref?
      false
    end
  end
  class Module
    # Module case equality passes through references
    alias old_case_equals ===
    def ===(other)
      other.kind_of? self
    end
  end
end
