Browse Source

TwoWayListKeyedSubscription added

Herbert Vojčík 11 years ago
parent
commit
e686d54bf8
2 changed files with 136 additions and 83 deletions
  1. 107 69
      lib/js/Trapped-Backend.js
  2. 29 14
      lib/st/Trapped-Backend.st

+ 107 - 69
lib/js/Trapped-Backend.js

@@ -547,6 +547,32 @@ smalltalk.ListKeyedSubscription);
 
 
 
+smalltalk.addClass('TwoWayListKeyedSubscription', smalltalk.KeyedSubscriptionBase, [], 'Trapped-Backend');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "accepts:",
+category: 'testing',
+fn: function (aKey){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=_st(_st(aKey)._size()).__lt_eq(_st(self["@key"])._size());
+if(smalltalk.assert($2)){
+$1=_st(aKey).__eq(_st(self["@key"])._copyFrom_to_((1),_st(aKey)._size()));
+} else {
+$1=_st(self["@key"]).__eq(_st(aKey)._copyFrom_to_((1),_st(self["@key"])._size()));
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"accepts:",{aKey:aKey},smalltalk.TwoWayListKeyedSubscription)})},
+args: ["aKey"],
+source: "accepts: aKey\x0a    ^aKey size <= key size\x0a\x09\x09ifTrue: [aKey = (key copyFrom: 1 to: aKey size)]\x0a\x09\x09ifFalse: [key = (aKey copyFrom: 1 to: key size)]",
+messageSends: ["ifTrue:ifFalse:", "=", "copyFrom:to:", "size", "<="],
+referencedClasses: []
+}),
+smalltalk.TwoWayListKeyedSubscription);
+
+
+
 smalltalk.addClass('ListKeyedEntity', smalltalk.Object, ['dispatcher', 'payload'], 'Trapped-Backend');
 smalltalk.ListKeyedEntity.comment="I am base class for #('string-at-index' #selector numeric-at-index)-array-path-keyed entities,\x0athat moderate access to the wrapped model object via read;do and modify:do:\x0aand allow pub-sub via watch:do:.\x0aThis wrapped model can be any smalltalk object.\x0a\x0aMy subclasses need to provide implementation for:\x0a\x09read:do:\x0a    modify:do:\x0a\x0aand must issue these calls when initializing:\x0a\x09model: (with a wrapped object)\x0a\x09dispatcher: (with a subclass of KeyedPubSubBase)";
 smalltalk.addMethod(
@@ -573,24 +599,36 @@ selector: "dispatcher:",
 category: 'accessing',
 fn: function (aDispatcher){
 var self=this;
+function $TwoWayListKeyedSubscription(){return smalltalk.TwoWayListKeyedSubscription||(typeof TwoWayListKeyedSubscription=="undefined"?nil:TwoWayListKeyedSubscription)}
 function $ListKeyedSubscription(){return smalltalk.ListKeyedSubscription||(typeof ListKeyedSubscription=="undefined"?nil:ListKeyedSubscription)}
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2,$3,$4;
+var $1,$2,$3,$4,$5,$6,$7;
 $1=aDispatcher;
 _st($1)._subscriptionFactory_((function(key,block){
 return smalltalk.withContext(function($ctx2) {
-$2=_st($ListKeyedSubscription())._new();
-_st($2)._key_block_(key,block);
-$3=_st($2)._yourself();
-return $3;
+$2=_st(_st(key)._notEmpty())._and_((function(){
+return smalltalk.withContext(function($ctx3) {
+return _st(_st(key)._last())._isNil();
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2)})}));
+if(smalltalk.assert($2)){
+$3=_st($TwoWayListKeyedSubscription())._new();
+_st($3)._key_block_(_st(key)._allButLast(),block);
+$4=_st($3)._yourself();
+return $4;
+} else {
+$5=_st($ListKeyedSubscription())._new();
+_st($5)._key_block_(key,block);
+$6=_st($5)._yourself();
+return $6;
+};
 }, function($ctx2) {$ctx2.fillBlock({key:key,block:block},$ctx1)})}));
-$4=_st($1)._yourself();
-self["@dispatcher"]=$4;
+$7=_st($1)._yourself();
+self["@dispatcher"]=$7;
 return self}, function($ctx1) {$ctx1.fill(self,"dispatcher:",{aDispatcher:aDispatcher},smalltalk.ListKeyedEntity)})},
 args: ["aDispatcher"],
