Browse Source

Merge branch 'master' into helios

Nicolas Petton 11 years ago
parent
commit
a4e33639b6

+ 4 - 2
js/Compiler-AST.deploy.js

@@ -1162,9 +1162,11 @@ smalltalk.method({
 selector: "isImmutable",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return true;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._value())._isImmutable();
+return $1;
 }, function($ctx1) {$ctx1.fill(self,"isImmutable",{},smalltalk.ValueNode)})},
-messageSends: []}),
+messageSends: ["isImmutable", "value"]}),
 smalltalk.ValueNode);
 
 smalltalk.addMethod(

+ 5 - 3
js/Compiler-AST.js

@@ -1589,11 +1589,13 @@ selector: "isImmutable",
 category: 'testing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return true;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._value())._isImmutable();
+return $1;
 }, function($ctx1) {$ctx1.fill(self,"isImmutable",{},smalltalk.ValueNode)})},
 args: [],
-source: "isImmutable\x0a\x09^true",
-messageSends: [],
+source: "isImmutable\x0a\x09^ self value isImmutable",
+messageSends: ["isImmutable", "value"],
 referencedClasses: []
 }),
 smalltalk.ValueNode);

+ 11 - 0
js/Compiler-Tests.deploy.js

@@ -521,6 +521,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"testMessageSends",{},smalltalk.C
 messageSends: ["should:return:"]}),
 smalltalk.CodeGeneratorTest);
 
+smalltalk.addMethod(
+"_testMutableLiterals",
+smalltalk.method({
+selector: "testMutableLiterals",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._should_return_("foo ^ #( 1 2 ) at: 1 put: 3; yourself",[(3), (2)]);
+return self}, function($ctx1) {$ctx1.fill(self,"testMutableLiterals",{},smalltalk.CodeGeneratorTest)})},
+messageSends: ["should:return:"]}),
+smalltalk.CodeGeneratorTest);
+
 smalltalk.addMethod(
 "_testNestedIfTrue",
 smalltalk.method({

+ 16 - 0
js/Compiler-Tests.js

@@ -711,6 +711,22 @@ referencedClasses: []
 }),
 smalltalk.CodeGeneratorTest);
 
+smalltalk.addMethod(
+"_testMutableLiterals",
+smalltalk.method({
+selector: "testMutableLiterals",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._should_return_("foo ^ #( 1 2 ) at: 1 put: 3; yourself",[(3), (2)]);
+return self}, function($ctx1) {$ctx1.fill(self,"testMutableLiterals",{},smalltalk.CodeGeneratorTest)})},
+args: [],
+source: "testMutableLiterals\x0a\x09\x22Mutable literals must be aliased in cascades.\x0a\x09See https://github.com/amber-smalltalk/amber/issues/428\x22\x0a\x09\x0a\x09self \x0a\x09\x09should: 'foo ^ #( 1 2 ) at: 1 put: 3; yourself' \x0a\x09\x09return: #(3 2)",
+messageSends: ["should:return:"],
+referencedClasses: []
+}),
+smalltalk.CodeGeneratorTest);
+
 smalltalk.addMethod(
 "_testNestedIfTrue",
 smalltalk.method({

+ 181 - 76
js/Kernel-Collections.deploy.js

@@ -469,16 +469,16 @@ messageSends: ["do:", "ifTrue:", "+", "="]}),
 smalltalk.Collection);
 
 smalltalk.addMethod(
-"_readStream",
+"_putOn_",
 smalltalk.method({
-selector: "readStream",
-fn: function (){
+selector: "putOn:",
+fn: function (aStream){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(self)._stream();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"readStream",{},smalltalk.Collection)})},
-messageSends: ["stream"]}),
+return smalltalk.withContext(function($ctx1) { 
_st(self)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(each)._putOn_(aStream);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"putOn:",{aStream:aStream},smalltalk.Collection)})},
+messageSends: ["do:", "putOn:"]}),
 smalltalk.Collection);
 
 smalltalk.addMethod(
@@ -554,45 +554,6 @@ return self}, function($ctx1) {$ctx1.fill(self,"size",{},smalltalk.Collection)})
 messageSends: ["subclassResponsibility"]}),
 smalltalk.Collection);
 
-smalltalk.addMethod(
-"_stream",
-smalltalk.method({
-selector: "stream",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._streamClass())._on_(self);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"stream",{},smalltalk.Collection)})},
-messageSends: ["on:", "streamClass"]}),
-smalltalk.Collection);
-
-smalltalk.addMethod(
-"_streamClass",
-smalltalk.method({
-selector: "streamClass",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._class())._streamClass();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"streamClass",{},smalltalk.Collection)})},
-messageSends: ["streamClass", "class"]}),
-smalltalk.Collection);
-
-smalltalk.addMethod(
-"_writeStream",
-smalltalk.method({
-selector: "writeStream",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(self)._stream();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"writeStream",{},smalltalk.Collection)})},
-messageSends: ["stream"]}),
-smalltalk.Collection);
-
 
 smalltalk.addMethod(
 "_new_",
@@ -607,19 +568,6 @@ return $1;
 messageSends: ["new"]}),
 smalltalk.Collection.klass);
 
-smalltalk.addMethod(
-"_streamClass",
-smalltalk.method({
-selector: "streamClass",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=(smalltalk.Stream || Stream);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"streamClass",{},smalltalk.Collection.klass)})},
-messageSends: []}),
-smalltalk.Collection.klass);
-
 smalltalk.addMethod(
 "_with_",
 smalltalk.method({
@@ -1774,6 +1722,32 @@ return $1;
 messageSends: ["at:", "size"]}),
 smalltalk.SequenceableCollection);
 
+smalltalk.addMethod(
+"_newStream",
+smalltalk.method({
+selector: "newStream",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._streamClass())._on_(self);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"newStream",{},smalltalk.SequenceableCollection)})},
+messageSends: ["on:", "streamClass"]}),
+smalltalk.SequenceableCollection);
+
+smalltalk.addMethod(
+"_readStream",
+smalltalk.method({
+selector: "readStream",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(self)._stream();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"readStream",{},smalltalk.SequenceableCollection)})},
+messageSends: ["stream"]}),
+smalltalk.SequenceableCollection);
+
 smalltalk.addMethod(
 "_removeLast",
 smalltalk.method({
@@ -1827,6 +1801,32 @@ return $1;
 messageSends: ["new:", "size", "class", "withIndexDo:", "at:put:"]}),
 smalltalk.SequenceableCollection);
 
+smalltalk.addMethod(
+"_stream",
+smalltalk.method({
+selector: "stream",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(self)._newStream();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"stream",{},smalltalk.SequenceableCollection)})},
+messageSends: ["newStream"]}),
+smalltalk.SequenceableCollection);
+
+smalltalk.addMethod(
+"_streamClass",
+smalltalk.method({
+selector: "streamClass",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._class())._streamClass();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"streamClass",{},smalltalk.SequenceableCollection)})},
+messageSends: ["streamClass", "class"]}),
+smalltalk.SequenceableCollection);
+
 smalltalk.addMethod(
 "_third",
 smalltalk.method({
@@ -1862,6 +1862,48 @@ return self}, function($ctx1) {$ctx1.fill(self,"withIndexDo:",{aBlock:aBlock},sm
 messageSends: []}),
 smalltalk.SequenceableCollection);
 
+smalltalk.addMethod(
+"_writeStream",
+smalltalk.method({
+selector: "writeStream",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(self)._stream();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"writeStream",{},smalltalk.SequenceableCollection)})},
+messageSends: ["stream"]}),
+smalltalk.SequenceableCollection);
+
+
+smalltalk.addMethod(
+"_streamClass",
+smalltalk.method({
+selector: "streamClass",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=(smalltalk.Stream || Stream);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"streamClass",{},smalltalk.SequenceableCollection.klass)})},
+messageSends: []}),
+smalltalk.SequenceableCollection.klass);
+
+smalltalk.addMethod(
+"_streamContents_",
+smalltalk.method({
+selector: "streamContents:",
+fn: function (aBlock){
+var self=this;
+var stream;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+stream=_st(_st(self)._streamClass())._on_(_st(self)._new());
+_st(aBlock)._value_(stream);
+$1=_st(stream)._contents();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"streamContents:",{aBlock:aBlock,stream:stream},smalltalk.SequenceableCollection.klass)})},
+messageSends: ["on:", "new", "streamClass", "value:", "contents"]}),
+smalltalk.SequenceableCollection.klass);
 
 
 smalltalk.addClass('Array', smalltalk.SequenceableCollection, [], 'Kernel-Collections');
@@ -2259,6 +2301,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"printOn:",{aStream:aStream},smal
 messageSends: ["printOn:", "asString"]}),
 smalltalk.CharacterArray);
 
+smalltalk.addMethod(
+"_putOn_",
+smalltalk.method({
+selector: "putOn:",
+fn: function (aStream){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(aStream)._nextPutString_(self);
+return self}, function($ctx1) {$ctx1.fill(self,"putOn:",{aStream:aStream},smalltalk.CharacterArray)})},
+messageSends: ["nextPutString:"]}),
+smalltalk.CharacterArray);
+
 smalltalk.addMethod(
 "_remove_",
 smalltalk.method({
@@ -2572,6 +2625,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"includesSubString:",{subString:s
 messageSends: []}),
 smalltalk.String);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isImmutable",{},smalltalk.String)})},
+messageSends: []}),
+smalltalk.String);
+
 smalltalk.addMethod(
 "_isString",
 smalltalk.method({
@@ -3065,22 +3129,6 @@ return $1;
 messageSends: []}),
 smalltalk.String.klass);
 
