فهرست منبع

Merge branch 'blackboard'

Conflicts:
	devel.html
Herbert Vojčík 11 سال پیش
والد
کامیت
f50003861c
7فایلهای تغییر یافته به همراه1244 افزوده شده و 0 حذف شده
  1. 18 0
      devel.html
  2. 130 0
      js/Trapped-Backend.deploy.js
  3. 181 0
      js/Trapped-Backend.js
  4. 319 0
      js/Trapped-Tests.deploy.js
  5. 384 0
      js/Trapped-Tests.js
  6. 75 0
      st/Trapped-Backend.st
  7. 137 0
      st/Trapped-Tests.st

+ 18 - 0
devel.html

@@ -0,0 +1,18 @@
+<html>
+<head>
+    <title>{{name}}</title>
+    <script src="/vendor/amber/js/amber.js"></script>
+</head>
+<body>
+<script type="text/javascript">
+    loadAmber({
+        files:['Trapped-Backend.js', 'Trapped-Tests.js'],
+        packageHome:'./',
+        ready:function () {
+            smalltalk.Browser._openOn_(smalltalk.IsolatorTest);
+        }});
+</script>
+<div>
+</div>
+</body>
+</html>

+ 130 - 0
js/Trapped-Backend.deploy.js

@@ -0,0 +1,130 @@
+smalltalk.addPackage('Trapped-Backend', {});
+smalltalk.addClass('EavModel', smalltalk.Object, ['getBlock', 'putBlock'], 'Trapped-Backend');
+smalltalk.addMethod(
+"_getBlock_",
+smalltalk.method({
+selector: "getBlock:",
+fn: function (aBlock){
+var self=this;
+self["@getBlock"]=aBlock;
+return self}
+}),
+smalltalk.EavModel);
+
+smalltalk.addMethod(
+"_initialize",
+smalltalk.method({
+selector: "initialize",
+fn: function (){
+var self=this;
+self["@getBlock"]=(function(){
+return smalltalk.send(self,"_error_",["No getter block."]);
+});
+self["@putBlock"]=(function(){
+return smalltalk.send(self,"_error_",["No putter block."]);
+});
+return self}
+}),
+smalltalk.EavModel);
+
+smalltalk.addMethod(
+"_on_",
+smalltalk.method({
+selector: "on:",
+fn: function (anObject){
+var self=this;
+var $1;
+$1=smalltalk.send(self["@getBlock"],"_value_",[anObject]);
+return $1;
+}
+}),
+smalltalk.EavModel);
+
+smalltalk.addMethod(
+"_on_put_",
+smalltalk.method({
+selector: "on:put:",
+fn: function (anObject,anObject2){
+var self=this;
+var $1;
+$1=smalltalk.send(self["@putBlock"],"_value_value_",[anObject,anObject2]);
+return $1;
+}
+}),
+smalltalk.EavModel);
+
+smalltalk.addMethod(
+"_putBlock_",
+smalltalk.method({
+selector: "putBlock:",
+fn: function (aBlock){
+var self=this;
+self["@putBlock"]=aBlock;
+return self}
+}),
+smalltalk.EavModel);
+
+
+
+smalltalk.addClass('Isolator', smalltalk.Object, ['root'], 'Trapped-Backend');
+smalltalk.addMethod(
+"_model_modify_",
+smalltalk.method({
+selector: "model:modify:",
+fn: function (anEavModel,aBlock){
+var self=this;
+var newValue;
+newValue=smalltalk.send(aBlock,"_value_",[smalltalk.send(anEavModel,"_on_",[self])]);
+smalltalk.send(anEavModel,"_on_put_",[self,smalltalk.send(newValue,"_deepCopy",[])]);
+return self}
+}),
+smalltalk.Isolator);
+
+smalltalk.addMethod(
+"_model_read_",
+smalltalk.method({
+selector: "model:read:",
+fn: function (anEavModel,aBlock){
+var self=this;
+smalltalk.send(aBlock,"_value_",[smalltalk.send(smalltalk.send(anEavModel,"_on_",[self]),"_deepCopy",[])]);
+return self}
+}),
+smalltalk.Isolator);
+
+smalltalk.addMethod(
+"_root",
+smalltalk.method({
+selector: "root",
+fn: function (){
+var self=this;
+return self["@root"];
+}
+}),
+smalltalk.Isolator);
+
+smalltalk.addMethod(
+"_root_",
+smalltalk.method({
+selector: "root:",
+fn: function (anObject){
+var self=this;
+self["@root"]=anObject;
+return self}
+}),
+smalltalk.Isolator);
+
+
+smalltalk.addMethod(
+"_on_",
+smalltalk.method({
+selector: "on:",
+fn: function (anObject){
+var self=this;
+var $1;
+$1=smalltalk.send(smalltalk.send(self,"_new",[]),"_root_",[anObject]);
+return $1;
+}
+}),
+smalltalk.Isolator.klass);
+
+

+ 181 - 0
js/Trapped-Backend.js

