Permalink
Browse files

Fixes for HAMT Hash implementation.

  • Loading branch information...
1 parent 21578f4 commit ad21fc5a9b09383a452231eee30e4a6c37bcaee4 @brixen brixen committed with subwindow Oct 11, 2011
View
@@ -578,6 +578,18 @@ def fetch(key, default=undefined)
raise IndexError, 'key not found'
end
+ # Searches for an item matching +key+. Returns the item
+ # if found. Otherwise returns +nil+. Called from the C-API.
+ def find_item(key)
+ unless empty?
+ if item = @table.lookup(key, key.hash)
+ return item
+ end
+ end
+
+ nil
+ end
+
def flatten(level=1)
to_a.flatten(level)
end
@@ -836,5 +848,8 @@ def values_at(*args)
end
end
end
+
+ # Used internally in Rubinius to get around subclasses redefining #[]=
+ alias_method :__store__, :[]=
end
end
@@ -1,20 +1,20 @@
require File.expand_path('../../../../spec_helper', __FILE__)
with_feature :hash_hamt do
- describe "Hash::Entry#delete" do
+ describe "Hash::Item#delete" do
before :each do
@state = Hash::State.new
end
it "decrements the size of @state" do
- entry = Hash::Entry.new :a, 1, @state
+ entry = Hash::Item.new :a, 1, @state
@state.size.should == 1
entry.delete(:a, :a.hash)
@state.size.should == 0
end
it "removes itself from a one element insertion chain and sets head and tail of @state to nil" do
- entry = Hash::Entry.new :a, 1, @state
+ entry = Hash::Item.new :a, 1, @state
@state.head.should equal(entry)
@state.tail.should equal(entry)
entry.delete(:a, :a.hash)
@@ -23,8 +23,8 @@
end
it "removes itself from the head of the insertion chain" do
- e1 = Hash::Entry.new :a, 1, @state
- e2 = Hash::Entry.new :b, 2, @state
+ e1 = Hash::Item.new :a, 1, @state
+ e2 = Hash::Item.new :b, 2, @state
@state.head.should equal(e1)
@state.tail.should equal(e2)
e1.delete(:a, :a.hash)
@@ -33,8 +33,8 @@
end
it "removes itself from the tail of the insertion chain" do
- e1 = Hash::Entry.new :a, 1, @state
- e2 = Hash::Entry.new :b, 2, @state
+ e1 = Hash::Item.new :a, 1, @state
+ e2 = Hash::Item.new :b, 2, @state
@state.head.should equal(e1)
@state.tail.should equal(e2)
e2.delete(:b, :b.hash)
@@ -43,9 +43,9 @@
end
it "removes itself from the middle of the insertion chain" do
- e1 = Hash::Entry.new :a, 1, @state
- e2 = Hash::Entry.new :b, 2, @state
- e3 = Hash::Entry.new :c, 3, @state
+ e1 = Hash::Item.new :a, 1, @state
+ e2 = Hash::Item.new :b, 2, @state
+ e3 = Hash::Item.new :c, 3, @state
@state.head.should equal(e1)
@state.tail.should equal(e3)
e2.delete(:b, :b.hash)
@@ -54,13 +54,13 @@
end
it "returns itself if the keys match" do
- entry = Hash::Entry.new 1, 2, @state
+ entry = Hash::Item.new 1, 2, @state
@state.should_receive(:match?).with(1, 1).and_return(true)
entry.delete(1, 0).should equal(entry)
end
it "retuns nil if the keys do not match" do
- entry = Hash::Entry.new 1, 2, @state
+ entry = Hash::Item.new 1, 2, @state
@state.should_receive(:match?).with(1, 1).and_return(false)
entry.delete(1, 0).should be_nil
end
@@ -1,10 +1,10 @@
require File.expand_path('../../../../spec_helper', __FILE__)
with_feature :hash_hamt do
- describe "Hash::Entry#insert" do
+ describe "Hash::Item#insert" do
before :each do
@state = Hash::State.new
- @entry = Hash::Entry.new 1, 2, @state
+ @entry = Hash::Item.new 1, 2, @state
end
it "updates the value if the keys match" do
@@ -1,10 +1,10 @@
require File.expand_path('../../../../spec_helper', __FILE__)
with_feature :hash_hamt do
- describe "Hash::Entry#lookup" do
+ describe "Hash::Item#lookup" do
before :each do
@state = Hash::State.new
- @entry = Hash::Entry.new 1, 2, @state
+ @entry = Hash::Item.new 1, 2, @state
end
it "returns itself if the keys match" do
@@ -1,26 +1,26 @@
require File.expand_path('../../../../spec_helper', __FILE__)
with_feature :hash_hamt do
- describe "Hash::Entry.new" do
+ describe "Hash::Item.new" do
before :each do
@state = Hash::State.new
end
it "increments the size of @state" do
@state.size.should == 0
- entry = Hash::Entry.new :a, 1, @state
+ entry = Hash::Item.new :a, 1, @state
@state.size.should == 1
end
it "inserts itself in an empty chain" do
- entry = Hash::Entry.new :a, 1, @state
+ entry = Hash::Item.new :a, 1, @state
@state.head.should equal(entry)
@state.tail.should equal(entry)
end
it "inserts itself at the tail of a non-empty chain" do
- e1 = Hash::Entry.new :a, 1, @state
- e2 = Hash::Entry.new :b, 2, @state
+ e1 = Hash::Item.new :a, 1, @state
+ e2 = Hash::Item.new :b, 2, @state
@state.head.should equal(e1)
@state.tail.should equal(e2)
end
@@ -5,7 +5,7 @@
before :each do
@state = Hash::State.new
@list = Hash::List.new @state, :a.hash
- @entry = Hash::Entry.new :a, 1, @state
+ @entry = Hash::Item.new :a, 1, @state
@list.add @entry, :b, :b.hash, 2
end
@@ -5,7 +5,7 @@
before :each do
@state = Hash::State.new
@list = Hash::List.new @state, :a.hash
- @entry = Hash::Entry.new :a, 1, @state
+ @entry = Hash::Item.new :a, 1, @state
@list.add @entry, :b, :b.hash, 2
end
@@ -19,7 +19,7 @@
end
it "inserts a new entry if the entry is not found" do
- @list.insert(:c, :c.hash, 3).should be_an_instance_of(Hash::Entry)
+ @list.insert(:c, :c.hash, 3).should be_an_instance_of(Hash::Item)
@list.entries.size.should == 3
end
end
@@ -5,7 +5,7 @@
before :each do
@state = Hash::State.new
@list = Hash::List.new @state, :a.hash
- @entry = Hash::Entry.new :a, 1, @state
+ @entry = Hash::Item.new :a, 1, @state
@list.add @entry, :b, :b.hash, 2
end
@@ -6,21 +6,21 @@
@state = Hash::State.new
@table = Hash::Table.new @state
@table.insert :a, :a.hash, 1
- @entry = @table.entries[@table.entry_index(:a.hash)]
+ @entry = @table.entries[@table.item_index(:a.hash)]
end
- it "returns nil if the entry is not found" do
+ it "returns nil if the item is not found" do
@table.delete(:b, :b.hash).should be_nil
end
- it "returns the entry if it is found" do
+ it "returns the item if it is found" do
@table.delete(:a, :a.hash).should equal(@entry)
end
- it "sets the index to nil if the Entry is deleted" do
- @table.entries[@table.entry_index(:a.hash)].should equal(@entry)
+ it "sets the index to nil if the Item is deleted" do
+ @table.entries[@table.item_index(:a.hash)].should equal(@entry)
@table.delete(:a, :a.hash)
- @table.entries[@table.entry_index(:a.hash)].should be_nil
+ @table.entries[@table.item_index(:a.hash)].should be_nil
end
end
end
@@ -7,12 +7,12 @@
@table = Hash::Table.new @state
end
- it "inserts an Entry if there is no entry at the index" do
+ it "inserts an Item if there is no entry at the index" do
@table.insert(:a, 0, 1)
- @table.entries[0].should be_an_instance_of(Hash::Entry)
+ @table.entries[0].should be_an_instance_of(Hash::Item)
end
- it "inserts a Trie if there is an Entry at the index" do
+ it "inserts a Trie if there is an Item at the index" do
k1 = mock("Hash key1")
k1_hash = 0b01000000
k1.should_receive(:hash).and_return(k1_hash)
@@ -1,7 +1,7 @@
require File.expand_path('../../../../spec_helper', __FILE__)
with_feature :hash_hamt do
- describe "Hash::Table#entry_index" do
+ describe "Hash::Table#item_index" do
it "returns the least significant six bits of the passed value" do
state = Hash::State.new
table = Hash::Table.new state
@@ -14,7 +14,7 @@
[ table, 80, 16],
[ table, 96, 32],
[ table, 127, 63]
- ].should be_computed_by(:entry_index)
+ ].should be_computed_by(:item_index)
end
end
end
@@ -14,7 +14,7 @@
it "returns the entry if it is found" do
entry = @table.lookup(:a, :a.hash)
- entry.should be_an_instance_of(Hash::Entry)
+ entry.should be_an_instance_of(Hash::Item)
entry.value.should == 1
end
end
@@ -15,7 +15,7 @@
k2 = mock("Hash key2")
- entry = Hash::Entry.new k1, 1, @state
+ entry = Hash::Item.new k1, 1, @state
@trie.add entry, k2, key_hash, 2
@trie.entries[0].should be_an_instance_of(Hash::List)
end
@@ -28,23 +28,23 @@
k2 = mock("Hash key2")
- entry = Hash::Entry.new k1, 1, @state
+ entry = Hash::Item.new k1, 1, @state
@trie.add entry, k2, 0b10_000001_000000, 2
@trie.entries[0].should be_an_instance_of(Hash::Trie)
end
- it "inserts two Entry instances if the key hash values do not collide" do
+ it "inserts two Item instances if the key hash values do not collide" do
k1_hash = 0b1_000001_001000
k1 = mock("Hash key1")
k1.should_receive(:hash).and_return(k1_hash)
k2 = mock("Hash key2")
- entry = Hash::Entry.new k1, 1, @state
+ entry = Hash::Item.new k1, 1, @state
@trie.add entry, k2, 0b10_000010_000000, 2
- @trie.entries[0].should be_an_instance_of(Hash::Entry)
- @trie.entries[1].should be_an_instance_of(Hash::Entry)
+ @trie.entries[0].should be_an_instance_of(Hash::Item)
+ @trie.entries[1].should be_an_instance_of(Hash::Item)
end
end
end
@@ -5,7 +5,7 @@
before :each do
@state = Hash::State.new
@trie = Hash::Trie.new @state, 0
- @entry = Hash::Entry.new :a, 1, @state
+ @entry = Hash::Item.new :a, 1, @state
@trie.add @entry, :b, :b.hash, 2
end
@@ -8,11 +8,11 @@
@trie.entries = Rubinius::Tuple[nil]
end
- it "inserts an Entry if there is no entry at the index" do
+ it "inserts an Item if there is no entry at the index" do
@trie.insert(:a, 0, 1)
entry = @trie.entries[0]
- entry.should be_an_instance_of(Hash::Entry)
+ entry.should be_an_instance_of(Hash::Item)
entry.key.should equal(:a)
end
@@ -1,14 +1,14 @@
require File.expand_path('../../../../spec_helper', __FILE__)
with_feature :hash_hamt do
- describe "Hash::Trie#entry_index" do
+ describe "Hash::Trie#item_index" do
before :each do
@state = Hash::State.new
@trie = Hash::Trie.new @state, 1
end
it "returns nil if there is no entry set for the key hash value" do
- @trie.entry_index(0).should be_nil
+ @trie.item_index(0).should be_nil
end
platform_is :wordsize => 32 do
@@ -23,7 +23,7 @@
[@trie, 0b0010000100101001, 2],
[@trie, 0b0000100100101001, 1],
[@trie, 0b0000000100101001, 0],
- ].should be_computed_by(:entry_index)
+ ].should be_computed_by(:item_index)
end
end
@@ -39,7 +39,7 @@
[@trie, 0b000100000100101001, 2],
[@trie, 0b000001000100101001, 1],
[@trie, 0b000000000100101001, 0],
- ].should be_computed_by(:entry_index)
+ ].should be_computed_by(:item_index)
end
end
end
@@ -12,7 +12,7 @@
end
it "returns the entry if it is found" do
- entry = Hash::Entry.new :a, 1, @state
+ entry = Hash::Item.new :a, 1, @state
@trie.add entry, :b, :b.hash, 2
@trie.lookup(:a, :a.hash).should equal(entry)
end

0 comments on commit ad21fc5

Please sign in to comment.