-smalltalk.addMethod(
-"_streamContents_",
-smalltalk.method({
-selector: "streamContents:",
-fn: function (blockWithArg){
-var self=this;
-var stream;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-stream=_st(_st(self)._streamClass())._on_(_st((smalltalk.String || String))._new());
-_st(blockWithArg)._value_(stream);
-$1=_st(stream)._contents();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"streamContents:",{blockWithArg:blockWithArg,stream:stream},smalltalk.String.klass)})},
-messageSends: ["on:", "new", "streamClass", "value:", "contents"]}),
-smalltalk.String.klass);
-
 smalltalk.addMethod(
 "_tab",
 smalltalk.method({
@@ -3313,6 +3361,19 @@ return self}, function($ctx1) {$ctx1.fill(self,"do:",{aBlock:aBlock},smalltalk.S
 messageSends: ["do:", "asString"]}),
 smalltalk.Symbol);
 
+smalltalk.addMethod(
+"_indexOf_",
+smalltalk.method({
+selector: "indexOf:",
+fn: function (anElement){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._asString())._indexOf_(anElement);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"indexOf:",{anElement:anElement},smalltalk.Symbol)})},
+messageSends: ["indexOf:", "asString"]}),
+smalltalk.Symbol);
+
 smalltalk.addMethod(
 "_isSymbol",
 smalltalk.method({
@@ -3772,6 +3833,17 @@ smalltalk.RegularExpression.klass);
 
 
 smalltalk.addClass('Stream', smalltalk.Object, ['collection', 'position', 'streamSize'], 'Kernel-Collections');
+smalltalk.addMethod(
+"__lt_lt",
+smalltalk.method({
+selector: "<<",
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._write_(anObject);
+return self}, function($ctx1) {$ctx1.fill(self,"<<",{anObject:anObject},smalltalk.Stream)})},
+messageSends: ["write:"]}),
+smalltalk.Stream);
+
 smalltalk.addMethod(
 "_atEnd",
 smalltalk.method({
@@ -3938,6 +4010,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"nextPutAll:",{aCollection:aColle
 messageSends: ["do:", "nextPut:"]}),
 smalltalk.Stream);
 
+smalltalk.addMethod(
+"_nextPutString_",
+smalltalk.method({
+selector: "nextPutString:",
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._nextPut_(aString);
+return self}, function($ctx1) {$ctx1.fill(self,"nextPutString:",{aString:aString},smalltalk.Stream)})},
+messageSends: ["nextPut:"]}),
+smalltalk.Stream);
+
 smalltalk.addMethod(
 "_peek",
 smalltalk.method({
@@ -4077,6 +4160,17 @@ return $1;
 messageSends: []}),
 smalltalk.Stream);
 
+smalltalk.addMethod(
+"_write_",
+smalltalk.method({
+selector: "write:",
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(anObject)._putOn_(self);
+return self}, function($ctx1) {$ctx1.fill(self,"write:",{anObject:anObject},smalltalk.Stream)})},
+messageSends: ["putOn:"]}),
+smalltalk.Stream);
+
 
 smalltalk.addMethod(
 "_on_",
@@ -4193,6 +4287,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"nextPutAll:",{aString:aString,pr
 messageSends: ["ifTrue:ifFalse:", "setCollection:", ",", "collection", "copyFrom:to:", "position", "+", "size", "atEnd", "position:", "setStreamSize:", "max:", "streamSize"]}),
 smalltalk.StringStream);
 
+smalltalk.addMethod(
+"_nextPutString_",
+smalltalk.method({
+selector: "nextPutString:",
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._nextPutAll_(aString);
+return self}, function($ctx1) {$ctx1.fill(self,"nextPutString:",{aString:aString},smalltalk.StringStream)})},
+messageSends: ["nextPutAll:"]}),
+smalltalk.StringStream);
+
 smalltalk.addMethod(
 "_space",
 smalltalk.method({

+ 256 - 106
js/Kernel-Collections.js

@@ -626,19 +626,19 @@ referencedClasses: []
 smalltalk.Collection);
 
 smalltalk.addMethod(
-"_readStream",
+"_putOn_",
 smalltalk.method({
-selector: "readStream",
-category: 'accessing',
-fn: function (){
+selector: "putOn:",
+category: 'streaming',
+fn: function (aStream){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(self)._stream();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"readStream",{},smalltalk.Collection)})},
-args: [],
-source: "readStream\x0a\x09^self stream",
-messageSends: ["stream"],
+return smalltalk.withContext(function($ctx1) { 
_st(self)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(each)._putOn_(aStream);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"putOn:",{aStream:aStream},smalltalk.Collection)})},
+args: ["aStream"],
+source: "putOn: aStream\x0a\x09self do: [ :each | each putOn: aStream ]",
+messageSends: ["do:", "putOn:"],
 referencedClasses: []
 }),
 smalltalk.Collection);
@@ -741,60 +741,6 @@ referencedClasses: []
 }),
 smalltalk.Collection);
 
-smalltalk.addMethod(
-"_stream",
-smalltalk.method({
-selector: "stream",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._streamClass())._on_(self);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"stream",{},smalltalk.Collection)})},
-args: [],
-source: "stream\x0a\x09^self streamClass on: self",
-messageSends: ["on:", "streamClass"],
-referencedClasses: []
-}),
-smalltalk.Collection);
-
-smalltalk.addMethod(
-"_streamClass",
-smalltalk.method({
-selector: "streamClass",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._class())._streamClass();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"streamClass",{},smalltalk.Collection)})},
-args: [],
-source: "streamClass\x0a\x09^self class streamClass",
-messageSends: ["streamClass", "class"],
-referencedClasses: []
-}),
-smalltalk.Collection);
-
-smalltalk.addMethod(
-"_writeStream",
-smalltalk.method({
-selector: "writeStream",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(self)._stream();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"writeStream",{},smalltalk.Collection)})},
-args: [],
-source: "writeStream\x0a\x09^self stream",
-messageSends: ["stream"],
-referencedClasses: []
-}),
-smalltalk.Collection);
-
 
 smalltalk.addMethod(
 "_new_",
@@ -814,24 +760,6 @@ referencedClasses: []
 }),
 smalltalk.Collection.klass);
 
-smalltalk.addMethod(
-"_streamClass",
-smalltalk.method({
-selector: "streamClass",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=(smalltalk.Stream || Stream);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"streamClass",{},smalltalk.Collection.klass)})},
-args: [],
-source: "streamClass\x0a\x09\x09^Stream",
-messageSends: [],
-referencedClasses: ["Stream"]
-}),
-smalltalk.Collection.klass);
-
 smalltalk.addMethod(
 "_with_",
 smalltalk.method({
@@ -1050,7 +978,7 @@ smalltalk.addMethod(
 "_with_do_",
 smalltalk.method({
 selector: "with:do:",
-category: 'enumeration',
+category: 'enumarating',
 fn: function (anotherCollection,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._withIndexDo_((function(each,index){
@@ -1068,7 +996,7 @@ smalltalk.addMethod(
 "_withIndexDo_",
 smalltalk.method({
 selector: "withIndexDo:",
-category: 'enumeration',
+category: 'enumarating',
 fn: function (aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._subclassReponsibility();
@@ -2375,6 +2303,42 @@ referencedClasses: []
 }),
 smalltalk.SequenceableCollection);
 
+smalltalk.addMethod(
+"_newStream",
+smalltalk.method({
+selector: "newStream",
+category: 'streaming',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._streamClass())._on_(self);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"newStream",{},smalltalk.SequenceableCollection)})},
+args: [],
+source: "newStream\x0a\x09^self streamClass on: self",
+messageSends: ["on:", "streamClass"],
+referencedClasses: []
+}),
+smalltalk.SequenceableCollection);
+
+smalltalk.addMethod(
+"_readStream",
+smalltalk.method({
+selector: "readStream",
+category: 'streaming',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(self)._stream();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"readStream",{},smalltalk.SequenceableCollection)})},
+args: [],
+source: "readStream\x0a\x09\x22For Pharo compatibility\x22\x0a\x09\x0a\x09^self stream",
+messageSends: ["stream"],
+referencedClasses: []
+}),
+smalltalk.SequenceableCollection);
+
 smalltalk.addMethod(
 "_removeLast",
 smalltalk.method({
@@ -2448,6 +2412,42 @@ referencedClasses: []
 }),
 smalltalk.SequenceableCollection);
 
+smalltalk.addMethod(
+"_stream",
+smalltalk.method({
+selector: "stream",
+category: 'streaming',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(self)._newStream();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"stream",{},smalltalk.SequenceableCollection)})},
+args: [],
+source: "stream\x0a\x09^self newStream",
+messageSends: ["newStream"],
+referencedClasses: []
+}),
+smalltalk.SequenceableCollection);
+
+smalltalk.addMethod(
+"_streamClass",
+smalltalk.method({
+selector: "streamClass",
+category: 'streaming',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._class())._streamClass();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"streamClass",{},smalltalk.SequenceableCollection)})},
+args: [],
+source: "streamClass\x0a\x09^self class streamClass",
+messageSends: ["streamClass", "class"],
+referencedClasses: []
+}),
+smalltalk.SequenceableCollection);
+
 smalltalk.addMethod(
 "_third",
 smalltalk.method({
@@ -2498,6 +2498,63 @@ referencedClasses: []
 }),
 smalltalk.SequenceableCollection);
 
+smalltalk.addMethod(
+"_writeStream",
+smalltalk.method({
+selector: "writeStream",
+category: 'streaming',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(self)._stream();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"writeStream",{},smalltalk.SequenceableCollection)})},
+args: [],
+source: "writeStream\x0a\x09\x22For Pharo compatibility\x22\x0a\x09\x0a\x09^self stream",
+messageSends: ["stream"],
+referencedClasses: []
+}),
+smalltalk.SequenceableCollection);
+
+
+smalltalk.addMethod(
+"_streamClass",
+smalltalk.method({
+selector: "streamClass",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=(smalltalk.Stream || Stream);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"streamClass",{},smalltalk.SequenceableCollection.klass)})},
+args: [],
+source: "streamClass\x0a\x09\x09^Stream",
+messageSends: [],
+referencedClasses: ["Stream"]
+}),
+smalltalk.SequenceableCollection.klass);
+
+smalltalk.addMethod(
+"_streamContents_",
+smalltalk.method({
+selector: "streamContents:",
+category: 'streaming',
+fn: function (aBlock){
+var self=this;
+var stream;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+stream=_st(_st(self)._streamClass())._on_(_st(self)._new());
+_st(aBlock)._value_(stream);
+$1=_st(stream)._contents();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"streamContents:",{aBlock:aBlock,stream:stream},smalltalk.SequenceableCollection.klass)})},
+args: ["aBlock"],
+source: "streamContents: aBlock\x0a\x09| stream |\x0a\x09stream := (self streamClass on: self new).\x0a\x09aBlock value: stream.\x0a\x09^ stream contents",
+messageSends: ["on:", "new", "streamClass", "value:", "contents"],
+referencedClasses: []
+}),
+smalltalk.SequenceableCollection.klass);
 
 
 smalltalk.addClass('Array', smalltalk.SequenceableCollection, [], 'Kernel-Collections');
@@ -3042,6 +3099,22 @@ referencedClasses: []
 }),
 smalltalk.CharacterArray);
 
