redid the type hashing

account for the class the type is for
by adding it to the hash code, so even the ivars are identical the
types are not
This commit is contained in:
Torsten Ruger 2016-12-31 14:51:06 +02:00
parent 0fa7f54bcc
commit b9073d0c88
5 changed files with 86 additions and 51 deletions

View File

@ -25,7 +25,7 @@ module Parfait
def self.type_for( arguments )
my_class = Parfait.object_space.classes[:NamedList]
Parfait::Type.for_hash( my_class , arguments.merge(type: my_class.instance_type))
Type.for_hash( my_class , {type: my_class.instance_type}.merge(arguments))
end
end
end

View File

@ -42,9 +42,7 @@ module Parfait
message = @first_message
end
@classes.each do |name , cl|
raise "upps #{cl.instance_type.hash}" unless cl.instance_type.hash.is_a?(Fixnum)
@types[cl.instance_type.hash] = cl.instance_type
add_type(cl.instance_type)
end
end

View File

@ -45,30 +45,6 @@ module Parfait
Parfait.object_space.add_type(new_type)
end
def self.hash_code_for_hash( dict )
index = 1
hash_code = str_hash(dict[:type])
dict.each do |name , type|
next if name == :type
item_hash = str_hash(name) + str_hash(type)
hash_code += item_hash + (item_hash / 256 ) * index
index += 1
end
hash_code
end
def self.str_hash(str)
if RUBY_ENGINE == 'opal'
hash = 5381
str.to_s.each_char do |c|
hash = ((hash << 5) + hash) + c.to_i; # hash * 33 + c without getting bignums
end
hash % (2 ** 51)
else
str.hash
end
end
def initialize( object_class , hash )
super()
set_object_class( object_class)
@ -192,16 +168,43 @@ module Parfait
end
alias :name :sof_reference_name
def each
index = 1
while( index <= get_length() )
yield( name_at(index) , type_at(index) )
index += 1
end
end
def to_hash
hash = Dictionary.new
@names.each_with_index do |name, index |
hash[name] = @types[index]
hash = {}
each do |name , type|
hash[name] = type
end
hash
end
def hash
Type.hash_code_for_hash( to_hash )
index = 1
hash_code = Type.str_hash( @object_class.name )
each do |name , type|
item_hash = Type.str_hash(name) + Type.str_hash(type)
hash_code += item_hash + (item_hash / 256 ) * index
index += 1
end
hash_code
end
def self.str_hash(str)
if RUBY_ENGINE == 'opal'
hash = 5381
str.to_s.each_char do |c|
hash = ((hash << 5) + hash) + c.to_i; # hash * 33 + c without getting bignums
end
hash % (2 ** 51)
else
str.hash
end
end
private

View File

@ -47,6 +47,20 @@ class TestSpace < MiniTest::Test
end
end
def test_classes_types_in_space_types
@space.classes do |name , clazz|
assert_equal clazz.instance_type , @space.get_type_for(clazz.instance_type.hash) , clazz.name
end
end
def test_word_class
word = @space.classes[:Word]
assert word.instance_type
t_word = @space.get_type_for(word.instance_type.hash)
assert_equal word.instance_type.hash , t_word.hash
assert_equal word.instance_type.object_id , t_word.object_id
end
def test_classes_type
classes.each do |name|
assert_equal Parfait::Type , @space.classes[name].get_type.class
@ -97,4 +111,38 @@ class TestSpace < MiniTest::Test
assert @space.get_class_by_name(:NewerClass)
end
def test_class_types_are_stored
@space.classes.each do |name,clazz|
assert @space.get_type_for(clazz.instance_type.hash)
end
end
def test_class_types_are_identical
@space.classes.each do |name , clazz|
cl_type = @space.get_type_for(clazz.instance_type.hash)
assert_equal cl_type.object_id , clazz.instance_type.object_id
end
end
def test_remove_methods
@space.each_type do | type |
type.method_names.each do |method|
type.remove_method(method)
end
end
assert_equal 0 , @space.collect_methods.length
end
def test_no_methods_in_types
test_remove_methods
@space.each_type do |type|
assert_equal 0 , type.methods.get_length , "name #{type.name}"
end
end
def ttest_no_methods_in_classes
test_remove_methods
@space.classes.each do |name , cl|
assert_equal 0 , cl.instance_type.methods.get_length , "name #{cl.name}"
end
end
end

View File

@ -26,25 +26,10 @@ class TypeHash < MiniTest::Test
end
def test_to_hash
assert_equal "Word_Type" , @first.name
assert_equal :Word , @first.object_class.name
hash = @first.to_hash
assert_equal :Type , @first.types.first
assert_equal hash[:type] , :Type
assert_equal hash[:char_length] , :Integer
assert_equal 2 , @first.instance_length
assert_equal 2 , hash.length
end
def test_hashcode_with_hash
assert_equal @first.hash , Parfait::Type.hash_code_for_hash( @first.to_hash)
end
def test_second_hash_different
hash2 = @first.to_hash
hash2[:random] = :Type
assert @first.hash != Parfait::Type.hash_code_for_hash( hash2 )
end
def test_add_is_different
type = @first.add_instance_variable :random , :Integer
assert type != @first , "new: #{type.inspect} , old: #{@first.inspect}"
@ -52,8 +37,9 @@ class TypeHash < MiniTest::Test
end
def test_hash_for_no_ivars
h1 = Parfait::Type.hash_code_for_hash( type: :NewInt)
h2 = Parfait::Type.hash_code_for_hash( type: :NewObj)
assert h1 != h2 , "Hashes should differ"
list = @space.get_class_by_name(:NamedList )
t1 = Parfait::Type.for_hash( list , type: :NewInt)
t2 = Parfait::Type.for_hash( list , type: :NewObj)
assert t1.hash != t2.hash , "Hashes should differ"
end
end