@@ -0,0 +1,181 @@
+smalltalk.addPackage('Trapped-Backend', {});
+smalltalk.addClass('EavModel', smalltalk.Object, ['getBlock', 'putBlock'], 'Trapped-Backend');
+smalltalk.EavModel.comment="External actor value model."
+smalltalk.addMethod(
+"_getBlock_",
+smalltalk.method({
+selector: "getBlock:",
+category: 'accessing',
+fn: function (aBlock){
+var self=this;
+self["@getBlock"]=aBlock;
+return self},
+args: ["aBlock"],
+source: "getBlock: aBlock\x0a\x0agetBlock := aBlock",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.EavModel);
+
+smalltalk.addMethod(
+"_initialize",
+smalltalk.method({
+selector: "initialize",
+category: 'initialization',
+fn: function (){
+var self=this;
+self["@getBlock"]=(function(){
+return smalltalk.send(self,"_error_",["No getter block."]);
+});
+self["@putBlock"]=(function(){
+return smalltalk.send(self,"_error_",["No putter block."]);
+});
+return self},
+args: [],
+source: "initialize\x0a\x0agetBlock := [ self error: 'No getter block.' ].\x0aputBlock := [ self error: 'No putter block.' ].",
+messageSends: ["error:"],
+referencedClasses: []
+}),
+smalltalk.EavModel);
+
+smalltalk.addMethod(
+"_on_",
+smalltalk.method({
+selector: "on:",
+category: 'accessing',
+fn: function (anObject){
+var self=this;
+var $1;
+$1=smalltalk.send(self["@getBlock"],"_value_",[anObject]);
+return $1;
+},
+args: ["anObject"],
+source: "on: anObject\x0a\x22Returns value of model applied on object\x22\x0a\x0a^getBlock value: anObject",
+messageSends: ["value:"],
+referencedClasses: []
+}),
+smalltalk.EavModel);
+
+smalltalk.addMethod(
+"_on_put_",
+smalltalk.method({
+selector: "on:put:",
+category: 'accessing',
+fn: function (anObject,anObject2){
+var self=this;
+var $1;
+$1=smalltalk.send(self["@putBlock"],"_value_value_",[anObject,anObject2]);
+return $1;
+},
+args: ["anObject", "anObject2"],
+source: "on: anObject put: anObject2\x0a\x22Puts a value via model applied on object\x22\x0a\x0a^putBlock value: anObject value: anObject2",
+messageSends: ["value:value:"],
+referencedClasses: []
+}),
+smalltalk.EavModel);
+
+smalltalk.addMethod(
+"_putBlock_",
+smalltalk.method({
+selector: "putBlock:",
+category: 'accessing',
+fn: function (aBlock){
+var self=this;
+self["@putBlock"]=aBlock;
+return self},
+args: ["aBlock"],
+source: "putBlock: aBlock\x0a\x0aputBlock := aBlock",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.EavModel);
+
+
+
+smalltalk.addClass('Isolator', smalltalk.Object, ['root'], 'Trapped-Backend');
+smalltalk.addMethod(
+"_model_modify_",
+smalltalk.method({
+selector: "model:modify:",
+category: 'action',
+fn: function (anEavModel,aBlock){
+var self=this;
+var newValue;
+newValue=smalltalk.send(aBlock,"_value_",[smalltalk.send(anEavModel,"_on_",[self])]);
+smalltalk.send(anEavModel,"_on_put_",[self,smalltalk.send(newValue,"_deepCopy",[])]);
+return self},
+args: ["anEavModel", "aBlock"],
+source: "model: anEavModel modify: aBlock\x0a\x0a| newValue |\x0anewValue := aBlock value: (anEavModel on: self).\x0aanEavModel on: self put: newValue deepCopy\x0a",
+messageSends: ["value:", "on:", "on:put:", "deepCopy"],
+referencedClasses: []
+}),
+smalltalk.Isolator);
+
+smalltalk.addMethod(
+"_model_read_",
+smalltalk.method({
+selector: "model:read:",
+category: 'action',
+fn: function (anEavModel,aBlock){
+var self=this;
+smalltalk.send(aBlock,"_value_",[smalltalk.send(smalltalk.send(anEavModel,"_on_",[self]),"_deepCopy",[])]);
+return self},
+args: ["anEavModel", "aBlock"],
+source: "model: anEavModel read: aBlock\x0a\x0aaBlock value: (anEavModel on: self) deepCopy",
+messageSends: ["value:", "deepCopy", "on:"],
+referencedClasses: []
+}),
+smalltalk.Isolator);
+
+smalltalk.addMethod(
+"_root",
+smalltalk.method({
+selector: "root",
+category: 'accessing',
+fn: function (){
+var self=this;
+return self["@root"];
+},
+args: [],
+source: "root\x0a\x0a^root\x0a",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Isolator);
+
+smalltalk.addMethod(
+"_root_",
+smalltalk.method({
+selector: "root:",
+category: 'accessing',
+fn: function (anObject){
+var self=this;
+self["@root"]=anObject;
+return self},
+args: ["anObject"],
+source: "root: anObject\x0a\x0aroot := anObject",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Isolator);
+
+
+smalltalk.addMethod(
+"_on_",
+smalltalk.method({
+selector: "on:",
+category: 'initialization',
+fn: function (anObject){
+var self=this;
+var $1;
+$1=smalltalk.send(smalltalk.send(self,"_new",[]),"_root_",[anObject]);
+return $1;
+},
+args: ["anObject"],
+source: "on: anObject\x0a^self new root: anObject",
+messageSends: ["root:", "new"],
+referencedClasses: []
+}),
+smalltalk.Isolator.klass);
+
+

+ 319 - 0
js/Trapped-Tests.deploy.js

@@ -0,0 +1,319 @@
+smalltalk.addPackage('Trapped-Tests', {});
+smalltalk.addClass('IsolatorTest', smalltalk.TestCase, ['rootModel'], 'Trapped-Tests');
+smalltalk.addMethod(
+"_setUp",
+smalltalk.method({
+selector: "setUp",
+fn: function (){
+var self=this;
+var $1,$2;
+$1=smalltalk.send((smalltalk.EavModel || EavModel),"_new",[]);
+smalltalk.send($1,"_getBlock_",[(function(x){
+return smalltalk.send(x,"_root",[]);
+})]);
+$2=smalltalk.send($1,"_putBlock_",[(function(x,y){
+return smalltalk.send(x,"_root_",[y]);
+})]);
+self["@rootModel"]=$2;
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testNontrivialModelGetsAppropriateValueForModification",
+smalltalk.method({
+selector: "testNontrivialModelGetsAppropriateValueForModification",
+fn: function (){
+var self=this;
+var $1,$2;
+var isolator;
+var model;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[["bar", [(1), [(2), (5)]], "baz"]]),smalltalk.send("moo","__minus_gt",["zoo"])])]);
+$1=smalltalk.send((smalltalk.EavModel || EavModel),"_new",[]);
+smalltalk.send($1,"_getBlock_",[(function(x){
+return smalltalk.send(smalltalk.send(smalltalk.send(x,"_root",[]),"_at_",["foo"]),"_at_",[(2)]);
+})]);
+$2=smalltalk.send($1,"_putBlock_",[(function(x,y){
+return smalltalk.send(smalltalk.send(smalltalk.send(x,"_root",[]),"_at_",["foo"]),"_at_put_",[(2),y]);
+})]);
+model=$2;
+smalltalk.send(isolator,"_model_modify_",[model,(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(1), [(2), (5)]],result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testNontrivialModelModifiesAppropriateValue",
+smalltalk.method({
+selector: "testNontrivialModelModifiesAppropriateValue",
+fn: function (){
+var self=this;
+var $1,$2;
+var isolator;
+var model;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[["bar", [(1), [(2), (3)]], "baz"]]),smalltalk.send("moo","__minus_gt",["zoo"])])]);
+$1=smalltalk.send((smalltalk.EavModel || EavModel),"_new",[]);
+smalltalk.send($1,"_getBlock_",[(function(x){
+return smalltalk.send(smalltalk.send(smalltalk.send(x,"_root",[]),"_at_",["foo"]),"_at_",[(2)]);
+})]);
+$2=smalltalk.send($1,"_putBlock_",[(function(x,y){
+return smalltalk.send(smalltalk.send(smalltalk.send(x,"_root",[]),"_at_",["foo"]),"_at_put_",[(2),y]);
+})]);
+model=$2;
+smalltalk.send(isolator,"_model_modify_",[model,(function(r){
+return smalltalk.symbolFor("new");
+})]);
+smalltalk.send(isolator,"_model_read_",[model,(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[smalltalk.symbolFor("new"),result]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[["bar", smalltalk.symbolFor("new"), "baz"]]),smalltalk.send("moo","__minus_gt",["zoo"])]),result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testNontrivialModelReturnsAppropriateValue",
+smalltalk.method({
+selector: "testNontrivialModelReturnsAppropriateValue",
+fn: function (){
+var self=this;
+var isolator;
+var model;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[["bar", [(1), [(2), (3)]], "baz"]]),smalltalk.send("moo","__minus_gt",["zoo"])])]);
+model=smalltalk.send(smalltalk.send((smalltalk.EavModel || EavModel),"_new",[]),"_getBlock_",[(function(x){
+return smalltalk.send(smalltalk.send(smalltalk.send(x,"_root",[]),"_at_",["foo"]),"_at_",[(2)]);
+})]);
+smalltalk.send(isolator,"_model_read_",[model,(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(1), [(2), (3)]],result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelExaminesThenModifiesRoot",
+smalltalk.method({
+selector: "testRootModelExaminesThenModifiesRoot",
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+return smalltalk.send(r,"_second",[]);
+})]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(2), (3)],result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelGetsRootForModification",
+smalltalk.method({
+selector: "testRootModelGetsRootForModification",
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(2), [(1), (0)]]]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(2), [(1), (0)]],result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelModifiesAndDeeplyIsolatesInPlaceModifiedRoot",
+smalltalk.method({
+selector: "testRootModelModifiesAndDeeplyIsolatesInPlaceModifiedRoot",
+fn: function (){
+var self=this;
+var isolator;
+var result;
+var newValue;
+result=nil;
+newValue=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+newValue=r;
+newValue;
+smalltalk.send(r,"_at_put_",[(1),(4)]);
+return r;
+})]);
+smalltalk.send(newValue,"_at_put_",[(2),"bar"]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(newValue,"_at_put_",[(2),"baz"]);
+smalltalk.send(self,"_assert_equals_",[[(4), [(2), (3)]],result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelModifiesAndDeeplyIsolatesRoot",
+smalltalk.method({
+selector: "testRootModelModifiesAndDeeplyIsolatesRoot",
+fn: function (){
+var self=this;
+var isolator;
+var result;
+var newValue;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+newValue=smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+return newValue;
+})]);
+smalltalk.send(smalltalk.send(newValue,"_at_",["foo"]),"_at_put_",[(1),"bar"]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(smalltalk.send(newValue,"_at_",["foo"]),"_at_put_",[(3),"baz"]);
+smalltalk.send(self,"_assert_equals_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]),result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelModifiesAndIsolatesRoot",
+smalltalk.method({
+selector: "testRootModelModifiesAndIsolatesRoot",
+fn: function (){
+var self=this;
+var isolator;
+var result;
+var newValue;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+newValue=smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+return newValue;
+})]);
+smalltalk.send(newValue,"_at_put_",["foo","bar"]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(newValue,"_at_put_",["foo","baz"]);
+smalltalk.send(self,"_assert_equals_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]),result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelModifiesRoot",
+smalltalk.method({
+selector: "testRootModelModifiesRoot",
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+return smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]);
+})]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]),result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelReturnsDeeplyIsolatedRoot",
+smalltalk.method({
+selector: "testRootModelReturnsDeeplyIsolatedRoot",
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+return smalltalk.send(smalltalk.send(r,"_at_",[(2)]),"_at_put_",[(1),(0)]);
+})]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(1), [(2), (3)]],result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelReturnsIsolatedRoot",
+smalltalk.method({
+selector: "testRootModelReturnsIsolatedRoot",
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (4)]]]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+return smalltalk.send(r,"_at_put_",[(2),nil]);
+})]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(1), [(2), (4)]],result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelReturnsRoot",
+smalltalk.method({
+selector: "testRootModelReturnsRoot",
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(1), [(2), (3)]],result]);
+return self}
+}),
+smalltalk.IsolatorTest);
+
+
+