+smalltalk.addMethod(
+"_putOn_",
+smalltalk.method({
+selector: "putOn:",
+category: 'streaming',
+fn: function (aStream){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(aStream)._nextPutString_(self);
+return self}, function($ctx1) {$ctx1.fill(self,"putOn:",{aStream:aStream},smalltalk.CharacterArray)})},
+args: ["aStream"],
+source: "putOn: aStream\x0a\x09aStream nextPutString: self",
+messageSends: ["nextPutString:"],
+referencedClasses: []
+}),
+smalltalk.CharacterArray);
+
 smalltalk.addMethod(
 "_remove_",
 smalltalk.method({
@@ -3486,6 +3559,22 @@ referencedClasses: []
 }),
 smalltalk.String);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isImmutable",{},smalltalk.String)})},
+args: [],
+source: "isImmutable\x0a\x09^ true",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.String);
+
 smalltalk.addMethod(
 "_isString",
 smalltalk.method({
@@ -4149,27 +4238,6 @@ referencedClasses: ["StringStream"]
 }),
 smalltalk.String.klass);
 
-smalltalk.addMethod(
-"_streamContents_",
-smalltalk.method({
-selector: "streamContents:",
-category: 'instance creation',
-fn: function (blockWithArg){
-var self=this;
-var stream;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-stream=_st(_st(self)._streamClass())._on_(_st((smalltalk.String || String))._new());
-_st(blockWithArg)._value_(stream);
-$1=_st(stream)._contents();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"streamContents:",{blockWithArg:blockWithArg,stream:stream},smalltalk.String.klass)})},
-args: ["blockWithArg"],
-source: "streamContents: blockWithArg\x0a\x09|stream|\x0a\x09stream := (self streamClass on: String new).\x0a\x09blockWithArg value: stream.\x0a\x09^ stream contents",
-messageSends: ["on:", "new", "streamClass", "value:", "contents"],
-referencedClasses: ["String"]
-}),
-smalltalk.String.klass);
-
 smalltalk.addMethod(
 "_tab",
 smalltalk.method({
@@ -4493,6 +4561,24 @@ referencedClasses: []
 }),
 smalltalk.Symbol);
 
+smalltalk.addMethod(
+"_indexOf_",
+smalltalk.method({
+selector: "indexOf:",
+category: 'accessing',
+fn: function (anElement){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._asString())._indexOf_(anElement);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"indexOf:",{anElement:anElement},smalltalk.Symbol)})},
+args: ["anElement"],
+source: "indexOf: anElement\x0a\x09^ self asString indexOf: anElement",
+messageSends: ["indexOf:", "asString"],
+referencedClasses: []
+}),
+smalltalk.Symbol);
+
 smalltalk.addMethod(
 "_isSymbol",
 smalltalk.method({
@@ -5111,6 +5197,22 @@ smalltalk.RegularExpression.klass);
 
 smalltalk.addClass('Stream', smalltalk.Object, ['collection', 'position', 'streamSize'], 'Kernel-Collections');
 smalltalk.Stream.comment="I represent an accessor for a sequence of objects. This sequence is referred to as my \x22contents\x22.\x0aMy instances are read/write streams to the contents sequence collection."
+smalltalk.addMethod(
+"__lt_lt",
+smalltalk.method({
+selector: "<<",
+category: 'writing',
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._write_(anObject);
+return self}, function($ctx1) {$ctx1.fill(self,"<<",{anObject:anObject},smalltalk.Stream)})},
+args: ["anObject"],
+source: "<< anObject\x0a\x09self write: anObject",
+messageSends: ["write:"],
+referencedClasses: []
+}),
+smalltalk.Stream);
+
 smalltalk.addMethod(
 "_atEnd",
 smalltalk.method({
@@ -5337,6 +5439,22 @@ referencedClasses: []
 }),
 smalltalk.Stream);
 
+smalltalk.addMethod(
+"_nextPutString_",
+smalltalk.method({
+selector: "nextPutString:",
+category: 'writing',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._nextPut_(aString);
+return self}, function($ctx1) {$ctx1.fill(self,"nextPutString:",{aString:aString},smalltalk.Stream)})},
+args: ["aString"],
+source: "nextPutString: aString\x0a\x09self nextPut: aString",
+messageSends: ["nextPut:"],
+referencedClasses: []
+}),
+smalltalk.Stream);
+
 smalltalk.addMethod(
 "_peek",
 smalltalk.method({
@@ -5531,6 +5649,22 @@ referencedClasses: []
 }),
 smalltalk.Stream);
 
+smalltalk.addMethod(
+"_write_",
+smalltalk.method({
+selector: "write:",
+category: 'writing',
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(anObject)._putOn_(self);
+return self}, function($ctx1) {$ctx1.fill(self,"write:",{anObject:anObject},smalltalk.Stream)})},
+args: ["anObject"],
+source: "write: anObject\x0a\x09anObject putOn: self",
+messageSends: ["putOn:"],
+referencedClasses: []
+}),
+smalltalk.Stream);
+
 
 smalltalk.addMethod(
 "_on_",
@@ -5683,6 +5817,22 @@ referencedClasses: []
 }),
 smalltalk.StringStream);
 
+smalltalk.addMethod(
+"_nextPutString_",
+smalltalk.method({
+selector: "nextPutString:",
+category: 'writing',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._nextPutAll_(aString);
+return self}, function($ctx1) {$ctx1.fill(self,"nextPutString:",{aString:aString},smalltalk.StringStream)})},
+args: ["aString"],
+source: "nextPutString: aString\x0a\x09self nextPutAll: aString",
+messageSends: ["nextPutAll:"],
+referencedClasses: []
+}),
+smalltalk.StringStream);
+
 smalltalk.addMethod(
 "_space",
 smalltalk.method({

+ 55 - 0
js/Kernel-Objects.deploy.js

@@ -367,6 +367,17 @@ return smalltalk.withContext(function($ctx1) { 
return false;
 messageSends: []}),
 smalltalk.Object);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return false;
+}, function($ctx1) {$ctx1.fill(self,"isImmutable",{},smalltalk.Object)})},
+messageSends: []}),
+smalltalk.Object);
+
 smalltalk.addMethod(
 "_isKindOf_",
 smalltalk.method({
@@ -546,6 +557,17 @@ return $1;
 messageSends: ["streamContents:", "printOn:"]}),
 smalltalk.Object);
 
+smalltalk.addMethod(
+"_putOn_",
+smalltalk.method({
+selector: "putOn:",
+fn: function (aStream){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(aStream)._nextPut_(self);
+return self}, function($ctx1) {$ctx1.fill(self,"putOn:",{aStream:aStream},smalltalk.Object)})},
+messageSends: ["nextPut:"]}),
+smalltalk.Object);
+
 smalltalk.addMethod(
 "_respondsTo_",
 smalltalk.method({
@@ -880,6 +902,17 @@ return smalltalk.withContext(function($ctx1) { 
return true;
 messageSends: []}),
 smalltalk.Boolean);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isImmutable",{},smalltalk.Boolean)})},
+messageSends: []}),
+smalltalk.Boolean);
+
 smalltalk.addMethod(
 "_not",
 smalltalk.method({
@@ -1778,6 +1811,17 @@ return $1;
 messageSends: ["x:y:"]}),
 smalltalk.Number);
 
+smalltalk.addMethod(
+"_IsImmutable",
+smalltalk.method({
+selector: "IsImmutable",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"IsImmutable",{},smalltalk.Number)})},
+messageSends: []}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 "__backslash",
 smalltalk.method({
@@ -3462,6 +3506,17 @@ return $1;
 messageSends: ["value"]}),
 smalltalk.UndefinedObject);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isImmutable",{},smalltalk.UndefinedObject)})},
+messageSends: []}),
+smalltalk.UndefinedObject);
+
 smalltalk.addMethod(
 "_isNil",
 smalltalk.method({

+ 80 - 0
js/Kernel-Objects.js

@@ -513,6 +513,22 @@ referencedClasses: []
 }),
 smalltalk.Object);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return false;
+}, function($ctx1) {$ctx1.fill(self,"isImmutable",{},smalltalk.Object)})},
+args: [],
+source: "isImmutable\x0a\x09^ false",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Object);
+
 smalltalk.addMethod(
 "_isKindOf_",
 smalltalk.method({
@@ -762,6 +778,22 @@ referencedClasses: ["String"]
 }),
 smalltalk.Object);
 
+smalltalk.addMethod(
+"_putOn_",
+smalltalk.method({
+selector: "putOn:",
+category: 'streaming',
+fn: function (aStream){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(aStream)._nextPut_(self);
+return self}, function($ctx1) {$ctx1.fill(self,"putOn:",{aStream:aStream},smalltalk.Object)})},
+args: ["aStream"],
+source: "putOn: aStream\x0a\x09aStream nextPut: self",
+messageSends: ["nextPut:"],
+referencedClasses: []
+}),
+smalltalk.Object);
+
 smalltalk.addMethod(
 "_respondsTo_",
 smalltalk.method({
@@ -1222,6 +1254,22 @@ referencedClasses: []
 }),
 smalltalk.Boolean);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isImmutable",{},smalltalk.Boolean)})},
+args: [],
+source: "isImmutable\x0a\x09^ true",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Boolean);
+
 smalltalk.addMethod(
 "_not",
 smalltalk.method({
@@ -2483,6 +2531,22 @@ referencedClasses: ["Point"]
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+"_IsImmutable",
+smalltalk.method({
+selector: "IsImmutable",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"IsImmutable",{},smalltalk.Number)})},
+args: [],
+source: "IsImmutable\x0a\x09^ true",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 "__backslash",
 smalltalk.method({
@@ -4763,6 +4827,22 @@ referencedClasses: []
 }),
 smalltalk.UndefinedObject);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isImmutable",{},smalltalk.UndefinedObject)})},
+args: [],
+source: "isImmutable\x0a\x09^ true",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.UndefinedObject);
+
 smalltalk.addMethod(
 "_isNil",
 smalltalk.method({

+ 372 - 29
js/Kernel-Tests.deploy.js

@@ -858,7 +858,69 @@ messageSends: ["isNil", "collectionClass"]}),
 smalltalk.CollectionTest.klass);
 
 
