From 064d02d031213f9e17aca3068e33e527929abc70 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Mon, 9 Jan 2017 09:11:36 +0000 Subject: [PATCH] added stix_deletedic() and Dictionary>>removeKey: and its derivatives --- stix/kernel/Apex.st | 50 ++++++++++++----- stix/kernel/Collect.st | 122 ++++++++++++++++++++++++++++++++++++----- stix/kernel/Except.st | 23 +++++--- stix/lib/dic.c | 66 ++++++++++++++++++++++ stix/lib/stix-prv.h | 8 ++- 5 files changed, 232 insertions(+), 37 deletions(-) diff --git a/stix/kernel/Apex.st b/stix/kernel/Apex.st index 744e564..43a5dcd 100644 --- a/stix/kernel/Apex.st +++ b/stix/kernel/Apex.st @@ -259,6 +259,16 @@ class Apex(nil) ^false } + method notError + { + ^true + } + + method(#class) notError + { + ^true + } + ## ------------------------------------------------------- ## ------------------------------------------------------- @@ -320,32 +330,37 @@ class Apex(nil) * ------------------------------------------------------------------ *) method primitiveFailed { - self class primitiveFailed. - } - - method doesNotUnderstand: messageSymbol - { - self class doesNotUnderstand: messageSymbol - } - - method index: index outOfRange: ubound - { - self class index: index outOfRange: ubound. + ^self class primitiveFailed. } method cannotInstantiate { - self class cannotInstantiate + ^self class cannotInstantiate } - method subclassResponsibility: message_name + method doesNotUnderstand: messageSymbol { - self class subclassResponsibility: message_name + ^self class doesNotUnderstand: messageSymbol + } + + method index: index outOfRange: ubound + { + ^self class index: index outOfRange: ubound. + } + + method subclassResponsibility: method_name + { + ^self class subclassResponsibility: method_name + } + + method notImplemented: method_name + { + ^self class notImplemented: method_name } method cannotExceptionizeError { - self class cannotExceptionizeError + ^self class cannotExceptionizeError } method(#class) error: msgText @@ -413,6 +428,11 @@ class Error(Apex) ^true } + method notError + { + ^false + } + method asInteger { diff --git a/stix/kernel/Collect.st b/stix/kernel/Collect.st index 1941a3c..70f5cb8 100644 --- a/stix/kernel/Collect.st +++ b/stix/kernel/Collect.st @@ -145,7 +145,7 @@ class Set(Collection) [(ass := self.bucket at: index) notNil] whileTrue: [ - [key == ass key] ifTrue: [ (* TODO: change it to equality??? *) + (key = ass key) ifTrue: [ (* found *) upsert ifTrue: [ass value: value]. ^ass @@ -153,7 +153,7 @@ class Set(Collection) index := (index + 1) rem: bs. ]. - upsert ifFalse: [^nil]. + upsert ifFalse: [^ErrorCode.NOENT]. ntally := self.tally + 1. (ntally >= bs) ifTrue: [ @@ -187,29 +187,42 @@ class Set(Collection) { | ass | ass := self __find: key or_upsert: false with: nil. - (ass notNil) ifTrue: [^ass value]. - ^ErrorCode.NOENT + (ass isError) ifTrue: [^ass]. + ^ass value } method at: key ifAbsent: error_block { | ass | ass := self __find: key or_upsert: false with: nil. - (ass notNil) ifTrue: [^ass value]. - ^error_block value. + (ass isError) ifTrue: [^error_block value]. + ^ass value + } + + method associationAt: key + { + ^self __find: key or_upsert: false with: nil. + } + + method associationAt: key ifAbsent: error_block + { + | ass | + ass := self __find: key or_upsert: false with: nil. + (ass isError) ifTrue: [^error_block value]. + ^ass } method at: key put: value { - self __find: key or_upsert: true with: value. - ^value + (* returns the affected/inserted association *) + ^self __find: key or_upsert: true with: value. } method includesKey: key { | ass | ass := self __find: key or_upsert: false with: nil. - ^ass notNil + ^ass notError } method includesAssociation: assoc @@ -225,19 +238,99 @@ class Set(Collection) ass := self __find: key or_upsert: false with: nil. ^ass key = key and: [ass value = value] } - + + method __find_index: key + { + | bs ass index | + + bs := self.bucket size. + index := (key hash) rem: bs. + + [(ass := self.bucket at: index) notNil] + whileTrue: [ + (key = ass key) ifTrue: [^index]. + index := (index + 1) rem: bs. + ]. + + ^ErrorCode.NOENT. + } + + method __remove_at: index + { + | bs x y i v | + + bs := self.bucket size. + v := self.bucket basicAt: index. + + x := index. + y := index. + i := 0. + [i < self.tally] whileTrue: [ + | ass z | + + y := (y + 1) rem: bs. + + ass := self.bucket at: i. + (ass isNil) + ifTrue: [ + (* done. the slot at the current index is nil *) + i := self.tally + ] + ifFalse: [ + (* get the natural hash index *) + z := (ass key hash) rem: bs. + + (* move an element if necessary *) + ((y > x and: [(z <= x) or: [z > y]]) or: + [(y < x) and: [(z <= x) and: [z > y]]]) ifTrue: [ + self.bucket at: x put: (self.bucket at: y). + x := y. + ]. + + i := i + 1 + ]. + ]. + + self.bucket at: x put: nil. + self.tally := self.tally - 1. + + (* return the affected association *) + ^v + } + method removeKey: key { -(* TODO: *) -self subclassResponsbility: #removeKey + | index | + index := self __find_index: key. + (index isError) ifTrue: [ ^index ]. + ^self __remove_at: index. } method removeKey: key ifAbsent: error_block { -(* TODO: *) -self subclassResponsbility: #removeKey + | index | + index := self __find_index: key. + (index isError) ifTrue: [ ^error_block value ]. + ^self __remove_at: index. } + + method removeAllKeys + { + (* remove all items from a dictionary *) + | bs | + bs := self.bucket size. + 0 priorTo: bs do: [:i | self.bucket at: i put: nil ]. + self.tally := 0 + } + +(* TODO: ... keys is an array of keys. + method removeAllKeys: keys + { + self notImplemented: #removeAllKeys: + } +*) + method remove: assoc { ^self removeKey: (assoc key) @@ -248,6 +341,7 @@ self subclassResponsbility: #removeKey ^self removeKey: (assoc key) ifAbsent: error_block } + method do: block { | bs | diff --git a/stix/kernel/Except.st b/stix/kernel/Except.st index 3eb6437..2a7e3b7 100644 --- a/stix/kernel/Except.st +++ b/stix/kernel/Except.st @@ -351,6 +351,10 @@ thisContext isExceptionContext dump. ##============================================================================ +class PrimitiveFailureException(Exception) +{ +} + class InstantiationFailureException(Exception) { } @@ -359,10 +363,6 @@ class NoSuchMessageException(Exception) { } -class PrimitiveFailureException(Exception) -{ -} - class IndexOutOfRangeException(Exception) { } @@ -371,7 +371,7 @@ class SubclassResponsibilityException(Exception) { } -class InvalidArgumentException(Exception) +class NotImplementedException(Exception) { } @@ -379,6 +379,10 @@ class ErrorExceptionizationFailureException(Exception) { } +class InvalidArgumentException(Exception) +{ +} + extend Apex { method(#class) primitiveFailed @@ -414,11 +418,16 @@ ctx := thisContext. IndexOutOfRangeException signal: 'Out of range'. } - method(#class) subclassResponsibility: message_name + method(#class) subclassResponsibility: method_name { - SubclassResponsibilityException signal: ('Subclass must implment ' & message_name). + SubclassResponsibilityException signal: ('Subclass must implement ' & method_name). } + method(#class) notImplemented: method_name + { + NotImplementedException signal: (method_name & ' not implemented by ' & (self name)). + } + method(#class) cannotExceptionizeError { ## todo: accept the object diff --git a/stix/lib/dic.c b/stix/lib/dic.c index 617e78c..4753270 100644 --- a/stix/lib/dic.c +++ b/stix/lib/dic.c @@ -261,6 +261,72 @@ stix_oop_association_t stix_lookupdic (stix_t* stix, stix_oop_set_t dic, const s return lookup (stix, dic, name); } +int stix_deletedic (stix_t* stix, stix_oop_set_t dic, const stix_oocs_t* name) +{ + stix_ooi_t tally; + stix_oow_t hv, index, bs, i, x, y, z; + stix_oop_association_t ass; + + STIX_ASSERT (stix, STIX_CLASSOF(stix,dic->tally) == stix->_small_integer); + STIX_ASSERT (stix, STIX_CLASSOF(stix,dic->bucket) == stix->_array); + + tally = STIX_OOP_TO_SMOOI(dic->tally); + + bs = STIX_OBJ_GET_SIZE(dic->bucket); + hv = stix_hashoochars(name->ptr, name->len) % bs; + index = hv % bs; + + /* find */ + while (dic->bucket->slot[index] != stix->_nil) + { + ass = (stix_oop_association_t)dic->bucket->slot[index]; + + STIX_ASSERT (stix, STIX_CLASSOF(stix,ass) == stix->_association); + STIX_ASSERT (stix, STIX_CLASSOF(stix,ass->key) == stix->_symbol); + + if (name->len == STIX_OBJ_GET_SIZE(ass->key) && + stix_equaloochars(name->ptr, ((stix_oop_char_t)ass->key)->slot, name->len)) + { + goto found; + } + + index = (index + 1) % bs; + } + + stix->errnum = STIX_ENOENT; + return -1; + +found: + /* compact the cluster */ + for (i = 0, x = index, y = index; i < tally; i++) + { + y = (y + 1) % bs; + + /* done if the slot at the current index is empty */ + if (dic->bucket->slot[y] == stix->_nil) break; + + /* get the natural hash index for the data in the slot at + * the current hash index */ + ass = (stix_oop_association_t)dic->bucket->slot[y]; + z = stix_hashoochars(((stix_oop_char_t)ass->key)->slot, STIX_OBJ_GET_SIZE(ass->key)) % bs; + + /* move an element if necesary */ + if ((y > x && (z <= x || z > y)) || + (y < x && (z <= x && z > y))) + { + dic->bucket->slot[x] = dic->bucket->slot[y]; + x = y; + } + } + + dic->bucket->slot[x] = stix->_nil; + + tally--; + dic->tally = STIX_SMOOI_TO_OOP(tally); + + return 0; +} + stix_oop_set_t stix_makedic (stix_t* stix, stix_oop_t cls, stix_oow_t size) { stix_oop_set_t dic; diff --git a/stix/lib/stix-prv.h b/stix/lib/stix-prv.h index 0f45c56..c60b35a 100644 --- a/stix/lib/stix-prv.h +++ b/stix/lib/stix-prv.h @@ -985,6 +985,12 @@ stix_oop_association_t stix_lookupdic ( const stix_oocs_t* name ); +int stix_deletedic ( + stix_t* stix, + stix_oop_set_t dic, + const stix_oocs_t* name +); + stix_oop_set_t stix_makedic ( stix_t* stix, stix_oop_t cls, @@ -1000,7 +1006,7 @@ stix_oop_process_t stix_makeproc ( /* ========================================================================= */ -/* bigint.c */ +/* bigint.c */ /* ========================================================================= */ int stix_isint ( stix_t* stix,