##
# 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