-smalltalk.addClass('HashedCollectionTest', smalltalk.CollectionTest, [], 'Kernel-Tests');
+smalltalk.addClass('IndexableCollectionTest', smalltalk.CollectionTest, [], 'Kernel-Tests');
+smalltalk.addMethod(
+"_testAt",
+smalltalk.method({
+selector: "testAt",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._at_((4)),(-4));
+_st(self)._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._at_((5));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
+return self}, function($ctx1) {$ctx1.fill(self,"testAt",{},smalltalk.IndexableCollectionTest)})},
+messageSends: ["assert:equals:", "at:", "collection", "should:raise:"]}),
+smalltalk.IndexableCollectionTest);
+
+smalltalk.addMethod(
+"_testAtIfAbsent",
+smalltalk.method({
+selector: "testAtIfAbsent",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._at_ifAbsent_(_st(_st(_st(self)._collection())._size()).__plus((1)),(function(){
+return smalltalk.withContext(function($ctx2) {
return "none";
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"none");
+return self}, function($ctx1) {$ctx1.fill(self,"testAtIfAbsent",{},smalltalk.IndexableCollectionTest)})},
+messageSends: ["assert:equals:", "at:ifAbsent:", "+", "size", "collection"]}),
+smalltalk.IndexableCollectionTest);
+
+smalltalk.addMethod(
+"_testIndexOf",
+smalltalk.method({
+selector: "testIndexOf",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_((2)),(2));
+_st(self)._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._indexOf_((999));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
+_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_ifAbsent_((999),(function(){
+return smalltalk.withContext(function($ctx2) {
return "sentinel";
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"sentinel");
+return self}, function($ctx1) {$ctx1.fill(self,"testIndexOf",{},smalltalk.IndexableCollectionTest)})},
+messageSends: ["assert:equals:", "indexOf:", "collection", "should:raise:", "indexOf:ifAbsent:"]}),
+smalltalk.IndexableCollectionTest);
+
+smalltalk.addMethod(
+"_testWithIndexDo",
+smalltalk.method({
+selector: "testWithIndexDo",
+fn: function (){
+var self=this;
+var collection;
+return smalltalk.withContext(function($ctx1) { 
collection=_st(self)._collection();
+_st(_st(self)._collection())._withIndexDo_((function(each,index){
+return smalltalk.withContext(function($ctx2) {
return _st(self)._assert_equals_(_st(collection)._at_(index),each);
+}, function($ctx2) {$ctx2.fillBlock({each:each,index:index},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"testWithIndexDo",{collection:collection},smalltalk.IndexableCollectionTest)})},
+messageSends: ["collection", "withIndexDo:", "assert:equals:", "at:"]}),
+smalltalk.IndexableCollectionTest);
+
+
+
+smalltalk.addClass('HashedCollectionTest', smalltalk.IndexableCollectionTest, [], 'Kernel-Tests');
 smalltalk.addMethod(
 "_collection",
 smalltalk.method({
@@ -885,6 +947,20 @@ return $1;
 messageSends: ["->"]}),
 smalltalk.HashedCollectionTest);
 
+smalltalk.addMethod(
+"_testAt",
+smalltalk.method({
+selector: "testAt",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._at_("a"),(2));
+_st(self)._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._at_((5));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
+return self}, function($ctx1) {$ctx1.fill(self,"testAt",{},smalltalk.HashedCollectionTest)})},
+messageSends: ["assert:equals:", "at:", "collection", "should:raise:"]}),
+smalltalk.HashedCollectionTest);
+
 smalltalk.addMethod(
 "_testIndexOf",
 smalltalk.method({
@@ -1255,34 +1331,7 @@ messageSends: []}),
 smalltalk.DictionaryTest.klass);
 
 
-smalltalk.addClass('SequenceableCollectionTest', smalltalk.CollectionTest, [], 'Kernel-Tests');
-smalltalk.addMethod(
-"_testAt",
-smalltalk.method({
-selector: "testAt",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._at_((4)),(-4));
-_st(self)._should_raise_((function(){
-return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._at_((5));
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
-return self}, function($ctx1) {$ctx1.fill(self,"testAt",{},smalltalk.SequenceableCollectionTest)})},
-messageSends: ["assert:equals:", "at:", "collection", "should:raise:"]}),
-smalltalk.SequenceableCollectionTest);
-
-smalltalk.addMethod(
-"_testAtIfAbsent",
-smalltalk.method({
-selector: "testAtIfAbsent",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._at_ifAbsent_(_st(_st(_st(self)._collection())._size()).__plus((1)),(function(){
-return smalltalk.withContext(function($ctx2) {
return "none";
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"none");
-return self}, function($ctx1) {$ctx1.fill(self,"testAtIfAbsent",{},smalltalk.SequenceableCollectionTest)})},
-messageSends: ["assert:equals:", "at:ifAbsent:", "+", "size", "collection"]}),
-smalltalk.SequenceableCollectionTest);
-
+smalltalk.addClass('SequenceableCollectionTest', smalltalk.IndexableCollectionTest, [], 'Kernel-Tests');
 
 
 smalltalk.addClass('ArrayTest', smalltalk.SequenceableCollectionTest, [], 'Kernel-Tests');
@@ -1543,6 +1592,23 @@ return self}, function($ctx1) {$ctx1.fill(self,"testIncludesSubString",{},smallt
 messageSends: ["assert:", "includesSubString:", "deny:"]}),
 smalltalk.StringTest);
 
+smalltalk.addMethod(
+"_testIndexOf",
+smalltalk.method({
+selector: "testIndexOf",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_("e"),(2));
+_st(self)._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._indexOf_((999));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
+_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_ifAbsent_((999),(function(){
+return smalltalk.withContext(function($ctx2) {
return "sentinel";
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"sentinel");
+return self}, function($ctx1) {$ctx1.fill(self,"testIndexOf",{},smalltalk.StringTest)})},
+messageSends: ["assert:equals:", "indexOf:", "collection", "should:raise:", "indexOf:ifAbsent:"]}),
+smalltalk.StringTest);
+
 smalltalk.addMethod(
 "_testJoin",
 smalltalk.method({
@@ -1780,6 +1846,23 @@ return self}, function($ctx1) {$ctx1.fill(self,"testIdentity",{},smalltalk.Symbo
 messageSends: ["assert:", "==", "deny:", "=", "yourself", "asSymbol", "asString"]}),
 smalltalk.SymbolTest);
 
+smalltalk.addMethod(
+"_testIndexOf",
+smalltalk.method({
+selector: "testIndexOf",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_("e"),(2));
+_st(self)._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._indexOf_((999));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
+_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_ifAbsent_((999),(function(){
+return smalltalk.withContext(function($ctx2) {
return "sentinel";
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"sentinel");
+return self}, function($ctx1) {$ctx1.fill(self,"testIndexOf",{},smalltalk.SymbolTest)})},
+messageSends: ["assert:equals:", "indexOf:", "collection", "should:raise:", "indexOf:ifAbsent:"]}),
+smalltalk.SymbolTest);
+
 smalltalk.addMethod(
 "_testIsEmpty",
 smalltalk.method({
@@ -3085,6 +3168,266 @@ smalltalk.SetTest);
 
 
 
+smalltalk.addClass('StreamTest', smalltalk.TestCase, [], 'Kernel-Tests');
+smalltalk.addMethod(
+"_collectionClass",
+smalltalk.method({
+selector: "collectionClass",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._class())._collectionClass();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"collectionClass",{},smalltalk.StreamTest)})},
+messageSends: ["collectionClass", "class"]}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_newCollection",
+smalltalk.method({
+selector: "newCollection",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._collectionClass())._new();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"newCollection",{},smalltalk.StreamTest)})},
+messageSends: ["new", "collectionClass"]}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_newStream",
+smalltalk.method({
+selector: "newStream",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(_st(self)._collectionClass())._new())._stream();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"newStream",{},smalltalk.StreamTest)})},
+messageSends: ["stream", "new", "collectionClass"]}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testAtStartAtEnd",
+smalltalk.method({
+selector: "testAtStartAtEnd",
+fn: function (){
+var self=this;
+var stream;
+return smalltalk.withContext(function($ctx1) { 
stream=_st(self)._newStream();
+_st(self)._assert_(_st(stream)._atStart());
+_st(self)._assert_(_st(stream)._atEnd());
+_st(stream)._nextPutAll_(_st(self)._newCollection());
+_st(self)._assert_(_st(stream)._atEnd());
+_st(self)._deny_(_st(stream)._atStart());
+_st(stream)._position_((1));
+_st(self)._deny_(_st(stream)._atEnd());
+_st(self)._deny_(_st(stream)._atStart());
+return self}, function($ctx1) {$ctx1.fill(self,"testAtStartAtEnd",{stream:stream},smalltalk.StreamTest)})},
+messageSends: ["newStream", "assert:", "atStart", "atEnd", "nextPutAll:", "newCollection", "deny:", "position:"]}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testContents",
+smalltalk.method({
+selector: "testContents",
+fn: function (){
+var self=this;
+var stream;
+return smalltalk.withContext(function($ctx1) { 
stream=_st(self)._newStream();
+_st(stream)._nextPutAll_(_st(self)._newCollection());
+_st(self)._assert_equals_(_st(stream)._contents(),_st(self)._newCollection());
+return self}, function($ctx1) {$ctx1.fill(self,"testContents",{stream:stream},smalltalk.StreamTest)})},
+messageSends: ["newStream", "nextPutAll:", "newCollection", "assert:equals:", "contents"]}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testIsEmpty",
+smalltalk.method({
+selector: "testIsEmpty",
+fn: function (){
+var self=this;
+var stream;
+return smalltalk.withContext(function($ctx1) { 
stream=_st(self)._newStream();
+_st(self)._assert_(_st(stream)._isEmpty());
+_st(stream)._nextPutAll_(_st(self)._newCollection());
+_st(self)._deny_(_st(stream)._isEmpty());
+return self}, function($ctx1) {$ctx1.fill(self,"testIsEmpty",{stream:stream},smalltalk.StreamTest)})},
+messageSends: ["newStream", "assert:", "isEmpty", "nextPutAll:", "newCollection", "deny:"]}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testPosition",
+smalltalk.method({
+selector: "testPosition",
+fn: function (){
+var self=this;
+var collection,stream;
+return smalltalk.withContext(function($ctx1) { 
collection=_st(self)._newCollection();
+stream=_st(self)._newStream();
+_st(stream)._nextPutAll_(collection);
+_st(self)._assert_equals_(_st(stream)._position(),_st(collection)._size());
+_st(stream)._position_((0));
+_st(self)._assert_equals_(_st(stream)._position(),(0));
+_st(stream)._next();
+_st(self)._assert_equals_(_st(stream)._position(),(1));
+_st(stream)._next();
+_st(self)._assert_equals_(_st(stream)._position(),(2));
+return self}, function($ctx1) {$ctx1.fill(self,"testPosition",{collection:collection,stream:stream},smalltalk.StreamTest)})},
+messageSends: ["newCollection", "newStream", "nextPutAll:", "assert:equals:", "position", "size", "position:", "next"]}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testReading",
+smalltalk.method({
+selector: "testReading",
+fn: function (){
+var self=this;
+var stream,collection;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+collection=_st(self)._newCollection();
+stream=_st(self)._newStream();
+$1=stream;
+_st($1)._nextPutAll_(collection);
+$2=_st($1)._position_((0));
+_st(collection)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(self)._assert_equals_(_st(stream)._next(),each);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+_st(self)._assert_(_st(_st(stream)._next())._isNil());
+return self}, function($ctx1) {$ctx1.fill(self,"testReading",{stream:stream,collection:collection},smalltalk.StreamTest)})},
+messageSends: ["newCollection", "newStream", "nextPutAll:", "position:", "do:", "assert:equals:", "next", "assert:", "isNil"]}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testStreamContents",
+smalltalk.method({
+selector: "testStreamContents",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return self}, function($ctx1) {$ctx1.fill(self,"testStreamContents",{},smalltalk.StreamTest)})},
+messageSends: []}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testWrite",
+smalltalk.method({
+selector: "testWrite",
+fn: function (){
+var self=this;
+var stream,collection;
+return smalltalk.withContext(function($ctx1) { 
collection=_st(self)._newCollection();
+stream=_st(self)._newStream();
+_st(collection)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(stream).__lt_lt(each);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+_st(self)._assert_equals_(_st(stream)._contents(),collection);
+return self}, function($ctx1) {$ctx1.fill(self,"testWrite",{stream:stream,collection:collection},smalltalk.StreamTest)})},
+messageSends: ["newCollection", "newStream", "do:", "<<", "assert:equals:", "contents"]}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testWriting",
+smalltalk.method({
+selector: "testWriting",
+fn: function (){
+var self=this;
+var stream,collection;
+return smalltalk.withContext(function($ctx1) { 
collection=_st(self)._newCollection();
+stream=_st(self)._newStream();
+_st(collection)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(stream)._nextPut_(each);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+_st(self)._assert_equals_(_st(stream)._contents(),collection);
+stream=_st(self)._newStream();
+_st(stream)._nextPutAll_(collection);
+_st(self)._assert_equals_(_st(stream)._contents(),collection);
+return self}, function($ctx1) {$ctx1.fill(self,"testWriting",{stream:stream,collection:collection},smalltalk.StreamTest)})},
+messageSends: ["newCollection", "newStream", "do:", "nextPut:", "assert:equals:", "contents", "nextPutAll:"]}),
+smalltalk.StreamTest);
+
+
+smalltalk.addMethod(
+"_collectionClass",
+smalltalk.method({
+selector: "collectionClass",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return nil;
+}, function($ctx1) {$ctx1.fill(self,"collectionClass",{},smalltalk.StreamTest.klass)})},
+messageSends: []}),
+smalltalk.StreamTest.klass);
+
+smalltalk.addMethod(
+"_isAbstract",
+smalltalk.method({
+selector: "isAbstract",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._collectionClass())._isNil();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isAbstract",{},smalltalk.StreamTest.klass)})},
+messageSends: ["isNil", "collectionClass"]}),
+smalltalk.StreamTest.klass);
+
+
+smalltalk.addClass('ArrayStreamTest', smalltalk.StreamTest, [], 'Kernel-Tests');
+smalltalk.addMethod(
+"_newCollection",
+smalltalk.method({
+selector: "newCollection",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=[true,(1),_st((3)).__at((4)),"foo"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"newCollection",{},smalltalk.ArrayStreamTest)})},
+messageSends: ["@"]}),
+smalltalk.ArrayStreamTest);
+
+
+smalltalk.addMethod(
+"_collectionClass",
+smalltalk.method({
+selector: "collectionClass",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=(smalltalk.Array || Array);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"collectionClass",{},smalltalk.ArrayStreamTest.klass)})},
+messageSends: []}),
+smalltalk.ArrayStreamTest.klass);
+
+
+smalltalk.addClass('StringStreamTest', smalltalk.StreamTest, [], 'Kernel-Tests');
+smalltalk.addMethod(
+"_newCollection",
+smalltalk.method({
+selector: "newCollection",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "hello world";
+}, function($ctx1) {$ctx1.fill(self,"newCollection",{},smalltalk.StringStreamTest)})},
+messageSends: []}),
+smalltalk.StringStreamTest);
+
+
+smalltalk.addMethod(
+"_collectionClass",
+smalltalk.method({
+selector: "collectionClass",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=(smalltalk.String || String);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"collectionClass",{},smalltalk.StringStreamTest.klass)})},
+messageSends: []}),
+smalltalk.StringStreamTest.klass);
+
+
 smalltalk.addClass('UndefinedTest', smalltalk.TestCase, [], 'Kernel-Tests');
 smalltalk.addMethod(
 "_testCopying",

+ 493 - 40
js/Kernel-Tests.js

@@ -1078,7 +1078,89 @@ referencedClasses: []
 smalltalk.CollectionTest.klass);
 
 
