File: //usr/local/rvm/rubies/default/lib/ruby/gems/3.0.0/gems/typeprof-0.12.0/lib/typeprof/utils.rb
module TypeProf
module Utils
def self.array_update(ary, idx, elem)
idx %= ary.size
ary[0...idx] + [elem] + ary[idx+1..-1]
end
module StructuralEquality
def self.included(klass)
klass.instance_eval do
def new(*args)
(@table ||= {})[[self] + args] ||= super
end
end
end
end
class Set
include StructuralEquality
attr_reader :tbl
def self.[](*values)
tbl = {}
values.each do |v|
tbl[v] = true
end
new(tbl)
end
def initialize(tbl)
@tbl = tbl
@tbl.freeze
end
def each(&blk)
@tbl.each_key(&blk)
end
include Enumerable
def sum(other)
if @tbl.size == 0
other
elsif other.tbl.size == 0
self
else
Set.new(@tbl.merge(other.tbl))
end
end
def add(new_val)
tbl = @tbl.dup
tbl[new_val] = true
Set.new(tbl)
end
def size
@tbl.size
end
def map(&blk)
tbl = {}
each do |elem|
v = yield(elem)
tbl[v] = true
end
Set.new(tbl)
end
def inspect
s = []
each {|v| s << v.inspect }
"{#{ s.join(", ") }}"
end
def include?(elem)
@tbl[elem]
end
def intersection(other)
tbl = {}
h = 0
each do |elem|
if other.include?(elem)
tbl << elem
h ^= elem.hash
end
end
Set.new(tbl, h)
end
end
class MutableSet
def initialize(*values)
@hash = {}
values.each {|v| @hash[v] = v }
end
def each(&blk)
@hash.each_key(&blk)
end
include Enumerable
def <<(v)
@hash[v] = true
end
def [](v)
@hash[v]
end
def delete(v)
@hash.delete(v)
end
def inspect
s = []
each {|v| s << v.inspect }
"{#{ s.join(", ") }}"
end
def size
@hash.size
end
def to_set
Set[*@hash.keys]
end
end
class HashWrapper
include StructuralEquality
def initialize(hash)
@internal_hash = hash.freeze
end
attr_reader :internal_hash
end
class WorkList
def initialize
@heap = []
@set = MutableSet.new
end
def insert(key, val)
i = @heap.size
@heap << [key, val]
while i > 0 && (@heap[i][0] <=> @heap[i / 2][0]) < 0
@heap[i], @heap[i / 2] = @heap[i / 2], @heap[i]
i /= 2
end
@set << val
end
def member?(val)
@set[val]
end
def deletemin
return nil if @heap.empty?
val = @heap[0][1]
@set.delete(val)
if @heap.size == 1
@heap.pop
return val
end
@heap[0] = @heap.pop
i = 0
while (j = i * 2 + 1) < @heap.size
j += 1 if j + 1 < @heap.size && (@heap[j][0] <=> @heap[j + 1][0]) >= 0
break if (@heap[i][0] <=> @heap[j][0]) < 0
@heap[i], @heap[j] = @heap[j], @heap[i]
i = j
end
return val
end
def size
@heap.size
end
def empty?
@heap.empty?
end
def inspect
"#<#{ self.class }:#{ @heap.map {|_key, val| val }.inspect }>"
end
end
end
end