added stix_deletedic() and Dictionary>>removeKey: and its derivatives

This commit is contained in:
hyunghwan.chung 2017-01-09 09:11:36 +00:00
parent 6e335cd4fb
commit 064d02d031
5 changed files with 232 additions and 37 deletions

View File

@ -259,6 +259,16 @@ class Apex(nil)
^false ^false
} }
method notError
{
^true
}
method(#class) notError
{
^true
}
## ------------------------------------------------------- ## -------------------------------------------------------
## ------------------------------------------------------- ## -------------------------------------------------------
@ -320,32 +330,37 @@ class Apex(nil)
* ------------------------------------------------------------------ *) * ------------------------------------------------------------------ *)
method primitiveFailed method primitiveFailed
{ {
self class primitiveFailed. ^self class primitiveFailed.
}
method doesNotUnderstand: messageSymbol
{
self class doesNotUnderstand: messageSymbol
}
method index: index outOfRange: ubound
{
self class index: index outOfRange: ubound.
} }
method cannotInstantiate 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 method cannotExceptionizeError
{ {
self class cannotExceptionizeError ^self class cannotExceptionizeError
} }
method(#class) error: msgText method(#class) error: msgText
@ -413,6 +428,11 @@ class Error(Apex)
^true ^true
} }
method notError
{
^false
}
method asInteger method asInteger
{ {
<primitive: #_error_as_integer> <primitive: #_error_as_integer>

View File

@ -145,7 +145,7 @@ class Set(Collection)
[(ass := self.bucket at: index) notNil] [(ass := self.bucket at: index) notNil]
whileTrue: [ whileTrue: [
[key == ass key] ifTrue: [ (* TODO: change it to equality??? *) (key = ass key) ifTrue: [
(* found *) (* found *)
upsert ifTrue: [ass value: value]. upsert ifTrue: [ass value: value].
^ass ^ass
@ -153,7 +153,7 @@ class Set(Collection)
index := (index + 1) rem: bs. index := (index + 1) rem: bs.
]. ].
upsert ifFalse: [^nil]. upsert ifFalse: [^ErrorCode.NOENT].
ntally := self.tally + 1. ntally := self.tally + 1.
(ntally >= bs) ifTrue: [ (ntally >= bs) ifTrue: [
@ -187,29 +187,42 @@ class Set(Collection)
{ {
| ass | | ass |
ass := self __find: key or_upsert: false with: nil. ass := self __find: key or_upsert: false with: nil.
(ass notNil) ifTrue: [^ass value]. (ass isError) ifTrue: [^ass].
^ErrorCode.NOENT ^ass value
} }
method at: key ifAbsent: error_block method at: key ifAbsent: error_block
{ {
| ass | | ass |
ass := self __find: key or_upsert: false with: nil. ass := self __find: key or_upsert: false with: nil.
(ass notNil) ifTrue: [^ass value]. (ass isError) ifTrue: [^error_block value].
^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 method at: key put: value
{ {
self __find: key or_upsert: true with: value. (* returns the affected/inserted association *)
^value ^self __find: key or_upsert: true with: value.
} }
method includesKey: key method includesKey: key
{ {
| ass | | ass |
ass := self __find: key or_upsert: false with: nil. ass := self __find: key or_upsert: false with: nil.
^ass notNil ^ass notError
} }
method includesAssociation: assoc method includesAssociation: assoc
@ -226,18 +239,98 @@ class Set(Collection)
^ass key = key and: [ass value = value] ^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 method removeKey: key
{ {
(* TODO: *) | index |
self subclassResponsbility: #removeKey index := self __find_index: key.
(index isError) ifTrue: [ ^index ].
^self __remove_at: index.
} }
method removeKey: key ifAbsent: error_block method removeKey: key ifAbsent: error_block
{ {
(* TODO: *) | index |
self subclassResponsbility: #removeKey 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 method remove: assoc
{ {
^self removeKey: (assoc key) ^self removeKey: (assoc key)
@ -248,6 +341,7 @@ self subclassResponsbility: #removeKey
^self removeKey: (assoc key) ifAbsent: error_block ^self removeKey: (assoc key) ifAbsent: error_block
} }
method do: block method do: block
{ {
| bs | | bs |

View File

@ -351,6 +351,10 @@ thisContext isExceptionContext dump.
##============================================================================ ##============================================================================
class PrimitiveFailureException(Exception)
{
}
class InstantiationFailureException(Exception) class InstantiationFailureException(Exception)
{ {
} }
@ -359,10 +363,6 @@ class NoSuchMessageException(Exception)
{ {
} }
class PrimitiveFailureException(Exception)
{
}
class IndexOutOfRangeException(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 extend Apex
{ {
method(#class) primitiveFailed method(#class) primitiveFailed
@ -414,9 +418,14 @@ ctx := thisContext.
IndexOutOfRangeException signal: 'Out of range'. 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 method(#class) cannotExceptionizeError

View File

@ -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); 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 stix_makedic (stix_t* stix, stix_oop_t cls, stix_oow_t size)
{ {
stix_oop_set_t dic; stix_oop_set_t dic;

View File

@ -985,6 +985,12 @@ stix_oop_association_t stix_lookupdic (
const stix_oocs_t* name 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_oop_set_t stix_makedic (
stix_t* stix, stix_t* stix,
stix_oop_t cls, stix_oop_t cls,