-smalltalk.addClass('HashedCollectionTest', smalltalk.CollectionTest, [], 'Kernel-Tests');
+smalltalk.addClass('IndexableCollectionTest', smalltalk.CollectionTest, [], 'Kernel-Tests');
+smalltalk.addMethod(
+"_testAt",
+smalltalk.method({
+selector: "testAt",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._at_((4)),(-4));
+_st(self)._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._at_((5));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
+return self}, function($ctx1) {$ctx1.fill(self,"testAt",{},smalltalk.IndexableCollectionTest)})},
+args: [],
+source: "testAt\x0a\x09self assert: (self collection at: 4) equals: -4.\x0a\x09self should: [ self collection at: 5 ] raise: Error",
+messageSends: ["assert:equals:", "at:", "collection", "should:raise:"],
+referencedClasses: ["Error"]
+}),
+smalltalk.IndexableCollectionTest);
+
+smalltalk.addMethod(
+"_testAtIfAbsent",
+smalltalk.method({
+selector: "testAtIfAbsent",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._at_ifAbsent_(_st(_st(_st(self)._collection())._size()).__plus((1)),(function(){
+return smalltalk.withContext(function($ctx2) {
return "none";
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"none");
+return self}, function($ctx1) {$ctx1.fill(self,"testAtIfAbsent",{},smalltalk.IndexableCollectionTest)})},
+args: [],
+source: "testAtIfAbsent\x0a\x09self assert: (self collection at: (self collection size + 1) ifAbsent: [ 'none' ]) equals: 'none'",
+messageSends: ["assert:equals:", "at:ifAbsent:", "+", "size", "collection"],
+referencedClasses: []
+}),
+smalltalk.IndexableCollectionTest);
+
+smalltalk.addMethod(
+"_testIndexOf",
+smalltalk.method({
+selector: "testIndexOf",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_((2)),(2));
+_st(self)._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._indexOf_((999));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
+_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_ifAbsent_((999),(function(){
+return smalltalk.withContext(function($ctx2) {
return "sentinel";
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"sentinel");
+return self}, function($ctx1) {$ctx1.fill(self,"testIndexOf",{},smalltalk.IndexableCollectionTest)})},
+args: [],
+source: "testIndexOf\x0a\x09self assert: (self collection indexOf: 2) equals: 2.\x0a\x09self should: [ self collection indexOf: 999 ] raise: Error.\x0a\x09self assert: (self collection indexOf: 999 ifAbsent: [ 'sentinel' ]) equals: 'sentinel'",
+messageSends: ["assert:equals:", "indexOf:", "collection", "should:raise:", "indexOf:ifAbsent:"],
+referencedClasses: ["Error"]
+}),
+smalltalk.IndexableCollectionTest);
+
+smalltalk.addMethod(
+"_testWithIndexDo",
+smalltalk.method({
+selector: "testWithIndexDo",
+category: 'tests',
+fn: function (){
+var self=this;
+var collection;
+return smalltalk.withContext(function($ctx1) { 
collection=_st(self)._collection();
+_st(_st(self)._collection())._withIndexDo_((function(each,index){
+return smalltalk.withContext(function($ctx2) {
return _st(self)._assert_equals_(_st(collection)._at_(index),each);
+}, function($ctx2) {$ctx2.fillBlock({each:each,index:index},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"testWithIndexDo",{collection:collection},smalltalk.IndexableCollectionTest)})},
+args: [],
+source: "testWithIndexDo\x0a\x09| collection |\x0a\x09collection := self collection.\x0a\x09\x0a\x09self collection withIndexDo: [ :each :index |\x0a\x09\x09self assert: (collection at: index) equals: each ]",
+messageSends: ["collection", "withIndexDo:", "assert:equals:", "at:"],
+referencedClasses: []
+}),
+smalltalk.IndexableCollectionTest);
+
+
+
+smalltalk.addClass('HashedCollectionTest', smalltalk.IndexableCollectionTest, [], 'Kernel-Tests');
 smalltalk.addMethod(
 "_collection",
 smalltalk.method({
@@ -1115,6 +1197,25 @@ referencedClasses: []
 }),
 smalltalk.HashedCollectionTest);
 
+smalltalk.addMethod(
+"_testAt",
+smalltalk.method({
+selector: "testAt",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._at_("a"),(2));
+_st(self)._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._at_((5));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
+return self}, function($ctx1) {$ctx1.fill(self,"testAt",{},smalltalk.HashedCollectionTest)})},
+args: [],
+source: "testAt\x0a\x09self assert: (self collection at: 'a') equals: 2.\x0a\x09self should: [ self collection at: 5 ] raise: Error",
+messageSends: ["assert:equals:", "at:", "collection", "should:raise:"],
+referencedClasses: ["Error"]
+}),
+smalltalk.HashedCollectionTest);
+
 smalltalk.addMethod(
 "_testIndexOf",
 smalltalk.method({
@@ -1131,7 +1232,7 @@ return smalltalk.withContext(function($ctx2) {
return "sentinel";
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"sentinel");
 return self}, function($ctx1) {$ctx1.fill(self,"testIndexOf",{},smalltalk.HashedCollectionTest)})},
 args: [],
-source: "testIndexOf\x0a\x0a\x09self assert: (self collection indexOf: 2) equals: 'a'.\x0a\x09self should: [ self collection indexOf: 999 ] raise: Error.\x0a\x09self assert: (self collection indexOf: 999 ifAbsent: [ 'sentinel' ]) equals: 'sentinel'",
+source: "testIndexOf\x0a\x09self assert: (self collection indexOf: 2) equals: 'a'.\x0a\x09self should: [ self collection indexOf: 999 ] raise: Error.\x0a\x09self assert: (self collection indexOf: 999 ifAbsent: [ 'sentinel' ]) equals: 'sentinel'",
 messageSends: ["assert:equals:", "indexOf:", "collection", "should:raise:", "indexOf:ifAbsent:"],
 referencedClasses: ["Error"]
 }),
@@ -1575,44 +1676,7 @@ referencedClasses: ["Dictionary"]
 smalltalk.DictionaryTest.klass);
 
 
