Browse Source

Extract TKeyValueCollection.

Remove IndexableCollection.
Herby Vojčík 5 years ago
parent
commit
5988579773
4 changed files with 364 additions and 369 deletions
  1. 2 1
      CHANGELOG
  2. 2 1
      lang/API-CHANGES.txt
  3. 277 279
      lang/src/Kernel-Collections.js
  4. 83 88
      lang/src/Kernel-Collections.st

+ 2 - 1
CHANGELOG

@@ -1,7 +1,8 @@
-? Jan 2019 - Release 0.22.2
+? Jan 2019 - Release 0.23.0
 ===================================
 
 * Fixes.
+* Flatter Collection hierarchy with traits, remove IndexableCollection class.
 * Remove some old IE8 cruft.
 * Push CharacterArray down, make it and alias to String and deprecate it.
 

+ 2 - 1
lang/API-CHANGES.txt

@@ -1,5 +1,6 @@
-0.22.2:
+0.23.0:
 
+* Remove class IndexableCollection, trait TKeyValueCollection.
 * Merge CharacterArray class into String class
 * Deprecate CharacterArray class
 

+ 277 - 279
lang/src/Kernel-Collections.js

@@ -1890,284 +1890,7 @@ messageSends: ["addAll:", "new", "yourself"]
 $globals.Collection.a$cls);
 
 