+ 384 - 0
js/Trapped-Tests.js

@@ -0,0 +1,384 @@
+smalltalk.addPackage('Trapped-Tests', {});
+smalltalk.addClass('IsolatorTest', smalltalk.TestCase, ['rootModel'], 'Trapped-Tests');
+smalltalk.addMethod(
+"_setUp",
+smalltalk.method({
+selector: "setUp",
+category: 'running',
+fn: function (){
+var self=this;
+var $1,$2;
+$1=smalltalk.send((smalltalk.EavModel || EavModel),"_new",[]);
+smalltalk.send($1,"_getBlock_",[(function(x){
+return smalltalk.send(x,"_root",[]);
+})]);
+$2=smalltalk.send($1,"_putBlock_",[(function(x,y){
+return smalltalk.send(x,"_root_",[y]);
+})]);
+self["@rootModel"]=$2;
+return self},
+args: [],
+source: "setUp\x0a\x0arootModel := EavModel new\x0a\x09getBlock: [:x | x root];\x0a    putBlock: [:x :y | x root: y].\x0a",
+messageSends: ["getBlock:", "root", "new", "putBlock:", "root:"],
+referencedClasses: ["EavModel"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testNontrivialModelGetsAppropriateValueForModification",
+smalltalk.method({
+selector: "testNontrivialModelGetsAppropriateValueForModification",
+category: 'tests',
+fn: function (){
+var self=this;
+var $1,$2;
+var isolator;
+var model;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[["bar", [(1), [(2), (5)]], "baz"]]),smalltalk.send("moo","__minus_gt",["zoo"])])]);
+$1=smalltalk.send((smalltalk.EavModel || EavModel),"_new",[]);
+smalltalk.send($1,"_getBlock_",[(function(x){
+return smalltalk.send(smalltalk.send(smalltalk.send(x,"_root",[]),"_at_",["foo"]),"_at_",[(2)]);
+})]);
+$2=smalltalk.send($1,"_putBlock_",[(function(x,y){
+return smalltalk.send(smalltalk.send(smalltalk.send(x,"_root",[]),"_at_",["foo"]),"_at_put_",[(2),y]);
+})]);
+model=$2;
+smalltalk.send(isolator,"_model_modify_",[model,(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(1), [(2), (5)]],result]);
+return self},
+args: [],
+source: "testNontrivialModelGetsAppropriateValueForModification\x0a| isolator model result |\x0aresult := nil.\x0aisolator := Isolator on: #{ 'foo' -> #('bar' #(1 #(2 5)) 'baz'). 'moo' -> 'zoo' }.\x0amodel := EavModel new\x0a\x09getBlock: [ :x | (x root at: 'foo') at: 2 ];\x0a\x09putBlock: [ :x :y | (x root at: 'foo') at: 2 put: y].\x0aisolator model: model modify: [:r|result := r].\x0aself assert: #(1 #(2 5)) equals: result\x0a",
+messageSends: ["on:", "->", "getBlock:", "at:", "root", "new", "putBlock:", "at:put:", "model:modify:", "assert:equals:"],
+referencedClasses: ["Isolator", "EavModel"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testNontrivialModelModifiesAppropriateValue",
+smalltalk.method({
+selector: "testNontrivialModelModifiesAppropriateValue",
+category: 'tests',
+fn: function (){
+var self=this;
+var $1,$2;
+var isolator;
+var model;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[["bar", [(1), [(2), (3)]], "baz"]]),smalltalk.send("moo","__minus_gt",["zoo"])])]);
+$1=smalltalk.send((smalltalk.EavModel || EavModel),"_new",[]);
+smalltalk.send($1,"_getBlock_",[(function(x){
+return smalltalk.send(smalltalk.send(smalltalk.send(x,"_root",[]),"_at_",["foo"]),"_at_",[(2)]);
+})]);
+$2=smalltalk.send($1,"_putBlock_",[(function(x,y){
+return smalltalk.send(smalltalk.send(smalltalk.send(x,"_root",[]),"_at_",["foo"]),"_at_put_",[(2),y]);
+})]);
+model=$2;
+smalltalk.send(isolator,"_model_modify_",[model,(function(r){
+return smalltalk.symbolFor("new");
+})]);
+smalltalk.send(isolator,"_model_read_",[model,(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[smalltalk.symbolFor("new"),result]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[["bar", smalltalk.symbolFor("new"), "baz"]]),smalltalk.send("moo","__minus_gt",["zoo"])]),result]);
+return self},
+args: [],
+source: "testNontrivialModelModifiesAppropriateValue\x0a| isolator model result |\x0aresult := nil.\x0aisolator := Isolator on: #{ 'foo' -> #('bar' #(1 #(2 3)) 'baz'). 'moo' -> 'zoo' }.\x0amodel := EavModel new\x0a\x09getBlock: [ :x | (x root at: 'foo') at: 2 ];\x0a\x09putBlock: [ :x :y | (x root at: 'foo') at: 2 put: y].\x0aisolator model: model modify: [:r|#new].\x0aisolator model: model read: [:r|result := r].\x0aself assert: #new equals: result.\x0aisolator model: rootModel read: [:r|result := r].\x0aself assert: #{ 'foo' -> #('bar' #new 'baz'). 'moo' -> 'zoo' } equals: result\x0a",
+messageSends: ["on:", "->", "getBlock:", "at:", "root", "new", "putBlock:", "at:put:", "model:modify:", "model:read:", "assert:equals:"],
+referencedClasses: ["Isolator", "EavModel"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testNontrivialModelReturnsAppropriateValue",
+smalltalk.method({
+selector: "testNontrivialModelReturnsAppropriateValue",
+category: 'tests',
+fn: function (){
+var self=this;
+var isolator;
+var model;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[["bar", [(1), [(2), (3)]], "baz"]]),smalltalk.send("moo","__minus_gt",["zoo"])])]);
+model=smalltalk.send(smalltalk.send((smalltalk.EavModel || EavModel),"_new",[]),"_getBlock_",[(function(x){
+return smalltalk.send(smalltalk.send(smalltalk.send(x,"_root",[]),"_at_",["foo"]),"_at_",[(2)]);
+})]);
+smalltalk.send(isolator,"_model_read_",[model,(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(1), [(2), (3)]],result]);
+return self},
+args: [],
+source: "testNontrivialModelReturnsAppropriateValue\x0a| isolator model result |\x0aresult := nil.\x0aisolator := Isolator on: #{ 'foo' -> #('bar' #(1 #(2 3)) 'baz'). 'moo' -> 'zoo' }.\x0amodel := EavModel new getBlock: [ :x | (x root at: 'foo') at: 2 ].\x0aisolator model: model read: [:r|result := r].\x0aself assert: #(1 #(2 3)) equals: result\x0a",
+messageSends: ["on:", "->", "getBlock:", "at:", "root", "new", "model:read:", "assert:equals:"],
+referencedClasses: ["Isolator", "EavModel"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelExaminesThenModifiesRoot",
+smalltalk.method({
+selector: "testRootModelExaminesThenModifiesRoot",
+category: 'tests',
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+return smalltalk.send(r,"_second",[]);
+})]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(2), (3)],result]);
+return self},
+args: [],
+source: "testRootModelExaminesThenModifiesRoot\x0a| isolator result |\x0aresult := nil.\x0aisolator := Isolator on: #(1 #(2 3)).\x0aisolator model: rootModel modify: [:r|r second].\x0aisolator model: rootModel read: [:r|result := r].\x0aself assert: #(2 3) equals: result\x0a",
+messageSends: ["on:", "model:modify:", "second", "model:read:", "assert:equals:"],
+referencedClasses: ["Isolator"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelGetsRootForModification",
+smalltalk.method({
+selector: "testRootModelGetsRootForModification",
+category: 'tests',
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(2), [(1), (0)]]]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(2), [(1), (0)]],result]);
+return self},
+args: [],
+source: "testRootModelGetsRootForModification\x0a| isolator result |\x0aresult := nil.\x0aisolator := Isolator on: #(2 #(1 0)).\x0aisolator model: rootModel modify: [:r|result := r].\x0aself assert: #(2 #(1 0)) equals: result\x0a",
+messageSends: ["on:", "model:modify:", "assert:equals:"],
+referencedClasses: ["Isolator"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelModifiesAndDeeplyIsolatesInPlaceModifiedRoot",
+smalltalk.method({
+selector: "testRootModelModifiesAndDeeplyIsolatesInPlaceModifiedRoot",
+category: 'tests',
+fn: function (){
+var self=this;
+var isolator;
+var result;
+var newValue;
+result=nil;
+newValue=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+newValue=r;
+newValue;
+smalltalk.send(r,"_at_put_",[(1),(4)]);
+return r;
+})]);
+smalltalk.send(newValue,"_at_put_",[(2),"bar"]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(newValue,"_at_put_",[(2),"baz"]);
+smalltalk.send(self,"_assert_equals_",[[(4), [(2), (3)]],result]);
+return self},
+args: [],
+source: "testRootModelModifiesAndDeeplyIsolatesInPlaceModifiedRoot\x0a| isolator result newValue |\x0aresult := nil. newValue := nil.\x0aisolator := Isolator on: #(1 #(2 3)).\x0aisolator model: rootModel modify: [:r|newValue := r. r at: 1 put: 4. r].\x0anewValue at: 2 put: 'bar'.\x0aisolator model: rootModel read: [:r|result := r].\x0anewValue at: 2 put: 'baz'.\x0aself assert: #(4 #(2 3)) equals: result\x0a",
+messageSends: ["on:", "model:modify:", "at:put:", "model:read:", "assert:equals:"],
+referencedClasses: ["Isolator"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelModifiesAndDeeplyIsolatesRoot",
+smalltalk.method({
+selector: "testRootModelModifiesAndDeeplyIsolatesRoot",
+category: 'tests',
+fn: function (){
+var self=this;
+var isolator;
+var result;
+var newValue;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+newValue=smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+return newValue;
+})]);
+smalltalk.send(smalltalk.send(newValue,"_at_",["foo"]),"_at_put_",[(1),"bar"]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(smalltalk.send(newValue,"_at_",["foo"]),"_at_put_",[(3),"baz"]);
+smalltalk.send(self,"_assert_equals_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]),result]);
+return self},
+args: [],
+source: "testRootModelModifiesAndDeeplyIsolatesRoot\x0a| isolator result newValue |\x0aresult := nil.\x0aisolator := Isolator on: #(1 #(2 3)).\x0anewValue := #{'foo'->#(4 5 6)}.\x0aisolator model: rootModel modify: [:r|newValue].\x0a(newValue at: 'foo') at: 1 put: 'bar'.\x0aisolator model: rootModel read: [:r|result := r].\x0a(newValue at: 'foo') at: 3 put: 'baz'.\x0aself assert: #{'foo'->#(4 5 6)} equals: result\x0a",
+messageSends: ["on:", "->", "model:modify:", "at:put:", "at:", "model:read:", "assert:equals:"],
+referencedClasses: ["Isolator"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelModifiesAndIsolatesRoot",
+smalltalk.method({
+selector: "testRootModelModifiesAndIsolatesRoot",
+category: 'tests',
+fn: function (){
+var self=this;
+var isolator;
+var result;
+var newValue;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+newValue=smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+return newValue;
+})]);
+smalltalk.send(newValue,"_at_put_",["foo","bar"]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(newValue,"_at_put_",["foo","baz"]);
+smalltalk.send(self,"_assert_equals_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]),result]);
+return self},
+args: [],
+source: "testRootModelModifiesAndIsolatesRoot\x0a| isolator result newValue |\x0aresult := nil.\x0aisolator := Isolator on: #(1 #(2 3)).\x0anewValue := #{'foo'->#(4 5 6)}.\x0aisolator model: rootModel modify: [:r|newValue].\x0anewValue at: 'foo' put: 'bar'.\x0aisolator model: rootModel read: [:r|result := r].\x0anewValue at: 'foo' put: 'baz'.\x0aself assert: #{'foo'->#(4 5 6)} equals: result\x0a",
+messageSends: ["on:", "->", "model:modify:", "at:put:", "model:read:", "assert:equals:"],
+referencedClasses: ["Isolator"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelModifiesRoot",
+smalltalk.method({
+selector: "testRootModelModifiesRoot",
+category: 'tests',
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+smalltalk.send(isolator,"_model_modify_",[self["@rootModel"],(function(r){
+return smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]);
+})]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[smalltalk.HashedCollection._fromPairs_([smalltalk.send("foo","__minus_gt",[[(4), (5), (6)]])]),result]);
+return self},
+args: [],
+source: "testRootModelModifiesRoot\x0a| isolator result |\x0aresult := nil.\x0aisolator := Isolator on: #(1 #(2 3)).\x0aisolator model: rootModel modify: [:r|#{'foo'->#(4 5 6)}].\x0aisolator model: rootModel read: [:r|result := r].\x0aself assert: #{'foo'->#(4 5 6)} equals: result\x0a",
+messageSends: ["on:", "model:modify:", "->", "model:read:", "assert:equals:"],
+referencedClasses: ["Isolator"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelReturnsDeeplyIsolatedRoot",
+smalltalk.method({
+selector: "testRootModelReturnsDeeplyIsolatedRoot",
+category: 'tests',
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+return smalltalk.send(smalltalk.send(r,"_at_",[(2)]),"_at_put_",[(1),(0)]);
+})]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(1), [(2), (3)]],result]);
+return self},
+args: [],
+source: "testRootModelReturnsDeeplyIsolatedRoot\x0a| isolator result |\x0aresult := nil.\x0aisolator := Isolator on: #(1 #(2 3)).\x0aisolator model: rootModel read: [:r|(r at: 2) at: 1 put: 0].\x0aisolator model: rootModel read: [:r|result := r].\x0aself assert: #(1 #(2 3)) equals: result\x0a",
+messageSends: ["on:", "model:read:", "at:put:", "at:", "assert:equals:"],
+referencedClasses: ["Isolator"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelReturnsIsolatedRoot",
+smalltalk.method({
+selector: "testRootModelReturnsIsolatedRoot",
+category: 'tests',
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (4)]]]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+return smalltalk.send(r,"_at_put_",[(2),nil]);
+})]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(1), [(2), (4)]],result]);
+return self},
+args: [],
+source: "testRootModelReturnsIsolatedRoot\x0a| isolator result |\x0aresult := nil.\x0aisolator := Isolator on: #(1 #(2 4)).\x0aisolator model: rootModel read: [:r|r at: 2 put: nil].\x0aisolator model: rootModel read: [:r|result := r].\x0aself assert: #(1 #(2 4)) equals: result\x0a",
+messageSends: ["on:", "model:read:", "at:put:", "assert:equals:"],
+referencedClasses: ["Isolator"]
+}),
+smalltalk.IsolatorTest);
+
+smalltalk.addMethod(
+"_testRootModelReturnsRoot",
+smalltalk.method({
+selector: "testRootModelReturnsRoot",
+category: 'tests',
+fn: function (){
+var self=this;
+var isolator;
+var result;
+result=nil;
+isolator=smalltalk.send((smalltalk.Isolator || Isolator),"_on_",[[(1), [(2), (3)]]]);
+smalltalk.send(isolator,"_model_read_",[self["@rootModel"],(function(r){
+result=r;
+return result;
+})]);
+smalltalk.send(self,"_assert_equals_",[[(1), [(2), (3)]],result]);
+return self},
+args: [],
+source: "testRootModelReturnsRoot\x0a| isolator result |\x0aresult := nil.\x0aisolator := Isolator on: #(1 #(2 3)).\x0aisolator model: rootModel read: [:r|result := r].\x0aself assert: #(1 #(2 3)) equals: result\x0a",
+messageSends: ["on:", "model:read:", "assert:equals:"],
+referencedClasses: ["Isolator"]
+}),
+smalltalk.IsolatorTest);
+
+
+