-smalltalk.addClass('SequenceableCollectionTest', smalltalk.CollectionTest, [], 'Kernel-Tests');
-smalltalk.addMethod(
-"_testAt",
-smalltalk.method({
-selector: "testAt",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._at_((4)),(-4));
-_st(self)._should_raise_((function(){
-return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._at_((5));
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
-return self}, function($ctx1) {$ctx1.fill(self,"testAt",{},smalltalk.SequenceableCollectionTest)})},
-args: [],
-source: "testAt\x0a\x09self assert: (self collection at: 4) equals: -4.\x0a\x09self should: [ self collection at: 5 ] raise: Error",
-messageSends: ["assert:equals:", "at:", "collection", "should:raise:"],
-referencedClasses: ["Error"]
-}),
-smalltalk.SequenceableCollectionTest);
-
-smalltalk.addMethod(
-"_testAtIfAbsent",
-smalltalk.method({
-selector: "testAtIfAbsent",
-category: 'tests',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._at_ifAbsent_(_st(_st(_st(self)._collection())._size()).__plus((1)),(function(){
-return smalltalk.withContext(function($ctx2) {
return "none";
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"none");
-return self}, function($ctx1) {$ctx1.fill(self,"testAtIfAbsent",{},smalltalk.SequenceableCollectionTest)})},
-args: [],
-source: "testAtIfAbsent\x0a\x09self assert: (self collection at: (self collection size + 1) ifAbsent: [ 'none' ]) equals: 'none'",
-messageSends: ["assert:equals:", "at:ifAbsent:", "+", "size", "collection"],
-referencedClasses: []
-}),
-smalltalk.SequenceableCollectionTest);
-
+smalltalk.addClass('SequenceableCollectionTest', smalltalk.IndexableCollectionTest, [], 'Kernel-Tests');
 
 
 smalltalk.addClass('ArrayTest', smalltalk.SequenceableCollectionTest, [], 'Kernel-Tests');
@@ -1958,6 +2022,28 @@ referencedClasses: []
 }),
 smalltalk.StringTest);
 
+smalltalk.addMethod(
+"_testIndexOf",
+smalltalk.method({
+selector: "testIndexOf",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_("e"),(2));
+_st(self)._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._indexOf_((999));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
+_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_ifAbsent_((999),(function(){
+return smalltalk.withContext(function($ctx2) {
return "sentinel";
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"sentinel");
+return self}, function($ctx1) {$ctx1.fill(self,"testIndexOf",{},smalltalk.StringTest)})},
+args: [],
+source: "testIndexOf\x0a\x09self assert: (self collection indexOf: 'e') equals: 2.\x0a\x09self should: [ self collection indexOf: 999 ] raise: Error.\x0a\x09self assert: (self collection indexOf: 999 ifAbsent: [ 'sentinel' ]) equals: 'sentinel'",
+messageSends: ["assert:equals:", "indexOf:", "collection", "should:raise:", "indexOf:ifAbsent:"],
+referencedClasses: ["Error"]
+}),
+smalltalk.StringTest);
+
 smalltalk.addMethod(
 "_testJoin",
 smalltalk.method({
@@ -2280,6 +2366,28 @@ referencedClasses: []
 }),
 smalltalk.SymbolTest);
 
