module Origami::ObjectCache

def cache_compound(object)

def cache_compound(object)
    @strings_cache.merge(object.strings_cache)
    @names_cache.merge(object.names_cache)
    @xref_cache.update(object.xref_cache) do |_, cache1, cache2|
        cache1.concat(cache2)
    end
    object.strings_cache.clear
    object.names_cache.clear
    object.xref_cache.clear
end

def cache_name(name)

def cache_name(name)
    @names_cache.add(name)
end

def cache_object(object)

def cache_object(object)
    case object
    when String then cache_string(object)
    when Name then cache_name(object)
    when Reference then cache_reference(object)
    when CompoundObject then cache_compound(object)
    end
    object
end

def cache_reference(ref)

def cache_reference(ref)
    @xref_cache[ref] ||= []
    @xref_cache[ref].push(self)
end

def cache_string(str)

def cache_string(str)
    @strings_cache.add(str)
end

def init_caches

def init_caches
    @strings_cache = Set.new
    @names_cache = Set.new
    @xref_cache = {}
end

def initialize(*args)

def initialize(*args)
    super(*args)
    init_caches
end

def rebuild_caches

def rebuild_caches
    self.each do |*items|
        items.each do |object|
            object.rebuild_caches if object.is_a?(CompoundObject)
            cache_object(object)
        end
    end
end