Browse Source

Extract Axon into Axxord-Axon category.

Herbert Vojčík 6 years ago
parent
commit
fc91e85ebd
4 changed files with 972 additions and 952 deletions
  1. 767 0
      src/Axxord-Axon.js
  2. 194 0
      src/Axxord-Axon.st
  3. 10 759
      src/Axxord.js
  4. 1 193
      src/Axxord.st

+ 767 - 0
src/Axxord-Axon.js

@@ -0,0 +1,767 @@
+define(["amber/boot", "amber_core/Kernel-Exceptions", "amber_core/Kernel-Objects"], function($boot){"use strict";
+if(!$boot.nilAsReceiver)$boot.nilAsReceiver=$boot.nil;
+if(!("nilAsValue" in $boot))$boot.nilAsValue=$boot.nilAsReceiver;
+var $core=$boot.api,nil=$boot.nilAsValue,$nil=$boot.nilAsReceiver,$recv=$boot.asReceiver,$globals=$boot.globals;
+if(!$boot.nilAsClass)$boot.nilAsClass=$boot.dnu;
+$core.addPackage("Axxord-Axon");
+$core.packages["Axxord-Axon"].innerEval = function (expr) { return eval(expr); };
+$core.packages["Axxord-Axon"].transport = {"type":"amd","amdNamespace":"axxord"};
+
+$core.addClass("Axon", $globals.Object, ["factory"], "Axxord-Axon");
+//>>excludeStart("ide", pragmas.excludeIdeData);
+$globals.Axon.comment="I represent a pub-sub based on a key (called 'aspect').\x0aI manage aspect-block subscriptions (called 'interests') as well as run blocks of dirtied interests.\x0aThe interest objects are responsible of decision if the change of an aspect is relevant for them.\x0aInterest object must be subclasses of `AxonInterest`.\x0a\x0aMy subclasses must provide implementation for:\x0a\x0a - add:\x0a - do:\x0a - clean";
+//>>excludeEnd("ide");
+$core.addMethod(
+$core.method({
+selector: "add:",
+protocol: "primitive ops",
+fn: function (anInterest){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"add:",{anInterest:anInterest},$globals.Axon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anInterest"],
+source: "add: anInterest\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.Axon);
+
+$core.addMethod(
+$core.method({
+selector: "addInterest:",
+protocol: "accessing",
+fn: function (anInterest){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1;
+$recv(anInterest)._flag();
+$1=$recv(anInterest)._yourself();
+$self._add_($1);
+$self._dirty_(true);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"addInterest:",{anInterest:anInterest},$globals.Axon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anInterest"],
+source: "addInterest: anInterest\x0a\x09self\x0a\x09\x09add: (anInterest flag; yourself);\x0a\x09\x09dirty: true",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["add:", "flag", "yourself", "dirty:"]
+}),
+$globals.Axon);
+
+$core.addMethod(
+$core.method({
+selector: "changed:",
+protocol: "change-update",
+fn: function (anAspect){
+var self=this,$self=this;
+var needsToRun;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1;
+needsToRun=false;
+$self._do_((function(each){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+$1=$recv(each)._accepts_(anAspect);
+if($core.assert($1)){
+$recv(each)._flag();
+needsToRun=true;
+return needsToRun;
+}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+$self._dirty_(needsToRun);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"changed:",{anAspect:anAspect,needsToRun:needsToRun},$globals.Axon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anAspect"],
+source: "changed: anAspect\x0a\x09| needsToRun |\x0a\x09needsToRun := false.\x0a\x09self do: [ :each |\x0a\x09\x09(each accepts: anAspect) ifTrue: [\x0a\x09\x09\x09each flag.\x0a\x09\x09\x09needsToRun := true ]].\x0a\x09self dirty: needsToRun",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["do:", "ifTrue:", "accepts:", "flag", "dirty:"]
+}),
+$globals.Axon);
+
+$core.addMethod(
+$core.method({
+selector: "changedAll",
+protocol: "change-update",
+fn: function (){
+var self=this,$self=this;
+var needsToRun;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+needsToRun=false;
+$self._do_((function(each){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+$recv(each)._flag();
+needsToRun=true;
+return needsToRun;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+$self._dirty_(needsToRun);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"changedAll",{needsToRun:needsToRun},$globals.Axon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "changedAll\x0a\x09| needsToRun |\x0a\x09needsToRun := false.\x0a\x09self do: [ :each |\x0a\x09\x09each flag.\x0a\x09\x09needsToRun := true ].\x0a\x09self dirty: needsToRun",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["do:", "flag", "dirty:"]
+}),
+$globals.Axon);
+
+$core.addMethod(
+$core.method({
+selector: "clean",
+protocol: "primitive ops",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"clean",{},$globals.Axon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "clean\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.Axon);
+
+$core.addMethod(
+$core.method({
+selector: "dirty:",
+protocol: "private",
+fn: function (aBoolean){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+if($core.assert(aBoolean)){
+$recv((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $self._run();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)});
+//>>excludeEnd("ctx");
+}))._fork();
+}
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"dirty:",{aBoolean:aBoolean},$globals.Axon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aBoolean"],
+source: "dirty: aBoolean\x0a\x09aBoolean ifTrue: [[ self run ] fork]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["ifTrue:", "fork", "run"]
+}),
+$globals.Axon);
+
+$core.addMethod(
+$core.method({
+selector: "do:",
+protocol: "primitive ops",
+fn: function (aBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"do:",{aBlock:aBlock},$globals.Axon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aBlock"],
+source: "do: aBlock\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.Axon);
+
+$core.addMethod(
+$core.method({
+selector: "run",
+protocol: "private",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2,$3;
+$recv((function(){
+var needsClean;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+needsClean=false;
+needsClean;
+$self._do_((function(each){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx3) {
+//>>excludeEnd("ctx");
+$1=$recv(each)._isFlagged();
+if($core.assert($1)){
+$recv(each)._run();
+}
+$2=$recv(each)._isClosed();
+if($core.assert($2)){
+needsClean=true;
+return needsClean;
+}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx3) {$ctx3.fillBlock({each:each},$ctx2,2)});
+//>>excludeEnd("ctx");
+}));
+$3=needsClean;
+if($core.assert($3)){
+return $self._clean();
+}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({needsClean:needsClean},$ctx1,1)});
+//>>excludeEnd("ctx");
+}))._on_do_($globals.Error,(function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $self._dirty_(true);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,6)});
+//>>excludeEnd("ctx");
+}));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"run",{},$globals.Axon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "run\x0a\x09[\x0a\x09\x09| needsClean |\x0a\x09    needsClean := false.\x0a\x09\x09self do: [ :each |\x0a\x09\x09\x09each isFlagged ifTrue: [ each run ].\x0a\x09        each isClosed ifTrue: [ needsClean := true ]\x0a\x09\x09].\x0a    \x09needsClean ifTrue: [ self clean ]\x0a\x09] on: Error do: [ self dirty: true ]",
+referencedClasses: ["Error"],
+//>>excludeEnd("ide");
+messageSends: ["on:do:", "do:", "ifTrue:", "isFlagged", "run", "isClosed", "clean", "dirty:"]
+}),
+$globals.Axon);
+
+
+
+$core.addClass("SimpleAxon", $globals.Axon, ["queue"], "Axxord-Axon");
+$core.addMethod(
+$core.method({
+selector: "add:",
+protocol: "primitive ops",
+fn: function (aSubscription){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$recv($self["@queue"])._add_(aSubscription);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"add:",{aSubscription:aSubscription},$globals.SimpleAxon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aSubscription"],
+source: "add: aSubscription\x0a\x09queue add: aSubscription.",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["add:"]
+}),
+$globals.SimpleAxon);
+
+$core.addMethod(
+$core.method({
+selector: "clean",
+protocol: "primitive ops",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self["@queue"]=$recv($self["@queue"])._reject_((function(each){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $recv(each)._isClosed();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"clean",{},$globals.SimpleAxon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "clean\x0a\x09queue := queue reject: [ :each | each isClosed ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["reject:", "isClosed"]
+}),
+$globals.SimpleAxon);
+
+$core.addMethod(
+$core.method({
+selector: "do:",
+protocol: "primitive ops",
+fn: function (aBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$recv($self["@queue"])._do_(aBlock);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"do:",{aBlock:aBlock},$globals.SimpleAxon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aBlock"],
+source: "do: aBlock\x0a\x09queue do: aBlock",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["do:"]
+}),
+$globals.SimpleAxon);
+
+$core.addMethod(
+$core.method({
+selector: "initialize",
+protocol: "initialization",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true,
+//>>excludeEnd("ctx");
+($globals.SimpleAxon.superclass||$boot.nilAsClass).fn.prototype._initialize.apply($self, []));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+$self["@queue"]=$recv($globals.OrderedCollection)._new();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.SimpleAxon)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "initialize\x0a    super initialize.\x0a\x09queue := OrderedCollection new",
+referencedClasses: ["OrderedCollection"],
+//>>excludeEnd("ide");
+messageSends: ["initialize", "new"]
+}),
+$globals.SimpleAxon);
+
+
+
+$core.addClass("AxonInterest", $globals.Object, ["flagged"], "Axxord-Axon");
+$core.addMethod(
+$core.method({
+selector: "accepts:",
+protocol: "testing",
+fn: function (anAspect){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"accepts:",{anAspect:anAspect},$globals.AxonInterest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anAspect"],
+source: "accepts: anAspect\x0a    \x22Should return true if change for anAspect is relevant for this AxonInterest\x22\x0a    self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.AxonInterest);
+
+$core.addMethod(
+$core.method({
+selector: "close",
+protocol: "action",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"close",{},$globals.AxonInterest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "close\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.AxonInterest);
+
+$core.addMethod(
+$core.method({
+selector: "enact",
+protocol: "action",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"enact",{},$globals.AxonInterest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "enact\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.AxonInterest);
+
+$core.addMethod(
+$core.method({
+selector: "flag",
+protocol: "accessing",
+fn: function (){
+var self=this,$self=this;
+$self["@flagged"]=true;
+return self;
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "flag\x0a\x09flagged := true",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.AxonInterest);
+
+$core.addMethod(
+$core.method({
+selector: "initialize",
+protocol: "initialization",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true,
+//>>excludeEnd("ctx");
+($globals.AxonInterest.superclass||$boot.nilAsClass).fn.prototype._initialize.apply($self, []));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+$self["@flagged"]=false;
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.AxonInterest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "initialize\x0a\x09super initialize.\x0a    flagged := false.",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["initialize"]
+}),
+$globals.AxonInterest);
+
+$core.addMethod(
+$core.method({
+selector: "isClosed",
+protocol: "testing",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._subclassResponsibility();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"isClosed",{},$globals.AxonInterest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isClosed\x0a\x09self subclassResponsibility",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclassResponsibility"]
+}),
+$globals.AxonInterest);
+
+$core.addMethod(
+$core.method({
+selector: "isFlagged",
+protocol: "testing",
+fn: function (){
+var self=this,$self=this;
+return $self["@flagged"];
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isFlagged\x0a\x09^flagged",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.AxonInterest);
+
+$core.addMethod(
+$core.method({
+selector: "run",
+protocol: "action",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$recv((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+$self["@flagged"]=false;
+$self["@flagged"];
+return $self._enact();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}))._on_do_($globals.AxonOff,(function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $self._close();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)});
+//>>excludeEnd("ctx");
+}));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"run",{},$globals.AxonInterest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "run\x0a\x09[ flagged := false. self enact ]\x0a    on: AxonOff do: [ self close ]",
+referencedClasses: ["AxonOff"],
+//>>excludeEnd("ide");
+messageSends: ["on:do:", "enact", "close"]
+}),
+$globals.AxonInterest);
+
+
+
+$core.addClass("PluggableInterest", $globals.AxonInterest, ["acceptBlock", "enactBlock"], "Axxord-Axon");
+$core.addMethod(
+$core.method({
+selector: "accept:enact:",
+protocol: "accessing",
+fn: function (aBlock,anotherBlock){
+var self=this,$self=this;
+$self["@acceptBlock"]=aBlock;
+$self["@enactBlock"]=anotherBlock;
+return self;
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aBlock", "anotherBlock"],
+source: "accept: aBlock enact: anotherBlock\x0a\x09acceptBlock := aBlock.\x0a    enactBlock := anotherBlock",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.PluggableInterest);
+
+$core.addMethod(
+$core.method({
+selector: "accepts:",
+protocol: "testing",
+fn: function (anAspect){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self["@acceptBlock"])._value_(anAspect);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"accepts:",{anAspect:anAspect},$globals.PluggableInterest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anAspect"],
+source: "accepts: anAspect\x0a    ^ acceptBlock value: anAspect",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["value:"]
+}),
+$globals.PluggableInterest);
+
+$core.addMethod(
+$core.method({
+selector: "close",
+protocol: "action",
+fn: function (){
+var self=this,$self=this;
+$self["@acceptBlock"]=nil;
+$self["@enactBlock"]=nil;
+return self;
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "close\x0a\x09acceptBlock := nil.\x0a\x09enactBlock := nil",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.PluggableInterest);
+
+$core.addMethod(
+$core.method({
+selector: "enact",
+protocol: "action",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$recv($self["@enactBlock"])._value();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"enact",{},$globals.PluggableInterest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "enact\x0a\x09enactBlock value",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["value"]
+}),
+$globals.PluggableInterest);
+
+$core.addMethod(
+$core.method({
+selector: "initialize",
+protocol: "initialization",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true,
+//>>excludeEnd("ctx");
+($globals.PluggableInterest.superclass||$boot.nilAsClass).fn.prototype._initialize.apply($self, []));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+$self._close();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.PluggableInterest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "initialize\x0a\x09super initialize.\x0a    self close",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["initialize", "close"]
+}),
+$globals.PluggableInterest);
+
+$core.addMethod(
+$core.method({
+selector: "isClosed",
+protocol: "testing",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self["@acceptBlock"])._isNil();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"isClosed",{},$globals.PluggableInterest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isClosed\x0a\x09^ acceptBlock isNil",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["isNil"]
+}),
+$globals.PluggableInterest);
+
+
+
+$core.addClass("AxonOff", $globals.Error, [], "Axxord-Axon");
+//>>excludeStart("ide", pragmas.excludeIdeData);
+$globals.AxonOff.comment="Signal me from the subscription block to unsubscribe it.";
+//>>excludeEnd("ide");
+
+});

+ 194 - 0
src/Axxord-Axon.st

@@ -0,0 +1,194 @@
+Smalltalk createPackage: 'Axxord-Axon'!
+Object subclass: #Axon
+	instanceVariableNames: 'factory'
+	package: 'Axxord-Axon'!
+!Axon commentStamp!
+I represent a pub-sub based on a key (called 'aspect').
+I manage aspect-block subscriptions (called 'interests') as well as run blocks of dirtied interests.
+The interest objects are responsible of decision if the change of an aspect is relevant for them.
+Interest object must be subclasses of `AxonInterest`.
+
+My subclasses must provide implementation for:
+
+ - add:
+ - do:
+ - clean!
+
+!Axon methodsFor: 'accessing'!
+
+addInterest: anInterest
+	self
+		add: (anInterest flag; yourself);
+		dirty: true
+! !
+
+!Axon methodsFor: 'change-update'!
+
+changed: anAspect
+	| needsToRun |
+	needsToRun := false.
+	self do: [ :each |
+		(each accepts: anAspect) ifTrue: [
+			each flag.
+			needsToRun := true ]].
+	self dirty: needsToRun
+!
+
+changedAll
+	| needsToRun |
+	needsToRun := false.
+	self do: [ :each |
+		each flag.
+		needsToRun := true ].
+	self dirty: needsToRun
+! !
+
+!Axon methodsFor: 'primitive ops'!
+
+add: anInterest
+	self subclassResponsibility
+!
+
+clean
+	self subclassResponsibility
+!
+
+do: aBlock
+	self subclassResponsibility
+! !
+
+!Axon methodsFor: 'private'!
+
+dirty: aBoolean
+	aBoolean ifTrue: [[ self run ] fork]
+!
+
+run
+	[
+		| needsClean |
+	    needsClean := false.
+		self do: [ :each |
+			each isFlagged ifTrue: [ each run ].
+	        each isClosed ifTrue: [ needsClean := true ]
+		].
+    	needsClean ifTrue: [ self clean ]
+	] on: Error do: [ self dirty: true ]
+! !
+
+Axon subclass: #SimpleAxon
+	instanceVariableNames: 'queue'
+	package: 'Axxord-Axon'!
+
+!SimpleAxon methodsFor: 'initialization'!
+
+initialize
+    super initialize.
+	queue := OrderedCollection new
+! !
+
+!SimpleAxon methodsFor: 'primitive ops'!
+
+add: aSubscription
+	queue add: aSubscription.
+!
+
+clean
+	queue := queue reject: [ :each | each isClosed ]
+!
+
+do: aBlock
+	queue do: aBlock
+! !
+
+Object subclass: #AxonInterest
+	instanceVariableNames: 'flagged'
+	package: 'Axxord-Axon'!
+
+!AxonInterest methodsFor: 'accessing'!
+
+flag
+	flagged := true
+! !
+
+!AxonInterest methodsFor: 'action'!
+
+close
+	self subclassResponsibility
+!
+
+enact
+	self subclassResponsibility
+!
+
+run
+	[ flagged := false. self enact ]
+    on: AxonOff do: [ self close ]
+! !
+
+!AxonInterest methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+    flagged := false.
+! !
+
+!AxonInterest methodsFor: 'testing'!
+
+accepts: anAspect
+    "Should return true if change for anAspect is relevant for this AxonInterest"
+    self subclassResponsibility
+!
+
+isClosed
+	self subclassResponsibility
+!
+
+isFlagged
+	^flagged
+! !
+
+AxonInterest subclass: #PluggableInterest
+	instanceVariableNames: 'acceptBlock enactBlock'
+	package: 'Axxord-Axon'!
+
+!PluggableInterest methodsFor: 'accessing'!
+
+accept: aBlock enact: anotherBlock
+	acceptBlock := aBlock.
+    enactBlock := anotherBlock
+! !
+
+!PluggableInterest methodsFor: 'action'!
+
+close
+	acceptBlock := nil.
+	enactBlock := nil
+!
+
+enact
+	enactBlock value
+! !
+
+!PluggableInterest methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+    self close
+! !
+
+!PluggableInterest methodsFor: 'testing'!
+
+accepts: anAspect
+    ^ acceptBlock value: anAspect
+!
+
+isClosed
+	^ acceptBlock isNil
+! !
+
+Error subclass: #AxonOff
+	instanceVariableNames: ''
+	package: 'Axxord-Axon'!
+!AxonOff commentStamp!
+Signal me from the subscription block to unsubscribe it.!
+

+ 10 - 759
src/Axxord.js

@@ -1,10 +1,19 @@
-define(["amber/boot", "amber_core/Kernel-Collections", "amber_core/Kernel-Exceptions", "amber_core/Kernel-Infrastructure", "amber_core/Kernel-Objects"], function($boot){"use strict";
+define(["amber/boot"
+//>>excludeStart("imports", pragmas.excludeImports);
+, "axxord/Axxord-Axon"
+//>>excludeEnd("imports");
+, "amber_core/Kernel-Collections", "amber_core/Kernel-Infrastructure", "amber_core/Kernel-Objects"], function($boot
+//>>excludeStart("imports", pragmas.excludeImports);
+
+//>>excludeEnd("imports");
+){"use strict";
 if(!$boot.nilAsReceiver)$boot.nilAsReceiver=$boot.nil;
 if(!("nilAsValue" in $boot))$boot.nilAsValue=$boot.nilAsReceiver;
 var $core=$boot.api,nil=$boot.nilAsValue,$nil=$boot.nilAsReceiver,$recv=$boot.asReceiver,$globals=$boot.globals;
 if(!$boot.nilAsClass)$boot.nilAsClass=$boot.dnu;
 $core.addPackage("Axxord");
 $core.packages["Axxord"].innerEval = function (expr) { return eval(expr); };
+$core.packages["Axxord"].imports = ["axxord/Axxord-Axon"];
 $core.packages["Axxord"].transport = {"type":"amd","amdNamespace":"axxord"};
 
 $core.addClass("Axes", $globals.Object, [], "Axxord");
@@ -574,764 +583,6 @@ messageSends: ["root:", "new"]
 }),
 $globals.Axolator.a$cls);
 
-
-$core.addClass("Axon", $globals.Object, ["factory"], "Axxord");
-//>>excludeStart("ide", pragmas.excludeIdeData);
-$globals.Axon.comment="I represent a pub-sub based on a key (called 'aspect').\x0aI manage aspect-block subscriptions (called 'interests') as well as run blocks of dirtied interests.\x0aThe interest objects are responsible of decision if the change of an aspect is relevant for them.\x0aInterest object must be subclasses of `AxonInterest`.\x0a\x0aMy subclasses must provide implementation for:\x0a\x0a - add:\x0a - do:\x0a - clean";
-//>>excludeEnd("ide");
-$core.addMethod(
-$core.method({
-selector: "add:",
-protocol: "primitive ops",
-fn: function (anInterest){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"add:",{anInterest:anInterest},$globals.Axon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anInterest"],
-source: "add: anInterest\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.Axon);
-
-$core.addMethod(
-$core.method({
-selector: "addInterest:",
-protocol: "accessing",
-fn: function (anInterest){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-var $1;
-$recv(anInterest)._flag();
-$1=$recv(anInterest)._yourself();
-$self._add_($1);
-$self._dirty_(true);
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"addInterest:",{anInterest:anInterest},$globals.Axon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anInterest"],
-source: "addInterest: anInterest\x0a\x09self\x0a\x09\x09add: (anInterest flag; yourself);\x0a\x09\x09dirty: true",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["add:", "flag", "yourself", "dirty:"]
-}),
-$globals.Axon);
-
-$core.addMethod(
-$core.method({
-selector: "changed:",
-protocol: "change-update",
-fn: function (anAspect){
-var self=this,$self=this;
-var needsToRun;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-var $1;
-needsToRun=false;
-$self._do_((function(each){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-$1=$recv(each)._accepts_(anAspect);
-if($core.assert($1)){
-$recv(each)._flag();
-needsToRun=true;
-return needsToRun;
-}
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-$self._dirty_(needsToRun);
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"changed:",{anAspect:anAspect,needsToRun:needsToRun},$globals.Axon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anAspect"],
-source: "changed: anAspect\x0a\x09| needsToRun |\x0a\x09needsToRun := false.\x0a\x09self do: [ :each |\x0a\x09\x09(each accepts: anAspect) ifTrue: [\x0a\x09\x09\x09each flag.\x0a\x09\x09\x09needsToRun := true ]].\x0a\x09self dirty: needsToRun",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["do:", "ifTrue:", "accepts:", "flag", "dirty:"]
-}),
-$globals.Axon);
-
-$core.addMethod(
-$core.method({
-selector: "changedAll",
-protocol: "change-update",
-fn: function (){
-var self=this,$self=this;
-var needsToRun;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-needsToRun=false;
-$self._do_((function(each){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-$recv(each)._flag();
-needsToRun=true;
-return needsToRun;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-$self._dirty_(needsToRun);
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"changedAll",{needsToRun:needsToRun},$globals.Axon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "changedAll\x0a\x09| needsToRun |\x0a\x09needsToRun := false.\x0a\x09self do: [ :each |\x0a\x09\x09each flag.\x0a\x09\x09needsToRun := true ].\x0a\x09self dirty: needsToRun",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["do:", "flag", "dirty:"]
-}),
-$globals.Axon);
-
-$core.addMethod(
-$core.method({
-selector: "clean",
-protocol: "primitive ops",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"clean",{},$globals.Axon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "clean\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.Axon);
-
-$core.addMethod(
-$core.method({
-selector: "dirty:",
-protocol: "private",
-fn: function (aBoolean){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-if($core.assert(aBoolean)){
-$recv((function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $self._run();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)});
-//>>excludeEnd("ctx");
-}))._fork();
-}
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"dirty:",{aBoolean:aBoolean},$globals.Axon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBoolean"],
-source: "dirty: aBoolean\x0a\x09aBoolean ifTrue: [[ self run ] fork]",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["ifTrue:", "fork", "run"]
-}),
-$globals.Axon);
-
-$core.addMethod(
-$core.method({
-selector: "do:",
-protocol: "primitive ops",
-fn: function (aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"do:",{aBlock:aBlock},$globals.Axon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBlock"],
-source: "do: aBlock\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.Axon);
-
-$core.addMethod(
-$core.method({
-selector: "run",
-protocol: "private",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-var $1,$2,$3;
-$recv((function(){
-var needsClean;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-needsClean=false;
-needsClean;
-$self._do_((function(each){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx3) {
-//>>excludeEnd("ctx");
-$1=$recv(each)._isFlagged();
-if($core.assert($1)){
-$recv(each)._run();
-}
-$2=$recv(each)._isClosed();
-if($core.assert($2)){
-needsClean=true;
-return needsClean;
-}
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx3) {$ctx3.fillBlock({each:each},$ctx2,2)});
-//>>excludeEnd("ctx");
-}));
-$3=needsClean;
-if($core.assert($3)){
-return $self._clean();
-}
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({needsClean:needsClean},$ctx1,1)});
-//>>excludeEnd("ctx");
-}))._on_do_($globals.Error,(function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $self._dirty_(true);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,6)});
-//>>excludeEnd("ctx");
-}));
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"run",{},$globals.Axon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "run\x0a\x09[\x0a\x09\x09| needsClean |\x0a\x09    needsClean := false.\x0a\x09\x09self do: [ :each |\x0a\x09\x09\x09each isFlagged ifTrue: [ each run ].\x0a\x09        each isClosed ifTrue: [ needsClean := true ]\x0a\x09\x09].\x0a    \x09needsClean ifTrue: [ self clean ]\x0a\x09] on: Error do: [ self dirty: true ]",
-referencedClasses: ["Error"],
-//>>excludeEnd("ide");
-messageSends: ["on:do:", "do:", "ifTrue:", "isFlagged", "run", "isClosed", "clean", "dirty:"]
-}),
-$globals.Axon);
-
-
-
-$core.addClass("SimpleAxon", $globals.Axon, ["queue"], "Axxord");
-$core.addMethod(
-$core.method({
-selector: "add:",
-protocol: "primitive ops",
-fn: function (aSubscription){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$recv($self["@queue"])._add_(aSubscription);
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"add:",{aSubscription:aSubscription},$globals.SimpleAxon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aSubscription"],
-source: "add: aSubscription\x0a\x09queue add: aSubscription.",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["add:"]
-}),
-$globals.SimpleAxon);
-
-$core.addMethod(
-$core.method({
-selector: "clean",
-protocol: "primitive ops",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self["@queue"]=$recv($self["@queue"])._reject_((function(each){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $recv(each)._isClosed();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"clean",{},$globals.SimpleAxon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "clean\x0a\x09queue := queue reject: [ :each | each isClosed ]",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["reject:", "isClosed"]
-}),
-$globals.SimpleAxon);
-
-$core.addMethod(
-$core.method({
-selector: "do:",
-protocol: "primitive ops",
-fn: function (aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$recv($self["@queue"])._do_(aBlock);
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"do:",{aBlock:aBlock},$globals.SimpleAxon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBlock"],
-source: "do: aBlock\x0a\x09queue do: aBlock",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["do:"]
-}),
-$globals.SimpleAxon);
-
-$core.addMethod(
-$core.method({
-selector: "initialize",
-protocol: "initialization",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-(
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.supercall = true,
-//>>excludeEnd("ctx");
-($globals.SimpleAxon.superclass||$boot.nilAsClass).fn.prototype._initialize.apply($self, []));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.supercall = false;
-//>>excludeEnd("ctx");;
-$self["@queue"]=$recv($globals.OrderedCollection)._new();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.SimpleAxon)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "initialize\x0a    super initialize.\x0a\x09queue := OrderedCollection new",
-referencedClasses: ["OrderedCollection"],
-//>>excludeEnd("ide");
-messageSends: ["initialize", "new"]
-}),
-$globals.SimpleAxon);
-
-
-
-$core.addClass("AxonInterest", $globals.Object, ["flagged"], "Axxord");
-$core.addMethod(
-$core.method({
-selector: "accepts:",
-protocol: "testing",
-fn: function (anAspect){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"accepts:",{anAspect:anAspect},$globals.AxonInterest)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anAspect"],
-source: "accepts: anAspect\x0a    \x22Should return true if change for anAspect is relevant for this AxonInterest\x22\x0a    self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.AxonInterest);
-
-$core.addMethod(
-$core.method({
-selector: "close",
-protocol: "action",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"close",{},$globals.AxonInterest)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "close\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.AxonInterest);
-
-$core.addMethod(
-$core.method({
-selector: "enact",
-protocol: "action",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"enact",{},$globals.AxonInterest)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "enact\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.AxonInterest);
-
-$core.addMethod(
-$core.method({
-selector: "flag",
-protocol: "accessing",
-fn: function (){
-var self=this,$self=this;
-$self["@flagged"]=true;
-return self;
-
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "flag\x0a\x09flagged := true",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.AxonInterest);
-
-$core.addMethod(
-$core.method({
-selector: "initialize",
-protocol: "initialization",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-(
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.supercall = true,
-//>>excludeEnd("ctx");
-($globals.AxonInterest.superclass||$boot.nilAsClass).fn.prototype._initialize.apply($self, []));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.supercall = false;
-//>>excludeEnd("ctx");;
-$self["@flagged"]=false;
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.AxonInterest)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "initialize\x0a\x09super initialize.\x0a    flagged := false.",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["initialize"]
-}),
-$globals.AxonInterest);
-
-$core.addMethod(
-$core.method({
-selector: "isClosed",
-protocol: "testing",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"isClosed",{},$globals.AxonInterest)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "isClosed\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.AxonInterest);
-
-$core.addMethod(
-$core.method({
-selector: "isFlagged",
-protocol: "testing",
-fn: function (){
-var self=this,$self=this;
-return $self["@flagged"];
-
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "isFlagged\x0a\x09^flagged",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.AxonInterest);
-
-$core.addMethod(
-$core.method({
-selector: "run",
-protocol: "action",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$recv((function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-$self["@flagged"]=false;
-$self["@flagged"];
-return $self._enact();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
-//>>excludeEnd("ctx");
-}))._on_do_($globals.AxonOff,(function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $self._close();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)});
-//>>excludeEnd("ctx");
-}));
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"run",{},$globals.AxonInterest)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "run\x0a\x09[ flagged := false. self enact ]\x0a    on: AxonOff do: [ self close ]",
-referencedClasses: ["AxonOff"],
-//>>excludeEnd("ide");
-messageSends: ["on:do:", "enact", "close"]
-}),
-$globals.AxonInterest);
-
-
-
-$core.addClass("PluggableInterest", $globals.AxonInterest, ["acceptBlock", "enactBlock"], "Axxord");
-$core.addMethod(
-$core.method({
-selector: "accept:enact:",
-protocol: "accessing",
-fn: function (aBlock,anotherBlock){
-var self=this,$self=this;
-$self["@acceptBlock"]=aBlock;
-$self["@enactBlock"]=anotherBlock;
-return self;
-
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBlock", "anotherBlock"],
-source: "accept: aBlock enact: anotherBlock\x0a\x09acceptBlock := aBlock.\x0a    enactBlock := anotherBlock",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.PluggableInterest);
-
-$core.addMethod(
-$core.method({
-selector: "accepts:",
-protocol: "testing",
-fn: function (anAspect){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $recv($self["@acceptBlock"])._value_(anAspect);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"accepts:",{anAspect:anAspect},$globals.PluggableInterest)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anAspect"],
-source: "accepts: anAspect\x0a    ^ acceptBlock value: anAspect",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["value:"]
-}),
-$globals.PluggableInterest);
-
-$core.addMethod(
-$core.method({
-selector: "close",
-protocol: "action",
-fn: function (){
-var self=this,$self=this;
-$self["@acceptBlock"]=nil;
-$self["@enactBlock"]=nil;
-return self;
-
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "close\x0a\x09acceptBlock := nil.\x0a\x09enactBlock := nil",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.PluggableInterest);
-
-$core.addMethod(
-$core.method({
-selector: "enact",
-protocol: "action",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$recv($self["@enactBlock"])._value();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"enact",{},$globals.PluggableInterest)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "enact\x0a\x09enactBlock value",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["value"]
-}),
-$globals.PluggableInterest);
-
-$core.addMethod(
-$core.method({
-selector: "initialize",
-protocol: "initialization",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-(
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.supercall = true,
-//>>excludeEnd("ctx");
-($globals.PluggableInterest.superclass||$boot.nilAsClass).fn.prototype._initialize.apply($self, []));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.supercall = false;
-//>>excludeEnd("ctx");;
-$self._close();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.PluggableInterest)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "initialize\x0a\x09super initialize.\x0a    self close",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["initialize", "close"]
-}),
-$globals.PluggableInterest);
-
-$core.addMethod(
-$core.method({
-selector: "isClosed",
-protocol: "testing",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $recv($self["@acceptBlock"])._isNil();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"isClosed",{},$globals.PluggableInterest)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "isClosed\x0a\x09^ acceptBlock isNil",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["isNil"]
-}),
-$globals.PluggableInterest);
-
-
-
-$core.addClass("AxonOff", $globals.Error, [], "Axxord");
-//>>excludeStart("ide", pragmas.excludeIdeData);
-$globals.AxonOff.comment="Signal me from the subscription block to unsubscribe it.";
-//>>excludeEnd("ide");
-
 $core.addMethod(
 $core.method({
 selector: "asAxisIn:ifAbsent:",

+ 1 - 193
src/Axxord.st

@@ -1,4 +1,5 @@
 Smalltalk createPackage: 'Axxord'!
+(Smalltalk packageAt: 'Axxord') imports: {'axxord/Axxord-Axon'}!
 Object subclass: #Axes
 	instanceVariableNames: ''
 	package: 'Axxord'!
@@ -104,199 +105,6 @@ on: anObject
 ^self new root: anObject
 ! !
 
-Object subclass: #Axon
-	instanceVariableNames: 'factory'
-	package: 'Axxord'!
-!Axon commentStamp!
-I represent a pub-sub based on a key (called 'aspect').
-I manage aspect-block subscriptions (called 'interests') as well as run blocks of dirtied interests.
-The interest objects are responsible of decision if the change of an aspect is relevant for them.
-Interest object must be subclasses of `AxonInterest`.
-
-My subclasses must provide implementation for:
-
- - add:
- - do:
- - clean!
-
-!Axon methodsFor: 'accessing'!
-
-addInterest: anInterest
-	self
-		add: (anInterest flag; yourself);
-		dirty: true
-! !
-
-!Axon methodsFor: 'change-update'!
-
-changed: anAspect
-	| needsToRun |
-	needsToRun := false.
-	self do: [ :each |
-		(each accepts: anAspect) ifTrue: [
-			each flag.
-			needsToRun := true ]].
-	self dirty: needsToRun
-!
-
-changedAll
-	| needsToRun |
-	needsToRun := false.
-	self do: [ :each |
-		each flag.
-		needsToRun := true ].
-	self dirty: needsToRun
-! !
-
-!Axon methodsFor: 'primitive ops'!
-
-add: anInterest
-	self subclassResponsibility
-!
-
-clean
-	self subclassResponsibility
-!
-
-do: aBlock
-	self subclassResponsibility
-! !
-
-!Axon methodsFor: 'private'!
-
-dirty: aBoolean
-	aBoolean ifTrue: [[ self run ] fork]
-!
-
-run
-	[
-		| needsClean |
-	    needsClean := false.
-		self do: [ :each |
-			each isFlagged ifTrue: [ each run ].
-	        each isClosed ifTrue: [ needsClean := true ]
-		].
-    	needsClean ifTrue: [ self clean ]
-	] on: Error do: [ self dirty: true ]
-! !
-
-Axon subclass: #SimpleAxon
-	instanceVariableNames: 'queue'
-	package: 'Axxord'!
-
-!SimpleAxon methodsFor: 'initialization'!
-
-initialize
-    super initialize.
-	queue := OrderedCollection new
-! !
-
-!SimpleAxon methodsFor: 'primitive ops'!
-
-add: aSubscription
-	queue add: aSubscription.
-!
-
-clean
-	queue := queue reject: [ :each | each isClosed ]
-!
-
-do: aBlock
-	queue do: aBlock
-! !
-
-Object subclass: #AxonInterest
-	instanceVariableNames: 'flagged'
-	package: 'Axxord'!
-
-!AxonInterest methodsFor: 'accessing'!
-
-flag
-	flagged := true
-! !
-
-!AxonInterest methodsFor: 'action'!
-
-close
-	self subclassResponsibility
-!
-
-enact
-	self subclassResponsibility
-!
-
-run
-	[ flagged := false. self enact ]
-    on: AxonOff do: [ self close ]
-! !
-
-!AxonInterest methodsFor: 'initialization'!
-
-initialize
-	super initialize.
-    flagged := false.
-! !
-
-!AxonInterest methodsFor: 'testing'!
-
-accepts: anAspect
-    "Should return true if change for anAspect is relevant for this AxonInterest"
-    self subclassResponsibility
-!
-
-isClosed
-	self subclassResponsibility
-!
-
-isFlagged
-	^flagged
-! !
-
-AxonInterest subclass: #PluggableInterest
-	instanceVariableNames: 'acceptBlock enactBlock'
-	package: 'Axxord'!
-
-!PluggableInterest methodsFor: 'accessing'!
-
-accept: aBlock enact: anotherBlock
-	acceptBlock := aBlock.
-    enactBlock := anotherBlock
-! !
-
-!PluggableInterest methodsFor: 'action'!
-
-close
-	acceptBlock := nil.
-	enactBlock := nil
-!
-
-enact
-	enactBlock value
-! !
-
-!PluggableInterest methodsFor: 'initialization'!
-
-initialize
-	super initialize.
-    self close
-! !
-
-!PluggableInterest methodsFor: 'testing'!
-
-accepts: anAspect
-    ^ acceptBlock value: anAspect
-!
-
-isClosed
-	^ acceptBlock isNil
-! !
-
-Error subclass: #AxonOff
-	instanceVariableNames: ''
-	package: 'Axxord'!
-!AxonOff commentStamp!
-Signal me from the subscription block to unsubscribe it.!
-
 !Array methodsFor: '*Axxord'!
 
 asAxisIn: anObject ifAbsent: aBlock