From b9073d0c885132c2b61494eb1b13a2987ee1a75d Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sat, 31 Dec 2016 14:51:06 +0200 Subject: [PATCH] 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 --- lib/typed/parfait/named_list.rb | 2 +- lib/typed/parfait/space.rb | 4 +-- lib/typed/parfait/type.rb | 59 +++++++++++++++++--------------- test/typed/parfait/test_space.rb | 48 ++++++++++++++++++++++++++ test/typed/type/test_hash.rb | 24 +++---------- 5 files changed, 86 insertions(+), 51 deletions(-) diff --git a/lib/typed/parfait/named_list.rb b/lib/typed/parfait/named_list.rb index 431b331e..1a136377 100644 --- a/lib/typed/parfait/named_list.rb +++ b/lib/typed/parfait/named_list.rb @@ -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 diff --git a/lib/typed/parfait/space.rb b/lib/typed/parfait/space.rb index 4f5c7c4b..4e53b8c7 100644 --- a/lib/typed/parfait/space.rb +++ b/lib/typed/parfait/space.rb @@ -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 diff --git a/lib/typed/parfait/type.rb b/lib/typed/parfait/type.rb index 2ba9c334..01e004e8 100644 --- a/lib/typed/parfait/type.rb +++ b/lib/typed/parfait/type.rb @@ -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 diff --git a/test/typed/parfait/test_space.rb b/test/typed/parfait/test_space.rb index 57289bfc..e63613f2 100644 --- a/test/typed/parfait/test_space.rb +++ b/test/typed/parfait/test_space.rb @@ -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 diff --git a/test/typed/type/test_hash.rb b/test/typed/type/test_hash.rb index 610f1aba..941ef572 100644 --- a/test/typed/type/test_hash.rb +++ b/test/typed/type/test_hash.rb @@ -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