Dave Thomas recently suggested a very promising mechanism for handling
platform dependencies in Ruby's libraries (see [ruby-talk: 36496]). Some of
his suggestions will require big chunks of C (eg the OS-specific
functionality: Win32 events, ACLs etc), but other bits can be done in Ruby
(or at least prototyped like that). See below for the beginnings of such
prototype. I don't have time to take this any further, but I'd be more than
happy if someone else wanted to pick it up. As far as I can see, the work
that can be done without C coding is:

- extend to other classes (Dir, File::Stat, Process, Kernel etc)
- handle special cases like File#open (some optional args are Unix specific)
- sort out the infrastructure: file organisation; write Dave's proposed
Kernel#sysdep method etc
- come up with suggestions for a better way of doing this!

Proviso: I'm not very Unix-aware, so I may have been over-zealous in
assigning 'Unix-only' status to some the methods below. Conversely, I may
have missed some too..

-- George


#################
# Infrastructure
#################
class Object
  # Returns the singleton class for self
  # FIXME Anyone know how to write this without using globals or similar?
  def singleton
    class << self
      $SINGLETON_CLASS = self
    end
    return $SINGLETON_CLASS
  end
end

class Module
  # Removes the methods named in NAMES from the class / module SRC and
recreates them on self
  def steal_methods(src, names)
    names.each do |name|
      m = src.instance_method(name)
      src.class_eval {remove_method(name)}
      self.class_eval {define_method(name, m)}
    end
  end

  # Removes the singleton method(s) called NAMES from the object SRC
  # and recreates them on self
  def steal_singleton_methods(src, names)
    steal_methods(src.singleton, names)
  end
end

#################
# Test on arrays
#################
class Array
  module ArrayTest
  end
  module ArrayTestSingleton
  end
end

Array::ArrayTest.steal_methods                    Array, [ :length ]
Array::ArrayTestSingleton.steal_singleton_methods Array, [ :[]     ]

# you'll get an error if you remove either of the include/extend lines below
..
class Array
  include ArrayTest
  extend ArrayTestSingleton
end

# .. but if you leave them in, the following lines work as expected
a = Array[1,2,3]
print "Test using arrays: length is #{a.length}, contents is #{a.inspect}\n"


##############################################
# This is what the real thing might look like
##############################################
class File
  module Posix
  end
  module PosixSingleton
  end
end

File::Posix.steal_methods(
  File,
  [ # ? :atime,     # Is access time recorded on all other OSes?
    :chmod,         # Permissions - clearly Unix only
    :chown,         # Ownership - clearly Unix only
    # ? :ctime,     # Is creation time recorded on all other OSes?
    :flock,         # Unix specific?
    :lstat,         # Symbolic links - clearly Unix only
    # ? truncate,   # Programming Ruby says platform-specific, but surely
doesn't have to be?
  ] )

File::PosixSingleton.steal_singleton_methods(
  File,
  [ # ? :atime,	  # as above
    :chmod,         # as above
    :chown,         # as above
    # ? :ctime,     # as above
    :link,          # Hard links - clearly Unix only
    :lstat,         # Symbolic links - clearly Unix only
    :readlink,      # Symbolic links - clearly Unix only
    # ? :stat,      # Probably OK, but File::Stat object is Unix-specific
    :symlink,       # Symbolic links - clearly Unix only
    # ? truncate,   # as above
    :umask,         # Permissions - clearly Unix only
    # ? utime,      # Is access time recorded on all other OSes?
  ] )