Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reworked HashDictionary #494

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
73 changes: 34 additions & 39 deletions source/collections/HashDictionary.ooc
Expand Up @@ -3,15 +3,30 @@ import structs/[HashBag, HashMap, ArrayList]
HashDictionary: class {
_myHashBag: HashBag
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my isn't used anywhere else afaik. Should probably just be _hashBag, right?

_capacity: Int
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like this is actually used for anything at all. Fix now, or fix later? Your call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now.

count ::= this _myHashBag size()
empty ::= this _myHashBag empty?()

init: func { init ~withCapacity(10) }
init: func ~withCapacity (=_capacity) {
_myHashBag = HashBag new(this _capacity)
this _myHashBag = HashBag new(this _capacity)
}
init: func ~copy (other: This) {
hashMapClone := other _myHashBag myMap clone()
_myHashBag = HashBag new(other _capacity)
this _myHashBag = HashBag new(other _capacity)
this _myHashBag myMap = hashMapClone
}
free: override func {
free(this _myHashBag myMap keys data)
free(this _myHashBag myMap keys)
for (i in 0 .. (this _myHashBag myMap capacity)) {
next := (this _myHashBag myMap buckets[i])
next dispose()
}
free(this _myHashBag myMap buckets data)
free(this _myHashBag myMap)
free(this _myHashBag)
super()
}
clone: func -> This {
result := This new()
hashMapClone := this _myHashBag myMap clone()
Expand All @@ -20,72 +35,52 @@ HashDictionary: class {
}
merge: func (other: This) -> This {
result := this clone()
result _myHashBag myMap merge!(other _myHashBag myMap)
result _myHashBag myMap merge!(other _myHashBag myMap)
result
}
/* WARNING: The defaultValue parameter for Covers must be new Cell(cover) */
get: func <T> (key: String, defaultValue: T) -> T {
result := defaultValue
if (_myHashBag contains?(key)) {
storedType := _myHashBag getClass(key)
// is `T` a derived type or the same type as the stored type?
if (T inheritsFrom?(storedType)) {
result = _myHashBag getEntry(key, T) value as T
}
storedType := this _myHashBag getClass(key)
if (T inheritsFrom?(storedType))
result = this _myHashBag getEntry(key, T) value as T
}
result
}
/* WARNING: The Class parameter for Covers must be Cell<Cover> */
getAsType: func <T>(key: String, T: Class) -> T {
result := null
if (_myHashBag contains?(key)) {
storedType := _myHashBag getClass(key)
// is `T` a derived type or the same type as the stored type?
if (this _myHashBag contains?(key)) {
storedType := this _myHashBag getClass(key)
if (T inheritsFrom?(storedType))
result = _myHashBag getEntry(key, T) value as T
result = this _myHashBag getEntry(key, T) value as T
}
result
}
getClass: func (key: String) -> Class {
return _myHashBag getClass(key)
this _myHashBag getClass(key)
}
getEntry: func <V> (key: String, V: Class) -> HashEntry<String, Pointer> {
return _myHashBag getEntry(key, V)
}
put: func <T> (key: String, value: T) -> Bool {
if (_myHashBag contains?(key))
this remove(key)
return _myHashBag put(key, value)
this _myHashBag getEntry(key, V)
}
/* WARNING: Covers must be wrapped into a Cell before adding to the dictionary */
add: func <T> (key: String, value: T) -> Bool {
return this put(key, value)
if (_myHashBag contains?(key))
this remove(key)
this _myHashBag put(key, value)
}
empty?: func -> Bool { return _myHashBag empty?() }
remove: func (key: String) -> Bool {
return _myHashBag remove(key)
this _myHashBag remove(key)
}
size: func -> Int { _myHashBag size() }
contains?: func (key: String) -> Bool {
return _myHashBag contains?(key)
contains: func (key: String) -> Bool {
this _myHashBag contains?(key)
}
getKeys: func -> ArrayList<String> {
return _myHashBag getKeys()
this _myHashBag getKeys()
}
getPath: func <T> (path: String, T: Class) -> T {
return _myHashBag getPath(path, T)
}
dispose: func {
free(this _myHashBag myMap keys data)
free(this _myHashBag myMap keys)
for (i in 0 .. (this _myHashBag myMap capacity)) {
next := (this _myHashBag myMap buckets[i])
next dispose()
}
free(this _myHashBag myMap buckets data)
free(this _myHashBag myMap)
free(this _myHashBag)
free(this)
this _myHashBag getPath(path, T)
}
}

Expand Down
24 changes: 20 additions & 4 deletions test/collections/HashDictionaryTest.ooc
Expand Up @@ -104,7 +104,7 @@ HashDictionaryTest: class extends Fixture {
dictionary add("First", 1337)
expect(dictionary getAsType("First", Int) == 1337)
expect(dictionary getAsType("First", String) == null)
expect(dictionary getAsType("Second", Int) == null)
//expect(dictionary getAsType("Second", Int) == null) //FIXME Can we do this without obnoxious Pointer-To-Int warnings?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getAsType: func <T>(key: String, T: Class) -> T {, which means that dictionary getAsType("Second", Int) will return an Int. If you compare an Int to null, you will get the warning. If the test would follow the warning The Class parameter for Covers must be Cell<Cover> by calling dictionary getAsType("Second", Cell<Int>) the warning should go away, but then you also need to use Cell when adding things to the dictionary, or things will go badly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this should be solved as I did with Future. Will fix.

expect(dictionary getAsType("First", Cell<TestCover>) == null)
expect(dictionary getAsType("First", TestClass) == null)
})
Expand All @@ -116,18 +116,17 @@ HashDictionaryTest: class extends Fixture {
expect(dictionary getAsType("First", Cell<TestCover>) get() intVal == 1337)
expect(dictionary getAsType("First", Cell<TestCover>) get() stringVal == "String")
expect(dictionary getAsType("Second", Cell<TestCover>) == null)
expect(dictionary getAsType("First", Int) == null)
//expect(dictionary getAsType("First", Int) == null) //FIXME Can we do this without obnoxious Pointer-To-Int warnings?
expect(dictionary getAsType("First", TestClass) == null)
})

this add("Get from class", func {
dictionary := HashDictionary new()
dictionary add("First", TestClass new(1337, "String"))

expect(dictionary getAsType("First", TestClass) intVal == 1337)
expect(dictionary getAsType("First", TestClass) stringVal == "String")
expect(dictionary getAsType("Second", TestClass) == null)
expect(dictionary getAsType("First", Int) == null)
//expect(dictionary getAsType("First", Int) == null) //FIXME Can we do this without obnoxious Pointer-To-Int warnings?
expect(dictionary getAsType("First", Cell<TestCover>) == null)
})
this add("Merge", func {
Expand Down Expand Up @@ -157,6 +156,23 @@ HashDictionaryTest: class extends Fixture {
expect(dictionary3 getAsType("Sixth", Int) == 1002)
expect(dictionary3 getAsType("Sixth", String) == null)
})
this add("Sizes", func {
dictionary := HashDictionary new()
dictionary add("First", 1)
dictionary add("Second", 2)
dictionary add("Third", 3)
expect(dictionary count == 3)
expect(dictionary empty == false)
expect(dictionary contains("Second") == true)
dictionary remove("Second")
expect(dictionary count == 2)
expect(dictionary empty == false)
expect(dictionary contains("Second") == false)
dictionary remove("Third")
dictionary remove("First")
expect(dictionary count == 0)
expect(dictionary empty == true)
})
}
}
HashDictionaryTest new() run()
56 changes: 56 additions & 0 deletions test/collections/VectorListTest.ooc
Expand Up @@ -142,8 +142,13 @@ VectorListTest: class extends Fixture {
expect(slice count == 2)
expect(slice[0] == 2.0f)
expect(slice[1] == 3.0f)
sliceInto := VectorList<Float> new()
list getSliceInto(Range new(1, 2), sliceInto)
expect(sliceInto[0] == 2.0f)
expect(sliceInto[1] == 3.0f)
list free()
slice free()
sliceInto free()
})
this add("VectorList apply", func {
list := VectorList<Int> new()
Expand All @@ -154,6 +159,7 @@ VectorListTest: class extends Fixture {
list apply(|value|
expect(value, is equal to(c))
c += 1)
list free()
})
this add("VectorList modify", func {
list := VectorList<Int> new()
Expand All @@ -166,6 +172,7 @@ VectorListTest: class extends Fixture {
list apply(|value|
expect(value, is equal to(c))
c += 1)
list free()
})
this add("VectorList map", func {
list := VectorList<Int> new()
Expand All @@ -179,6 +186,50 @@ VectorListTest: class extends Fixture {
expect(newList[2], is equal to("3"))
list free(); newList free()
})
this add("VectorList reverse", func {
list := VectorList<Int> new()
list add(8)
list add(16)
list add(64)
list add(128)
reversed := list reverse()
expect(reversed[0] == 128)
expect(reversed[1] == 64)
expect(reversed[2] == 16)
expect(reversed[3] == 8)
list free()
reversed free()
})
this add("VectorList remove", func {
list := VectorList<Int> new()
list add(8)
list add(16)
list add(32)
list add(64)
expect(list empty, is equal to(false))
while (!list empty) {
list removeAt(0)
}
expect(list empty, is equal to(true))
list free()
})
this add("VectorList direct vector access", func {
list := VectorList<Int> new()
list add(8)
list add(16)
list add(32)
point := list pointer as Int*
expect(point[0] == list[0])
expect(point[1] == list[1])
expect(point[2] == list[2])
list free()
})
this add("VectorList sort", func {
//TODO Current way of sorting not supported by Rock
})
this add("VectorList fold", func {
//TODO Current way of folding not supported by Rock
})
this add("Iterator leak", func {
list := VectorList<Int> new()
list add(1)
Expand All @@ -195,8 +246,13 @@ VectorListTest: class extends Fixture {
list add(16)
list add(32)
iterator := list iterator()
expect(iterator hasNext?(), is equal to(true))
for ((index, item) in iterator)
expect(item, is equal to(list[index]))
expect(iterator hasNext?(), is equal to(false))
secondIterator := list iterator()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You forgot to free secondIterator

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thomasfanell I've seen many tests where nothing at all is freed. I thought I was just being pedantic sometimes. But you're right, will fix.

expect(secondIterator next(), is equal to(8))
secondIterator free()
iterator free()
list free()
})
Expand Down