added more methods to Dictionary.

made a simple optimization in dic.c
This commit is contained in:
hyunghwan.chung 2017-01-06 14:49:42 +00:00
parent 23d80e77aa
commit 6e335cd4fb
3 changed files with 93 additions and 28 deletions

View File

@ -127,7 +127,7 @@ class Set(Collection)
method initialize method initialize
{ {
self.tally := 0. self.tally := 0.
self.bucket := Array new: 100. self.bucket := Array new: 128. (* TODO: initial size *)
} }
method size method size
@ -135,28 +135,6 @@ class Set(Collection)
^self.tally ^self.tally
} }
method at: key
{
| ass |
ass := self __find: key or_upsert: false with: nil.
(ass notNil) ifTrue: [^ass value].
^ErrorCode.NOENT
}
method at: key ifAbsent: error_block
{
| ass |
ass := self __find: key or_upsert: false with: nil.
(ass notNil) ifTrue: [^ass value].
^error_block value.
}
method at: key put: value
{
self __find: key or_upsert: true with: value.
^value
}
method __find: key or_upsert: upsert with: value method __find: key or_upsert: upsert with: value
{ {
| hv ass bs index ntally | | hv ass bs index ntally |
@ -179,8 +157,23 @@ class Set(Collection)
ntally := self.tally + 1. ntally := self.tally + 1.
(ntally >= bs) ifTrue: [ (ntally >= bs) ifTrue: [
| newbuc newsz |
(* expand the bucket *) (* expand the bucket *)
newsz := bs + 123. (* TODO: keep this growth policy in sync with VM(dic.c) *)
newbuc := Array new: newsz.
0 priorTo: bs do: [:i |
ass := self.bucket at: i.
(ass notNil) ifTrue: [
index := (ass key hash) rem: newsz.
[(newbuc at: index) notNil] whileTrue: [index := (index + 1) rem: newsz].
newbuc at: index put: ass
]
].
self.bucket := newbuc.
bs := self.bucket size.
index := hv rem: bs.
[(self.bucket at: index) notNil] whileTrue: [index := (index + 1) rem: bs ].
]. ].
ass := Association key: key value: value. ass := Association key: key value: value.
@ -190,6 +183,71 @@ class Set(Collection)
^ass ^ass
} }
method at: key
{
| ass |
ass := self __find: key or_upsert: false with: nil.
(ass notNil) ifTrue: [^ass value].
^ErrorCode.NOENT
}
method at: key ifAbsent: error_block
{
| ass |
ass := self __find: key or_upsert: false with: nil.
(ass notNil) ifTrue: [^ass value].
^error_block value.
}
method at: key put: value
{
self __find: key or_upsert: true with: value.
^value
}
method includesKey: key
{
| ass |
ass := self __find: key or_upsert: false with: nil.
^ass notNil
}
method includesAssociation: assoc
{
| ass |
ass := self __find: (assoc key) or_upsert: false with: nil.
^ass = assoc.
}
method includesKey: key value: value
{
| ass |
ass := self __find: key or_upsert: false with: nil.
^ass key = key and: [ass value = value]
}
method removeKey: key
{
(* TODO: *)
self subclassResponsbility: #removeKey
}
method removeKey: key ifAbsent: error_block
{
(* TODO: *)
self subclassResponsbility: #removeKey
}
method remove: assoc
{
^self removeKey: (assoc key)
}
method remove: assoc ifAbsent: error_block
{
^self removeKey: (assoc key) ifAbsent: error_block
}
method do: block method do: block
{ {
| bs | | bs |

View File

@ -10,12 +10,18 @@ class Association(Magnitude)
{ {
^self new key: key value: value ^self new key: key value: value
} }
method key: key value: value method key: key value: value
{ {
self.key := key. self.key := key.
self.value := value. self.value := value.
} }
method value: value
{
self.value := value
}
method key method key
{ {
^self.key ^self.key

View File

@ -88,7 +88,7 @@ static stix_oop_oop_t expand_bucket (stix_t* stix, stix_oop_oop_t oldbuc)
static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic, stix_oop_char_t key, stix_oop_t value) static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic, stix_oop_char_t key, stix_oop_t value)
{ {
stix_ooi_t tally; stix_ooi_t tally;
stix_oow_t index; stix_oow_t hv, index;
stix_oop_association_t ass; stix_oop_association_t ass;
stix_oow_t tmp_count = 0; stix_oow_t tmp_count = 0;
@ -98,7 +98,8 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic,
STIX_ASSERT (stix, STIX_CLASSOF(stix,dic->tally) == stix->_small_integer); STIX_ASSERT (stix, STIX_CLASSOF(stix,dic->tally) == stix->_small_integer);
STIX_ASSERT (stix, STIX_CLASSOF(stix,dic->bucket) == stix->_array); STIX_ASSERT (stix, STIX_CLASSOF(stix,dic->bucket) == stix->_array);
index = stix_hashoochars(key->slot, STIX_OBJ_GET_SIZE(key)) % STIX_OBJ_GET_SIZE(dic->bucket); hv = stix_hashoochars(key->slot, STIX_OBJ_GET_SIZE(key));
index = hv % STIX_OBJ_GET_SIZE(dic->bucket);
/* find */ /* find */
while (dic->bucket->slot[index] != stix->_nil) while (dic->bucket->slot[index] != stix->_nil)
@ -164,7 +165,7 @@ static stix_oop_association_t find_or_upsert (stix_t* stix, stix_oop_set_t dic,
dic->bucket = bucket; dic->bucket = bucket;
/* recalculate the index for the expanded bucket */ /* recalculate the index for the expanded bucket */
index = stix_hashoochars(key->slot, STIX_OBJ_GET_SIZE(key)) % STIX_OBJ_GET_SIZE(dic->bucket); index = hv % STIX_OBJ_GET_SIZE(dic->bucket);
while (dic->bucket->slot[index] != stix->_nil) while (dic->bucket->slot[index] != stix->_nil)
index = (index + 1) % STIX_OBJ_GET_SIZE(dic->bucket); index = (index + 1) % STIX_OBJ_GET_SIZE(dic->bucket);