-source: "dispatcher: aDispatcher\x0a\x09dispatcher := aDispatcher\x0a        subscriptionFactory: [ :key :block | ListKeyedSubscription new key: key block: block; yourself ];\x0a        yourself",
-messageSends: ["subscriptionFactory:", "key:block:", "new", "yourself"],
-referencedClasses: ["ListKeyedSubscription"]
+source: "dispatcher: aDispatcher\x0a\x09dispatcher := aDispatcher\x0a        subscriptionFactory: [ :key :block |\x0a\x09\x09\x09(key notEmpty and: [ key last isNil ])\x0a\x09\x09\x09\x09ifTrue: [ TwoWayListKeyedSubscription new key: key allButLast block: block; yourself ]\x0a\x09\x09\x09\x09ifFalse: [ ListKeyedSubscription new key: key block: block; yourself ]];\x0a        yourself",
+messageSends: ["subscriptionFactory:", "ifTrue:ifFalse:", "key:block:", "allButLast", "new", "yourself", "and:", "isNil", "last", "notEmpty"],
+referencedClasses: ["TwoWayListKeyedSubscription", "ListKeyedSubscription"]
 }),
 smalltalk.ListKeyedEntity);
 
@@ -773,6 +811,45 @@ referencedClasses: []
 }),
 smalltalk.Object);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "reverseTrapAt:",
+category: '*Trapped-Backend',
+fn: function (anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(anObject)._at_ifAbsent_(self,(function(){
+return smalltalk.withContext(function($ctx2) {
+return nil;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"reverseTrapAt:",{anObject:anObject},smalltalk.Number)})},
+args: ["anObject"],
+source: "reverseTrapAt: anObject\x0a\x09^anObject at: self ifAbsent: [nil]",
+messageSends: ["at:ifAbsent:"],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "reverseTrapAt:put:",
+category: '*Trapped-Backend',
+fn: function (anObject,value){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(anObject)._at_put_(self,value);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"reverseTrapAt:put:",{anObject:anObject,value:value},smalltalk.Number)})},
+args: ["anObject", "value"],
+source: "reverseTrapAt: anObject put: value\x0a\x09^anObject at: self put: value",
+messageSends: ["at:put:"],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "asEavModel",
@@ -824,53 +901,6 @@ referencedClasses: ["EavModel"]
 }),
 smalltalk.SequenceableCollection);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "reverseTrapAt:",
-category: '*Trapped-Backend',
-fn: function (anObject){
-var self=this;
-function $MessageNotUnderstood(){return smalltalk.MessageNotUnderstood||(typeof MessageNotUnderstood=="undefined"?nil:MessageNotUnderstood)}
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-var $early={};
-try {
-$1=_st((function(){
-return smalltalk.withContext(function($ctx2) {
-return _st(anObject)._perform_(self._first());
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._on_do_($MessageNotUnderstood(),(function(){
-return smalltalk.withContext(function($ctx2) {
-throw $early=[nil];
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-return $1;
-}
-catch(e) {if(e===$early)return e[0]; throw e}
-}, function($ctx1) {$ctx1.fill(self,"reverseTrapAt:",{anObject:anObject},smalltalk.Array)})},
-args: ["anObject"],
-source: "reverseTrapAt: anObject\x0a\x09^[anObject perform: self first] on: MessageNotUnderstood do: [^nil]",
-messageSends: ["on:do:", "perform:", "first"],
-referencedClasses: ["MessageNotUnderstood"]
-}),
-smalltalk.Array);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "reverseTrapAt:put:",
-category: '*Trapped-Backend',
-fn: function (anObject,value){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(anObject)._perform_withArguments_(_st(_st(self._first()).__comma(":"))._asSymbol(),[value]);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"reverseTrapAt:put:",{anObject:anObject,value:value},smalltalk.Array)})},
-args: ["anObject", "value"],
-source: "reverseTrapAt: anObject put: value\x0a    ^anObject perform: (self first, ':') asSymbol withArguments: { value }",
-messageSends: ["perform:withArguments:", "asSymbol", ",", "first"],
-referencedClasses: []
-}),
-smalltalk.Array);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "reverseTrapAt:",
@@ -916,20 +946,28 @@ selector: "reverseTrapAt:",
 category: '*Trapped-Backend',
 fn: function (anObject){
 var self=this;
+function $MessageNotUnderstood(){return smalltalk.MessageNotUnderstood||(typeof MessageNotUnderstood=="undefined"?nil:MessageNotUnderstood)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(anObject)._at_ifAbsent_(self,(function(){
+var $early={};
+try {
+$1=_st((function(){
 return smalltalk.withContext(function($ctx2) {
-return nil;
+return _st(anObject)._perform_(self._first());
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._on_do_($MessageNotUnderstood(),(function(){
+return smalltalk.withContext(function($ctx2) {
+throw $early=[nil];
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"reverseTrapAt:",{anObject:anObject},smalltalk.Number)})},
+}
+catch(e) {if(e===$early)return e[0]; throw e}
+}, function($ctx1) {$ctx1.fill(self,"reverseTrapAt:",{anObject:anObject},smalltalk.Array)})},
 args: ["anObject"],
-source: "reverseTrapAt: anObject\x0a\x09^anObject at: self ifAbsent: [nil]",
-messageSends: ["at:ifAbsent:"],
-referencedClasses: []
+source: "reverseTrapAt: anObject\x0a\x09^[anObject perform: self first] on: MessageNotUnderstood do: [^nil]",
+messageSends: ["on:do:", "perform:", "first"],
+referencedClasses: ["MessageNotUnderstood"]
 }),
-smalltalk.Number);
+smalltalk.Array);
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -939,14 +977,14 @@ fn: function (anObject,value){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(anObject)._at_put_(self,value);
+$1=_st(anObject)._perform_withArguments_(_st(_st(self._first()).__comma(":"))._asSymbol(),[value]);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"reverseTrapAt:put:",{anObject:anObject,value:value},smalltalk.Number)})},
+}, function($ctx1) {$ctx1.fill(self,"reverseTrapAt:put:",{anObject:anObject,value:value},smalltalk.Array)})},
 args: ["anObject", "value"],
