Browse Source

Dictionary and HashedCollection under common base class

Herbert Vojčík 11 năm trước cách đây
mục cha
commit
5d4702f63b
4 tập tin đã thay đổi với 408 bổ sung297 xóa
  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();
 variables=_st($Dictionary())._new();
 _st(variables)._at_put_("#self",self);
 _st(variables)._at_put_("#self",self);
 $ctx1.sendIdx["at:put:"]=1;
 $ctx1.sendIdx["at:put:"]=1;
-_st(variables)._at_put_("#keys",self._keys());
+_st(variables)._at_put_("#home",self._home());
 $ctx1.sendIdx["at:put:"]=2;
 $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 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());
 _st(anInspector)._setLabel_(self._printString());
 $1=_st(anInspector)._setVariables_(variables);
 $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"],
 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"]
 referencedClasses: ["Dictionary"]
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.MethodContext);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -7434,19 +7440,21 @@ var $1;
 variables=_st($Dictionary())._new();
 variables=_st($Dictionary())._new();
 _st(variables)._at_put_("#self",self);
 _st(variables)._at_put_("#self",self);
 $ctx1.sendIdx["at:put:"]=1;
 $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 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());
 _st(anInspector)._setLabel_(self._printString());
 $1=_st(anInspector)._setVariables_(variables);
 $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"],
 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"]
 referencedClasses: ["Dictionary"]
 }),
 }),
-smalltalk.Set);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -7461,26 +7469,18 @@ var $1;
 variables=_st($Dictionary())._new();
 variables=_st($Dictionary())._new();
 _st(variables)._at_put_("#self",self);
 _st(variables)._at_put_("#self",self);
 $ctx1.sendIdx["at:put:"]=1;
 $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 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());
 _st(anInspector)._setLabel_(self._printString());
 $1=_st(anInspector)._setVariables_(variables);
 $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"],
 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"]
 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.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "=",
 selector: "=",
 protocol: 'comparing',
 protocol: 'comparing',