+ 75 - 0
st/Trapped-Backend.st

@@ -0,0 +1,75 @@
+Smalltalk current createPackage: 'Trapped-Backend' properties: #{}!
+Object subclass: #EavModel
+	instanceVariableNames: 'getBlock putBlock'
+	package: 'Trapped-Backend'!
+!EavModel commentStamp!
+External actor value model.!
+
+!EavModel methodsFor: 'accessing'!
+
+getBlock: aBlock
+
+getBlock := aBlock
+!
+
+on: anObject
+"Returns value of model applied on object"
+
+^getBlock value: anObject
+!
+
+on: anObject put: anObject2
+"Puts a value via model applied on object"
+
+^putBlock value: anObject value: anObject2
+!
+
+putBlock: aBlock
+
+putBlock := aBlock
+! !
+
+!EavModel methodsFor: 'initialization'!
+
+initialize
+
+getBlock := [ self error: 'No getter block.' ].
+putBlock := [ self error: 'No putter block.' ].
+! !
+
+Object subclass: #Isolator
+	instanceVariableNames: 'root'
+	package: 'Trapped-Backend'!
+
+!Isolator methodsFor: 'accessing'!
+
+root
+
+^root
+!
+
+root: anObject
+
+root := anObject
+! !
+
+!Isolator methodsFor: 'action'!
+
+model: anEavModel modify: aBlock
+
+| newValue |
+newValue := aBlock value: (anEavModel on: self).
+anEavModel on: self put: newValue deepCopy
+!
+
+model: anEavModel read: aBlock
+
+aBlock value: (anEavModel on: self) deepCopy
+! !
+
+!Isolator class methodsFor: 'initialization'!
+
+on: anObject
+^self new root: anObject
+! !
+

