Forráskód Böngészése

Dictionary and HashedCollection under common base class

Herbert Vojčík 11 éve
szülő
commit
5d4702f63b
4 módosított fájl, 408 hozzáadás és 297 törlés
  1. 30 30
      js/IDE.js
  2. 277 197
      js/Kernel-Collections.js
  3. 14 14
      st/IDE.st
  4. 87 56
      st/Kernel-Collections.st

+ 30 - 30
js/IDE.js

@@ -7405,21 +7405,27 @@ var $1;
 variables=_st($Dictionary())._new();
 _st(variables)._at_put_("#self",self);
 $ctx1.sendIdx["at:put:"]=1;
-_st(variables)._at_put_("#keys",self._keys());
+_st(variables)._at_put_("#home",self._home());
 $ctx1.sendIdx["at:put:"]=2;
-self._keysAndValuesDo_((function(key,value){
+_st(variables)._at_put_("#receiver",self._receiver());
+$ctx1.sendIdx["at:put:"]=3;
+_st(variables)._at_put_("#selector",self._selector());
+$ctx1.sendIdx["at:put:"]=4;
+_st(variables)._at_put_("#temps",self._temps());
+$ctx1.sendIdx["at:put:"]=5;
+_st(_st(self._class())._instanceVariableNames())._do_((function(each){
 return smalltalk.withContext(function($ctx2) {
-return _st(variables)._at_put_(key,value);
-}, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
+return _st(variables)._at_put_(each,self._instVarAt_(each));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 _st(anInspector)._setLabel_(self._printString());
 $1=_st(anInspector)._setVariables_(variables);
-return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector,variables:variables},smalltalk.HashedCollection)})},
+return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector,variables:variables},smalltalk.MethodContext)})},
 args: ["anInspector"],
-source: "inspectOn: anInspector\x0a\x09| variables |\x0a\x09variables := Dictionary new.\x0a\x09variables at: '#self' put: self.\x0a\x09variables at: '#keys' put: self keys.\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09variables at: key put: value ].\x0a\x09anInspector\x0a\x09\x09setLabel: self printString;\x0a\x09\x09setVariables: variables",
-messageSends: ["new", "at:put:", "keys", "keysAndValuesDo:", "setLabel:", "printString", "setVariables:"],
+source: "inspectOn: anInspector\x0a\x09| variables |\x0a\x09variables := Dictionary new.\x0a\x09variables at: '#self' put: self.\x0a\x09variables at: '#home' put: self home.\x0a\x09variables at: '#receiver' put: self receiver.\x0a\x09variables at: '#selector' put: self selector.\x0a\x09variables at: '#temps' put: self temps.\x0a\x09self class instanceVariableNames do: [ :each |\x0a\x09\x09variables at: each put: (self instVarAt: each) ].\x0a\x09anInspector\x0a\x09\x09setLabel: self printString;\x0a\x09\x09setVariables: variables",
+messageSends: ["new", "at:put:", "home", "receiver", "selector", "temps", "do:", "instanceVariableNames", "class", "instVarAt:", "setLabel:", "printString", "setVariables:"],
 referencedClasses: ["Dictionary"]
 }),
-smalltalk.HashedCollection);
+smalltalk.MethodContext);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -7434,19 +7440,21 @@ var $1;
 variables=_st($Dictionary())._new();
 _st(variables)._at_put_("#self",self);
 $ctx1.sendIdx["at:put:"]=1;
-_st(self["@elements"])._withIndexDo_((function(each,i){
+_st(variables)._at_put_("#keys",self._keys());
+$ctx1.sendIdx["at:put:"]=2;
+self._keysAndValuesDo_((function(key,value){
 return smalltalk.withContext(function($ctx2) {
-return _st(variables)._at_put_(i,each);
-}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1,1)})}));
+return _st(variables)._at_put_(key,value);
+}, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 _st(anInspector)._setLabel_(self._printString());
 $1=_st(anInspector)._setVariables_(variables);
-return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector,variables:variables},smalltalk.Set)})},
+return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector,variables:variables},smalltalk.AssociativeCollection)})},
 args: ["anInspector"],
-source: "inspectOn: anInspector\x0a\x09| variables |\x0a\x09variables := Dictionary new.\x0a\x09variables at: '#self' put: self.\x0a\x09elements withIndexDo: [ :each :i |\x0a\x09\x09variables at: i put: each ].\x0a\x09anInspector\x0a\x09\x09setLabel: self printString;\x0a\x09\x09setVariables: variables",
-messageSends: ["new", "at:put:", "withIndexDo:", "setLabel:", "printString", "setVariables:"],
+source: "inspectOn: anInspector\x0a\x09| variables |\x0a\x09variables := Dictionary new.\x0a\x09variables at: '#self' put: self.\x0a\x09variables at: '#keys' put: self keys.\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09variables at: key put: value ].\x0a\x09anInspector\x0a\x09\x09setLabel: self printString;\x0a\x09\x09setVariables: variables",
+messageSends: ["new", "at:put:", "keys", "keysAndValuesDo:", "setLabel:", "printString", "setVariables:"],
 referencedClasses: ["Dictionary"]
 }),
-smalltalk.Set);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -7461,26 +7469,18 @@ var $1;
 variables=_st($Dictionary())._new();
 _st(variables)._at_put_("#self",self);
 $ctx1.sendIdx["at:put:"]=1;
-_st(variables)._at_put_("#home",self._home());
-$ctx1.sendIdx["at:put:"]=2;
-_st(variables)._at_put_("#receiver",self._receiver());
-$ctx1.sendIdx["at:put:"]=3;
-_st(variables)._at_put_("#selector",self._selector());
-$ctx1.sendIdx["at:put:"]=4;
-_st(variables)._at_put_("#temps",self._temps());
-$ctx1.sendIdx["at:put:"]=5;
-_st(_st(self._class())._instanceVariableNames())._do_((function(each){
+_st(self["@elements"])._withIndexDo_((function(each,i){
 return smalltalk.withContext(function($ctx2) {
-return _st(variables)._at_put_(each,self._instVarAt_(each));
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+return _st(variables)._at_put_(i,each);
+}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1,1)})}));
 _st(anInspector)._setLabel_(self._printString());
 $1=_st(anInspector)._setVariables_(variables);
-return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector,variables:variables},smalltalk.MethodContext)})},
+return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector,variables:variables},smalltalk.Set)})},
 args: ["anInspector"],
