##
# Used to implement Module#autoload.
class Autoload
attr_reader :name
attr_reader :scope
attr_reader :path
attr_reader :original_path
def initialize(name, scope, path)
@name = name
@scope = scope
@original_path = path
@path, = __split_path__(path)
Autoload.add(self)
end
def call
require(path)
scope.const_get(name)
end
def discard
scope.__send__(:remove_const, name)
end
class << self
def autoloads
@autoloads ||= []
end
def add(al)
autoloads << al
end
##
# ruthlessly taken from Array#delete
# modified to return after the first one
# This code is specific to Autoload, see line 52
# for the coupling. It calls #path on the Autoload object
def delete_first(array, obj)
i = array.start
tot = array.start + array.total
already_placed = false # initialize our check
# Leaves the tuple to the original size still
while i < tot
if array.tuple.at(i) == obj
j = i
i += 1
while i < tot
if (array.tuple.at(i).path != obj) || already_placed
array.tuple.put(j, array.tuple.at(i))
j += 1
else
already_placed = true # move all the others if we placed one
end
i += 1
end
array.total = j - array.start
return obj
end
i += 1
end
yield if block_given?
end
def remove(path)
al = delete_first(autoloads, path)
al.discard if al
end
end
end
__END__
##
# Used to implement Module#autoload.
class Autoload
attr_reader :name
attr_reader :scope
attr_reader :path
attr_reader :original_path
def initialize(name, scope, path)
@name = name
@scope = scope
@original_path = path
@path, = __split_path__(path)
Autoload.add(self)
end
def call
require(path)
scope.const_get(name)
end
def discard
scope.__send__(:remove_const, name)
end
class << self
def autoloads
@autoloads ||= {}
end
def add(al)
autoloads[al.path] = al
end
def remove(path)
al = autoloads.delete(path)
al.discard if al
end
end
end