+ 137 - 0
st/Trapped-Tests.st

@@ -0,0 +1,137 @@
+Smalltalk current createPackage: 'Trapped-Tests' properties: #{}!
+TestCase subclass: #IsolatorTest
+	instanceVariableNames: 'rootModel'
+	package: 'Trapped-Tests'!
+
+!IsolatorTest methodsFor: 'running'!
+
+setUp
+
+rootModel := EavModel new
+	getBlock: [:x | x root];
+    putBlock: [:x :y | x root: y].
+! !
+
+!IsolatorTest methodsFor: 'tests'!
+
+testNontrivialModelGetsAppropriateValueForModification
+| isolator model result |
+result := nil.
+isolator := Isolator on: #{ 'foo' -> #('bar' #(1 #(2 5)) 'baz'). 'moo' -> 'zoo' }.
+model := EavModel new
+	getBlock: [ :x | (x root at: 'foo') at: 2 ];
+	putBlock: [ :x :y | (x root at: 'foo') at: 2 put: y].
+isolator model: model modify: [:r|result := r].
+self assert: #(1 #(2 5)) equals: result
+!
+
+testNontrivialModelModifiesAppropriateValue
+| isolator model result |
+result := nil.
+isolator := Isolator on: #{ 'foo' -> #('bar' #(1 #(2 3)) 'baz'). 'moo' -> 'zoo' }.
+model := EavModel new
+	getBlock: [ :x | (x root at: 'foo') at: 2 ];
+	putBlock: [ :x :y | (x root at: 'foo') at: 2 put: y].
+isolator model: model modify: [:r|#new].
+isolator model: model read: [:r|result := r].
+self assert: #new equals: result.
+isolator model: rootModel read: [:r|result := r].
+self assert: #{ 'foo' -> #('bar' #new 'baz'). 'moo' -> 'zoo' } equals: result
+!
+
+testNontrivialModelReturnsAppropriateValue
+| isolator model result |
+result := nil.
+isolator := Isolator on: #{ 'foo' -> #('bar' #(1 #(2 3)) 'baz'). 'moo' -> 'zoo' }.
+model := EavModel new getBlock: [ :x | (x root at: 'foo') at: 2 ].
+isolator model: model read: [:r|result := r].
+self assert: #(1 #(2 3)) equals: result
+!
+
+testRootModelExaminesThenModifiesRoot
+| isolator result |
+result := nil.
+isolator := Isolator on: #(1 #(2 3)).
+isolator model: rootModel modify: [:r|r second].
+isolator model: rootModel read: [:r|result := r].
+self assert: #(2 3) equals: result
+!
+
+testRootModelGetsRootForModification
+| isolator result |
+result := nil.
+isolator := Isolator on: #(2 #(1 0)).
+isolator model: rootModel modify: [:r|result := r].
+self assert: #(2 #(1 0)) equals: result
+!
+
+testRootModelModifiesAndDeeplyIsolatesInPlaceModifiedRoot
+| isolator result newValue |
+result := nil. newValue := nil.
+isolator := Isolator on: #(1 #(2 3)).
+isolator model: rootModel modify: [:r|newValue := r. r at: 1 put: 4. r].
+newValue at: 2 put: 'bar'.
+isolator model: rootModel read: [:r|result := r].
+newValue at: 2 put: 'baz'.
+self assert: #(4 #(2 3)) equals: result
+!
+
+testRootModelModifiesAndDeeplyIsolatesRoot
+| isolator result newValue |
+result := nil.
+isolator := Isolator on: #(1 #(2 3)).
+newValue := #{'foo'->#(4 5 6)}.
+isolator model: rootModel modify: [:r|newValue].
+(newValue at: 'foo') at: 1 put: 'bar'.
+isolator model: rootModel read: [:r|result := r].
+(newValue at: 'foo') at: 3 put: 'baz'.
+self assert: #{'foo'->#(4 5 6)} equals: result
+!
+
+testRootModelModifiesAndIsolatesRoot
+| isolator result newValue |
+result := nil.
+isolator := Isolator on: #(1 #(2 3)).
+newValue := #{'foo'->#(4 5 6)}.
+isolator model: rootModel modify: [:r|newValue].
+newValue at: 'foo' put: 'bar'.
+isolator model: rootModel read: [:r|result := r].
+newValue at: 'foo' put: 'baz'.
+self assert: #{'foo'->#(4 5 6)} equals: result
+!
+
+testRootModelModifiesRoot
+| isolator result |
+result := nil.
+isolator := Isolator on: #(1 #(2 3)).
+isolator model: rootModel modify: [:r|#{'foo'->#(4 5 6)}].
+isolator model: rootModel read: [:r|result := r].
+self assert: #{'foo'->#(4 5 6)} equals: result
+!
+
+testRootModelReturnsDeeplyIsolatedRoot
+| isolator result |
+result := nil.
+isolator := Isolator on: #(1 #(2 3)).
+isolator model: rootModel read: [:r|(r at: 2) at: 1 put: 0].
+isolator model: rootModel read: [:r|result := r].
+self assert: #(1 #(2 3)) equals: result
+!
+
+testRootModelReturnsIsolatedRoot
+| isolator result |
+result := nil.
+isolator := Isolator on: #(1 #(2 4)).
+isolator model: rootModel read: [:r|r at: 2 put: nil].
+isolator model: rootModel read: [:r|result := r].
+self assert: #(1 #(2 4)) equals: result
+!
+
+testRootModelReturnsRoot
+| isolator result |
+result := nil.
+isolator := Isolator on: #(1 #(2 3)).
+isolator model: rootModel read: [:r|result := r].
+self assert: #(1 #(2 3)) equals: result
+! !
+