-source: "inspectOn: anInspector\x0a\x09| variables |\x0a\x09variables := Dictionary new.\x0a\x09variables at: '#self' put: self.\x0a\x09variables at: '#home' put: self home.\x0a\x09variables at: '#receiver' put: self receiver.\x0a\x09variables at: '#selector' put: self selector.\x0a\x09variables at: '#temps' put: self temps.\x0a\x09self class instanceVariableNames do: [ :each |\x0a\x09\x09variables at: each put: (self instVarAt: each) ].\x0a\x09anInspector\x0a\x09\x09setLabel: self printString;\x0a\x09\x09setVariables: variables",
-messageSends: ["new", "at:put:", "home", "receiver", "selector", "temps", "do:", "instanceVariableNames", "class", "instVarAt:", "setLabel:", "printString", "setVariables:"],
+source: "inspectOn: anInspector\x0a\x09| variables |\x0a\x09variables := Dictionary new.\x0a\x09variables at: '#self' put: self.\x0a\x09elements withIndexDo: [ :each :i |\x0a\x09\x09variables at: i put: each ].\x0a\x09anInspector\x0a\x09\x09setLabel: self printString;\x0a\x09\x09setVariables: variables",
+messageSends: ["new", "at:put:", "withIndexDo:", "setLabel:", "printString", "setVariables:"],
 referencedClasses: ["Dictionary"]
 }),
-smalltalk.MethodContext);
+smalltalk.Set);
 
 });

+ 277 - 197
js/Kernel-Collections.js

@@ -1301,41 +1301,41 @@ smalltalk.IndexableCollection);
 
 
 
-smalltalk.addClass('HashedCollection', smalltalk.IndexableCollection, [], 'Kernel-Collections');
-smalltalk.HashedCollection.comment="I am a traditional JavaScript object, or a Smalltalk `Dictionary`.\x0a\x0aUnlike a `Dictionary`, I can only have strings as keys.";
+smalltalk.addClass('AssociativeCollection', smalltalk.IndexableCollection, [], 'Kernel-Collections');
+smalltalk.AssociativeCollection.comment="I am a base class for object-indexed collections (Dictionary et.al.).";
 smalltalk.addMethod(
 smalltalk.method({
 selector: "=",
 protocol: 'comparing',
-fn: function (aHashedCollection){
+fn: function (anAssocitativeCollection){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $2,$1,$4,$3,$6,$5;
 $2=self._class();
 $ctx1.sendIdx["class"]=1;
-$1=_st($2).__eq(_st(aHashedCollection)._class());
+$1=_st($2).__eq(_st(anAssocitativeCollection)._class());
 $ctx1.sendIdx["="]=1;
 if(! smalltalk.assert($1)){
 return false;
 };
 $4=self._size();
 $ctx1.sendIdx["size"]=1;
-$3=_st($4).__eq(_st(aHashedCollection)._size());
+$3=_st($4).__eq(_st(anAssocitativeCollection)._size());
 $ctx1.sendIdx["="]=2;
 if(! smalltalk.assert($3)){
 return false;
 };
 $6=self._associations();
 $ctx1.sendIdx["associations"]=1;
-$5=_st($6).__eq(_st(aHashedCollection)._associations());
+$5=_st($6).__eq(_st(anAssocitativeCollection)._associations());
 return $5;
-}, function($ctx1) {$ctx1.fill(self,"=",{aHashedCollection:aHashedCollection},smalltalk.HashedCollection)})},
-args: ["aHashedCollection"],
-source: "= aHashedCollection\x0a\x09self class = aHashedCollection class ifFalse: [ ^ false ].\x0a\x09self size = aHashedCollection size ifFalse: [ ^ false ].\x0a\x09^ self associations = aHashedCollection associations",
+}, function($ctx1) {$ctx1.fill(self,"=",{anAssocitativeCollection:anAssocitativeCollection},smalltalk.AssociativeCollection)})},
+args: ["anAssocitativeCollection"],
+source: "= anAssocitativeCollection\x0a\x09self class = anAssocitativeCollection class ifFalse: [ ^ false ].\x0a\x09self size = anAssocitativeCollection size ifFalse: [ ^ false ].\x0a\x09^ self associations = anAssocitativeCollection associations",
 messageSends: ["ifFalse:", "=", "class", "size", "associations"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1345,30 +1345,30 @@ fn: function (anAssociation){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._at_put_(_st(anAssociation)._key(),_st(anAssociation)._value());
-return self}, function($ctx1) {$ctx1.fill(self,"add:",{anAssociation:anAssociation},smalltalk.HashedCollection)})},
+return self}, function($ctx1) {$ctx1.fill(self,"add:",{anAssociation:anAssociation},smalltalk.AssociativeCollection)})},
 args: ["anAssociation"],
 source: "add: anAssociation\x0a\x09self at: anAssociation key put: anAssociation value",
 messageSends: ["at:put:", "key", "value"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
 selector: "addAll:",
 protocol: 'adding/removing',
-fn: function (aHashedCollection){
+fn: function (anAssocitativeCollection){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-smalltalk.HashedCollection.superclass.fn.prototype._addAll_.apply(_st(self), [_st(aHashedCollection)._associations()]);
-return aHashedCollection;
-}, function($ctx1) {$ctx1.fill(self,"addAll:",{aHashedCollection:aHashedCollection},smalltalk.HashedCollection)})},
-args: ["aHashedCollection"],
-source: "addAll: aHashedCollection\x0a\x09super addAll: aHashedCollection associations.\x0a\x09^ aHashedCollection",
+smalltalk.AssociativeCollection.superclass.fn.prototype._addAll_.apply(_st(self), [_st(anAssocitativeCollection)._associations()]);
+return anAssocitativeCollection;
+}, function($ctx1) {$ctx1.fill(self,"addAll:",{anAssocitativeCollection:anAssocitativeCollection},smalltalk.AssociativeCollection)})},
+args: ["anAssocitativeCollection"],
+source: "addAll: anAssocitativeCollection\x0a\x09super addAll: anAssocitativeCollection associations.\x0a\x09^ anAssocitativeCollection",
 messageSends: ["addAll:", "associations"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1381,13 +1381,32 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 $1=_st($Dictionary())._from_(self._associations());
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"asDictionary",{},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"asDictionary",{},smalltalk.AssociativeCollection)})},
 args: [],
 source: "asDictionary\x0a\x09^ Dictionary from: self associations",
 messageSends: ["from:", "associations"],
 referencedClasses: ["Dictionary"]
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "asHashedCollection",
+protocol: 'converting',
+fn: function (){
+var self=this;
+function $HashedCollection(){return smalltalk.HashedCollection||(typeof HashedCollection=="undefined"?nil:HashedCollection)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st($HashedCollection())._from_(self._associations());
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"asHashedCollection",{},smalltalk.AssociativeCollection)})},
+args: [],
+source: "asHashedCollection\x0a\x09^ HashedCollection from: self associations",
+messageSends: ["from:", "associations"],
+referencedClasses: ["HashedCollection"]
+}),
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1396,22 +1415,23 @@ protocol: 'converting',
 fn: function (){
 var self=this;
 var c;
+function $HashedCollection(){return smalltalk.HashedCollection||(typeof HashedCollection=="undefined"?nil:HashedCollection)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-c=_st(self._class())._new();
+c=_st($HashedCollection())._new();
 self._keysAndValuesDo_((function(key,value){
 return smalltalk.withContext(function($ctx2) {
 return _st(c)._at_put_(key,_st(value)._asJSON());
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 $1=c;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"asJSON",{c:c},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"asJSON",{c:c},smalltalk.AssociativeCollection)})},
 args: [],
-source: "asJSON\x0a\x09| c |\x0a\x09c := self class new.\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09c at: key put: value asJSON ].\x0a\x09^ c",
-messageSends: ["new", "class", "keysAndValuesDo:", "at:put:", "asJSON"],
-referencedClasses: []
+source: "asJSON\x0a\x09| c |\x0a\x09c := HashedCollection new.\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09c at: key put: value asJSON ].\x0a\x09^ c",
+messageSends: ["new", "keysAndValuesDo:", "at:put:", "asJSON"],
+referencedClasses: ["HashedCollection"]
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1429,13 +1449,13 @@ return _st(associations)._add_(each);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 $1=associations;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"associations",{associations:associations},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"associations",{associations:associations},smalltalk.AssociativeCollection)})},
 args: [],
 source: "associations\x0a\x09| associations |\x0a\x09associations := #().\x0a\x09self associationsDo: [ :each | associations add: each ].\x0a\x09^ associations",
 messageSends: ["associationsDo:", "add:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1449,35 +1469,13 @@ self._keysAndValuesDo_((function(key,value){
 return smalltalk.withContext(function($ctx2) {
 return _st(aBlock)._value_(_st($Association())._key_value_(key,value));
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"associationsDo:",{aBlock:aBlock},smalltalk.HashedCollection)})},
+return self}, function($ctx1) {$ctx1.fill(self,"associationsDo:",{aBlock:aBlock},smalltalk.AssociativeCollection)})},
 args: ["aBlock"],
 source: "associationsDo: aBlock\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09aBlock value: (Association key: key value: value) ]",
 messageSends: ["keysAndValuesDo:", "value:", "key:value:"],
 referencedClasses: ["Association"]
 }),