+smalltalk.addMethod(
+"_testIndexOf",
+smalltalk.method({
+selector: "testIndexOf",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_("e"),(2));
+_st(self)._should_raise_((function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._collection())._indexOf_((999));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}),(smalltalk.Error || Error));
+_st(self)._assert_equals_(_st(_st(self)._collection())._indexOf_ifAbsent_((999),(function(){
+return smalltalk.withContext(function($ctx2) {
return "sentinel";
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})),"sentinel");
+return self}, function($ctx1) {$ctx1.fill(self,"testIndexOf",{},smalltalk.SymbolTest)})},
+args: [],
+source: "testIndexOf\x0a\x09self assert: (self collection indexOf: 'e') equals: 2.\x0a\x09self should: [ self collection indexOf: 999 ] raise: Error.\x0a\x09self assert: (self collection indexOf: 999 ifAbsent: [ 'sentinel' ]) equals: 'sentinel'",
+messageSends: ["assert:equals:", "indexOf:", "collection", "should:raise:", "indexOf:ifAbsent:"],
+referencedClasses: ["Error"]
+}),
+smalltalk.SymbolTest);
+
 smalltalk.addMethod(
 "_testIsEmpty",
 smalltalk.method({
@@ -3971,6 +4079,351 @@ smalltalk.SetTest);
 
 
 
+smalltalk.addClass('StreamTest', smalltalk.TestCase, [], 'Kernel-Tests');
+smalltalk.addMethod(
+"_collectionClass",
+smalltalk.method({
+selector: "collectionClass",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._class())._collectionClass();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"collectionClass",{},smalltalk.StreamTest)})},
+args: [],
+source: "collectionClass\x0a\x09^ self class collectionClass",
+messageSends: ["collectionClass", "class"],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_newCollection",
+smalltalk.method({
+selector: "newCollection",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._collectionClass())._new();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"newCollection",{},smalltalk.StreamTest)})},
+args: [],
+source: "newCollection\x0a\x09^ self collectionClass new",
+messageSends: ["new", "collectionClass"],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_newStream",
+smalltalk.method({
+selector: "newStream",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(_st(self)._collectionClass())._new())._stream();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"newStream",{},smalltalk.StreamTest)})},
+args: [],
+source: "newStream\x0a\x09^ self collectionClass new stream",
+messageSends: ["stream", "new", "collectionClass"],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testAtStartAtEnd",
+smalltalk.method({
+selector: "testAtStartAtEnd",
+category: 'tests',
+fn: function (){
+var self=this;
+var stream;
+return smalltalk.withContext(function($ctx1) { 
stream=_st(self)._newStream();
+_st(self)._assert_(_st(stream)._atStart());
+_st(self)._assert_(_st(stream)._atEnd());
+_st(stream)._nextPutAll_(_st(self)._newCollection());
+_st(self)._assert_(_st(stream)._atEnd());
+_st(self)._deny_(_st(stream)._atStart());
+_st(stream)._position_((1));
+_st(self)._deny_(_st(stream)._atEnd());
+_st(self)._deny_(_st(stream)._atStart());
+return self}, function($ctx1) {$ctx1.fill(self,"testAtStartAtEnd",{stream:stream},smalltalk.StreamTest)})},
+args: [],
+source: "testAtStartAtEnd\x0a\x09| stream |\x0a\x09\x0a\x09stream := self newStream.\x0a\x09self assert: stream atStart.\x0a\x09self assert: stream atEnd.\x0a\x09\x0a\x09stream nextPutAll: self newCollection.\x0a\x09self assert: stream atEnd.\x0a\x09self deny: stream atStart.\x0a\x09\x0a\x09stream position: 1.\x0a\x09self deny: stream atEnd.\x0a\x09self deny: stream atStart",
+messageSends: ["newStream", "assert:", "atStart", "atEnd", "nextPutAll:", "newCollection", "deny:", "position:"],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testContents",
+smalltalk.method({
+selector: "testContents",
+category: 'tests',
+fn: function (){
+var self=this;
+var stream;
+return smalltalk.withContext(function($ctx1) { 
stream=_st(self)._newStream();
+_st(stream)._nextPutAll_(_st(self)._newCollection());
+_st(self)._assert_equals_(_st(stream)._contents(),_st(self)._newCollection());
+return self}, function($ctx1) {$ctx1.fill(self,"testContents",{stream:stream},smalltalk.StreamTest)})},
+args: [],
+source: "testContents\x0a\x09| stream |\x0a\x09\x0a\x09stream := self newStream.\x0a\x09stream nextPutAll: self newCollection.\x0a\x09\x0a\x09self assert: stream contents equals: self newCollection",
+messageSends: ["newStream", "nextPutAll:", "newCollection", "assert:equals:", "contents"],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testIsEmpty",
+smalltalk.method({
+selector: "testIsEmpty",
+category: 'tests',
+fn: function (){
+var self=this;
+var stream;
+return smalltalk.withContext(function($ctx1) { 
stream=_st(self)._newStream();
+_st(self)._assert_(_st(stream)._isEmpty());
+_st(stream)._nextPutAll_(_st(self)._newCollection());
+_st(self)._deny_(_st(stream)._isEmpty());
+return self}, function($ctx1) {$ctx1.fill(self,"testIsEmpty",{stream:stream},smalltalk.StreamTest)})},
+args: [],
+source: "testIsEmpty\x0a\x09| stream |\x0a\x09\x0a\x09stream := self newStream.\x0a\x09self assert: stream isEmpty.\x0a\x09\x0a\x09stream nextPutAll: self newCollection.\x0a\x09self deny: stream isEmpty",
+messageSends: ["newStream", "assert:", "isEmpty", "nextPutAll:", "newCollection", "deny:"],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testPosition",
+smalltalk.method({
+selector: "testPosition",
+category: 'tests',
+fn: function (){
+var self=this;
+var collection,stream;
+return smalltalk.withContext(function($ctx1) { 
collection=_st(self)._newCollection();
+stream=_st(self)._newStream();
+_st(stream)._nextPutAll_(collection);
+_st(self)._assert_equals_(_st(stream)._position(),_st(collection)._size());
+_st(stream)._position_((0));
+_st(self)._assert_equals_(_st(stream)._position(),(0));
+_st(stream)._next();
+_st(self)._assert_equals_(_st(stream)._position(),(1));
+_st(stream)._next();
+_st(self)._assert_equals_(_st(stream)._position(),(2));
+return self}, function($ctx1) {$ctx1.fill(self,"testPosition",{collection:collection,stream:stream},smalltalk.StreamTest)})},
+args: [],
+source: "testPosition\x0a\x09| collection stream |\x0a\x09\x0a\x09collection := self newCollection.\x0a\x09stream := self newStream.\x0a\x09\x0a\x09stream nextPutAll: collection.\x0a\x09self assert: stream position equals: collection size.\x0a\x09\x0a\x09stream position: 0.\x0a\x09self assert: stream position equals: 0.\x0a\x09\x0a\x09stream next.\x0a\x09self assert: stream position equals: 1.\x0a\x09\x0a\x09stream next.\x0a\x09self assert: stream position equals: 2",
+messageSends: ["newCollection", "newStream", "nextPutAll:", "assert:equals:", "position", "size", "position:", "next"],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testReading",
+smalltalk.method({
+selector: "testReading",
+category: 'tests',
+fn: function (){
+var self=this;
+var stream,collection;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+collection=_st(self)._newCollection();
+stream=_st(self)._newStream();
+$1=stream;
+_st($1)._nextPutAll_(collection);
+$2=_st($1)._position_((0));
+_st(collection)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(self)._assert_equals_(_st(stream)._next(),each);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+_st(self)._assert_(_st(_st(stream)._next())._isNil());
+return self}, function($ctx1) {$ctx1.fill(self,"testReading",{stream:stream,collection:collection},smalltalk.StreamTest)})},
+args: [],
+source: "testReading\x0a\x09| stream collection |\x0a\x09\x0a\x09collection := self newCollection.\x0a\x09stream := self newStream.\x0a\x09\x0a\x09stream \x0a\x09\x09nextPutAll: collection;\x0a\x09\x09position: 0.\x0a\x09\x0a\x09collection do: [ :each |\x0a\x09\x09self assert: stream next equals: each ].\x0a\x09\x09\x0a\x09self assert: stream next isNil",
+messageSends: ["newCollection", "newStream", "nextPutAll:", "position:", "do:", "assert:equals:", "next", "assert:", "isNil"],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testStreamContents",
+smalltalk.method({
+selector: "testStreamContents",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return self}, function($ctx1) {$ctx1.fill(self,"testStreamContents",{},smalltalk.StreamTest)})},
+args: [],
+source: "testStreamContents",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testWrite",
+smalltalk.method({
+selector: "testWrite",
+category: 'tests',
+fn: function (){
+var self=this;
+var stream,collection;
+return smalltalk.withContext(function($ctx1) { 
collection=_st(self)._newCollection();
+stream=_st(self)._newStream();
+_st(collection)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(stream).__lt_lt(each);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+_st(self)._assert_equals_(_st(stream)._contents(),collection);
+return self}, function($ctx1) {$ctx1.fill(self,"testWrite",{stream:stream,collection:collection},smalltalk.StreamTest)})},
+args: [],
+source: "testWrite\x0a\x09| stream collection |\x0a\x09\x0a\x09collection := self newCollection.\x0a\x09stream := self newStream.\x0a\x09\x0a\x09collection do: [ :each | stream << each ].\x0a\x09self assert: stream contents equals: collection",
+messageSends: ["newCollection", "newStream", "do:", "<<", "assert:equals:", "contents"],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+smalltalk.addMethod(
+"_testWriting",
+smalltalk.method({
+selector: "testWriting",
+category: 'tests',
+fn: function (){
+var self=this;
+var stream,collection;
+return smalltalk.withContext(function($ctx1) { 
collection=_st(self)._newCollection();
+stream=_st(self)._newStream();
+_st(collection)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(stream)._nextPut_(each);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+_st(self)._assert_equals_(_st(stream)._contents(),collection);
+stream=_st(self)._newStream();
+_st(stream)._nextPutAll_(collection);
+_st(self)._assert_equals_(_st(stream)._contents(),collection);
+return self}, function($ctx1) {$ctx1.fill(self,"testWriting",{stream:stream,collection:collection},smalltalk.StreamTest)})},
+args: [],
+source: "testWriting\x0a\x09| stream collection |\x0a\x09\x0a\x09collection := self newCollection.\x0a\x09stream := self newStream.\x0a\x09\x0a\x09collection do: [ :each | stream nextPut: each ].\x0a\x09self assert: stream contents equals: collection.\x0a\x09\x0a\x09stream := self newStream.\x0a\x09stream nextPutAll: collection.\x0a\x09self assert: stream contents equals: collection",
+messageSends: ["newCollection", "newStream", "do:", "nextPut:", "assert:equals:", "contents", "nextPutAll:"],
+referencedClasses: []
+}),
+smalltalk.StreamTest);
+
+
+smalltalk.addMethod(
+"_collectionClass",
+smalltalk.method({
+selector: "collectionClass",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return nil;
+}, function($ctx1) {$ctx1.fill(self,"collectionClass",{},smalltalk.StreamTest.klass)})},
+args: [],
+source: "collectionClass\x0a\x09^ nil",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.StreamTest.klass);
+
+smalltalk.addMethod(
+"_isAbstract",
+smalltalk.method({
+selector: "isAbstract",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._collectionClass())._isNil();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isAbstract",{},smalltalk.StreamTest.klass)})},
+args: [],
+source: "isAbstract\x0a\x09^ self collectionClass isNil",
+messageSends: ["isNil", "collectionClass"],
+referencedClasses: []
+}),
+smalltalk.StreamTest.klass);
+
+
+smalltalk.addClass('ArrayStreamTest', smalltalk.StreamTest, [], 'Kernel-Tests');
+smalltalk.addMethod(
+"_newCollection",
+smalltalk.method({
+selector: "newCollection",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=[true,(1),_st((3)).__at((4)),"foo"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"newCollection",{},smalltalk.ArrayStreamTest)})},
+args: [],
+source: "newCollection\x0a\x09^ { true. 1. 3@4. 'foo' }",
+messageSends: ["@"],
+referencedClasses: []
+}),
+smalltalk.ArrayStreamTest);
+
+
+smalltalk.addMethod(
+"_collectionClass",
+smalltalk.method({
+selector: "collectionClass",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=(smalltalk.Array || Array);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"collectionClass",{},smalltalk.ArrayStreamTest.klass)})},
+args: [],
+source: "collectionClass\x0a\x09^ Array",
+messageSends: [],
+referencedClasses: ["Array"]
+}),
+smalltalk.ArrayStreamTest.klass);
+
+
+smalltalk.addClass('StringStreamTest', smalltalk.StreamTest, [], 'Kernel-Tests');
+smalltalk.addMethod(
+"_newCollection",
+smalltalk.method({
+selector: "newCollection",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return "hello world";
+}, function($ctx1) {$ctx1.fill(self,"newCollection",{},smalltalk.StringStreamTest)})},
+args: [],
+source: "newCollection\x0a\x09^ 'hello world'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.StringStreamTest);
+
+
+smalltalk.addMethod(
+"_collectionClass",
+smalltalk.method({
+selector: "collectionClass",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=(smalltalk.String || String);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"collectionClass",{},smalltalk.StringStreamTest.klass)})},
+args: [],
+source: "collectionClass\x0a\x09^ String",
+messageSends: [],
+referencedClasses: ["String"]
+}),
+smalltalk.StringStreamTest.klass);
+
+
 smalltalk.addClass('UndefinedTest', smalltalk.TestCase, [], 'Kernel-Tests');
 smalltalk.addMethod(
 "_testCopying",

+ 1 - 1
st/Compiler-AST.st

@@ -482,7 +482,7 @@ value: anObject
 !ValueNode methodsFor: 'testing'!
 
 isImmutable
-	^true
+	^ self value isImmutable
 !
 
 isValueNode

+ 9 - 0
st/Compiler-Tests.st

@@ -332,6 +332,15 @@ testMessageSends
 	self should: 'foo ^ 1 to: 5 by: 2' return: #(1 3 5)
 !
 
+testMutableLiterals
+	"Mutable literals must be aliased in cascades.
+	See https://github.com/amber-smalltalk/amber/issues/428"
+	
+	self 
+		should: 'foo ^ #( 1 2 ) at: 1 put: 3; yourself' 
+		return: #(3 2)
+!
+
 testNestedIfTrue
 	self should: 'foo ^ true ifTrue: [ false ifFalse: [ 1 ] ]' return: 1.
 	self should: 'foo ^ true ifTrue: [ false ifTrue: [ 1 ] ]' return: nil.

+ 78 - 30
st/Kernel-Collections.st

@@ -69,24 +69,8 @@ occurrencesOf: anObject
 	^tally
 !
 
-readStream
-	^self stream
-!
-
 size
 	self subclassResponsibility
-!
-
-stream
-	^self streamClass on: self
-!
-
-streamClass
-	^self class streamClass
-!
-
-writeStream
-	^self stream
 ! !
 
 !Collection methodsFor: 'adding/removing'!
@@ -223,6 +207,12 @@ errorNotFound
 	self error: 'Object is not in the collection'
 ! !
 
+!Collection methodsFor: 'streaming'!
+
+putOn: aStream
+	self do: [ :each | each putOn: aStream ]
+! !
+
 !Collection methodsFor: 'testing'!
 
 ifEmpty: aBlock
@@ -251,12 +241,6 @@ notEmpty
 	^self isEmpty not
 ! !
 
-!Collection class methodsFor: 'accessing'!
-
-streamClass
-		^Stream
-! !
-
 !Collection class methodsFor: 'instance creation'!
 
 new: anInteger
@@ -354,7 +338,7 @@ indexOf: anObject ifAbsent: aBlock
 	self subclassResponsibility
 ! !
 
-!IndexableCollection methodsFor: 'enumeration'!
+!IndexableCollection methodsFor: 'enumarating'!
 
 with: anotherCollection do: aBlock
 	"Calls aBlock with every value from self
@@ -850,12 +834,53 @@ withIndexDo: aBlock
 	<for(var i=0;i<self.length;i++){aBlock(self[i], i+1);}>
 ! !
 
+!SequenceableCollection methodsFor: 'streaming'!
+
+newStream
+	^self streamClass on: self
+!
+
+readStream
+	"For Pharo compatibility"
+	
+	^self stream
+!
+
+stream
+	^self newStream
+!
+
+streamClass
+	^self class streamClass
+!
+
+writeStream
+	"For Pharo compatibility"
+	
+	^self stream
+! !
+
 !SequenceableCollection methodsFor: 'testing'!
 
 includes: anObject
 	^(self indexOf: anObject ifAbsent: [nil]) notNil
 ! !
 
+!SequenceableCollection class methodsFor: 'accessing'!
+
+streamClass
+		^Stream
+! !
+
+!SequenceableCollection class methodsFor: 'streaming'!
+
+streamContents: aBlock
+	| stream |
+	stream := (self streamClass on: self new).
+	aBlock value: stream.
+	^ stream contents
+! !
+
 SequenceableCollection subclass: #Array
 	instanceVariableNames: ''
 	package: 'Kernel-Collections'!
@@ -1049,6 +1074,12 @@ printOn: aStream
 	self asString printOn: aStream
 ! !
 
+!CharacterArray methodsFor: 'streaming'!
+
+putOn: aStream
+	aStream nextPutString: self
+! !
+
 !CharacterArray class methodsFor: 'instance creation'!
 
 fromString: aString
@@ -1335,6 +1366,10 @@ includesSubString: subString
 	< return self.indexOf(subString) !!= -1 >
 !
 
+isImmutable
+	^ true
+!
+
 isString
 	^true
 !
@@ -1381,13 +1416,6 @@ fromString: aString
 		<return String(aString)>
 !
 
-streamContents: blockWithArg
-	|stream|
-	stream := (self streamClass on: String new).
-	blockWithArg value: stream.
-	^ stream contents
-!
-
 value: aUTFCharCode
 
 	<return String.fromCharCode(aUTFCharCode);>
@@ -1421,6 +1449,10 @@ at: anIndex ifAbsent: aBlock
 	^self asString at: anIndex ifAbsent: aBlock
 !
 
+indexOf: anElement
+	^ self asString indexOf: anElement
+!
+
 size
 	^self asString size
 ! !
@@ -1834,6 +1866,10 @@ isEmpty
 
 !Stream methodsFor: 'writing'!
 
+<< anObject
+	self write: anObject
+!
+
 nextPut: anObject
 	self position: self position + 1.
 	self collection at: self position put: anObject.
@@ -1843,6 +1879,14 @@ nextPut: anObject
 nextPutAll: aCollection
 	aCollection do: [:each |
 		self nextPut: each]
+!
+
+nextPutString: aString
+	self nextPut: aString
+!
+
+write: anObject
+	anObject putOn: self
 ! !
 
 !Stream class methodsFor: 'instance creation'!
@@ -1900,6 +1944,10 @@ nextPutAll: aString
 	self setStreamSize: (self streamSize max: self position)
 !
 
+nextPutString: aString
+	self nextPutAll: aString
+!
+
 space
 	self nextPut: ' '
 !

+ 22 - 0
st/Kernel-Objects.st

@@ -250,6 +250,12 @@ printString
 	^ String streamContents: [ :stream | self printOn: stream ]
 ! !
 
+!Object methodsFor: 'streaming'!
+
+putOn: aStream
+	aStream nextPut: self
+! !
+
 !Object methodsFor: 'testing'!
 
 ifNil: aBlock
@@ -280,6 +286,10 @@ isClass
 	^false
 !
 
+isImmutable
+	^ false
+!
+
 isKindOf: aClass
 	^(self isMemberOf: aClass)
 		ifTrue: [true]
@@ -446,6 +456,10 @@ printOn: aStream
 
 isBoolean
 	^ true
+!
+
+isImmutable
+	^ true
 ! !
 
 Object subclass: #Date
@@ -1024,6 +1038,10 @@ printShowingDecimalPlaces: placesDesired
 
 !Number methodsFor: 'testing'!
 
+IsImmutable
+	^ true
+!
+
 even
 	^ 0 = (self \\ 2)
 !
@@ -1744,6 +1762,10 @@ ifNotNil: aBlock ifNil: anotherBlock
 	^anotherBlock value
 !
 
+isImmutable
+	^ true
+!
+
 isNil
 	^true
 !

+ 209 - 14
st/Kernel-Tests.st

@@ -421,7 +421,36 @@ isAbstract
 	^ self collectionClass isNil
 ! !
 
-CollectionTest subclass: #HashedCollectionTest
+CollectionTest subclass: #IndexableCollectionTest
+	instanceVariableNames: ''
+	package: 'Kernel-Tests'!
+
+!IndexableCollectionTest methodsFor: 'tests'!
+
+testAt
+	self assert: (self collection at: 4) equals: -4.
+	self should: [ self collection at: 5 ] raise: Error
+!
+
+testAtIfAbsent
+	self assert: (self collection at: (self collection size + 1) ifAbsent: [ 'none' ]) equals: 'none'
+!
+
+testIndexOf
+	self assert: (self collection indexOf: 2) equals: 2.
+	self should: [ self collection indexOf: 999 ] raise: Error.
+	self assert: (self collection indexOf: 999 ifAbsent: [ 'sentinel' ]) equals: 'sentinel'
+!
+
+testWithIndexDo
+	| collection |
+	collection := self collection.
+	
+	self collection withIndexDo: [ :each :index |
+		self assert: (collection at: index) equals: each ]
+! !
+
+IndexableCollectionTest subclass: #HashedCollectionTest
 	instanceVariableNames: ''
 	package: 'Kernel-Tests'!
 
@@ -437,8 +466,12 @@ collectionWithDuplicates
 
 !HashedCollectionTest methodsFor: 'tests'!
 
-testIndexOf
+testAt
+	self assert: (self collection at: 'a') equals: 2.
+	self should: [ self collection at: 5 ] raise: Error
+!
 
+testIndexOf
 	self assert: (self collection indexOf: 2) equals: 'a'.
 	self should: [ self collection indexOf: 999 ] raise: Error.
 	self assert: (self collection indexOf: 999 ifAbsent: [ 'sentinel' ]) equals: 'sentinel'
@@ -663,21 +696,10 @@ collectionClass
 	^ Dictionary
 ! !
 
-CollectionTest subclass: #SequenceableCollectionTest
+IndexableCollectionTest subclass: #SequenceableCollectionTest
 	instanceVariableNames: ''
 	package: 'Kernel-Tests'!
 
-!SequenceableCollectionTest methodsFor: 'tests'!
-
-testAt
-	self assert: (self collection at: 4) equals: -4.
-	self should: [ self collection at: 5 ] raise: Error
-!
-
-testAtIfAbsent
-	self assert: (self collection at: (self collection size + 1) ifAbsent: [ 'none' ]) equals: 'none'
-! !
-
 SequenceableCollectionTest subclass: #ArrayTest
 	instanceVariableNames: ''
 	package: 'Kernel-Tests'!
@@ -810,6 +832,12 @@ testIncludesSubString
 	self deny: ('amber' includesSubString: 'zork').
 !
 
+testIndexOf
+	self assert: (self collection indexOf: 'e') equals: 2.
+	self should: [ self collection indexOf: 999 ] raise: Error.
+	self assert: (self collection indexOf: 999 ifAbsent: [ 'sentinel' ]) equals: 'sentinel'
+!
+
 testJoin
 	self assert: (',' join: #('hello' 'world')) equals: 'hello,world'
 !
@@ -932,6 +960,12 @@ testIdentity
 	self assert: #hello yourself = #hello asString asSymbol
 !
 
+testIndexOf
+	self assert: (self collection indexOf: 'e') equals: 2.
+	self should: [ self collection indexOf: 999 ] raise: Error.
+	self assert: (self collection indexOf: 999 ifAbsent: [ 'sentinel' ]) equals: 'sentinel'
+!
+
 testIsEmpty
 	self deny: self collection isEmpty.
 	self assert: '' asSymbol isEmpty
@@ -1602,6 +1636,167 @@ testUnicity
 	self assert: set asArray equals: #(21 'hello')
 ! !
 
+TestCase subclass: #StreamTest
+	instanceVariableNames: ''
+	package: 'Kernel-Tests'!
+
+!StreamTest methodsFor: 'accessing'!
+
+collectionClass
+	^ self class collectionClass
+!
+
+newCollection
+	^ self collectionClass new
+!
+
+newStream
+	^ self collectionClass new stream
+! !
+
+!StreamTest methodsFor: 'tests'!
+
+testAtStartAtEnd
+	| stream |
+	
+	stream := self newStream.
+	self assert: stream atStart.
+	self assert: stream atEnd.
+	
+	stream nextPutAll: self newCollection.
+	self assert: stream atEnd.
+	self deny: stream atStart.
+	
+	stream position: 1.
+	self deny: stream atEnd.
+	self deny: stream atStart
+!
+
+testContents
+	| stream |
+	
+	stream := self newStream.
+	stream nextPutAll: self newCollection.
+	
+	self assert: stream contents equals: self newCollection
+!
+
+testIsEmpty
+	| stream |
+	
+	stream := self newStream.
+	self assert: stream isEmpty.
+	
+	stream nextPutAll: self newCollection.
+	self deny: stream isEmpty
+!
+
+testPosition
+	| collection stream |
+	
+	collection := self newCollection.
+	stream := self newStream.
+	
+	stream nextPutAll: collection.
+	self assert: stream position equals: collection size.
+	
+	stream position: 0.
+	self assert: stream position equals: 0.
+	
+	stream next.
+	self assert: stream position equals: 1.
+	
+	stream next.
+	self assert: stream position equals: 2
+!
+
+testReading
+	| stream collection |
+	
+	collection := self newCollection.
+	stream := self newStream.
+	
+	stream 
+		nextPutAll: collection;
+		position: 0.
+	
+	collection do: [ :each |
+		self assert: stream next equals: each ].
+		
+	self assert: stream next isNil
+!
+
+testStreamContents
+!
+
+testWrite
+	| stream collection |
+	
+	collection := self newCollection.
+	stream := self newStream.
+	
+	collection do: [ :each | stream << each ].
+	self assert: stream contents equals: collection
+!
+
+testWriting
+	| stream collection |
+	
+	collection := self newCollection.
+	stream := self newStream.
+	
+	collection do: [ :each | stream nextPut: each ].
+	self assert: stream contents equals: collection.
+	
+	stream := self newStream.
+	stream nextPutAll: collection.
+	self assert: stream contents equals: collection
+! !
+
+!StreamTest class methodsFor: 'accessing'!
+
+collectionClass
+	^ nil
+! !
+
+!StreamTest class methodsFor: 'testing'!
+
+isAbstract
+	^ self collectionClass isNil
+! !
+
+StreamTest subclass: #ArrayStreamTest
+	instanceVariableNames: ''
+	package: 'Kernel-Tests'!
+
+!ArrayStreamTest methodsFor: 'accessing'!
+
+newCollection
+	^ { true. 1. 3@4. 'foo' }
+! !
+
+!ArrayStreamTest class methodsFor: 'accessing'!
+
+collectionClass
+	^ Array
+! !
+
+StreamTest subclass: #StringStreamTest
+	instanceVariableNames: ''
+	package: 'Kernel-Tests'!
+
+!StringStreamTest methodsFor: 'accessing'!
+
+newCollection
+	^ 'hello world'
+! !
+
+!StringStreamTest class methodsFor: 'accessing'!
+
+collectionClass
+	^ String
+! !
+
 TestCase subclass: #UndefinedTest
 	instanceVariableNames: ''
 	package: 'Kernel-Tests'!