smalltalk: HashedCollection/Set/Dictionary/IdentityDictionary + 29 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
This commit is contained in:
@@ -378,7 +378,9 @@
|
||||
(st-class-define! "String" "ArrayedCollection" (list))
|
||||
(st-class-define! "Symbol" "String" (list))
|
||||
(st-class-define! "OrderedCollection" "SequenceableCollection" (list "array" "firstIndex" "lastIndex"))
|
||||
(st-class-define! "Dictionary" "Collection" (list))
|
||||
;; Hashed collection family
|
||||
(st-class-define! "HashedCollection" "Collection" (list "array"))
|
||||
(st-class-define! "Set" "HashedCollection" (list))
|
||||
;; Blocks / contexts
|
||||
(st-class-define! "BlockClosure" "Object" (list))
|
||||
;; Reflection support — Message holds the selector/args for a DNU send.
|
||||
@@ -478,6 +480,113 @@
|
||||
(st-parse-method "notEmpty ^ self size > 0"))
|
||||
(st-class-add-method! "SequenceableCollection" "asString"
|
||||
(st-parse-method "asString ^ self printString"))
|
||||
;; ── HashedCollection / Set / Dictionary ──
|
||||
;; Implemented as user instances with array-backed storage. Sets
|
||||
;; use a single `array` ivar; Dictionaries use parallel `keys`/
|
||||
;; `values` arrays. New is class-side and routes through `init`.
|
||||
(st-class-add-method! "HashedCollection" "init"
|
||||
(st-parse-method "init array := Array new: 0. ^ self"))
|
||||
(st-class-add-method! "HashedCollection" "size"
|
||||
(st-parse-method "size ^ array size"))
|
||||
(st-class-add-method! "HashedCollection" "isEmpty"
|
||||
(st-parse-method "isEmpty ^ array isEmpty"))
|
||||
(st-class-add-method! "HashedCollection" "notEmpty"
|
||||
(st-parse-method "notEmpty ^ array notEmpty"))
|
||||
(st-class-add-method! "HashedCollection" "do:"
|
||||
(st-parse-method "do: aBlock array do: aBlock. ^ self"))
|
||||
(st-class-add-method! "HashedCollection" "asArray"
|
||||
(st-parse-method "asArray ^ array"))
|
||||
(st-class-add-class-method! "Set" "new"
|
||||
(st-parse-method "new ^ super new init"))
|
||||
(st-class-add-method! "Set" "add:"
|
||||
(st-parse-method
|
||||
"add: anObject
|
||||
(self includes: anObject) ifFalse: [array add: anObject].
|
||||
^ anObject"))
|
||||
(st-class-add-method! "Set" "addAll:"
|
||||
(st-parse-method
|
||||
"addAll: aCollection
|
||||
aCollection do: [:e | self add: e].
|
||||
^ aCollection"))
|
||||
(st-class-add-method! "Set" "remove:"
|
||||
(st-parse-method
|
||||
"remove: anObject
|
||||
array := array reject: [:e | e = anObject].
|
||||
^ anObject"))
|
||||
(st-class-add-method! "Set" "includes:"
|
||||
(st-parse-method "includes: anObject ^ array includes: anObject"))
|
||||
(st-class-define! "Dictionary" "HashedCollection" (list "keys" "values"))
|
||||
(st-class-add-class-method! "Dictionary" "new"
|
||||
(st-parse-method "new ^ super new init"))
|
||||
(st-class-add-method! "Dictionary" "init"
|
||||
(st-parse-method
|
||||
"init keys := Array new: 0. values := Array new: 0. ^ self"))
|
||||
(st-class-add-method! "Dictionary" "size"
|
||||
(st-parse-method "size ^ keys size"))
|
||||
(st-class-add-method! "Dictionary" "isEmpty"
|
||||
(st-parse-method "isEmpty ^ keys isEmpty"))
|
||||
(st-class-add-method! "Dictionary" "notEmpty"
|
||||
(st-parse-method "notEmpty ^ keys notEmpty"))
|
||||
(st-class-add-method! "Dictionary" "keys"
|
||||
(st-parse-method "keys ^ keys"))
|
||||
(st-class-add-method! "Dictionary" "values"
|
||||
(st-parse-method "values ^ values"))
|
||||
(st-class-add-method! "Dictionary" "at:"
|
||||
(st-parse-method
|
||||
"at: aKey
|
||||
| i |
|
||||
i := keys indexOf: aKey.
|
||||
i = 0 ifTrue: [^ nil].
|
||||
^ values at: i"))
|
||||
(st-class-add-method! "Dictionary" "at:ifAbsent:"
|
||||
(st-parse-method
|
||||
"at: aKey ifAbsent: aBlock
|
||||
| i |
|
||||
i := keys indexOf: aKey.
|
||||
i = 0 ifTrue: [^ aBlock value].
|
||||
^ values at: i"))
|
||||
(st-class-add-method! "Dictionary" "at:put:"
|
||||
(st-parse-method
|
||||
"at: aKey put: aValue
|
||||
| i |
|
||||
i := keys indexOf: aKey.
|
||||
i = 0
|
||||
ifTrue: [keys add: aKey. values add: aValue]
|
||||
ifFalse: [values at: i put: aValue].
|
||||
^ aValue"))
|
||||
(st-class-add-method! "Dictionary" "includesKey:"
|
||||
(st-parse-method "includesKey: aKey ^ (keys indexOf: aKey) > 0"))
|
||||
(st-class-add-method! "Dictionary" "removeKey:"
|
||||
(st-parse-method
|
||||
"removeKey: aKey
|
||||
| i nk nv j |
|
||||
i := keys indexOf: aKey.
|
||||
i = 0 ifTrue: [^ nil].
|
||||
nk := Array new: 0. nv := Array new: 0.
|
||||
j := 1.
|
||||
[j <= keys size] whileTrue: [
|
||||
j = i ifFalse: [
|
||||
nk add: (keys at: j).
|
||||
nv add: (values at: j)].
|
||||
j := j + 1].
|
||||
keys := nk. values := nv.
|
||||
^ aKey"))
|
||||
(st-class-add-method! "Dictionary" "do:"
|
||||
(st-parse-method "do: aBlock values do: aBlock. ^ self"))
|
||||
(st-class-add-method! "Dictionary" "keysDo:"
|
||||
(st-parse-method "keysDo: aBlock keys do: aBlock. ^ self"))
|
||||
(st-class-add-method! "Dictionary" "valuesDo:"
|
||||
(st-parse-method "valuesDo: aBlock values do: aBlock. ^ self"))
|
||||
(st-class-add-method! "Dictionary" "keysAndValuesDo:"
|
||||
(st-parse-method
|
||||
"keysAndValuesDo: aBlock
|
||||
| i |
|
||||
i := 1.
|
||||
[i <= keys size] whileTrue: [
|
||||
aBlock value: (keys at: i) value: (values at: i).
|
||||
i := i + 1].
|
||||
^ self"))
|
||||
(st-class-define! "IdentityDictionary" "Dictionary" (list))
|
||||
"ok")))
|
||||
|
||||
;; Initialise on load. Tests can re-bootstrap to reset state.
|
||||
|
||||
Reference in New Issue
Block a user