-smalltalk.HashedCollection);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "at:ifAbsent:",
-protocol: 'accessing',
-fn: function (aKey,aBlock){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self._includesKey_(aKey);
-$1=_st($2)._ifTrue_ifFalse_((function(){
-return smalltalk.withContext(function($ctx2) {
-return self._basicAt_(aKey);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}),aBlock);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"at:ifAbsent:",{aKey:aKey,aBlock:aBlock},smalltalk.HashedCollection)})},
-args: ["aKey", "aBlock"],
-source: "at: aKey ifAbsent: aBlock\x0a\x09^ (self includesKey: aKey)\x0a\x09\x09ifTrue: [ self basicAt: aKey ]\x0a\x09\x09ifFalse: aBlock",
-messageSends: ["ifTrue:ifFalse:", "includesKey:", "basicAt:"],
-referencedClasses: []
-}),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1493,31 +1491,13 @@ return smalltalk.withContext(function($ctx2) {
 return _st(aBlock)._value_(self._at_(aKey));
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}),anotherBlock);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"at:ifPresent:ifAbsent:",{aKey:aKey,aBlock:aBlock,anotherBlock:anotherBlock},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"at:ifPresent:ifAbsent:",{aKey:aKey,aBlock:aBlock,anotherBlock:anotherBlock},smalltalk.AssociativeCollection)})},
 args: ["aKey", "aBlock", "anotherBlock"],
 source: "at: aKey ifPresent: aBlock ifAbsent: anotherBlock\x0a\x09\x22Lookup the given key in the receiver.\x0a\x09If it is present, answer the value of evaluating the oneArgBlock with the value associated with the key,\x0a\x09otherwise answer the value of absentBlock.\x22\x0a\x09^ (self includesKey: aKey)\x0a\x09\x09ifTrue: [ aBlock value: (self at: aKey) ]\x0a\x09\x09ifFalse: anotherBlock",
 messageSends: ["ifTrue:ifFalse:", "includesKey:", "value:", "at:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "at:put:",
-protocol: 'accessing',
-fn: function (aKey,aValue){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=self._basicAt_put_(aKey,aValue);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"at:put:",{aKey:aKey,aValue:aValue},smalltalk.HashedCollection)})},
-args: ["aKey", "aValue"],
-source: "at: aKey put: aValue\x0a\x09^ self basicAt: aKey put: aValue",
-messageSends: ["basicAt:put:"],
-referencedClasses: []
-}),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1535,13 +1515,13 @@ return _st(newDict)._at_put_(key,_st(aBlock)._value_(value));
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 $1=newDict;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"collect:",{aBlock:aBlock,newDict:newDict},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"collect:",{aBlock:aBlock,newDict:newDict},smalltalk.AssociativeCollection)})},
 args: ["aBlock"],
 source: "collect: aBlock\x0a\x09| newDict |\x0a\x09newDict := self class new.\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09newDict at: key put: (aBlock value: value) ].\x0a\x09^ newDict",
 messageSends: ["new", "class", "keysAndValuesDo:", "at:put:", "value:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1559,13 +1539,13 @@ return _st(copy)._at_put_(key,_st(value)._deepCopy());
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 $1=copy;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"deepCopy",{copy:copy},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"deepCopy",{copy:copy},smalltalk.AssociativeCollection)})},
 args: [],
 source: "deepCopy\x0a\x09| copy |\x0a\x09copy := self class new.\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09copy at: key put: value deepCopy ].\x0a\x09^ copy",
 messageSends: ["new", "class", "keysAndValuesDo:", "at:put:", "deepCopy"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1577,13 +1557,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 $1=_st(self._values())._detect_ifNone_(aBlock,anotherBlock);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"detect:ifNone:",{aBlock:aBlock,anotherBlock:anotherBlock},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"detect:ifNone:",{aBlock:aBlock,anotherBlock:anotherBlock},smalltalk.AssociativeCollection)})},
 args: ["aBlock", "anotherBlock"],
 source: "detect: aBlock ifNone: anotherBlock\x0a\x09^ self values detect: aBlock ifNone: anotherBlock",
 messageSends: ["detect:ifNone:", "values"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1593,13 +1573,13 @@ fn: function (aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 self._valuesDo_(aBlock);
-return self}, function($ctx1) {$ctx1.fill(self,"do:",{aBlock:aBlock},smalltalk.HashedCollection)})},
+return self}, function($ctx1) {$ctx1.fill(self,"do:",{aBlock:aBlock},smalltalk.AssociativeCollection)})},
 args: ["aBlock"],
 source: "do: aBlock\x0a\x09self valuesDo: aBlock",
 messageSends: ["valuesDo:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1611,13 +1591,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 $1=_st(self._values())._includes_(anObject);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"includes:",{anObject:anObject},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"includes:",{anObject:anObject},smalltalk.AssociativeCollection)})},
 args: ["anObject"],
 source: "includes: anObject\x0a\x09^ self values includes: anObject",
 messageSends: ["includes:", "values"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1626,14 +1606,14 @@ protocol: 'testing',
 fn: function (aKey){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-return self.hasOwnProperty(aKey);
-return self}, function($ctx1) {$ctx1.fill(self,"includesKey:",{aKey:aKey},smalltalk.HashedCollection)})},
+self._subclassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"includesKey:",{aKey:aKey},smalltalk.AssociativeCollection)})},
 args: ["aKey"],
