|
@@ -6,10 +6,369 @@ $core.addPackage('Kernel-Dag');
|
|
|
$core.packages["Kernel-Dag"].innerEval = function (expr) { return eval(expr); };
|
|
|
$core.packages["Kernel-Dag"].transport = {"type":"amd","amdNamespace":"amber_core"};
|
|
|
|
|
|
+$core.addClass('AbstractDagVisitor', $globals.Object, [], 'Kernel-Dag');
|
|
|
+
|
|
|
+$globals.AbstractDagVisitor.comment="I am base class of `DagNode` visitor.\x0a\x0aConcrete classes should implement `visitDagNode:`,\x0athey can reuse possible variants of implementation\x0aoffered directly: `visitDagNodeVariantSimple:`\x0aand `visitDagNodeVariantRedux:`.";
|
|
|
+
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "visit:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+return $recv(aNode)._acceptDagVisitor_(self);
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"visit:",{aNode:aNode},$globals.AbstractDagVisitor)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aNode"],
|
|
|
+source: "visit: aNode\x0a\x09^ aNode acceptDagVisitor: self",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["acceptDagVisitor:"]
|
|
|
+}),
|
|
|
+$globals.AbstractDagVisitor);
|
|
|
+
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "visitAll:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aCollection){
|
|
|
+var self=this;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+return $recv(aCollection)._collect_((function(each){
|
|
|
+
|
|
|
+return $core.withContext(function($ctx2) {
|
|
|
+
|
|
|
+return self._visit_(each);
|
|
|
+
|
|
|
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
|
|
|
+
|
|
|
+}));
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"visitAll:",{aCollection:aCollection},$globals.AbstractDagVisitor)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aCollection"],
|
|
|
+source: "visitAll: aCollection\x0a\x09^ aCollection collect: [ :each | self visit: each ]",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["collect:", "visit:"]
|
|
|
+}),
|
|
|
+$globals.AbstractDagVisitor);
|
|
|
+
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "visitAllChildren:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aDagNode){
|
|
|
+var self=this;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+return self._visitAll_($recv(aDagNode)._dagChildren());
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"visitAllChildren:",{aDagNode:aDagNode},$globals.AbstractDagVisitor)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aDagNode"],
|
|
|
+source: "visitAllChildren: aDagNode\x0a\x09^ self visitAll: aDagNode dagChildren",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["visitAll:", "dagChildren"]
|
|
|
+}),
|
|
|
+$globals.AbstractDagVisitor);
|
|
|
+
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "visitDagNode:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+self._subclassResponsibility();
|
|
|
+return self;
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"visitDagNode:",{aNode:aNode},$globals.AbstractDagVisitor)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aNode"],
|
|
|
+source: "visitDagNode: aNode\x0a\x09self subclassResponsibility",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["subclassResponsibility"]
|
|
|
+}),
|
|
|
+$globals.AbstractDagVisitor);
|
|
|
+
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "visitDagNodeVariantRedux:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+var newChildren,oldChildren;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+var $2,$3,$1,$4,$5;
|
|
|
+var $early={};
|
|
|
+try {
|
|
|
+oldChildren=$recv(aNode)._dagChildren();
|
|
|
+newChildren=self._visitAllChildren_(aNode);
|
|
|
+$2=$recv(oldChildren)._size();
|
|
|
+
|
|
|
+$ctx1.sendIdx["size"]=1;
|
|
|
+
|
|
|
+$3=$recv(newChildren)._size();
|
|
|
+
|
|
|
+$ctx1.sendIdx["size"]=2;
|
|
|
+
|
|
|
+$1=$recv($2).__eq($3);
|
|
|
+if($core.assert($1)){
|
|
|
+$recv((1)._to_($recv(oldChildren)._size()))._detect_ifNone_((function(i){
|
|
|
+
|
|
|
+return $core.withContext(function($ctx2) {
|
|
|
+
|
|
|
+$4=$recv(oldChildren)._at_(i);
|
|
|
+
|
|
|
+$ctx2.sendIdx["at:"]=1;
|
|
|
+
|
|
|
+return $recv($4).__tild_eq($recv(newChildren)._at_(i));
|
|
|
+
|
|
|
+}, function($ctx2) {$ctx2.fillBlock({i:i},$ctx1,2)});
|
|
|
+
|
|
|
+}),(function(){
|
|
|
+throw $early=[aNode];
|
|
|
+
|
|
|
+}));
|
|
|
+};
|
|
|
+$5=$recv(aNode)._copy();
|
|
|
+$recv($5)._dagChildren_(newChildren);
|
|
|
+return $recv($5)._yourself();
|
|
|
+}
|
|
|
+catch(e) {if(e===$early)return e[0]; throw e}
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"visitDagNodeVariantRedux:",{aNode:aNode,newChildren:newChildren,oldChildren:oldChildren},$globals.AbstractDagVisitor)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aNode"],
|
|
|
+source: "visitDagNodeVariantRedux: aNode\x0a\x09\x22Immutable-guarded implementation of visitDagNode:.\x0a\x09Visits all children and checks if there were changes.\x0a\x09If not, returns aNode.\x0a\x09If yes, returns copy of aNode with new children.\x22\x0a\x0a\x09| newChildren oldChildren |\x0a\x09oldChildren := aNode dagChildren.\x0a\x09newChildren := self visitAllChildren: aNode.\x0a\x09oldChildren size = newChildren size ifTrue: [\x0a\x09\x09(1 to: oldChildren size) detect: [ :i |\x0a\x09\x09\x09(oldChildren at: i) ~= (newChildren at: i)\x0a\x09\x09] ifNone: [ \x22no change\x22 ^ aNode ] ].\x0a\x09^ aNode copy dagChildren: newChildren; yourself",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["dagChildren", "visitAllChildren:", "ifTrue:", "=", "size", "detect:ifNone:", "to:", "~=", "at:", "dagChildren:", "copy", "yourself"]
|
|
|
+}),
|
|
|
+$globals.AbstractDagVisitor);
|
|
|
+
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "visitDagNodeVariantSimple:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+self._visitAllChildren_(aNode);
|
|
|
+return aNode;
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"visitDagNodeVariantSimple:",{aNode:aNode},$globals.AbstractDagVisitor)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aNode"],
|
|
|
+source: "visitDagNodeVariantSimple: aNode\x0a\x09\x22Simple implementation of visitDagNode:.\x0a\x09Visits children, then returns aNode\x22\x0a\x0a\x09self visitAllChildren: aNode.\x0a\x09^ aNode",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["visitAllChildren:"]
|
|
|
+}),
|
|
|
+$globals.AbstractDagVisitor);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+$core.addClass('PathDagVisitor', $globals.AbstractDagVisitor, ['path'], 'Kernel-Dag');
|
|
|
+
|
|
|
+$globals.PathDagVisitor.comment="I am base class of `DagNode` visitor.\x0a\x0aI hold the path of ancestors up to actual node\x0ain `self path`.";
|
|
|
+
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "initialize",
|
|
|
+protocol: 'initialization',
|
|
|
+fn: function (){
|
|
|
+var self=this;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+(
|
|
|
+
|
|
|
+$ctx1.supercall = true,
|
|
|
+
|
|
|
+($globals.PathDagVisitor.superclass||$boot.nilAsClass).fn.prototype._initialize.apply($recv(self), []));
|
|
|
+
|
|
|
+$ctx1.supercall = false;
|
|
|
+
|
|
|
+self["@path"]=[];
|
|
|
+return self;
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.PathDagVisitor)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: [],
|
|
|
+source: "initialize\x0a\x09super initialize.\x0a\x0a\x09path := #()",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["initialize"]
|
|
|
+}),
|
|
|
+$globals.PathDagVisitor);
|
|
|
+
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "path",
|
|
|
+protocol: 'accessing',
|
|
|
+fn: function (){
|
|
|
+var self=this;
|
|
|
+return self["@path"];
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: [],
|
|
|
+source: "path\x0a\x09^ path",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: []
|
|
|
+}),
|
|
|
+$globals.PathDagVisitor);
|
|
|
+
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "visit:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+var oldPath;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+var $1;
|
|
|
+var $early={};
|
|
|
+try {
|
|
|
+oldPath=self["@path"];
|
|
|
+self["@path"]=$recv(self["@path"]).__comma([aNode]);
|
|
|
+$recv((function(){
|
|
|
+
|
|
|
+return $core.withContext(function($ctx2) {
|
|
|
+
|
|
|
+$1=(
|
|
|
+
|
|
|
+$ctx2.supercall = true,
|
|
|
+
|
|
|
+($globals.PathDagVisitor.superclass||$boot.nilAsClass).fn.prototype._visit_.apply($recv(self), [aNode]));
|
|
|
+
|
|
|
+$ctx2.supercall = false;
|
|
|
+
|
|
|
+throw $early=[$1];
|
|
|
+
|
|
|
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
|
|
|
+
|
|
|
+}))._ensure_((function(){
|
|
|
+self["@path"]=oldPath;
|
|
|
+return self["@path"];
|
|
|
+
|
|
|
+}));
|
|
|
+return self;
|
|
|
+}
|
|
|
+catch(e) {if(e===$early)return e[0]; throw e}
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"visit:",{aNode:aNode,oldPath:oldPath},$globals.PathDagVisitor)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aNode"],
|
|
|
+source: "visit: aNode\x0a\x09| oldPath |\x0a\x09oldPath := path.\x0a\x09path := path, {aNode}.\x0a\x09[ ^ super visit: aNode ] ensure: [ path := oldPath ]",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: [",", "ensure:", "visit:"]
|
|
|
+}),
|
|
|
+$globals.PathDagVisitor);
|
|
|
+
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "visitDagNodeVariantRedux:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+var newNode;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+var $1;
|
|
|
+newNode=(
|
|
|
+
|
|
|
+$ctx1.supercall = true,
|
|
|
+
|
|
|
+($globals.PathDagVisitor.superclass||$boot.nilAsClass).fn.prototype._visitDagNodeVariantRedux_.apply($recv(self), [aNode]));
|
|
|
+
|
|
|
+$ctx1.supercall = false;
|
|
|
+
|
|
|
+$1=$recv(aNode).__eq_eq(newNode);
|
|
|
+if(!$core.assert($1)){
|
|
|
+$recv(self["@path"])._at_put_($recv(self["@path"])._size(),newNode);
|
|
|
+};
|
|
|
+return newNode;
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"visitDagNodeVariantRedux:",{aNode:aNode,newNode:newNode},$globals.PathDagVisitor)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aNode"],
|
|
|
+source: "visitDagNodeVariantRedux: aNode\x0a\x09| newNode |\x0a\x09newNode := super visitDagNodeVariantRedux: aNode.\x0a\x09aNode == newNode ifFalse: [ path at: path size put: newNode ].\x0a\x09^ newNode",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["visitDagNodeVariantRedux:", "ifFalse:", "==", "at:put:", "size"]
|
|
|
+}),
|
|
|
+$globals.PathDagVisitor);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
$core.addClass('DagNode', $globals.Object, [], 'Kernel-Dag');
|
|
|
|
|
|
$globals.DagNode.comment="I am the abstract root class of any directed acyclic graph.\x0a\x0aConcrete classes should implement `dagChildren` and `dagChildren:`\x0ato get / set direct successor nodes (aka child nodes / subnodes).";
|
|
|
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "acceptDagVisitor:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aVisitor){
|
|
|
+var self=this;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+return $recv(aVisitor)._visitDagNode_(self);
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"acceptDagVisitor:",{aVisitor:aVisitor},$globals.DagNode)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aVisitor"],
|
|
|
+source: "acceptDagVisitor: aVisitor\x0a\x09^ aVisitor visitDagNode: self",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["visitDagNode:"]
|
|
|
+}),
|
|
|
+$globals.DagNode);
|
|
|
+
|
|
|
$core.addMethod(
|
|
|
$core.method({
|
|
|
selector: "allDagChildren",
|