-fn: function (aHashedCollection){
+fn: function (anAssocitativeCollection){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
 var $2,$1,$4,$3,$6,$5;
 var $2,$1,$4,$3,$6,$5;
 $2=self._class();
 $2=self._class();
 $ctx1.sendIdx["class"]=1;
 $ctx1.sendIdx["class"]=1;
-$1=_st($2).__eq(_st(aHashedCollection)._class());
+$1=_st($2).__eq(_st(anAssocitativeCollection)._class());
 $ctx1.sendIdx["="]=1;
 $ctx1.sendIdx["="]=1;
 if(! smalltalk.assert($1)){
 if(! smalltalk.assert($1)){
 return false;
 return false;
 };
 };
 $4=self._size();
 $4=self._size();
 $ctx1.sendIdx["size"]=1;
 $ctx1.sendIdx["size"]=1;
-$3=_st($4).__eq(_st(aHashedCollection)._size());
+$3=_st($4).__eq(_st(anAssocitativeCollection)._size());
 $ctx1.sendIdx["="]=2;
 $ctx1.sendIdx["="]=2;
 if(! smalltalk.assert($3)){
 if(! smalltalk.assert($3)){
 return false;
 return false;
 };
 };
 $6=self._associations();
 $6=self._associations();
 $ctx1.sendIdx["associations"]=1;
 $ctx1.sendIdx["associations"]=1;
-$5=_st($6).__eq(_st(aHashedCollection)._associations());
+$5=_st($6).__eq(_st(anAssocitativeCollection)._associations());
 return $5;
 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"],
 messageSends: ["ifFalse:", "=", "class", "size", "associations"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1345,30 +1345,30 @@ fn: function (anAssociation){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
 self._at_put_(_st(anAssociation)._key(),_st(anAssociation)._value());
 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"],
 args: ["anAssociation"],
 source: "add: anAssociation\x0a\x09self at: anAssociation key put: anAssociation value",
 source: "add: anAssociation\x0a\x09self at: anAssociation key put: anAssociation value",
 messageSends: ["at:put:", "key", "value"],
 messageSends: ["at:put:", "key", "value"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "addAll:",
 selector: "addAll:",
 protocol: 'adding/removing',
 protocol: 'adding/removing',
-fn: function (aHashedCollection){
+fn: function (anAssocitativeCollection){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 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"],
 messageSends: ["addAll:", "associations"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1381,13 +1381,32 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 var $1;
 $1=_st($Dictionary())._from_(self._associations());
 $1=_st($Dictionary())._from_(self._associations());
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"asDictionary",{},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"asDictionary",{},smalltalk.AssociativeCollection)})},
 args: [],
 args: [],
 source: "asDictionary\x0a\x09^ Dictionary from: self associations",
 source: "asDictionary\x0a\x09^ Dictionary from: self associations",
 messageSends: ["from:", "associations"],
 messageSends: ["from:", "associations"],
 referencedClasses: ["Dictionary"]
 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.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1396,22 +1415,23 @@ protocol: 'converting',
 fn: function (){
 fn: function (){
 var self=this;
 var self=this;
 var c;
 var c;
+function $HashedCollection(){return smalltalk.HashedCollection||(typeof HashedCollection=="undefined"?nil:HashedCollection)}
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
 var $1;
 var $1;
-c=_st(self._class())._new();
+c=_st($HashedCollection())._new();
 self._keysAndValuesDo_((function(key,value){
 self._keysAndValuesDo_((function(key,value){
 return smalltalk.withContext(function($ctx2) {
 return smalltalk.withContext(function($ctx2) {
 return _st(c)._at_put_(key,_st(value)._asJSON());
 return _st(c)._at_put_(key,_st(value)._asJSON());
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 $1=c;
 $1=c;
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"asJSON",{c:c},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"asJSON",{c:c},smalltalk.AssociativeCollection)})},
 args: [],
 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.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1429,13 +1449,13 @@ return _st(associations)._add_(each);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 $1=associations;
 $1=associations;
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"associations",{associations:associations},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"associations",{associations:associations},smalltalk.AssociativeCollection)})},
 args: [],
 args: [],
 source: "associations\x0a\x09| associations |\x0a\x09associations := #().\x0a\x09self associationsDo: [ :each | associations add: each ].\x0a\x09^ associations",
 source: "associations\x0a\x09| associations |\x0a\x09associations := #().\x0a\x09self associationsDo: [ :each | associations add: each ].\x0a\x09^ associations",
 messageSends: ["associationsDo:", "add:"],
 messageSends: ["associationsDo:", "add:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1449,35 +1469,13 @@ self._keysAndValuesDo_((function(key,value){
 return smalltalk.withContext(function($ctx2) {
 return smalltalk.withContext(function($ctx2) {
 return _st(aBlock)._value_(_st($Association())._key_value_(key,value));
 return _st(aBlock)._value_(_st($Association())._key_value_(key,value));
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 }, 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"],
 args: ["aBlock"],
 source: "associationsDo: aBlock\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09aBlock value: (Association key: key value: value) ]",
 source: "associationsDo: aBlock\x0a\x09self keysAndValuesDo: [ :key :value |\x0a\x09\x09aBlock value: (Association key: key value: value) ]",
 messageSends: ["keysAndValuesDo:", "value:", "key:value:"],
 messageSends: ["keysAndValuesDo:", "value:", "key:value:"],
 referencedClasses: ["Association"]
 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.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1493,31 +1491,13 @@ return smalltalk.withContext(function($ctx2) {
 return _st(aBlock)._value_(self._at_(aKey));
 return _st(aBlock)._value_(self._at_(aKey));
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}),anotherBlock);
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}),anotherBlock);
 return $1;
 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"],
 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",
 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:"],
 messageSends: ["ifTrue:ifFalse:", "includesKey:", "value:", "at:"],
 referencedClasses: []
 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.addMethod(
 smalltalk.method({
 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)})}));
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 $1=newDict;
 $1=newDict;
 return $1;
 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"],
 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",
 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:"],
 messageSends: ["new", "class", "keysAndValuesDo:", "at:put:", "value:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 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)})}));
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 $1=copy;
 $1=copy;
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"deepCopy",{copy:copy},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"deepCopy",{copy:copy},smalltalk.AssociativeCollection)})},
 args: [],
 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",
 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"],
 messageSends: ["new", "class", "keysAndValuesDo:", "at:put:", "deepCopy"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1577,13 +1557,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 var $1;
 $1=_st(self._values())._detect_ifNone_(aBlock,anotherBlock);
 $1=_st(self._values())._detect_ifNone_(aBlock,anotherBlock);
 return $1;
 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"],
 args: ["aBlock", "anotherBlock"],
 source: "detect: aBlock ifNone: anotherBlock\x0a\x09^ self values detect: aBlock ifNone: anotherBlock",
 source: "detect: aBlock ifNone: anotherBlock\x0a\x09^ self values detect: aBlock ifNone: anotherBlock",
 messageSends: ["detect:ifNone:", "values"],
 messageSends: ["detect:ifNone:", "values"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1593,13 +1573,13 @@ fn: function (aBlock){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 return smalltalk.withContext(function($ctx1) { 
 self._valuesDo_(aBlock);
 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"],
 args: ["aBlock"],
 source: "do: aBlock\x0a\x09self valuesDo: aBlock",
 source: "do: aBlock\x0a\x09self valuesDo: aBlock",
 messageSends: ["valuesDo:"],
 messageSends: ["valuesDo:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1611,13 +1591,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 var $1;
 $1=_st(self._values())._includes_(anObject);
 $1=_st(self._values())._includes_(anObject);
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"includes:",{anObject:anObject},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"includes:",{anObject:anObject},smalltalk.AssociativeCollection)})},
 args: ["anObject"],
 args: ["anObject"],
 source: "includes: anObject\x0a\x09^ self values includes: anObject",
 source: "includes: anObject\x0a\x09^ self values includes: anObject",
 messageSends: ["includes:", "values"],
 messageSends: ["includes:", "values"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1626,14 +1606,14 @@ protocol: 'testing',
 fn: function (aKey){
 fn: function (aKey){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 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"],
 args: ["aKey"],
-source: "includesKey: aKey\x0a\x09<return self.hasOwnProperty(aKey)>",
-messageSends: [],
+source: "includesKey: aKey\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1648,13 +1628,13 @@ return smalltalk.withContext(function($ctx2) {
 return _st(self._at_(each)).__eq(anObject);
 return _st(self._at_(each)).__eq(anObject);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}),aBlock);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}),aBlock);
 return $1;
 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"],
 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:"],
 messageSends: ["detect:ifNone:", "keys", "=", "at:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1669,13 +1649,13 @@ return smalltalk.withContext(function($ctx2) {
 return self._errorNotFound();
 return self._errorNotFound();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
 return $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"],
 args: ["anObject"],
 source: "keyAtValue: anObject\x0a\x09^ self keyAtValue: anObject ifAbsent: [ self errorNotFound ]",
 source: "keyAtValue: anObject\x0a\x09^ self keyAtValue: anObject ifAbsent: [ self errorNotFound ]",
 messageSends: ["keyAtValue:ifAbsent:", "errorNotFound"],
 messageSends: ["keyAtValue:ifAbsent:", "errorNotFound"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1687,13 +1667,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 var $1;
 $1=self._indexOf_ifAbsent_(anObject,aBlock);
 $1=self._indexOf_ifAbsent_(anObject,aBlock);
 return $1;
 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"],
 args: ["anObject", "aBlock"],
 source: "keyAtValue: anObject ifAbsent: aBlock\x0a\x09^ self indexOf: anObject ifAbsent: aBlock",
 source: "keyAtValue: anObject ifAbsent: aBlock\x0a\x09^ self indexOf: anObject ifAbsent: aBlock",
 messageSends: ["indexOf:ifAbsent:"],
 messageSends: ["indexOf:ifAbsent:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1702,14 +1682,14 @@ protocol: 'accessing',
 fn: function (){
 fn: function (){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 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: [],
 args: [],
-source: "keys\x0a\x09<return Object.keys(self)>",
-messageSends: [],
+source: "keys\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1722,13 +1702,13 @@ self._keysDo_((function(each){
 return smalltalk.withContext(function($ctx2) {
 return smalltalk.withContext(function($ctx2) {
 return _st(aBlock)._value_value_(each,self._at_(each));
 return _st(aBlock)._value_value_(each,self._at_(each));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 }, 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"],
 args: ["aBlock"],
 source: "keysAndValuesDo: aBlock\x0a\x09self keysDo: [ :each |\x0a\x09\x09aBlock value: each value: (self at: each) ]",
 source: "keysAndValuesDo: aBlock\x0a\x09self keysDo: [ :each |\x0a\x09\x09aBlock value: each value: (self at: each) ]",
 messageSends: ["keysDo:", "value:value:", "at:"],
 messageSends: ["keysDo:", "value:value:", "at:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1737,14 +1717,14 @@ protocol: 'enumerating',
 fn: function (aBlock){
 fn: function (aBlock){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 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"],
 args: ["aBlock"],
-source: "keysDo: aBlock\x0a\x09self keys do: aBlock",
-messageSends: ["do:", "keys"],
+source: "keysDo: aBlock\x0a\x09self subclassResponsibility",
+messageSends: ["subclassResponsibility"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1753,7 +1733,7 @@ protocol: 'printing',
 fn: function (aStream){
 fn: function (aStream){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 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;
 $ctx1.sendIdx["printOn:"]=1;
 _st(aStream)._nextPutAll_(" (");
 _st(aStream)._nextPutAll_(" (");
 $ctx1.sendIdx["nextPutAll:"]=1;
 $ctx1.sendIdx["nextPutAll:"]=1;
@@ -1766,13 +1746,13 @@ return _st(aStream)._nextPutAll_(" , ");
 $ctx2.sendIdx["nextPutAll:"]=2;
 $ctx2.sendIdx["nextPutAll:"]=2;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)})}));
 _st(aStream)._nextPutAll_(")");
 _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"],
 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: ')'",
 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"],
 messageSends: ["printOn:", "nextPutAll:", "do:separatedBy:", "associations"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1784,13 +1764,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 var $1;
 $1=self._removeKey_ifAbsent_(aKey,aBlock);
 $1=self._removeKey_ifAbsent_(aKey,aBlock);
 return $1;
 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"],
 args: ["aKey", "aBlock"],
 source: "remove: aKey ifAbsent: aBlock\x0a\x09^ self removeKey: aKey ifAbsent: aBlock",
 source: "remove: aKey ifAbsent: aBlock\x0a\x09^ self removeKey: aKey ifAbsent: aBlock",
 messageSends: ["removeKey:ifAbsent:"],
 messageSends: ["removeKey:ifAbsent:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1805,13 +1785,13 @@ return smalltalk.withContext(function($ctx2) {
 return self._removeKey_(each);
 return self._removeKey_(each);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"removeAll",{},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"removeAll",{},smalltalk.AssociativeCollection)})},
 args: [],
 args: [],
 source: "removeAll\x0a\x09^ self keys do: [ :each | self removeKey: each ]",
 source: "removeAll\x0a\x09^ self keys do: [ :each | self removeKey: each ]",
 messageSends: ["do:", "keys", "removeKey:"],
 messageSends: ["do:", "keys", "removeKey:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1823,13 +1803,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 var $1;
 $1=self._remove_(aKey);
 $1=self._remove_(aKey);
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"removeKey:",{aKey:aKey},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"removeKey:",{aKey:aKey},smalltalk.AssociativeCollection)})},
 args: ["aKey"],
 args: ["aKey"],
 source: "removeKey: aKey\x0a\x09^ self remove: aKey",
 source: "removeKey: aKey\x0a\x09^ self remove: aKey",
 messageSends: ["remove:"],
 messageSends: ["remove:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1838,21 +1818,14 @@ protocol: 'adding/removing',
 fn: function (aKey,aBlock){
 fn: function (aKey,aBlock){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 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"],
 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: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1873,13 +1846,13 @@ return _st(newDict)._at_put_(key,value);
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 $2=newDict;
 $2=newDict;
 return $2;
 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"],
 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",
 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:"],
 messageSends: ["new", "class", "keysAndValuesDo:", "ifTrue:", "value:", "at:put:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1897,13 +1870,13 @@ return _st(copy)._at_put_(key,value);
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 $1=copy;
 $1=copy;
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"shallowCopy",{copy:copy},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"shallowCopy",{copy:copy},smalltalk.AssociativeCollection)})},
 args: [],
 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",
 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:"],
 messageSends: ["new", "class", "keysAndValuesDo:", "at:put:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1915,13 +1888,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 var $1;
 $1=_st(self._keys())._size();
 $1=_st(self._keys())._size();
 return $1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"size",{},smalltalk.HashedCollection)})},
+}, function($ctx1) {$ctx1.fill(self,"size",{},smalltalk.AssociativeCollection)})},
 args: [],
 args: [],
 source: "size\x0a\x09^ self keys size",
 source: "size\x0a\x09^ self keys size",
 messageSends: ["size", "keys"],
 messageSends: ["size", "keys"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1930,18 +1903,14 @@ protocol: 'accessing',
 fn: function (){
 fn: function (){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 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: [],
 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: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1950,17 +1919,14 @@ protocol: 'enumerating',
 fn: function (aBlock){
 fn: function (aBlock){
 var self=this;
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 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"],
 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: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -1973,13 +1939,13 @@ self._keysAndValuesDo_((function(key,value){
 return smalltalk.withContext(function($ctx2) {
 return smalltalk.withContext(function($ctx2) {
 return _st(aBlock)._value_value_(value,key);
 return _st(aBlock)._value_value_(value,key);
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1,1)})}));
 }, 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"],
 args: ["aBlock"],
 source: "withIndexDo: aBlock\x0a\x09self keysAndValuesDo: [ :key :value | aBlock value: value value: key ]",
 source: "withIndexDo: aBlock\x0a\x09self keysAndValuesDo: [ :key :value | aBlock value: value value: key ]",
 messageSends: ["keysAndValuesDo:", "value:value:"],
 messageSends: ["keysAndValuesDo:", "value:value:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection);
+smalltalk.AssociativeCollection);
 
 
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
@@ -1998,13 +1964,13 @@ return _st(newCollection)._add_(each);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 $1=newCollection;
 $1=newCollection;
 return $1;
 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"],
 args: ["aCollection"],
 source: "from: aCollection\x0a\x09| newCollection |\x0a\x09newCollection := self new.\x0a\x09aCollection do: [ :each | newCollection add: each ].\x0a\x09^ newCollection",
 source: "from: aCollection\x0a\x09| newCollection |\x0a\x09newCollection := self new.\x0a\x09aCollection do: [ :each | newCollection add: each ].\x0a\x09^ newCollection",
 messageSends: ["new", "do:", "add:"],
 messageSends: ["new", "do:", "add:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection.klass);
+smalltalk.AssociativeCollection.klass);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
@@ -2016,13 +1982,13 @@ return smalltalk.withContext(function($ctx1) {
 var $1;
 var $1;
 $1=self._from_(aCollection);
 $1=self._from_(aCollection);
 return $1;
 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"],
 args: ["aCollection"],
 source: "fromPairs: aCollection\x0a\x09\x22This message is poorly named and has been replaced by #from:\x22\x0a\x09^ self from: 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:"],
 messageSends: ["from:"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
-smalltalk.HashedCollection.klass);
+smalltalk.AssociativeCollection.klass);
 
 
 smalltalk.addMethod(
 smalltalk.addMethod(
 smalltalk.method({
 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)})}));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}));
 $5=newCollection;
 $5=newCollection;
 return $5;
 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"],
 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",
 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:", "+"],
 messageSends: ["ifFalse:", "even", "size", "error:", "new", "do:", "to:by:", "at:put:", "at:", "+"],
 referencedClasses: []
 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.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.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "at:ifAbsent:",
 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.addClass('SequenceableCollection', smalltalk.IndexableCollection, [], 'Kernel-Collections');
 smalltalk.SequenceableCollection.comment="I am an IndexableCollection\x0awith numeric indexes starting with 1.";
 smalltalk.SequenceableCollection.comment="I am an IndexableCollection\x0awith numeric indexes starting with 1.";
 smalltalk.addMethod(
 smalltalk.addMethod(

+ 14 - 14
st/IDE.st

@@ -2343,45 +2343,45 @@ inspectOn: anInspector
 	anInspector setLabel: label
 	anInspector setLabel: label
 ! !
 ! !
 
 
-!HashedCollection methodsFor: '*IDE'!
+!MethodContext methodsFor: '*IDE'!
 
 
 inspectOn: anInspector
 inspectOn: anInspector
 	| variables |
 	| variables |
 	variables := Dictionary new.
 	variables := Dictionary new.
 	variables at: '#self' put: self.
 	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
 	anInspector
 		setLabel: self printString;
 		setLabel: self printString;
 		setVariables: variables
 		setVariables: variables
 ! !
 ! !
 
 
-!Set methodsFor: '*IDE'!
+!AssociativeCollection methodsFor: '*IDE'!
 
 
 inspectOn: anInspector
 inspectOn: anInspector
 	| variables |
 	| variables |
 	variables := Dictionary new.
 	variables := Dictionary new.
 	variables at: '#self' put: self.
 	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
 	anInspector
 		setLabel: self printString;
 		setLabel: self printString;
 		setVariables: variables
 		setVariables: variables
 ! !
 ! !
 
 
-!MethodContext methodsFor: '*IDE'!
+!Set methodsFor: '*IDE'!
 
 
 inspectOn: anInspector
 inspectOn: anInspector
 	| variables |
 	| variables |
 	variables := Dictionary new.
 	variables := Dictionary new.
 	variables at: '#self' put: self.
 	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
 	anInspector
 		setLabel: self printString;
 		setLabel: self printString;
 		setVariables: variables
 		setVariables: variables

+ 87 - 56
st/Kernel-Collections.st

@@ -435,15 +435,13 @@ withIndexDo: aBlock
 	self subclassResponsibility
 	self subclassResponsibility
 ! !
 ! !
 
 
-IndexableCollection subclass: #HashedCollection
+IndexableCollection subclass: #AssociativeCollection
 	instanceVariableNames: ''
 	instanceVariableNames: ''
 	package: 'Kernel-Collections'!
 	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
 	| associations |
 	| associations |
@@ -452,12 +450,6 @@ associations
 	^ associations
 	^ associations
 !
 !
 
 
-at: aKey ifAbsent: aBlock
-	^ (self includesKey: aKey)
-		ifTrue: [ self basicAt: aKey ]
-		ifFalse: aBlock
-!
-
 at: aKey ifPresent: aBlock ifAbsent: anotherBlock
 at: aKey ifPresent: aBlock ifAbsent: anotherBlock
 	"Lookup the given key in the receiver.
 	"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,
 	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
 		ifFalse: anotherBlock
 !
 !
 
 
-at: aKey put: aValue
-	^ self basicAt: aKey put: aValue
-!
-
 indexOf: anObject ifAbsent: aBlock
 indexOf: anObject ifAbsent: aBlock
-
 	^ self keys detect: [ :each | (self at: each) = anObject ] ifNone: aBlock
 	^ self keys detect: [ :each | (self at: each) = anObject ] ifNone: aBlock
 !
 !
 
 
@@ -485,7 +472,7 @@ keyAtValue: anObject ifAbsent: aBlock
 !
 !
 
 
 keys
 keys
-	<return Object.keys(self)>
+	self subclassResponsibility
 !
 !
 
 
 size
 size
@@ -493,22 +480,18 @@ size
 !
 !
 
 
 values
 values
-	<
-		return self._keys().map(function(key){
-			return self._at_(key);
-		});
-	>
+	self subclassResponsibility
 ! !
 ! !
 
 
-!HashedCollection methodsFor: 'adding/removing'!
+!AssociativeCollection methodsFor: 'adding/removing'!
 
 
 add: anAssociation
 add: anAssociation
 	self at: anAssociation key put: anAssociation value
 	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
 remove: aKey ifAbsent: aBlock
@@ -524,34 +507,36 @@ removeKey: aKey
 !
 !
 
 
 removeKey: aKey ifAbsent: aBlock
 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
 asDictionary
 	^ Dictionary from: self associations
 	^ Dictionary from: self associations
 !
 !
 
 
+asHashedCollection
+	^ HashedCollection from: self associations
+!
+
 asJSON
 asJSON
 	| c |
 	| c |
-	c := self class new.
+	c := HashedCollection new.
 	self keysAndValuesDo: [ :key :value |
 	self keysAndValuesDo: [ :key :value |
 		c at: key put: value asJSON ].
 		c at: key put: value asJSON ].
 	^ c
 	^ c
 ! !
 ! !
 
 
-!HashedCollection methodsFor: 'copying'!
+!AssociativeCollection methodsFor: 'copying'!
 
 
 deepCopy
 deepCopy
 	| copy |
 	| copy |
@@ -569,7 +554,7 @@ shallowCopy
 	^ copy
 	^ copy
 ! !
 ! !
 
 
-!HashedCollection methodsFor: 'enumerating'!
+!AssociativeCollection methodsFor: 'enumerating'!
 
 
 associationsDo: aBlock
 associationsDo: aBlock
 	self keysAndValuesDo: [ :key :value |
 	self keysAndValuesDo: [ :key :value |
@@ -602,7 +587,7 @@ keysAndValuesDo: aBlock
 !
 !
 
 
 keysDo: aBlock
 keysDo: aBlock
-	self keys do: aBlock
+	self subclassResponsibility
 !
 !
 
 
 select: aBlock
 select: aBlock
@@ -614,14 +599,14 @@ select: aBlock
 !
 !
 
 
 valuesDo: aBlock
 valuesDo: aBlock
-	self values do: [ :value | aBlock value: value ]
+	self subclassResponsibility
 !
 !
 
 
 withIndexDo: aBlock
 withIndexDo: aBlock
 	self keysAndValuesDo: [ :key :value | aBlock value: value value: key ]
 	self keysAndValuesDo: [ :key :value | aBlock value: value value: key ]
 ! !
 ! !
 
 
-!HashedCollection methodsFor: 'printing'!
+!AssociativeCollection methodsFor: 'printing'!
 
 
 printOn: aStream
 printOn: aStream
 	super printOn: aStream.
 	super printOn: aStream.
@@ -633,13 +618,13 @@ printOn: aStream
 	aStream nextPutAll: ')'
 	aStream nextPutAll: ')'
 ! !
 ! !
 
 
-!HashedCollection methodsFor: 'testing'!
+!AssociativeCollection methodsFor: 'testing'!
 
 
 includesKey: aKey
 includesKey: aKey
-	<return self.hasOwnProperty(aKey)>
+	self subclassResponsibility
 ! !
 ! !
 
 
-!HashedCollection class methodsFor: 'instance creation'!
+!AssociativeCollection class methodsFor: 'instance creation'!
 
 
 from: aCollection
 from: aCollection
 	| newCollection |
 	| newCollection |
@@ -669,7 +654,7 @@ newFromPairs: aCollection
 	^ newCollection
 	^ newCollection
 ! !
 ! !
 
 
-HashedCollection subclass: #Dictionary
+AssociativeCollection subclass: #Dictionary
 	instanceVariableNames: 'keys values'
 	instanceVariableNames: 'keys values'
 	package: 'Kernel-Collections'!
 	package: 'Kernel-Collections'!
 !Dictionary commentStamp!
 !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'!
 !Dictionary methodsFor: 'enumerating'!
 
 
 keysAndValuesDo: aBlock
 keysAndValuesDo: aBlock
@@ -792,6 +767,62 @@ includesKey: aKey
 	< return self._positionOfKey_(aKey) >>= 0; >
 	< 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
 IndexableCollection subclass: #SequenceableCollection
 	instanceVariableNames: ''
 	instanceVariableNames: ''
 	package: 'Kernel-Collections'!
 	package: 'Kernel-Collections'!