-source: "includesKey: aKey\x0a\x09<return self.hasOwnProperty(aKey)>",
-messageSends: [],
+source: "includesKey: aKey\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1648,13 +1628,13 @@ return smalltalk.withContext(function($ctx2) {
 return _st(self._at_(each)).__eq(anObject);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}),aBlock);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"indexOf:ifAbsent:",{anObject:anObject,aBlock:aBlock},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"indexOf:ifAbsent:",{anObject:anObject,aBlock:aBlock},smalltalk.AssociativeCollection)})},
 args: ["anObject", "aBlock"],
-source: "indexOf: anObject ifAbsent: aBlock\x0a\x0a\x09^ self keys detect: [ :each | (self at: each) = anObject ] ifNone: aBlock",
+source: "indexOf: anObject ifAbsent: aBlock\x0a\x09^ self keys detect: [ :each | (self at: each) = anObject ] ifNone: aBlock",
 messageSends: ["detect:ifNone:", "keys", "=", "at:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1669,13 +1649,13 @@ return smalltalk.withContext(function($ctx2) {
 return self._errorNotFound();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"keyAtValue:",{anObject:anObject},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"keyAtValue:",{anObject:anObject},smalltalk.AssociativeCollection)})},
 args: ["anObject"],
 source: "keyAtValue: anObject\x0a\x09^ self keyAtValue: anObject ifAbsent: [ self errorNotFound ]",
 messageSends: ["keyAtValue:ifAbsent:", "errorNotFound"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1687,13 +1667,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 $1=self._indexOf_ifAbsent_(anObject,aBlock);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"keyAtValue:ifAbsent:",{anObject:anObject,aBlock:aBlock},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"keyAtValue:ifAbsent:",{anObject:anObject,aBlock:aBlock},smalltalk.AssociativeCollection)})},
 args: ["anObject", "aBlock"],
 source: "keyAtValue: anObject ifAbsent: aBlock\x0a\x09^ self indexOf: anObject ifAbsent: aBlock",
 messageSends: ["indexOf:ifAbsent:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1702,14 +1682,14 @@ protocol: 'accessing',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-return Object.keys(self);
-return self}, function($ctx1) {$ctx1.fill(self,"keys",{},smalltalk.HashedCollection)})},
+self._subclassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"keys",{},smalltalk.AssociativeCollection)})},
 args: [],
-source: "keys\x0a\x09<return Object.keys(self)>",
-messageSends: [],
+source: "keys\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1722,13 +1702,13 @@ self._keysDo_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return _st(aBlock)._value_value_(each,self._at_(each));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"keysAndValuesDo:",{aBlock:aBlock},smalltalk.HashedCollection)})},
+return self}, function($ctx1) {$ctx1.fill(self,"keysAndValuesDo:",{aBlock:aBlock},smalltalk.AssociativeCollection)})},
 args: ["aBlock"],
 source: "keysAndValuesDo: aBlock\x0a\x09self keysDo: [ :each |\x0a\x09\x09aBlock value: each value: (self at: each) ]",
 messageSends: ["keysDo:", "value:value:", "at:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1737,14 +1717,14 @@ protocol: 'enumerating',
 fn: function (aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(self._keys())._do_(aBlock);
-return self}, function($ctx1) {$ctx1.fill(self,"keysDo:",{aBlock:aBlock},smalltalk.HashedCollection)})},
+self._subclassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"keysDo:",{aBlock:aBlock},smalltalk.AssociativeCollection)})},
 args: ["aBlock"],
