Trapped-Backend.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. smalltalk.addPackage('Trapped-Backend', {});
  2. smalltalk.addClass('EavModel', smalltalk.Object, ['getBlock', 'putBlock'], 'Trapped-Backend');
  3. smalltalk.EavModel.comment="External actor value model."
  4. smalltalk.addMethod(
  5. "_getBlock_",
  6. smalltalk.method({
  7. selector: "getBlock:",
  8. category: 'accessing',
  9. fn: function (aBlock){
  10. var self=this;
  11. self["@getBlock"]=aBlock;
  12. return self},
  13. args: ["aBlock"],
  14. source: "getBlock: aBlock\x0a\x0agetBlock := aBlock",
  15. messageSends: [],
  16. referencedClasses: []
  17. }),
  18. smalltalk.EavModel);
  19. smalltalk.addMethod(
  20. "_initialize",
  21. smalltalk.method({
  22. selector: "initialize",
  23. category: 'initialization',
  24. fn: function (){
  25. var self=this;
  26. smalltalk.send(self,"_initialize",[],smalltalk.Object);
  27. self["@getBlock"]=(function(){
  28. return smalltalk.send(self,"_error_",["No getter block."]);
  29. });
  30. self["@putBlock"]=(function(){
  31. return smalltalk.send(self,"_error_",["No putter block."]);
  32. });
  33. return self},
  34. args: [],
  35. source: "initialize\x0a\x09super initialize.\x0a\x09getBlock := [ self error: 'No getter block.' ].\x0a\x09putBlock := [ self error: 'No putter block.' ].",
  36. messageSends: ["initialize", "error:"],
  37. referencedClasses: []
  38. }),
  39. smalltalk.EavModel);
  40. smalltalk.addMethod(
  41. "_on_",
  42. smalltalk.method({
  43. selector: "on:",
  44. category: 'accessing',
  45. fn: function (anObject){
  46. var self=this;
  47. var $1;
  48. $1=smalltalk.send(self["@getBlock"],"_value_",[anObject]);
  49. return $1;
  50. },
  51. args: ["anObject"],
  52. source: "on: anObject\x0a\x22Returns value of model applied on object\x22\x0a\x0a^getBlock value: anObject",
  53. messageSends: ["value:"],
  54. referencedClasses: []
  55. }),
  56. smalltalk.EavModel);
  57. smalltalk.addMethod(
  58. "_on_put_",
  59. smalltalk.method({
  60. selector: "on:put:",
  61. category: 'accessing',
  62. fn: function (anObject,anObject2){
  63. var self=this;
  64. var $1;
  65. $1=smalltalk.send(self["@putBlock"],"_value_value_",[anObject,anObject2]);
  66. return $1;
  67. },
  68. args: ["anObject", "anObject2"],
  69. source: "on: anObject put: anObject2\x0a\x22Puts a value via model applied on object\x22\x0a\x0a^putBlock value: anObject value: anObject2",
  70. messageSends: ["value:value:"],
  71. referencedClasses: []
  72. }),
  73. smalltalk.EavModel);
  74. smalltalk.addMethod(
  75. "_putBlock_",
  76. smalltalk.method({
  77. selector: "putBlock:",
  78. category: 'accessing',
  79. fn: function (aBlock){
  80. var self=this;
  81. self["@putBlock"]=aBlock;
  82. return self},
  83. args: ["aBlock"],
  84. source: "putBlock: aBlock\x0a\x0aputBlock := aBlock",
  85. messageSends: [],
  86. referencedClasses: []
  87. }),
  88. smalltalk.EavModel);
  89. smalltalk.addClass('Isolator', smalltalk.Object, ['root'], 'Trapped-Backend');
  90. smalltalk.addMethod(
  91. "_model_modify_",
  92. smalltalk.method({
  93. selector: "model:modify:",
  94. category: 'action',
  95. fn: function (anEavModel,aBlock){
  96. var self=this;
  97. var newValue;
  98. newValue=smalltalk.send(aBlock,"_value_",[smalltalk.send(anEavModel,"_on_",[self])]);
  99. smalltalk.send(anEavModel,"_on_put_",[self,smalltalk.send(newValue,"_deepCopy",[])]);
  100. return self},
  101. args: ["anEavModel", "aBlock"],
  102. source: "model: anEavModel modify: aBlock\x0a\x0a| newValue |\x0anewValue := aBlock value: (anEavModel on: self).\x0aanEavModel on: self put: newValue deepCopy\x0a",
  103. messageSends: ["value:", "on:", "on:put:", "deepCopy"],
  104. referencedClasses: []
  105. }),
  106. smalltalk.Isolator);
  107. smalltalk.addMethod(
  108. "_model_read_",
  109. smalltalk.method({
  110. selector: "model:read:",
  111. category: 'action',
  112. fn: function (anEavModel,aBlock){
  113. var self=this;
  114. smalltalk.send(aBlock,"_value_",[smalltalk.send(smalltalk.send(anEavModel,"_on_",[self]),"_deepCopy",[])]);
  115. return self},
  116. args: ["anEavModel", "aBlock"],
  117. source: "model: anEavModel read: aBlock\x0a\x0aaBlock value: (anEavModel on: self) deepCopy",
  118. messageSends: ["value:", "deepCopy", "on:"],
  119. referencedClasses: []
  120. }),
  121. smalltalk.Isolator);
  122. smalltalk.addMethod(
  123. "_root",
  124. smalltalk.method({
  125. selector: "root",
  126. category: 'accessing',
  127. fn: function (){
  128. var self=this;
  129. return self["@root"];
  130. },
  131. args: [],
  132. source: "root\x0a\x0a^root\x0a",
  133. messageSends: [],
  134. referencedClasses: []
  135. }),
  136. smalltalk.Isolator);
  137. smalltalk.addMethod(
  138. "_root_",
  139. smalltalk.method({
  140. selector: "root:",
  141. category: 'accessing',
  142. fn: function (anObject){
  143. var self=this;
  144. self["@root"]=anObject;
  145. return self},
  146. args: ["anObject"],
  147. source: "root: anObject\x0a\x0aroot := anObject",
  148. messageSends: [],
  149. referencedClasses: []
  150. }),
  151. smalltalk.Isolator);
  152. smalltalk.addMethod(
  153. "_on_",
  154. smalltalk.method({
  155. selector: "on:",
  156. category: 'instance creation',
  157. fn: function (anObject){
  158. var self=this;
  159. var $1;
  160. $1=smalltalk.send(smalltalk.send(self,"_new",[]),"_root_",[anObject]);
  161. return $1;
  162. },
  163. args: ["anObject"],
  164. source: "on: anObject\x0a^self new root: anObject",
  165. messageSends: ["root:", "new"],
  166. referencedClasses: []
  167. }),
  168. smalltalk.Isolator.klass);
  169. smalltalk.addClass('TrappedDispatcher', smalltalk.Object, [], 'Trapped-Backend');
  170. smalltalk.TrappedDispatcher.comment="I am base class for change event dispatchers.\x0aI manage changed path - action block subscriptions.\x0aThese subscription must be three-element arrays\x0a\x09{ dirty. path. block }\x0a\x0aMy subclasses need to provide implementation for:\x0a\x09add:\x0a do:\x0a clean\x0a (optionally) run\x0a"
  171. smalltalk.addMethod(
  172. "_changed_",
  173. smalltalk.method({
  174. selector: "changed:",
  175. category: 'action',
  176. fn: function (path){
  177. var self=this;
  178. var $1;
  179. var needsToRun;
  180. needsToRun=false;
  181. smalltalk.send(self,"_do_",[(function(each){
  182. var aPath;
  183. var lesser;
  184. aPath=smalltalk.send(each,"_second",[]);
  185. aPath;
  186. lesser=smalltalk.send(smalltalk.send(aPath,"_size",[]),"_min_",[smalltalk.send(path,"_size",[])]);
  187. lesser;
  188. $1=smalltalk.send(smalltalk.send(path,"_copyFrom_to_",[(1),lesser]),"__eq",[smalltalk.send(aPath,"_copyFrom_to_",[(1),lesser])]);
  189. if(smalltalk.assert($1)){
  190. smalltalk.send(each,"_at_put_",[(1),true]);
  191. needsToRun=true;
  192. return needsToRun;
  193. };
  194. })]);
  195. smalltalk.send(self,"_dirty_",[needsToRun]);
  196. return self},
  197. args: ["path"],
  198. source: "changed: path\x0a\x09| needsToRun |\x0a needsToRun := false.\x0a\x09self do: [ :each |\x0a\x09\x09| aPath lesser |\x0a\x09\x09aPath := each second.\x0a\x09\x09lesser := aPath size min: path size.\x0a\x09\x09(path copyFrom: 1 to: lesser) = (aPath copyFrom: 1 to: lesser) ifTrue: [\x0a\x09\x09\x09each at: 1 put: true.\x0a needsToRun := true.\x0a\x09\x09]\x0a\x09].\x0a\x09self dirty: needsToRun",
  199. messageSends: ["do:", "second", "min:", "size", "ifTrue:", "at:put:", "=", "copyFrom:to:", "dirty:"],
  200. referencedClasses: []
  201. }),
  202. smalltalk.TrappedDispatcher);
  203. smalltalk.addMethod(
  204. "_dirty_",
  205. smalltalk.method({
  206. selector: "dirty:",
  207. category: 'action',
  208. fn: function (aBoolean){
  209. var self=this;
  210. if(smalltalk.assert(aBoolean)){
  211. smalltalk.send((function(){
  212. return smalltalk.send(self,"_run",[]);
  213. }),"_fork",[]);
  214. };
  215. return self},
  216. args: ["aBoolean"],
  217. source: "dirty: aBoolean\x0a\x09aBoolean ifTrue: [[ self run ] fork]",
  218. messageSends: ["ifTrue:", "fork", "run"],
  219. referencedClasses: []
  220. }),
  221. smalltalk.TrappedDispatcher);
  222. smalltalk.addMethod(
  223. "_on_hook_",
  224. smalltalk.method({
  225. selector: "on:hook:",
  226. category: 'action',
  227. fn: function (path,aBlock){
  228. var self=this;
  229. smalltalk.send(self,"_add_",[[true,path,aBlock]]);
  230. smalltalk.send(self,"_dirty_",[true]);
  231. return self},
  232. args: ["path", "aBlock"],
  233. source: "on: path hook: aBlock\x0a\x09self add: { true. path. aBlock }.\x0a \x09self dirty: true",
  234. messageSends: ["add:", "dirty:"],
  235. referencedClasses: []
  236. }),
  237. smalltalk.TrappedDispatcher);
  238. smalltalk.addMethod(
  239. "_run",
  240. smalltalk.method({
  241. selector: "run",
  242. category: 'action',
  243. fn: function (){
  244. var self=this;
  245. var $1;
  246. var needsClean;
  247. needsClean=false;
  248. smalltalk.send(self,"_do_",[(function(each){
  249. $1=smalltalk.send(each,"_first",[]);
  250. if(smalltalk.assert($1)){
  251. return smalltalk.send((function(){
  252. return smalltalk.send((function(){
  253. return smalltalk.send(smalltalk.send(each,"_third",[]),"_value",[]);
  254. }),"_ensure_",[(function(){
  255. return smalltalk.send(each,"_at_put_",[(1),false]);
  256. })]);
  257. }),"_on_do_",[(smalltalk.TrappedUnwatch || TrappedUnwatch),(function(){
  258. smalltalk.send(each,"_at_put_",[(3),nil]);
  259. needsClean=true;
  260. return needsClean;
  261. })]);
  262. };
  263. })]);
  264. if(smalltalk.assert(needsClean)){
  265. smalltalk.send(self,"_clean",[]);
  266. };
  267. return self},
  268. args: [],
  269. source: "run\x0a\x09| needsClean |\x0a needsClean := false.\x0a\x09self do: [ :each |\x0a\x09\x09each first ifTrue: [\x0a [[ each third value ] ensure: [ each at: 1 put: false ]]\x0a on: TrappedUnwatch do: [ each at: 3 put: nil. needsClean := true ]\x0a ]\x0a\x09].\x0a needsClean ifTrue: [ self clean ]",
  270. messageSends: ["do:", "ifTrue:", "on:do:", "at:put:", "ensure:", "value", "third", "first", "clean"],
  271. referencedClasses: ["TrappedUnwatch"]
  272. }),
  273. smalltalk.TrappedDispatcher);
  274. smalltalk.addClass('TrappedUnwatch', smalltalk.Error, [], 'Trapped-Backend');
  275. smalltalk.TrappedUnwatch.comment="SIgnal me from the watch: block to unwatch it."
  276. smalltalk.addMethod(
  277. "_reverseTrapAt_",
  278. smalltalk.method({
  279. selector: "reverseTrapAt:",
  280. category: '*Trapped-Backend',
  281. fn: function (anObject){
  282. var self=this;
  283. return nil;
  284. },
  285. args: ["anObject"],
  286. source: "reverseTrapAt: anObject\x0a\x09^nil",
  287. messageSends: [],
  288. referencedClasses: []
  289. }),
  290. smalltalk.Object);
  291. smalltalk.addMethod(
  292. "_reverseTrapAt_put_",
  293. smalltalk.method({
  294. selector: "reverseTrapAt:put:",
  295. category: '*Trapped-Backend',
  296. fn: function (anObject,value){
  297. var self=this;
  298. smalltalk.send(self,"_error_",[smalltalk.send(smalltalk.send("Trapped cannot put at ","__comma",[smalltalk.send(smalltalk.send(self,"_class",[]),"_name",[])]),"__comma",[" type key."])]);
  299. return self},
  300. args: ["anObject", "value"],
  301. source: "reverseTrapAt: anObject put: value\x0a\x09self error: 'Trapped cannot put at ', self class name, ' type key.'",
  302. messageSends: ["error:", ",", "name", "class"],
  303. referencedClasses: []
  304. }),
  305. smalltalk.Object);
  306. smalltalk.addMethod(
  307. "_asEavModel",
  308. smalltalk.method({
  309. selector: "asEavModel",
  310. category: '*Trapped-Backend',
  311. fn: function (){
  312. var self=this;
  313. var $1;
  314. var model;
  315. model=smalltalk.send((smalltalk.EavModel || EavModel),"_new",[]);
  316. smalltalk.send(model,"_getBlock_",[(function(anObject){
  317. return smalltalk.send(self,"_inject_into_",[anObject,(function(soFar,segment){
  318. if(($receiver = soFar) == nil || $receiver == undefined){
  319. return soFar;
  320. } else {
  321. return smalltalk.send(segment,"_reverseTrapAt_",[soFar]);
  322. };
  323. })]);
  324. })]);
  325. $1=smalltalk.send(self,"_isEmpty",[]);
  326. if(! smalltalk.assert($1)){
  327. smalltalk.send(model,"_putBlock_",[(function(anObject,value){
  328. var penultimate;
  329. penultimate=smalltalk.send(smalltalk.send(self,"_allButLast",[]),"_inject_into_",[anObject,(function(soFar,segment){
  330. if(($receiver = soFar) == nil || $receiver == undefined){
  331. return soFar;
  332. } else {
  333. return smalltalk.send(segment,"_reverseTrapAt_",[soFar]);
  334. };
  335. })]);
  336. penultimate;
  337. return smalltalk.send(smalltalk.send(self,"_last",[]),"_reverseTrapAt_put_",[penultimate,value]);
  338. })]);
  339. };
  340. return model;
  341. },
  342. args: [],
  343. source: "asEavModel\x0a | model |\x0a model := EavModel new.\x0a model getBlock: [ :anObject |\x0a self inject: anObject into: [ :soFar :segment |\x0a soFar ifNotNil: [ segment reverseTrapAt: soFar ]]].\x0a self isEmpty ifFalse: [\x0a model putBlock: [ :anObject :value | | penultimate |\x0a penultimate := self allButLast inject: anObject into: [ :soFar :segment |\x0a soFar ifNotNil: [ segment reverseTrapAt: soFar ]].\x0a self last reverseTrapAt: penultimate put: value ]].\x0a ^model",
  344. messageSends: ["new", "getBlock:", "inject:into:", "ifNotNil:", "reverseTrapAt:", "ifFalse:", "putBlock:", "allButLast", "reverseTrapAt:put:", "last", "isEmpty"],
  345. referencedClasses: ["EavModel"]
  346. }),
  347. smalltalk.SequenceableCollection);
  348. smalltalk.addMethod(
  349. "_reverseTrapAt_",
  350. smalltalk.method({
  351. selector: "reverseTrapAt:",
  352. category: '*Trapped-Backend',
  353. fn: function (anObject){
  354. var self=this;
  355. var $1;
  356. $1=smalltalk.send(anObject,"_at_ifAbsent_",[self,(function(){
  357. return nil;
  358. })]);
  359. return $1;
  360. },
  361. args: ["anObject"],
  362. source: "reverseTrapAt: anObject\x0a\x09^anObject at: self ifAbsent: [nil]",
  363. messageSends: ["at:ifAbsent:"],
  364. referencedClasses: []
  365. }),
  366. smalltalk.String);
  367. smalltalk.addMethod(
  368. "_reverseTrapAt_put_",
  369. smalltalk.method({
  370. selector: "reverseTrapAt:put:",
  371. category: '*Trapped-Backend',
  372. fn: function (anObject,value){
  373. var self=this;
  374. var $1;
  375. $1=smalltalk.send(anObject,"_at_put_",[self,value]);
  376. return $1;
  377. },
  378. args: ["anObject", "value"],
  379. source: "reverseTrapAt: anObject put: value\x0a\x09^anObject at: self put: value",
  380. messageSends: ["at:put:"],
  381. referencedClasses: []
  382. }),
  383. smalltalk.String);
  384. smalltalk.addMethod(
  385. "_reverseTrapAt_",
  386. smalltalk.method({
  387. selector: "reverseTrapAt:",
  388. category: '*Trapped-Backend',
  389. fn: function (anObject){
  390. var self=this;
  391. var $1;
  392. var $early={};
  393. try {
  394. $1=smalltalk.send((function(){
  395. return smalltalk.send(anObject,"_perform_",[self]);
  396. }),"_on_do_",[(smalltalk.MessageNotUnderstood || MessageNotUnderstood),(function(){
  397. throw $early=[nil];
  398. })]);
  399. return $1;
  400. }
  401. catch(e) {if(e===$early)return e[0]; throw e}
  402. },
  403. args: ["anObject"],
  404. source: "reverseTrapAt: anObject\x0a\x09^[anObject perform: self] on: MessageNotUnderstood do: [^nil]",
  405. messageSends: ["on:do:", "perform:"],
  406. referencedClasses: ["MessageNotUnderstood"]
  407. }),
  408. smalltalk.Symbol);
  409. smalltalk.addMethod(
  410. "_reverseTrapAt_put_",
  411. smalltalk.method({
  412. selector: "reverseTrapAt:put:",
  413. category: '*Trapped-Backend',
  414. fn: function (anObject,value){
  415. var self=this;
  416. var $1;
  417. $1=smalltalk.send(anObject,"_perform_withArguments_",[smalltalk.send(smalltalk.send(self,"__comma",[":"]),"_asSymbol",[]),[value]]);
  418. return $1;
  419. },
  420. args: ["anObject", "value"],
  421. source: "reverseTrapAt: anObject put: value\x0a ^anObject perform: (self, ':') asSymbol withArguments: { value }",
  422. messageSends: ["perform:withArguments:", "asSymbol", ","],
  423. referencedClasses: []
  424. }),
  425. smalltalk.Symbol);
  426. smalltalk.addMethod(
  427. "_reverseTrapAt_",
  428. smalltalk.method({
  429. selector: "reverseTrapAt:",
  430. category: '*Trapped-Backend',
  431. fn: function (anObject){
  432. var self=this;
  433. var $1;
  434. $1=smalltalk.send(anObject,"_at_ifAbsent_",[self,(function(){
  435. return nil;
  436. })]);
  437. return $1;
  438. },
  439. args: ["anObject"],
  440. source: "reverseTrapAt: anObject\x0a\x09^anObject at: self ifAbsent: [nil]",
  441. messageSends: ["at:ifAbsent:"],
  442. referencedClasses: []
  443. }),
  444. smalltalk.Number);
  445. smalltalk.addMethod(
  446. "_reverseTrapAt_put_",
  447. smalltalk.method({
  448. selector: "reverseTrapAt:put:",
  449. category: '*Trapped-Backend',
  450. fn: function (anObject,value){
  451. var self=this;
  452. var $1;
  453. $1=smalltalk.send(anObject,"_at_put_",[self,value]);
  454. return $1;
  455. },
  456. args: ["anObject", "value"],
  457. source: "reverseTrapAt: anObject put: value\x0a\x09^anObject at: self put: value",
  458. messageSends: ["at:put:"],
  459. referencedClasses: []
  460. }),
  461. smalltalk.Number);