diff --git a/stix/kernel/Collect.st b/stix/kernel/Collect.st index dfc346f..1941a3c 100644 --- a/stix/kernel/Collect.st +++ b/stix/kernel/Collect.st @@ -127,7 +127,7 @@ class Set(Collection) method initialize { self.tally := 0. - self.bucket := Array new: 100. + self.bucket := Array new: 128. (* TODO: initial size *) } method size @@ -135,28 +135,6 @@ class Set(Collection) ^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 { | hv ass bs index ntally | @@ -179,8 +157,23 @@ class Set(Collection) ntally := self.tally + 1. (ntally >= bs) ifTrue: [ + | newbuc newsz | (* 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. @@ -190,6 +183,71 @@ class Set(Collection) ^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 { | bs | @@ -351,4 +409,4 @@ extend Apex { ^Association new key: self value: object } -} +} \ No newline at end of file diff --git a/stix/kernel/Magnitu.st b/stix/kernel/Magnitu.st index b016ea8..76ebe4e 100644 --- a/stix/kernel/Magnitu.st +++ b/stix/kernel/Magnitu.st @@ -10,11 +10,17 @@ class Association(Magnitude) { ^self new key: key value: value } + method key: key value: value { self.key := key. self.value := value. } + + method value: value + { + self.value := value + } method key { diff --git a/stix/lib/dic.c b/stix/lib/dic.c index 4310c49..617e78c 100644 --- a/stix/lib/dic.c +++ b/stix/lib/dic.c @@ -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) { stix_ooi_t tally; - stix_oow_t index; + stix_oow_t hv, index; stix_oop_association_t ass; 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->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 */ 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; /* 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) index = (index + 1) % STIX_OBJ_GET_SIZE(dic->bucket);