-source: "keysDo: aBlock\x0a\x09self keys do: aBlock",
-messageSends: ["do:", "keys"],
+source: "keysDo: aBlock\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1753,7 +1733,7 @@ protocol: 'printing',
 fn: function (aStream){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-smalltalk.HashedCollection.superclass.fn.prototype._printOn_.apply(_st(self), [aStream]);
+smalltalk.AssociativeCollection.superclass.fn.prototype._printOn_.apply(_st(self), [aStream]);
 $ctx1.sendIdx["printOn:"]=1;
 _st(aStream)._nextPutAll_(" (");
 $ctx1.sendIdx["nextPutAll:"]=1;
@@ -1766,13 +1746,13 @@ return _st(aStream)._nextPutAll_(" , ");
 $ctx2.sendIdx["nextPutAll:"]=2;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 _st(aStream)._nextPutAll_(")");
-return self}, function($ctx1) {$ctx1.fill(self,"printOn:",{aStream:aStream},smalltalk.HashedCollection)})},
+return self}, function($ctx1) {$ctx1.fill(self,"printOn:",{aStream:aStream},smalltalk.AssociativeCollection)})},
 args: ["aStream"],
 source: "printOn: aStream\x0a\x09super printOn: aStream.\x0a\x09\x0a\x09aStream nextPutAll: ' ('.\x0a\x09self associations\x0a\x09\x09do: [ :each | each printOn: aStream ]\x0a\x09\x09separatedBy: [ aStream nextPutAll: ' , ' ].\x0a\x09aStream nextPutAll: ')'",
 messageSends: ["printOn:", "nextPutAll:", "do:separatedBy:", "associations"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1784,13 +1764,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 $1=self._removeKey_ifAbsent_(aKey,aBlock);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"remove:ifAbsent:",{aKey:aKey,aBlock:aBlock},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"remove:ifAbsent:",{aKey:aKey,aBlock:aBlock},smalltalk.AssociativeCollection)})},
 args: ["aKey", "aBlock"],
 source: "remove: aKey ifAbsent: aBlock\x0a\x09^ self removeKey: aKey ifAbsent: aBlock",
 messageSends: ["removeKey:ifAbsent:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1805,13 +1785,13 @@ return smalltalk.withContext(function($ctx2) {
 return self._removeKey_(each);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"removeAll",{},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"removeAll",{},smalltalk.AssociativeCollection)})},
 args: [],
 source: "removeAll\x0a\x09^ self keys do: [ :each | self removeKey: each ]",
 messageSends: ["do:", "keys", "removeKey:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1823,13 +1803,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 $1=self._remove_(aKey);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"removeKey:",{aKey:aKey},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"removeKey:",{aKey:aKey},smalltalk.AssociativeCollection)})},
 args: ["aKey"],
 source: "removeKey: aKey\x0a\x09^ self remove: aKey",
 messageSends: ["remove:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1838,21 +1818,14 @@ protocol: 'adding/removing',
 fn: function (aKey,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self._includesKey_(aKey);
-if(smalltalk.assert($2)){
-$1=self._basicDelete_(aKey);
-} else {
-$1=_st(aBlock)._value();
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"removeKey:ifAbsent:",{aKey:aKey,aBlock:aBlock},smalltalk.HashedCollection)})},
+self._subclassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"removeKey:ifAbsent:",{aKey:aKey,aBlock:aBlock},smalltalk.AssociativeCollection)})},
 args: ["aKey", "aBlock"],
-source: "removeKey: aKey ifAbsent: aBlock\x0a\x09^ (self includesKey: aKey)\x0a\x09\x09ifFalse: [ aBlock value ]\x0a\x09\x09ifTrue: [ self basicDelete: aKey ]",
-messageSends: ["ifFalse:ifTrue:", "includesKey:", "value", "basicDelete:"],
+source: "removeKey: aKey ifAbsent: aBlock\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1873,13 +1846,13 @@ return _st(newDict)._at_put_(key,value);
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 $2=newDict;
 return $2;
-}, function($ctx1) {$ctx1.fill(self,"select:",{aBlock:aBlock,newDict:newDict},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"select:",{aBlock:aBlock,newDict:newDict},smalltalk.AssociativeCollection)})},
 args: ["aBlock"],
 source: "select: aBlock\x0a\x09| newDict |\x0a\x09newDict := self class new.\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09(aBlock value: value) ifTrue: [ newDict at: key put: value ]].\x0a\x09^ newDict",
 messageSends: ["new", "class", "keysAndValuesDo:", "ifTrue:", "value:", "at:put:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1897,13 +1870,13 @@ return _st(copy)._at_put_(key,value);
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 $1=copy;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"shallowCopy",{copy:copy},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"shallowCopy",{copy:copy},smalltalk.AssociativeCollection)})},
 args: [],
 source: "shallowCopy\x0a\x09| copy |\x0a\x09copy := self class new.\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09copy at: key put: value ].\x0a\x09^ copy",
 messageSends: ["new", "class", "keysAndValuesDo:", "at:put:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1915,13 +1888,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 $1=_st(self._keys())._size();
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"size",{},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"size",{},smalltalk.AssociativeCollection)})},
 args: [],
 source: "size\x0a\x09^ self keys size",
 messageSends: ["size", "keys"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1930,18 +1903,14 @@ protocol: 'accessing',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-
-		return self._keys().map(function(key){
-			return self._at_(key);
-		});
-	;
-return self}, function($ctx1) {$ctx1.fill(self,"values",{},smalltalk.HashedCollection)})},
+self._subclassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"values",{},smalltalk.AssociativeCollection)})},
 args: [],
-source: "values\x0a\x09<\x0a\x09\x09return self._keys().map(function(key){\x0a\x09\x09\x09return self._at_(key);\x0a\x09\x09});\x0a\x09>",
-messageSends: [],
+source: "values\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1950,17 +1919,14 @@ protocol: 'enumerating',
 fn: function (aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(self._values())._do_((function(value){
-return smalltalk.withContext(function($ctx2) {
-return _st(aBlock)._value_(value);
-}, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1,1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"valuesDo:",{aBlock:aBlock},smalltalk.HashedCollection)})},
+self._subclassResponsibility();
+return self}, function($ctx1) {$ctx1.fill(self,"valuesDo:",{aBlock:aBlock},smalltalk.AssociativeCollection)})},
 args: ["aBlock"],
-source: "valuesDo: aBlock\x0a\x09self values do: [ :value | aBlock value: value ]",
-messageSends: ["do:", "values", "value:"],
+source: "valuesDo: aBlock\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -1973,13 +1939,13 @@ self._keysAndValuesDo_((function(key,value){
 return smalltalk.withContext(function($ctx2) {
 return _st(aBlock)._value_value_(value,key);
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"withIndexDo:",{aBlock:aBlock},smalltalk.HashedCollection)})},
+return self}, function($ctx1) {$ctx1.fill(self,"withIndexDo:",{aBlock:aBlock},smalltalk.AssociativeCollection)})},
 args: ["aBlock"],
 source: "withIndexDo: aBlock\x0a\x09self keysAndValuesDo: [ :key :value | aBlock value: value value: key ]",
 messageSends: ["keysAndValuesDo:", "value:value:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
@@ -1998,13 +1964,13 @@ return _st(newCollection)._add_(each);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 $1=newCollection;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"from:",{aCollection:aCollection,newCollection:newCollection},smalltalk.HashedCollection.klass)})},
+}, function($ctx1) {$ctx1.fill(self,"from:",{aCollection:aCollection,newCollection:newCollection},smalltalk.AssociativeCollection.klass)})},
 args: ["aCollection"],
 source: "from: aCollection\x0a\x09| newCollection |\x0a\x09newCollection := self new.\x0a\x09aCollection do: [ :each | newCollection add: each ].\x0a\x09^ newCollection",
 messageSends: ["new", "do:", "add:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection.klass);
+smalltalk.AssociativeCollection.klass);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -2016,13 +1982,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 $1=self._from_(aCollection);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"fromPairs:",{aCollection:aCollection},smalltalk.HashedCollection.klass)})},
+}, function($ctx1) {$ctx1.fill(self,"fromPairs:",{aCollection:aCollection},smalltalk.AssociativeCollection.klass)})},
 args: ["aCollection"],
 source: "fromPairs: aCollection\x0a\x09\x22This message is poorly named and has been replaced by #from:\x22\x0a\x09^ self from: aCollection",
 messageSends: ["from:"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection.klass);