-$core.addClass("IndexableCollection", $globals.Collection, [], "Kernel-Collections");
-//>>excludeStart("ide", pragmas.excludeIdeData);
-$globals.IndexableCollection.comment="I am a key-value store collection, that is,\x0aI store values under indexes.\x0a\x0aAs a rule of thumb, if a collection has `#at:` and `#at:put:`,\x0ait is an IndexableCollection.";
-//>>excludeEnd("ide");
-$core.addMethod(
-$core.method({
-selector: "at:",
-protocol: "accessing",
-fn: function (anIndex){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $self._at_ifAbsent_(anIndex,(function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $self._errorNotFound();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"at:",{anIndex:anIndex},$globals.IndexableCollection)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anIndex"],
-source: "at: anIndex\x0a\x09\x22Lookup the given index in the receiver.\x0a\x09If it is present, answer the value stored at anIndex.\x0a\x09Otherwise, raise an error.\x22\x0a\x0a\x09^ self at: anIndex ifAbsent: [ self errorNotFound ]",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["at:ifAbsent:", "errorNotFound"]
-}),
-$globals.IndexableCollection);
-
-$core.addMethod(
-$core.method({
-selector: "at:ifAbsent:",
-protocol: "accessing",
-fn: function (anIndex,aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"at:ifAbsent:",{anIndex:anIndex,aBlock:aBlock},$globals.IndexableCollection)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anIndex", "aBlock"],
-source: "at: anIndex ifAbsent: aBlock\x0a\x09\x22Lookup the given index in the receiver.\x0a\x09If it is present, answer the value stored at anIndex.\x0a\x09Otherwise, answer the value of aBlock.\x22\x0a\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.IndexableCollection);
-
-$core.addMethod(
-$core.method({
-selector: "at:ifAbsentPut:",
-protocol: "accessing",
-fn: function (aKey,aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $self._at_ifAbsent_(aKey,(function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $self._at_put_(aKey,$recv(aBlock)._value());
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"at:ifAbsentPut:",{aKey:aKey,aBlock:aBlock},$globals.IndexableCollection)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aKey", "aBlock"],
-source: "at: aKey ifAbsentPut: aBlock\x0a\x09^ self at: aKey ifAbsent: [\x0a\x09\x09self at: aKey put: aBlock value ]",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["at:ifAbsent:", "at:put:", "value"]
-}),
-$globals.IndexableCollection);
-
-$core.addMethod(
-$core.method({
-selector: "at:ifPresent:",
-protocol: "accessing",
-fn: function (anIndex,aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $self._at_ifPresent_ifAbsent_(anIndex,aBlock,(function(){
-return nil;
-
-}));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"at:ifPresent:",{anIndex:anIndex,aBlock:aBlock},$globals.IndexableCollection)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anIndex", "aBlock"],
-source: "at: anIndex ifPresent: aBlock\x0a\x09\x22Lookup the given index in the receiver.\x0a\x09If it is present, answer the value of evaluating aBlock with the value stored at anIndex.\x0a\x09Otherwise, answer nil.\x22\x0a\x0a\x09^ self at: anIndex ifPresent: aBlock ifAbsent: [ nil ]",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["at:ifPresent:ifAbsent:"]
-}),
-$globals.IndexableCollection);
-
-$core.addMethod(
-$core.method({
-selector: "at:ifPresent:ifAbsent:",
-protocol: "accessing",
-fn: function (anIndex,aBlock,anotherBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"at:ifPresent:ifAbsent:",{anIndex:anIndex,aBlock:aBlock,anotherBlock:anotherBlock},$globals.IndexableCollection)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anIndex", "aBlock", "anotherBlock"],
-source: "at: anIndex ifPresent: aBlock ifAbsent: anotherBlock\x0a\x09\x22Lookup the given index in the receiver.\x0a\x09If it is present, answer the value of evaluating aBlock with the value stored at anIndex.\x0a\x09Otherwise, answer the value of anotherBlock.\x22\x0a\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.IndexableCollection);
-
-$core.addMethod(
-$core.method({
-selector: "at:put:",
-protocol: "accessing",
-fn: function (anIndex,anObject){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"at:put:",{anIndex:anIndex,anObject:anObject},$globals.IndexableCollection)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anIndex", "anObject"],
-source: "at: anIndex put: anObject\x0a\x09\x22Store anObject under the given index in the receiver.\x22\x0a\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.IndexableCollection);
-
-$core.addMethod(
-$core.method({
-selector: "indexOf:",
-protocol: "accessing",
-fn: function (anObject){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $self._indexOf_ifAbsent_(anObject,(function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $self._errorNotFound();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"indexOf:",{anObject:anObject},$globals.IndexableCollection)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anObject"],
-source: "indexOf: anObject\x0a\x09\x22Lookup index at which anObject is stored in the receiver.\x0a\x09If not present, raise an error.\x22\x0a\x0a\x09^ self indexOf: anObject ifAbsent: [ self errorNotFound ]",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["indexOf:ifAbsent:", "errorNotFound"]
-}),
-$globals.IndexableCollection);
-
-$core.addMethod(
-$core.method({
-selector: "indexOf:ifAbsent:",
-protocol: "accessing",
-fn: function (anObject,aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"indexOf:ifAbsent:",{anObject:anObject,aBlock:aBlock},$globals.IndexableCollection)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anObject", "aBlock"],
-source: "indexOf: anObject ifAbsent: aBlock\x0a\x09\x22Lookup index at which anObject is stored in the receiver.\x0a\x09If not present, return value of executing aBlock.\x22\x0a\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.IndexableCollection);
-
-$core.addMethod(
-$core.method({
-selector: "with:do:",
-protocol: "enumerating",
-fn: function (anotherCollection,aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._withIndexDo_((function(each,index){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $recv(aBlock)._value_value_(each,$recv(anotherCollection)._at_(index));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each,index:index},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"with:do:",{anotherCollection:anotherCollection,aBlock:aBlock},$globals.IndexableCollection)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anotherCollection", "aBlock"],
-source: "with: anotherCollection do: aBlock\x0a\x09\x22Calls aBlock with every value from self\x0a\x09and with indetically-indexed value from anotherCollection\x22\x0a\x0a\x09self withIndexDo: [ :each :index |\x0a\x09\x09aBlock value: each value: (anotherCollection at: index) ]",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["withIndexDo:", "value:value:", "at:"]
-}),
-$globals.IndexableCollection);
-
-$core.addMethod(
-$core.method({
-selector: "withIndexDo:",
-protocol: "enumerating",
-fn: function (aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"withIndexDo:",{aBlock:aBlock},$globals.IndexableCollection)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBlock"],
-source: "withIndexDo: aBlock\x0a\x09\x22Calls aBlock with every value from self\x0a\x09and with its index as the second argument\x22\x0a\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.IndexableCollection);
-
-
-
-$core.addClass("AssociativeCollection", $globals.IndexableCollection, [], "Kernel-Collections");
+$core.addClass("AssociativeCollection", $globals.Collection, [], "Kernel-Collections");
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.AssociativeCollection.comment="I am a base class for object-indexed collections (Dictionary et.al.).";
 //>>excludeEnd("ide");
@@ -3845,7 +3568,7 @@ $globals.HashedCollection);
 
 
 
-$core.addClass("SequenceableCollection", $globals.IndexableCollection, [], "Kernel-Collections");
+$core.addClass("SequenceableCollection", $globals.Collection, [], "Kernel-Collections");
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.SequenceableCollection.comment="I am an IndexableCollection\x0awith numeric indexes starting with 1.";
 //>>excludeEnd("ide");
@@ -9911,6 +9634,279 @@ messageSends: []
 $globals.RegularExpression.a$cls);
 
 
+$core.addTrait("TKeyValueCollection", "Kernel-Collections");
+$core.addMethod(
+$core.method({
+selector: "at:",
+protocol: "accessing",
+fn: function (anIndex){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._at_ifAbsent_(anIndex,(function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $self._errorNotFound();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"at:",{anIndex:anIndex},$globals.TKeyValueCollection)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anIndex"],
+source: "at: anIndex\x0a\x09\x22Lookup the given index in the receiver.\x0a\x09If it is present, answer the value stored at anIndex.\x0a\x09Otherwise, raise an error.\x22\x0a\x0a\x09^ self at: anIndex ifAbsent: [ self errorNotFound ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["at:ifAbsent:", "errorNotFound"]
+}),
+$globals.TKeyValueCollection);
+
+$core.addMethod(
+$core.method({
+selector: "at:ifAbsent:",
+protocol: "accessing",
+fn: function (anIndex,aBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"at:ifAbsent:",{anIndex:anIndex,aBlock:aBlock},$globals.TKeyValueCollection)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anIndex", "aBlock"],
+source: "at: anIndex ifAbsent: aBlock\x0a\x09\x22Lookup the given index in the receiver.\x0a\x09If it is present, answer the value stored at anIndex.\x0a\x09Otherwise, answer the value of aBlock.\x22\x0a\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.TKeyValueCollection);
+
+$core.addMethod(
+$core.method({
+selector: "at:ifAbsentPut:",
+protocol: "accessing",
+fn: function (aKey,aBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._at_ifAbsent_(aKey,(function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $self._at_put_(aKey,$recv(aBlock)._value());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"at:ifAbsentPut:",{aKey:aKey,aBlock:aBlock},$globals.TKeyValueCollection)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aKey", "aBlock"],
+source: "at: aKey ifAbsentPut: aBlock\x0a\x09^ self at: aKey ifAbsent: [\x0a\x09\x09self at: aKey put: aBlock value ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["at:ifAbsent:", "at:put:", "value"]
+}),
+$globals.TKeyValueCollection);
+
+$core.addMethod(
+$core.method({
+selector: "at:ifPresent:",
+protocol: "accessing",
+fn: function (anIndex,aBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._at_ifPresent_ifAbsent_(anIndex,aBlock,(function(){
+return nil;
+
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"at:ifPresent:",{anIndex:anIndex,aBlock:aBlock},$globals.TKeyValueCollection)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anIndex", "aBlock"],
+source: "at: anIndex ifPresent: aBlock\x0a\x09\x22Lookup the given index in the receiver.\x0a\x09If it is present, answer the value of evaluating aBlock with the value stored at anIndex.\x0a\x09Otherwise, answer nil.\x22\x0a\x0a\x09^ self at: anIndex ifPresent: aBlock ifAbsent: [ nil ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["at:ifPresent:ifAbsent:"]
+}),
+$globals.TKeyValueCollection);
+
+$core.addMethod(
+$core.method({
+selector: "at:ifPresent:ifAbsent:",
+protocol: "accessing",
+fn: function (anIndex,aBlock,anotherBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"at:ifPresent:ifAbsent:",{anIndex:anIndex,aBlock:aBlock,anotherBlock:anotherBlock},$globals.TKeyValueCollection)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anIndex", "aBlock", "anotherBlock"],
+source: "at: anIndex ifPresent: aBlock ifAbsent: anotherBlock\x0a\x09\x22Lookup the given index in the receiver.\x0a\x09If it is present, answer the value of evaluating aBlock with the value stored at anIndex.\x0a\x09Otherwise, answer the value of anotherBlock.\x22\x0a\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.TKeyValueCollection);
+
+$core.addMethod(
+$core.method({
+selector: "at:put:",
+protocol: "accessing",
+fn: function (anIndex,anObject){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"at:put:",{anIndex:anIndex,anObject:anObject},$globals.TKeyValueCollection)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anIndex", "anObject"],
+source: "at: anIndex put: anObject\x0a\x09\x22Store anObject under the given index in the receiver.\x22\x0a\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.TKeyValueCollection);
+
+$core.addMethod(
+$core.method({
+selector: "indexOf:",
+protocol: "accessing",
+fn: function (anObject){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._indexOf_ifAbsent_(anObject,(function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $self._errorNotFound();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"indexOf:",{anObject:anObject},$globals.TKeyValueCollection)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anObject"],
+source: "indexOf: anObject\x0a\x09\x22Lookup index at which anObject is stored in the receiver.\x0a\x09If not present, raise an error.\x22\x0a\x0a\x09^ self indexOf: anObject ifAbsent: [ self errorNotFound ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["indexOf:ifAbsent:", "errorNotFound"]
+}),
+$globals.TKeyValueCollection);
+
+$core.addMethod(
+$core.method({
+selector: "indexOf:ifAbsent:",
+protocol: "accessing",
+fn: function (anObject,aBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"indexOf:ifAbsent:",{anObject:anObject,aBlock:aBlock},$globals.TKeyValueCollection)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anObject", "aBlock"],
+source: "indexOf: anObject ifAbsent: aBlock\x0a\x09\x22Lookup index at which anObject is stored in the receiver.\x0a\x09If not present, return value of executing aBlock.\x22\x0a\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.TKeyValueCollection);
+
+$core.addMethod(
+$core.method({
+selector: "with:do:",
+protocol: "enumerating",
+fn: function (anotherCollection,aBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._withIndexDo_((function(each,index){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $recv(aBlock)._value_value_(each,$recv(anotherCollection)._at_(index));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({each:each,index:index},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"with:do:",{anotherCollection:anotherCollection,aBlock:aBlock},$globals.TKeyValueCollection)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anotherCollection", "aBlock"],
+source: "with: anotherCollection do: aBlock\x0a\x09\x22Calls aBlock with every value from self\x0a\x09and with indetically-indexed value from anotherCollection\x22\x0a\x0a\x09self withIndexDo: [ :each :index |\x0a\x09\x09aBlock value: each value: (anotherCollection at: index) ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["withIndexDo:", "value:value:", "at:"]
+}),
+$globals.TKeyValueCollection);
+
+$core.addMethod(
+$core.method({
+selector: "withIndexDo:",
+protocol: "enumerating",
+fn: function (aBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"withIndexDo:",{aBlock:aBlock},$globals.TKeyValueCollection)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aBlock"],
+source: "withIndexDo: aBlock\x0a\x09\x22Calls aBlock with every value from self\x0a\x09and with its index as the second argument\x22\x0a\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.TKeyValueCollection);
+
+
 $core.addTrait("TNativeZeroBasedCollection", "Kernel-Collections");
 $core.addMethod(
 $core.method({
@@ -10111,6 +10107,8 @@ messageSends: []
 }),
 $globals.TNativeZeroBasedCollection);
 
+$core.setTraitComposition([{trait: $globals.TKeyValueCollection}], $globals.AssociativeCollection);
+$core.setTraitComposition([{trait: $globals.TKeyValueCollection}], $globals.SequenceableCollection);
 $core.setTraitComposition([{trait: $globals.TNativeZeroBasedCollection}], $globals.Array);
 $core.setTraitComposition([{trait: $globals.TNativeZeroBasedCollection}], $globals.String);
 

+ 83 - 88
lang/src/Kernel-Collections.st

@@ -460,93 +460,7 @@ withAll: aCollection
 		yourself
 ! !
 
-Collection subclass: #IndexableCollection
-	instanceVariableNames: ''
-	package: 'Kernel-Collections'!
-!IndexableCollection commentStamp!
-I am a key-value store collection, that is,
-I store values under indexes.
-
-As a rule of thumb, if a collection has `#at:` and `#at:put:`,
-it is an IndexableCollection.!
-
-!IndexableCollection methodsFor: 'accessing'!
-
-at: anIndex
-	"Lookup the given index in the receiver.
-	If it is present, answer the value stored at anIndex.
-	Otherwise, raise an error."
-
-	^ self at: anIndex ifAbsent: [ self errorNotFound ]
-!
-
-at: anIndex ifAbsent: aBlock
-	"Lookup the given index in the receiver.
-	If it is present, answer the value stored at anIndex.
-	Otherwise, answer the value of aBlock."
-
-	self subclassResponsibility
-!
-
-at: aKey ifAbsentPut: aBlock
-	^ self at: aKey ifAbsent: [
-		self at: aKey put: aBlock value ]
-!
-
-at: anIndex ifPresent: aBlock
-	"Lookup the given index in the receiver.
-	If it is present, answer the value of evaluating aBlock with the value stored at anIndex.
-	Otherwise, answer nil."
-
-	^ self at: anIndex ifPresent: aBlock ifAbsent: [ nil ]
-!
-
-at: anIndex ifPresent: aBlock ifAbsent: anotherBlock
-	"Lookup the given index in the receiver.
-	If it is present, answer the value of evaluating aBlock with the value stored at anIndex.
-	Otherwise, answer the value of anotherBlock."
-
-	self subclassResponsibility
-!
-
-at: anIndex put: anObject
-	"Store anObject under the given index in the receiver."
-
-	self subclassResponsibility
-!
-
-indexOf: anObject
-	"Lookup index at which anObject is stored in the receiver.
-	If not present, raise an error."
-
-	^ self indexOf: anObject ifAbsent: [ self errorNotFound ]
-!
-
-indexOf: anObject ifAbsent: aBlock
-	"Lookup index at which anObject is stored in the receiver.
-	If not present, return value of executing aBlock."
-
-	self subclassResponsibility
-! !
-
-!IndexableCollection methodsFor: 'enumerating'!
-
-with: anotherCollection do: aBlock
-	"Calls aBlock with every value from self
-	and with indetically-indexed value from anotherCollection"
-
-	self withIndexDo: [ :each :index |
-		aBlock value: each value: (anotherCollection at: index) ]
-!
-
-withIndexDo: aBlock
-	"Calls aBlock with every value from self
-	and with its index as the second argument"
-
-	self subclassResponsibility
-! !
-
-IndexableCollection subclass: #AssociativeCollection
+Collection subclass: #AssociativeCollection
 	instanceVariableNames: ''
 	package: 'Kernel-Collections'!
 !AssociativeCollection commentStamp!
@@ -947,7 +861,7 @@ includesKey: aKey
 	<inlineJS: 'return self.hasOwnProperty(aKey)'>
 ! !
 
-IndexableCollection subclass: #SequenceableCollection
+Collection subclass: #SequenceableCollection
 	instanceVariableNames: ''
 	package: 'Kernel-Collections'!
 !SequenceableCollection commentStamp!
@@ -2345,6 +2259,85 @@ fromString: aString flag: anotherString
 	<inlineJS: 'return new RegExp(aString, anotherString)'>
 ! !
 
+Trait named: #TKeyValueCollection
+	package: 'Kernel-Collections'!
+
+!TKeyValueCollection methodsFor: 'accessing'!
+
+at: anIndex
+	"Lookup the given index in the receiver.
+	If it is present, answer the value stored at anIndex.
+	Otherwise, raise an error."
+
+	^ self at: anIndex ifAbsent: [ self errorNotFound ]
+!
+
+at: anIndex ifAbsent: aBlock
+	"Lookup the given index in the receiver.
+	If it is present, answer the value stored at anIndex.
+	Otherwise, answer the value of aBlock."
+
+	self subclassResponsibility
+!
+
+at: aKey ifAbsentPut: aBlock
+	^ self at: aKey ifAbsent: [
+		self at: aKey put: aBlock value ]
+!
+
+at: anIndex ifPresent: aBlock
+	"Lookup the given index in the receiver.
+	If it is present, answer the value of evaluating aBlock with the value stored at anIndex.
+	Otherwise, answer nil."
+
+	^ self at: anIndex ifPresent: aBlock ifAbsent: [ nil ]
+!
+
+at: anIndex ifPresent: aBlock ifAbsent: anotherBlock
+	"Lookup the given index in the receiver.
+	If it is present, answer the value of evaluating aBlock with the value stored at anIndex.
+	Otherwise, answer the value of anotherBlock."
+
+	self subclassResponsibility
+!
+
+at: anIndex put: anObject
+	"Store anObject under the given index in the receiver."
+
+	self subclassResponsibility
+!
+
+indexOf: anObject
+	"Lookup index at which anObject is stored in the receiver.
+	If not present, raise an error."
+
+	^ self indexOf: anObject ifAbsent: [ self errorNotFound ]
+!
+
+indexOf: anObject ifAbsent: aBlock
+	"Lookup index at which anObject is stored in the receiver.
+	If not present, return value of executing aBlock."
+
+	self subclassResponsibility
+! !
+
+!TKeyValueCollection methodsFor: 'enumerating'!
+
+with: anotherCollection do: aBlock
+	"Calls aBlock with every value from self
+	and with indetically-indexed value from anotherCollection"
+
+	self withIndexDo: [ :each :index |
+		aBlock value: each value: (anotherCollection at: index) ]
+!
+
+withIndexDo: aBlock
+	"Calls aBlock with every value from self
+	and with its index as the second argument"
+
+	self subclassResponsibility
+! !
+
 Trait named: #TNativeZeroBasedCollection
 	package: 'Kernel-Collections'!
 
@@ -2412,6 +2405,8 @@ withIndexDo: aBlock
 	'>
 ! !
 
+AssociativeCollection setTraitComposition: {TKeyValueCollection} asTraitComposition!
+SequenceableCollection setTraitComposition: {TKeyValueCollection} asTraitComposition!
 Array setTraitComposition: {TNativeZeroBasedCollection} asTraitComposition!
 String setTraitComposition: {TNativeZeroBasedCollection} asTraitComposition!
 ! !