-source: "reverseTrapAt: anObject put: value\x0a\x09^anObject at: self put: value",
-messageSends: ["at:put:"],
+source: "reverseTrapAt: anObject put: value\x0a    ^anObject perform: (self first, ':') asSymbol withArguments: { value }",
+messageSends: ["perform:withArguments:", "asSymbol", ",", "first"],
 referencedClasses: []
 }),
-smalltalk.Number);
+smalltalk.Array);
 
 });

+ 29 - 14
lib/st/Trapped-Backend.st

@@ -221,6 +221,18 @@ accepts: aKey
     ^aKey size <= key size and: [aKey = (key copyFrom: 1 to: aKey size)]
 ! !
 
+KeyedSubscriptionBase subclass: #TwoWayListKeyedSubscription
+	instanceVariableNames: ''
+	package: 'Trapped-Backend'!
+
+!TwoWayListKeyedSubscription methodsFor: 'testing'!
+
+accepts: aKey
+    ^aKey size <= key size
+		ifTrue: [aKey = (key copyFrom: 1 to: aKey size)]
+		ifFalse: [key = (aKey copyFrom: 1 to: key size)]
+! !
+
 Object subclass: #ListKeyedEntity
 	instanceVariableNames: 'dispatcher payload'
 	package: 'Trapped-Backend'!
@@ -246,7 +258,10 @@ dispatcher
 
 dispatcher: aDispatcher
 	dispatcher := aDispatcher
-        subscriptionFactory: [ :key :block | ListKeyedSubscription new key: key block: block; yourself ];
+        subscriptionFactory: [ :key :block |
+			(key notEmpty and: [ key last isNil ])
+				ifTrue: [ TwoWayListKeyedSubscription new key: key allButLast block: block; yourself ]
+				ifFalse: [ ListKeyedSubscription new key: key block: block; yourself ]];
         yourself
 !
 
@@ -320,6 +335,16 @@ reverseTrapAt: anObject put: value
 	self error: 'Trapped cannot put at ', self class name, ' type key.'
 ! !
 
+!Number methodsFor: '*Trapped-Backend'!
+
+reverseTrapAt: anObject
+	^anObject at: self ifAbsent: [nil]
+!
+
+reverseTrapAt: anObject put: value
+	^anObject at: self put: value
+! !
+
 !SequenceableCollection methodsFor: '*Trapped-Backend'!
 
 asEavModel
@@ -336,16 +361,6 @@ asEavModel
     ^model
 ! !
 
-!Array methodsFor: '*Trapped-Backend'!
-
-reverseTrapAt: anObject
-	^[anObject perform: self first] on: MessageNotUnderstood do: [^nil]
-!
-
-reverseTrapAt: anObject put: value
-    ^anObject perform: (self first, ':') asSymbol withArguments: { value }
-! !
-
 !String methodsFor: '*Trapped-Backend'!
 
 reverseTrapAt: anObject
@@ -356,13 +371,13 @@ reverseTrapAt: anObject put: value
 	^anObject at: self put: value
 ! !
 
-!Number methodsFor: '*Trapped-Backend'!
+!Array methodsFor: '*Trapped-Backend'!
 
 reverseTrapAt: anObject
-	^anObject at: self ifAbsent: [nil]
+	^[anObject perform: self first] on: MessageNotUnderstood do: [^nil]
 !
 
 reverseTrapAt: anObject put: value
-	^anObject at: self put: value
+    ^anObject perform: (self first, ':') asSymbol withArguments: { value }
 ! !