+smalltalk.AssociativeCollection.klass);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -2049,54 +2015,17 @@ return _st($3)._at_put_($4,_st(aCollection)._at_(_st(each).__plus((1))));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}));
 $5=newCollection;
 return $5;
-}, function($ctx1) {$ctx1.fill(self,"newFromPairs:",{aCollection:aCollection,newCollection:newCollection},smalltalk.HashedCollection.klass)})},
+}, function($ctx1) {$ctx1.fill(self,"newFromPairs:",{aCollection:aCollection,newCollection:newCollection},smalltalk.AssociativeCollection.klass)})},
 args: ["aCollection"],
 source: "newFromPairs: aCollection\x0a\x09\x22Accept an array of elements where every two elements form an \x0a\x09association - the odd element being the key, and the even element the value.\x22\x0a\x09\x0a\x09| newCollection |\x0a\x09\x0a\x09aCollection size even ifFalse: [ \x0a\x09\x09self error: '#newFromPairs only accepts arrays of an even length' ].\x0a\x09\x09\x0a\x09newCollection := self new.\x0a\x09( 1 to: aCollection size by: 2 ) do: [ :each | \x0a\x09\x09newCollection at: (aCollection at: each) put: (aCollection at: each + 1) ].\x0a\x09\x09\x0a\x09^ newCollection",
 messageSends: ["ifFalse:", "even", "size", "error:", "new", "do:", "to:by:", "at:put:", "at:", "+"],
 referencedClasses: []
 }),
-smalltalk.HashedCollection.klass);
+smalltalk.AssociativeCollection.klass);
 
 
-smalltalk.addClass('Dictionary', smalltalk.HashedCollection, ['keys', 'values'], 'Kernel-Collections');
+smalltalk.addClass('Dictionary', smalltalk.AssociativeCollection, ['keys', 'values'], 'Kernel-Collections');
 smalltalk.Dictionary.comment="I represent a set of elements that can be viewed from one of two perspectives: a set of associations,\x0aor a container of values that are externally named where the name can be any object that responds to `=`.\x0a\x0aThe external name is referred to as the key.";
-smalltalk.addMethod(
-smalltalk.method({
-selector: "asHashedCollection",
-protocol: 'converting',
-fn: function (){
-var self=this;
-function $HashedCollection(){return smalltalk.HashedCollection||(typeof HashedCollection=="undefined"?nil:HashedCollection)}
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st($HashedCollection())._from_(self._associations());
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"asHashedCollection",{},smalltalk.Dictionary)})},
-args: [],
-source: "asHashedCollection\x0a\x09^ HashedCollection from: self associations",
-messageSends: ["from:", "associations"],
-referencedClasses: ["HashedCollection"]
-}),
-smalltalk.Dictionary);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "asJSON",
-protocol: 'converting',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(self._asHashedCollection())._asJSON();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"asJSON",{},smalltalk.Dictionary)})},
-args: [],
-source: "asJSON\x0a\x09^ self asHashedCollection asJSON",
-messageSends: ["asJSON", "asHashedCollection"],
-referencedClasses: []
-}),
-smalltalk.Dictionary);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "at:ifAbsent:",
@@ -2364,6 +2293,157 @@ smalltalk.Dictionary);
 
 
 
+smalltalk.addClass('HashedCollection', smalltalk.AssociativeCollection, [], 'Kernel-Collections');
+smalltalk.HashedCollection.comment="I am a traditional JavaScript object, or a Smalltalk `Dictionary`.\x0a\x0aUnlike a `Dictionary`, I can only have strings as keys.";
+smalltalk.addMethod(
+smalltalk.method({
+selector: "at:ifAbsent:",
+protocol: 'accessing',
+fn: function (aKey,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self._includesKey_(aKey);
+$1=_st($2)._ifTrue_ifFalse_((function(){
+return smalltalk.withContext(function($ctx2) {
+return self._basicAt_(aKey);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}),aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"at:ifAbsent:",{aKey:aKey,aBlock:aBlock},smalltalk.HashedCollection)})},
+args: ["aKey", "aBlock"],
+source: "at: aKey ifAbsent: aBlock\x0a\x09^ (self includesKey: aKey)\x0a\x09\x09ifTrue: [ self basicAt: aKey ]\x0a\x09\x09ifFalse: aBlock",
+messageSends: ["ifTrue:ifFalse:", "includesKey:", "basicAt:"],
+referencedClasses: []
+}),
+smalltalk.HashedCollection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "at:put:",
+protocol: 'accessing',
+fn: function (aKey,aValue){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self._basicAt_put_(aKey,aValue);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"at:put:",{aKey:aKey,aValue:aValue},smalltalk.HashedCollection)})},
+args: ["aKey", "aValue"],
+source: "at: aKey put: aValue\x0a\x09^ self basicAt: aKey put: aValue",
+messageSends: ["basicAt:put:"],
+referencedClasses: []
+}),
+smalltalk.HashedCollection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "includesKey:",
+protocol: 'testing',
+fn: function (aKey){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return self.hasOwnProperty(aKey);
+return self}, function($ctx1) {$ctx1.fill(self,"includesKey:",{aKey:aKey},smalltalk.HashedCollection)})},
+args: ["aKey"],
+source: "includesKey: aKey\x0a\x09<return self.hasOwnProperty(aKey)>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HashedCollection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "keys",
+protocol: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Object.keys(self);
+return self}, function($ctx1) {$ctx1.fill(self,"keys",{},smalltalk.HashedCollection)})},
+args: [],
+source: "keys\x0a\x09<return Object.keys(self)>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HashedCollection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "keysDo:",
+protocol: 'enumerating',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self._keys())._do_(aBlock);
+return self}, function($ctx1) {$ctx1.fill(self,"keysDo:",{aBlock:aBlock},smalltalk.HashedCollection)})},
+args: ["aBlock"],
+source: "keysDo: aBlock\x0a\x09self keys do: aBlock",
+messageSends: ["do:", "keys"],
+referencedClasses: []
+}),
+smalltalk.HashedCollection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "removeKey:ifAbsent:",
+protocol: 'adding/removing',
+fn: function (aKey,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self._includesKey_(aKey);
+if(smalltalk.assert($2)){
+$1=self._basicDelete_(aKey);
+} else {
+$1=_st(aBlock)._value();
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"removeKey:ifAbsent:",{aKey:aKey,aBlock:aBlock},smalltalk.HashedCollection)})},
+args: ["aKey", "aBlock"],
+source: "removeKey: aKey ifAbsent: aBlock\x0a\x09^ (self includesKey: aKey)\x0a\x09\x09ifFalse: [ aBlock value ]\x0a\x09\x09ifTrue: [ self basicDelete: aKey ]",
+messageSends: ["ifFalse:ifTrue:", "includesKey:", "value", "basicDelete:"],
+referencedClasses: []
+}),
+smalltalk.HashedCollection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "values",
+protocol: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+
+		return self._keys().map(function(key){
+			return self._at_(key);
+		});
+	;
+return self}, function($ctx1) {$ctx1.fill(self,"values",{},smalltalk.HashedCollection)})},
+args: [],
+source: "values\x0a\x09<\x0a\x09\x09return self._keys().map(function(key){\x0a\x09\x09\x09return self._at_(key);\x0a\x09\x09});\x0a\x09>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HashedCollection);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "valuesDo:",
+protocol: 'enumerating',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self._values())._do_(aBlock);
+return self}, function($ctx1) {$ctx1.fill(self,"valuesDo:",{aBlock:aBlock},smalltalk.HashedCollection)})},
+args: ["aBlock"],
+source: "valuesDo: aBlock\x0a\x09self values do: aBlock",
+messageSends: ["do:", "values"],
+referencedClasses: []
+}),
+smalltalk.HashedCollection);
+
+
+
 smalltalk.addClass('SequenceableCollection', smalltalk.IndexableCollection, [], 'Kernel-Collections');
 smalltalk.SequenceableCollection.comment="I am an IndexableCollection\x0awith numeric indexes starting with 1.";
 smalltalk.addMethod(

+ 14 - 14
st/IDE.st

@@ -2343,45 +2343,45 @@ inspectOn: anInspector
 	anInspector setLabel: label
 ! !
 
-!HashedCollection methodsFor: '*IDE'!
+!MethodContext methodsFor: '*IDE'!
 
 inspectOn: anInspector
 	| variables |
 	variables := Dictionary new.
 	variables at: '#self' put: self.
-	variables at: '#keys' put: self keys.
-	self keysAndValuesDo: [ :key :value |
-		variables at: key put: value ].
+	variables at: '#home' put: self home.
+	variables at: '#receiver' put: self receiver.
+	variables at: '#selector' put: self selector.
+	variables at: '#temps' put: self temps.
+	self class instanceVariableNames do: [ :each |
+		variables at: each put: (self instVarAt: each) ].
 	anInspector
 		setLabel: self printString;
 		setVariables: variables
 ! !
 
-!Set methodsFor: '*IDE'!
+!AssociativeCollection methodsFor: '*IDE'!
 
 inspectOn: anInspector
 	| variables |
 	variables := Dictionary new.
 	variables at: '#self' put: self.
-	elements withIndexDo: [ :each :i |
-		variables at: i put: each ].
+	variables at: '#keys' put: self keys.
+	self keysAndValuesDo: [ :key :value |
+		variables at: key put: value ].
 	anInspector
 		setLabel: self printString;
 		setVariables: variables
 ! !
 
-!MethodContext methodsFor: '*IDE'!
+!Set methodsFor: '*IDE'!
 
 inspectOn: anInspector
 	| variables |
 	variables := Dictionary new.
 	variables at: '#self' put: self.
-	variables at: '#home' put: self home.
-	variables at: '#receiver' put: self receiver.
-	variables at: '#selector' put: self selector.
-	variables at: '#temps' put: self temps.
-	self class instanceVariableNames do: [ :each |
-		variables at: each put: (self instVarAt: each) ].
+	elements withIndexDo: [ :each :i |
+		variables at: i put: each ].
 	anInspector
 		setLabel: self printString;
 		setVariables: variables

+ 87 - 56
st/Kernel-Collections.st

@@ -435,15 +435,13 @@ withIndexDo: aBlock
 	self subclassResponsibility
 ! !
 
-IndexableCollection subclass: #HashedCollection
+IndexableCollection subclass: #AssociativeCollection
 	instanceVariableNames: ''
 	package: 'Kernel-Collections'!
-!HashedCollection commentStamp!
-I am a traditional JavaScript object, or a Smalltalk `Dictionary`.
+!AssociativeCollection commentStamp!
+I am a base class for object-indexed collections (Dictionary et.al.).!
 
-Unlike a `Dictionary`, I can only have strings as keys.!
-
-!HashedCollection methodsFor: 'accessing'!
+!AssociativeCollection methodsFor: 'accessing'!
 
 associations
 	| associations |
@@ -452,12 +450,6 @@ associations
 	^ associations
 !
 
-at: aKey ifAbsent: aBlock
-	^ (self includesKey: aKey)
-		ifTrue: [ self basicAt: aKey ]
-		ifFalse: aBlock
-!
-
 at: aKey ifPresent: aBlock ifAbsent: anotherBlock
 	"Lookup the given key in the receiver.
 	If it is present, answer the value of evaluating the oneArgBlock with the value associated with the key,
@@ -467,12 +459,7 @@ at: aKey ifPresent: aBlock ifAbsent: anotherBlock
 		ifFalse: anotherBlock
 !
 
-at: aKey put: aValue
-	^ self basicAt: aKey put: aValue
-!
-
 indexOf: anObject ifAbsent: aBlock
-
 	^ self keys detect: [ :each | (self at: each) = anObject ] ifNone: aBlock
 !
 
@@ -485,7 +472,7 @@ keyAtValue: anObject ifAbsent: aBlock
 !
 
 keys
-	<return Object.keys(self)>
+	self subclassResponsibility
 !
 
 size
@@ -493,22 +480,18 @@ size
 !
 
 values
-	<
-		return self._keys().map(function(key){
-			return self._at_(key);
-		});
-	>
+	self subclassResponsibility
 ! !
 
-!HashedCollection methodsFor: 'adding/removing'!
+!AssociativeCollection methodsFor: 'adding/removing'!
 
 add: anAssociation
 	self at: anAssociation key put: anAssociation value
 !
 
-addAll: aHashedCollection
-	super addAll: aHashedCollection associations.
-	^ aHashedCollection
+addAll: anAssocitativeCollection
+	super addAll: anAssocitativeCollection associations.
+	^ anAssocitativeCollection
 !
 
 remove: aKey ifAbsent: aBlock
@@ -524,34 +507,36 @@ removeKey: aKey
 !
 
 removeKey: aKey ifAbsent: aBlock
-	^ (self includesKey: aKey)
-		ifFalse: [ aBlock value ]
-		ifTrue: [ self basicDelete: aKey ]
+	self subclassResponsibility
 ! !
 
-!HashedCollection methodsFor: 'comparing'!
+!AssociativeCollection methodsFor: 'comparing'!
 
-= aHashedCollection
-	self class = aHashedCollection class ifFalse: [ ^ false ].
-	self size = aHashedCollection size ifFalse: [ ^ false ].
-	^ self associations = aHashedCollection associations
+= anAssocitativeCollection
+	self class = anAssocitativeCollection class ifFalse: [ ^ false ].
+	self size = anAssocitativeCollection size ifFalse: [ ^ false ].
+	^ self associations = anAssocitativeCollection associations
 ! !
 
-!HashedCollection methodsFor: 'converting'!
+!AssociativeCollection methodsFor: 'converting'!
 
 asDictionary
 	^ Dictionary from: self associations
 !
 
+asHashedCollection
+	^ HashedCollection from: self associations
+!
+
 asJSON
 	| c |
-	c := self class new.
+	c := HashedCollection new.
 	self keysAndValuesDo: [ :key :value |
 		c at: key put: value asJSON ].
 	^ c
 ! !
 
-!HashedCollection methodsFor: 'copying'!
+!AssociativeCollection methodsFor: 'copying'!
 
 deepCopy
 	| copy |
@@ -569,7 +554,7 @@ shallowCopy
 	^ copy
 ! !
 
-!HashedCollection methodsFor: 'enumerating'!
+!AssociativeCollection methodsFor: 'enumerating'!
 
 associationsDo: aBlock
 	self keysAndValuesDo: [ :key :value |
@@ -602,7 +587,7 @@ keysAndValuesDo: aBlock
 !
 
 keysDo: aBlock
-	self keys do: aBlock
+	self subclassResponsibility
 !
 
 select: aBlock
@@ -614,14 +599,14 @@ select: aBlock
 !
 
 valuesDo: aBlock
-	self values do: [ :value | aBlock value: value ]
+	self subclassResponsibility
 !
 
 withIndexDo: aBlock
 	self keysAndValuesDo: [ :key :value | aBlock value: value value: key ]
 ! !
 
-!HashedCollection methodsFor: 'printing'!
+!AssociativeCollection methodsFor: 'printing'!
 
 printOn: aStream
 	super printOn: aStream.
@@ -633,13 +618,13 @@ printOn: aStream
 	aStream nextPutAll: ')'
 ! !
 
-!HashedCollection methodsFor: 'testing'!
+!AssociativeCollection methodsFor: 'testing'!
 
 includesKey: aKey
-	<return self.hasOwnProperty(aKey)>
+	self subclassResponsibility
 ! !
 
-!HashedCollection class methodsFor: 'instance creation'!
+!AssociativeCollection class methodsFor: 'instance creation'!
 
 from: aCollection
 	| newCollection |
@@ -669,7 +654,7 @@ newFromPairs: aCollection
 	^ newCollection
 ! !
 
-HashedCollection subclass: #Dictionary
+AssociativeCollection subclass: #Dictionary
 	instanceVariableNames: 'keys values'
 	package: 'Kernel-Collections'!
 !Dictionary commentStamp!
@@ -742,16 +727,6 @@ removeKey: aKey ifAbsent: aBlock
 	>
 ! !
 
-!Dictionary methodsFor: 'converting'!
-
-asHashedCollection
-	^ HashedCollection from: self associations
-!
-
-asJSON
-	^ self asHashedCollection asJSON
-! !
-
 !Dictionary methodsFor: 'enumerating'!
 
 keysAndValuesDo: aBlock
@@ -792,6 +767,62 @@ includesKey: aKey
 	< return self._positionOfKey_(aKey) >>= 0; >
 ! !
 
+AssociativeCollection subclass: #HashedCollection
+	instanceVariableNames: ''
+	package: 'Kernel-Collections'!
+!HashedCollection commentStamp!
+I am a traditional JavaScript object, or a Smalltalk `Dictionary`.
+
+Unlike a `Dictionary`, I can only have strings as keys.!
+
+!HashedCollection methodsFor: 'accessing'!
+
+at: aKey ifAbsent: aBlock
+	^ (self includesKey: aKey)
+		ifTrue: [ self basicAt: aKey ]
+		ifFalse: aBlock
+!
+
+at: aKey put: aValue
+	^ self basicAt: aKey put: aValue
+!
+
+keys
+	<return Object.keys(self)>
+!
+
+values
+	<
+		return self._keys().map(function(key){
+			return self._at_(key);
+		});
+	>
+! !
+
+!HashedCollection methodsFor: 'adding/removing'!
+
+removeKey: aKey ifAbsent: aBlock
+	^ (self includesKey: aKey)
+		ifFalse: [ aBlock value ]
+		ifTrue: [ self basicDelete: aKey ]
+! !
+
+!HashedCollection methodsFor: 'enumerating'!
+
+keysDo: aBlock
+	self keys do: aBlock
+!
+
+valuesDo: aBlock
+	self values do: aBlock
+! !
+
+!HashedCollection methodsFor: 'testing'!
+
+includesKey: aKey
+	<return self.hasOwnProperty(aKey)>
+! !
+
 IndexableCollection subclass: #SequenceableCollection
 	instanceVariableNames: ''
 	package: 'Kernel-Collections'!