Split and rename route.js into trie.js, struct.js and special.js
This commit is contained in:
parent
062e4603af
commit
9c5f427366
|
@ -8,7 +8,7 @@ Source files in `src/`, from most general to most specific:
|
|||
- `util.js`: Functions `extend` and `kwApply`.
|
||||
- `randomid.js`: Generation of (cryptographically) random base64 strings.
|
||||
|
||||
- `route.js`: Implementation of dataspace trie structure.
|
||||
- `trie.js`: Implementation of dataspace trie structure.
|
||||
- `patch.js`: Implementation of patches over dataspace tries.
|
||||
- `mux.js`: Use of tries plus patches to build a (de)multiplexing routing structure.
|
||||
- `dataspace.js`: Implementation of core leaf actors and dataspaces.
|
||||
|
|
|
@ -122,7 +122,7 @@ var modifiedSourceActions = {
|
|||
var label = maybeLabel.numChildren === 1
|
||||
? maybeLabel.children[0].interval.contents
|
||||
: JSON.stringify(typeName.interval.contents);
|
||||
return 'var ' + typeName.asES5 + ' = Syndicate.Route.makeStructureConstructor(' +
|
||||
return 'var ' + typeName.asES5 + ' = Syndicate.Struct.makeStructureConstructor(' +
|
||||
label + ', ' + JSON.stringify(formals) + ');';
|
||||
},
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
var beep = Syndicate.Route.makeStructureConstructor('beep', ['counter']);
|
||||
var beep = Syndicate.Struct.makeStructureConstructor('beep', ['counter']);
|
||||
|
||||
var G;
|
||||
$(document).ready(function () {
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
// GUI
|
||||
|
||||
var Dataspace = Syndicate.Dataspace;
|
||||
var Route = Syndicate.Route;
|
||||
var Trie = Syndicate.Trie;
|
||||
var Patch = Syndicate.Patch;
|
||||
var __ = Syndicate.__;
|
||||
var _$ = Syndicate._$;
|
||||
|
||||
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
|
||||
var fieldContents = Route.makeStructureConstructor('fieldContents', ['text', 'pos']);
|
||||
var highlight = Route.makeStructureConstructor('highlight', ['state']);
|
||||
var fieldCommand = Route.makeStructureConstructor('fieldCommand', ['detail']);
|
||||
var fieldContents = Syndicate.Struct.makeStructureConstructor('fieldContents', ['text', 'pos']);
|
||||
var highlight = Syndicate.Struct.makeStructureConstructor('highlight', ['state']);
|
||||
var fieldCommand = Syndicate.Struct.makeStructureConstructor('fieldCommand', ['detail']);
|
||||
|
||||
function escapeText(text) {
|
||||
text = text.replace(/&/g, '&');
|
||||
|
@ -63,10 +63,10 @@ function spawnGui() {
|
|||
}
|
||||
break;
|
||||
case "stateChange":
|
||||
Route.projectObjects(e.patch.added, this.fieldContentsProjection).forEach(function (c) {
|
||||
Trie.projectObjects(e.patch.added, this.fieldContentsProjection).forEach(function (c) {
|
||||
self.field = c;
|
||||
});
|
||||
Route.projectObjects(e.patch.added, this.highlightProjection).forEach(function (c) {
|
||||
Trie.projectObjects(e.patch.added, this.highlightProjection).forEach(function (c) {
|
||||
self.highlight = c;
|
||||
});
|
||||
this.updateDisplay();
|
||||
|
@ -160,7 +160,7 @@ function spawnSearch() {
|
|||
this.search();
|
||||
}
|
||||
if (e.type === "stateChange") {
|
||||
Route.projectObjects(e.patch.added, this.fieldContentsProjection).forEach(function (c) {
|
||||
Trie.projectObjects(e.patch.added, this.fieldContentsProjection).forEach(function (c) {
|
||||
self.fieldValue = c.text;
|
||||
});
|
||||
this.search();
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
var RandomID = require('./randomid.js');
|
||||
var Dataspace = require('./dataspace.js').Dataspace;
|
||||
var Route = require('./route.js');
|
||||
var Struct = require('./struct.js');
|
||||
var Patch = require('./patch.js');
|
||||
|
||||
var ack = Route.makeStructureConstructor('ack', ['id']);
|
||||
var ack = Struct.makeStructureConstructor('ack', ['id']);
|
||||
|
||||
function Ack(metaLevel, id) {
|
||||
this.metaLevel = metaLevel || 0;
|
||||
|
|
|
@ -4,7 +4,7 @@ var Immutable = require('immutable');
|
|||
var Dataspace = require('./dataspace.js').Dataspace;
|
||||
var Mux = require('./mux.js');
|
||||
var Patch = require('./patch.js');
|
||||
var Route = require('./route.js');
|
||||
var Trie = require('./trie.js');
|
||||
var Util = require('./util.js');
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -79,7 +79,7 @@ Facet.prototype.onEvent = function(isTerminal, eventType, subscriptionFn, projec
|
|||
if (e.type === 'message') {
|
||||
var proj = projectionFn.call(facet.actor.state);
|
||||
var spec = Patch.prependAtMeta(proj.assertion, proj.metalevel);
|
||||
var match = Route.matchPattern(e.message, spec);
|
||||
var match = Trie.matchPattern(e.message, spec);
|
||||
// console.log(match);
|
||||
if (match) {
|
||||
if (isTerminal) { facet.terminate(); }
|
||||
|
@ -94,10 +94,10 @@ Facet.prototype.onEvent = function(isTerminal, eventType, subscriptionFn, projec
|
|||
if (e.type === 'stateChange') {
|
||||
var proj = projectionFn.call(facet.actor.state);
|
||||
var spec = Patch.prependAtMeta(proj.assertion, proj.metalevel);
|
||||
var objects = Route.projectObjects(eventType === 'asserted'
|
||||
? e.patch.added
|
||||
: e.patch.removed,
|
||||
spec);
|
||||
var objects = Trie.projectObjects(eventType === 'asserted'
|
||||
? e.patch.added
|
||||
: e.patch.removed,
|
||||
spec);
|
||||
if (objects && objects.size > 0) {
|
||||
// console.log(objects.toArray());
|
||||
if (isTerminal) { facet.terminate(); }
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
var Immutable = require('immutable');
|
||||
var Route = require('./route.js');
|
||||
var Patch = require('./patch.js');
|
||||
var Mux = require('./mux.js');
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
var Immutable = require('immutable');
|
||||
var Route = require('./route.js');
|
||||
var Trie = require('./trie.js');
|
||||
var Patch = require('./patch.js');
|
||||
var Util = require('./util.js');
|
||||
|
||||
|
@ -18,12 +18,12 @@ function DemandMatcher(demandSpec, supplySpec, options) {
|
|||
this.onSupplyDecrease = options.onSupplyDecrease;
|
||||
this.demandSpec = demandSpec;
|
||||
this.supplySpec = supplySpec;
|
||||
this.demandPattern = Route.projectionToPattern(demandSpec);
|
||||
this.supplyPattern = Route.projectionToPattern(supplySpec);
|
||||
this.demandPattern = Trie.projectionToPattern(demandSpec);
|
||||
this.supplyPattern = Trie.projectionToPattern(supplySpec);
|
||||
this.demandProjection = Patch.prependAtMeta(demandSpec, this.metaLevel);
|
||||
this.supplyProjection = Patch.prependAtMeta(supplySpec, this.metaLevel);
|
||||
this.demandProjectionNames = Route.projectionNames(this.demandProjection);
|
||||
this.supplyProjectionNames = Route.projectionNames(this.supplyProjection);
|
||||
this.demandProjectionNames = Trie.projectionNames(this.demandProjection);
|
||||
this.supplyProjectionNames = Trie.projectionNames(this.supplyProjection);
|
||||
this.currentDemand = Immutable.Set();
|
||||
this.currentSupply = Immutable.Set();
|
||||
}
|
||||
|
@ -44,10 +44,10 @@ DemandMatcher.prototype.handlePatch = function (p) {
|
|||
|
||||
var dN = self.demandProjectionNames.length;
|
||||
var sN = self.supplyProjectionNames.length;
|
||||
var addedDemand = Route.trieKeys(Route.project(p.added, self.demandProjection), dN);
|
||||
var removedDemand = Route.trieKeys(Route.project(p.removed, self.demandProjection), dN);
|
||||
var addedSupply = Route.trieKeys(Route.project(p.added, self.supplyProjection), sN);
|
||||
var removedSupply = Route.trieKeys(Route.project(p.removed, self.supplyProjection), sN);
|
||||
var addedDemand = Trie.trieKeys(Trie.project(p.added, self.demandProjection), dN);
|
||||
var removedDemand = Trie.trieKeys(Trie.project(p.removed, self.demandProjection), dN);
|
||||
var addedSupply = Trie.trieKeys(Trie.project(p.added, self.supplyProjection), sN);
|
||||
var removedSupply = Trie.trieKeys(Trie.project(p.removed, self.supplyProjection), sN);
|
||||
|
||||
if (addedDemand === null) {
|
||||
throw new Error("Syndicate: wildcard demand detected:\n" +
|
||||
|
@ -65,12 +65,12 @@ DemandMatcher.prototype.handlePatch = function (p) {
|
|||
|
||||
removedSupply.forEach(function (captures) {
|
||||
if (self.currentDemand.has(captures)) {
|
||||
self.onSupplyDecrease(Route.captureToObject(captures, self.supplyProjectionNames));
|
||||
self.onSupplyDecrease(Trie.captureToObject(captures, self.supplyProjectionNames));
|
||||
}
|
||||
});
|
||||
addedDemand.forEach(function (captures) {
|
||||
if (!self.currentSupply.has(captures)) {
|
||||
self.onDemandIncrease(Route.captureToObject(captures, self.demandProjectionNames));
|
||||
self.onDemandIncrease(Trie.captureToObject(captures, self.demandProjectionNames));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// DOM fragment display driver
|
||||
var Patch = require("./patch.js");
|
||||
var DemandMatcher = require('./demand-matcher.js').DemandMatcher;
|
||||
var Route = require('./route.js');
|
||||
var Struct = require('./struct.js');
|
||||
var Ack = require('./ack.js').Ack;
|
||||
var Seal = require('./seal.js').Seal;
|
||||
|
||||
|
@ -10,7 +10,7 @@ var Dataspace = Dataspace_.Dataspace;
|
|||
var __ = Dataspace_.__;
|
||||
var _$ = Dataspace_._$;
|
||||
|
||||
var DOM = Route.makeStructureConstructor('DOM', ['selector', 'fragmentClass', 'fragmentSpec']);
|
||||
var DOM = Struct.makeStructureConstructor('DOM', ['selector', 'fragmentClass', 'fragmentSpec']);
|
||||
|
||||
function spawnDOMDriver(domWrapFunction, jQueryWrapFunction) {
|
||||
domWrapFunction = domWrapFunction || DOM;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// JQuery event driver
|
||||
var Patch = require("./patch.js");
|
||||
var DemandMatcher = require('./demand-matcher.js').DemandMatcher;
|
||||
var Route = require('./route.js');
|
||||
var Struct = require('./struct.js');
|
||||
|
||||
var Dataspace_ = require("./dataspace.js");
|
||||
var Dataspace = Dataspace_.Dataspace;
|
||||
var __ = Dataspace_.__;
|
||||
var _$ = Dataspace_._$;
|
||||
|
||||
var jQueryEvent = Route.makeStructureConstructor('jQueryEvent', ['selector', 'eventName', 'eventValue']);
|
||||
var jQueryEvent = Struct.makeStructureConstructor('jQueryEvent', ['selector', 'eventName', 'eventValue']);
|
||||
|
||||
function spawnJQueryDriver(baseSelector, metaLevel, wrapFunction) {
|
||||
metaLevel = metaLevel || 0;
|
||||
|
|
|
@ -8,14 +8,15 @@ function copyKeys(keys, to, from) {
|
|||
|
||||
module.exports = require("./dataspace.js");
|
||||
|
||||
module.exports.Route = require("./route.js");
|
||||
module.exports.Trie = require("./trie.js");
|
||||
copyKeys(['__', '_$', '$Capture', '$Special',
|
||||
'is_emptyTrie', 'emptyTrie',
|
||||
'embeddedTrie', 'compilePattern',
|
||||
'project', 'projectObjects',
|
||||
'prettyTrie'],
|
||||
module.exports,
|
||||
module.exports.Route);
|
||||
module.exports.Trie);
|
||||
module.exports.Struct = require('./struct.js');
|
||||
|
||||
var Seal = require('./seal.js')
|
||||
copyKeys(['Seal', 'seal'],
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
"use strict";
|
||||
|
||||
var Immutable = require('immutable');
|
||||
var Route = require('./route.js');
|
||||
var Trie = require('./trie.js');
|
||||
var Patch = require('./patch.js');
|
||||
|
||||
function Mux(nextPid, routingTable, interestTable) {
|
||||
this.nextPid = nextPid || 0;
|
||||
this.routingTable = routingTable || Route.emptyTrie;
|
||||
this.routingTable = routingTable || Trie.emptyTrie;
|
||||
this.interestTable = interestTable || Immutable.Map(); // pid -> Trie
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ Mux.prototype.updateStream = function (pid, unclampedPatch) {
|
|||
|
||||
this.routingTable = newRoutingTable;
|
||||
|
||||
if (Route.is_emptyTrie(newInterests)) {
|
||||
if (Trie.is_emptyTrie(newInterests)) {
|
||||
this.interestTable = this.interestTable.remove(pid);
|
||||
} else {
|
||||
this.interestTable = this.interestTable.set(pid, newInterests);
|
||||
|
@ -44,13 +44,13 @@ Mux.prototype.updateStream = function (pid, unclampedPatch) {
|
|||
deltaAggregate: deltaAggregate };
|
||||
};
|
||||
|
||||
var atMetaEverything = Route.compilePattern(true, Patch.atMeta(Route.__));
|
||||
var atMetaEverything = Trie.compilePattern(true, Patch.atMeta(Trie.__));
|
||||
var atMetaBranchKeys = Immutable.List([[Patch.atMeta.meta.arguments.length, Patch.atMeta.meta]]);
|
||||
var onlyMeta = Route.trieSuccess(Immutable.Set.of("meta"));
|
||||
var onlyMeta = Trie.trieSuccess(Immutable.Set.of("meta"));
|
||||
|
||||
function echoCancelledTrie(t) {
|
||||
return Route.subtract(t, atMetaEverything, function (v1, v2) {
|
||||
return v1.has("meta") ? onlyMeta : Route.emptyTrie;
|
||||
return Trie.subtract(t, atMetaEverything, function (v1, v2) {
|
||||
return v1.has("meta") ? onlyMeta : Trie.emptyTrie;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -60,8 +60,8 @@ function computeEvents(oldMux, newMux, updateStreamResult) {
|
|||
var deltaAggregate = updateStreamResult.deltaAggregate;
|
||||
var deltaAggregateNoEcho = (actingPid === "meta")
|
||||
? delta // because echo-cancellation means that meta-SCNs are always new information
|
||||
: new Patch.Patch(Route.triePruneBranch(deltaAggregate.added, atMetaBranchKeys),
|
||||
Route.triePruneBranch(deltaAggregate.removed, atMetaBranchKeys));
|
||||
: new Patch.Patch(Trie.triePruneBranch(deltaAggregate.added, atMetaBranchKeys),
|
||||
Trie.triePruneBranch(deltaAggregate.removed, atMetaBranchKeys));
|
||||
var oldRoutingTable = oldMux.routingTable;
|
||||
var newRoutingTable = newMux.routingTable;
|
||||
var affectedPids =
|
||||
|
@ -94,16 +94,16 @@ function computeEvents(oldMux, newMux, updateStreamResult) {
|
|||
}
|
||||
|
||||
function computeAffectedPids(routingTable, delta) {
|
||||
var cover = Route._union(delta.added, delta.removed);
|
||||
var cover = Trie._union(delta.added, delta.removed);
|
||||
routingTable =
|
||||
Route.trieStep(routingTable, Patch.observe.meta.arguments.length, Patch.observe.meta);
|
||||
return Route.matchTrie(cover, routingTable, Immutable.Set(),
|
||||
function (v1, v2, acc) { return acc.union(v2); });
|
||||
Trie.trieStep(routingTable, Patch.observe.meta.arguments.length, Patch.observe.meta);
|
||||
return Trie.matchTrie(cover, routingTable, Immutable.Set(),
|
||||
function (v1, v2, acc) { return acc.union(v2); });
|
||||
}
|
||||
|
||||
Mux.prototype.routeMessage = function (body) {
|
||||
if (Route.matchValue(this.routingTable, body) === null) {
|
||||
return Route.matchValue(this.routingTable, Patch.observe(body)) || Immutable.Set();
|
||||
if (Trie.matchValue(this.routingTable, body) === null) {
|
||||
return Trie.matchValue(this.routingTable, Patch.observe(body)) || Immutable.Set();
|
||||
} else {
|
||||
// Some other stream has declared body
|
||||
return Immutable.Set();
|
||||
|
@ -111,7 +111,7 @@ Mux.prototype.routeMessage = function (body) {
|
|||
};
|
||||
|
||||
Mux.prototype.interestsOf = function (pid) {
|
||||
return this.interestTable.get(pid, Route.emptyTrie);
|
||||
return this.interestTable.get(pid, Trie.emptyTrie);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
129
js/src/patch.js
129
js/src/patch.js
|
@ -1,23 +1,24 @@
|
|||
"use strict";
|
||||
|
||||
var Route = require("./route.js");
|
||||
var Trie = require("./trie.js");
|
||||
var Struct = require("./struct.js");
|
||||
var Immutable = require("immutable");
|
||||
|
||||
var __ = Route.__;
|
||||
var _$ = Route._$;
|
||||
var __ = Trie.__;
|
||||
var _$ = Trie._$;
|
||||
|
||||
function Patch(added, removed) {
|
||||
this.added = added;
|
||||
this.removed = removed;
|
||||
}
|
||||
|
||||
var emptyPatch = new Patch(Route.emptyTrie, Route.emptyTrie);
|
||||
var removeEverythingPatch = new Patch(Route.emptyTrie, Route.compilePattern(true, __));
|
||||
var trueLabel = Route.trieSuccess(true);
|
||||
var emptyPatch = new Patch(Trie.emptyTrie, Trie.emptyTrie);
|
||||
var removeEverythingPatch = new Patch(Trie.emptyTrie, Trie.compilePattern(true, __));
|
||||
var trueLabel = Trie.trieSuccess(true);
|
||||
|
||||
var observe = Route.makeStructureConstructor('observe', ['assertion']);
|
||||
var atMeta = Route.makeStructureConstructor('atMeta', ['assertion']);
|
||||
var advertise = Route.makeStructureConstructor('advertise', ['assertion']);
|
||||
var observe = Struct.makeStructureConstructor('observe', ['assertion']);
|
||||
var atMeta = Struct.makeStructureConstructor('atMeta', ['assertion']);
|
||||
var advertise = Struct.makeStructureConstructor('advertise', ['assertion']);
|
||||
|
||||
function prependAtMeta(p, level) {
|
||||
while (level--) {
|
||||
|
@ -39,11 +40,11 @@ function stripAtMeta(p, level) {
|
|||
|
||||
function observeAtMeta(p, level) {
|
||||
if (level === 0) {
|
||||
return Route.compilePattern(true, observe(p));
|
||||
return Trie.compilePattern(true, observe(p));
|
||||
} else {
|
||||
return Route._union(
|
||||
Route.compilePattern(true, observe(prependAtMeta(p, level))),
|
||||
Route.compilePattern(true, atMeta(Route.embeddedTrie(observeAtMeta(p, level - 1)))));
|
||||
return Trie._union(
|
||||
Trie.compilePattern(true, observe(prependAtMeta(p, level))),
|
||||
Trie.compilePattern(true, atMeta(Trie.embeddedTrie(observeAtMeta(p, level - 1)))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,21 +56,21 @@ function _check(p) {
|
|||
}
|
||||
|
||||
function assert(p, metaLevel) {
|
||||
return new Patch(Route.compilePattern(true, prependAtMeta(_check(p), metaLevel || 0)),
|
||||
Route.emptyTrie);
|
||||
return new Patch(Trie.compilePattern(true, prependAtMeta(_check(p), metaLevel || 0)),
|
||||
Trie.emptyTrie);
|
||||
}
|
||||
|
||||
function retract(p, metaLevel) {
|
||||
return new Patch(Route.emptyTrie,
|
||||
Route.compilePattern(true, prependAtMeta(_check(p), metaLevel || 0)));
|
||||
return new Patch(Trie.emptyTrie,
|
||||
Trie.compilePattern(true, prependAtMeta(_check(p), metaLevel || 0)));
|
||||
}
|
||||
|
||||
function sub(p, metaLevel) {
|
||||
return new Patch(observeAtMeta(_check(p), metaLevel || 0), Route.emptyTrie);
|
||||
return new Patch(observeAtMeta(_check(p), metaLevel || 0), Trie.emptyTrie);
|
||||
}
|
||||
|
||||
function unsub(p, metaLevel) {
|
||||
return new Patch(Route.emptyTrie, observeAtMeta(_check(p), metaLevel || 0));
|
||||
return new Patch(Trie.emptyTrie, observeAtMeta(_check(p), metaLevel || 0));
|
||||
}
|
||||
|
||||
function pub(p, metaLevel) {
|
||||
|
@ -88,7 +89,7 @@ Patch.prototype.equals = function (other) {
|
|||
};
|
||||
|
||||
Patch.prototype.isEmpty = function () {
|
||||
return this.added === Route.emptyTrie && this.removed === Route.emptyTrie;
|
||||
return this.added === Trie.emptyTrie && this.removed === Trie.emptyTrie;
|
||||
};
|
||||
|
||||
Patch.prototype.isNonEmpty = function () {
|
||||
|
@ -96,89 +97,89 @@ Patch.prototype.isNonEmpty = function () {
|
|||
};
|
||||
|
||||
Patch.prototype.hasAdded = function () {
|
||||
return this.added !== Route.emptyTrie;
|
||||
return this.added !== Trie.emptyTrie;
|
||||
};
|
||||
|
||||
Patch.prototype.hasRemoved = function () {
|
||||
return this.removed !== Route.emptyTrie;
|
||||
return this.removed !== Trie.emptyTrie;
|
||||
};
|
||||
|
||||
Patch.prototype.lift = function () {
|
||||
return new Patch(Route.compilePattern(true, atMeta(Route.embeddedTrie(this.added))),
|
||||
Route.compilePattern(true, atMeta(Route.embeddedTrie(this.removed))));
|
||||
return new Patch(Trie.compilePattern(true, atMeta(Trie.embeddedTrie(this.added))),
|
||||
Trie.compilePattern(true, atMeta(Trie.embeddedTrie(this.removed))));
|
||||
};
|
||||
|
||||
var atMetaProj = atMeta(_$);
|
||||
Patch.prototype.drop = function () {
|
||||
return new Patch(Route.project(this.added, atMetaProj),
|
||||
Route.project(this.removed, atMetaProj));
|
||||
return new Patch(Trie.project(this.added, atMetaProj),
|
||||
Trie.project(this.removed, atMetaProj));
|
||||
};
|
||||
|
||||
Patch.prototype.strip = function () {
|
||||
return new Patch(Route.relabel(this.added, function (v) { return true; }),
|
||||
Route.relabel(this.removed, function (v) { return true; }));
|
||||
return new Patch(Trie.relabel(this.added, function (v) { return true; }),
|
||||
Trie.relabel(this.removed, function (v) { return true; }));
|
||||
};
|
||||
|
||||
Patch.prototype.label = function (labelValue) {
|
||||
return new Patch(Route.relabel(this.added, function (v) { return labelValue; }),
|
||||
Route.relabel(this.removed, function (v) { return labelValue; }));
|
||||
return new Patch(Trie.relabel(this.added, function (v) { return labelValue; }),
|
||||
Trie.relabel(this.removed, function (v) { return labelValue; }));
|
||||
};
|
||||
|
||||
Patch.prototype.limit = function (bound) {
|
||||
return new Patch(Route.subtract(this.added, bound, function (v1, v2) { return Route.emptyTrie; }),
|
||||
Route.intersect(this.removed, bound,
|
||||
function (v1, v2) { return Route.trieSuccess(v1); }));
|
||||
return new Patch(Trie.subtract(this.added, bound, function (v1, v2) { return Trie.emptyTrie; }),
|
||||
Trie.intersect(this.removed, bound,
|
||||
function (v1, v2) { return Trie.trieSuccess(v1); }));
|
||||
};
|
||||
|
||||
var metaLabelSet = Immutable.Set(["meta"]);
|
||||
Patch.prototype.computeAggregate = function (label, base, removeMeta /* optional flag */) {
|
||||
return new Patch(Route.subtract(this.added, base, addCombiner),
|
||||
Route.subtract(this.removed, base, removeCombiner));
|
||||
return new Patch(Trie.subtract(this.added, base, addCombiner),
|
||||
Trie.subtract(this.removed, base, removeCombiner));
|
||||
|
||||
function addCombiner(v1, v2) {
|
||||
if (removeMeta && Immutable.is(v2, metaLabelSet)) {
|
||||
return Route.trieSuccess(v1);
|
||||
return Trie.trieSuccess(v1);
|
||||
} else {
|
||||
return Route.emptyTrie;
|
||||
return Trie.emptyTrie;
|
||||
}
|
||||
}
|
||||
|
||||
function removeCombiner(v1, v2) {
|
||||
if (v2.size === 1) {
|
||||
return Route.trieSuccess(v1);
|
||||
return Trie.trieSuccess(v1);
|
||||
} else {
|
||||
if (removeMeta && v2.size === 2 && v2.has("meta")) {
|
||||
return Route.trieSuccess(v1);
|
||||
return Trie.trieSuccess(v1);
|
||||
} else {
|
||||
return Route.emptyTrie;
|
||||
return Trie.emptyTrie;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Patch.prototype.applyTo = function (base) {
|
||||
return Route._union(Route.subtract(base, this.removed), this.added);
|
||||
return Trie._union(Trie.subtract(base, this.removed), this.added);
|
||||
};
|
||||
|
||||
Patch.prototype.updateInterests = function (base) {
|
||||
return Route._union(Route.subtract(base,
|
||||
this.removed,
|
||||
function (v1, v2) { return Route.emptyTrie; }),
|
||||
this.added,
|
||||
function (v1, v2) { return trueLabel; });
|
||||
return Trie._union(Trie.subtract(base,
|
||||
this.removed,
|
||||
function (v1, v2) { return Trie.emptyTrie; }),
|
||||
this.added,
|
||||
function (v1, v2) { return trueLabel; });
|
||||
};
|
||||
|
||||
Patch.prototype.unapplyTo = function (base) {
|
||||
return Route._union(Route.subtract(base, this.added), this.removed);
|
||||
return Trie._union(Trie.subtract(base, this.added), this.removed);
|
||||
};
|
||||
|
||||
Patch.prototype.andThen = function (nextPatch) {
|
||||
return new Patch(nextPatch.updateInterests(this.added),
|
||||
Route._union(Route.subtract(this.removed,
|
||||
nextPatch.added,
|
||||
function (v1, v2) { return Route.emptyTrie; }),
|
||||
nextPatch.removed,
|
||||
function (v1, v2) { return trueLabel; }));
|
||||
Trie._union(Trie.subtract(this.removed,
|
||||
nextPatch.added,
|
||||
function (v1, v2) { return Trie.emptyTrie; }),
|
||||
nextPatch.removed,
|
||||
function (v1, v2) { return trueLabel; }));
|
||||
};
|
||||
|
||||
function patchSeq(/* patch, patch, ... */) {
|
||||
|
@ -190,13 +191,13 @@ function patchSeq(/* patch, patch, ... */) {
|
|||
}
|
||||
|
||||
function computePatch(oldBase, newBase) {
|
||||
return new Patch(Route.subtract(newBase, oldBase),
|
||||
Route.subtract(oldBase, newBase));
|
||||
return new Patch(Trie.subtract(newBase, oldBase),
|
||||
Trie.subtract(oldBase, newBase));
|
||||
}
|
||||
|
||||
function biasedIntersection(object, subject) {
|
||||
subject = Route.trieStep(subject, observe.meta.arguments.length, observe.meta);
|
||||
return Route.intersect(object, subject, function (v1, v2) { return Route.trieSuccess(v1); });
|
||||
subject = Trie.trieStep(subject, observe.meta.arguments.length, observe.meta);
|
||||
return Trie.intersect(object, subject, function (v1, v2) { return Trie.trieSuccess(v1); });
|
||||
}
|
||||
|
||||
Patch.prototype.viewFrom = function (interests) {
|
||||
|
@ -207,23 +208,23 @@ Patch.prototype.viewFrom = function (interests) {
|
|||
Patch.prototype.unsafeUnion = function (other) {
|
||||
// Unsafe because does not necessarily preserve invariant that added
|
||||
// and removed are disjoint.
|
||||
return new Patch(Route._union(this.added, other.added),
|
||||
Route._union(this.removed, other.removed));
|
||||
return new Patch(Trie._union(this.added, other.added),
|
||||
Trie._union(this.removed, other.removed));
|
||||
};
|
||||
|
||||
Patch.prototype.project = function (compiledProjection) {
|
||||
return new Patch(Route.project(this.added, compiledProjection),
|
||||
Route.project(this.removed, compiledProjection));
|
||||
return new Patch(Trie.project(this.added, compiledProjection),
|
||||
Trie.project(this.removed, compiledProjection));
|
||||
};
|
||||
|
||||
Patch.prototype.projectObjects = function (compiledProjection) {
|
||||
return [Route.projectObjects(this.added, compiledProjection),
|
||||
Route.projectObjects(this.removed, compiledProjection)];
|
||||
return [Trie.projectObjects(this.added, compiledProjection),
|
||||
Trie.projectObjects(this.removed, compiledProjection)];
|
||||
};
|
||||
|
||||
Patch.prototype.pretty = function () {
|
||||
return ("<<<<<<<< Removed:\n" + Route.prettyTrie(this.removed) + "\n" +
|
||||
"======== Added:\n" + Route.prettyTrie(this.added) + "\n" +
|
||||
return ("<<<<<<<< Removed:\n" + Trie.prettyTrie(this.removed) + "\n" +
|
||||
"======== Added:\n" + Trie.prettyTrie(this.added) + "\n" +
|
||||
">>>>>>>>");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
"use strict";
|
||||
// $Special: Builder of singleton "atoms".
|
||||
|
||||
function $Special(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
module.exports = $Special;
|
|
@ -0,0 +1,60 @@
|
|||
"use strict";
|
||||
// "Structures": Simple named-tuple-like records.
|
||||
// TODO: shore up $SyndicateMeta$, making it a proper object
|
||||
|
||||
var Immutable = require("immutable");
|
||||
var $Special = require('./special.js');
|
||||
|
||||
/* Defined here rather than in trie.js because we need it in makeStructureConstructor. */
|
||||
var __ = new $Special("wildcard"); /* wildcard marker */
|
||||
|
||||
function instantiateStructure($SyndicateMeta$, argvals) {
|
||||
var result = {"$SyndicateMeta$": $SyndicateMeta$};
|
||||
var argnames = $SyndicateMeta$.arguments;
|
||||
for (var i = 0; i < argnames.length; i++) {
|
||||
result[argnames[i]] = argvals[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function makeStructureConstructor(label, argumentNames) {
|
||||
var $SyndicateMeta$ = {
|
||||
label: label,
|
||||
arguments: argumentNames
|
||||
};
|
||||
var ctor = function() {
|
||||
return instantiateStructure($SyndicateMeta$, arguments);
|
||||
};
|
||||
ctor.meta = $SyndicateMeta$;
|
||||
ctor.isClassOf = function (v) { return v && v.$SyndicateMeta$ === $SyndicateMeta$; };
|
||||
ctor.pattern = ctor.apply(null, Immutable.Repeat(__, argumentNames.length).toArray());
|
||||
return ctor;
|
||||
}
|
||||
|
||||
function isSyndicateMeta(m) {
|
||||
// TODO: include more structure in $SyndicateMeta$ objects to make
|
||||
// this judgement less sloppy.
|
||||
return m && m.label && Array.isArray(m.arguments);
|
||||
}
|
||||
|
||||
function isStructure(s) {
|
||||
return (s !== null) && (typeof s === 'object') && ("$SyndicateMeta$" in s);
|
||||
}
|
||||
|
||||
function structureToArray(s, excludeLabel) {
|
||||
var result = excludeLabel ? [] : [s.$SyndicateMeta$.label];
|
||||
var args = s.$SyndicateMeta$.arguments;
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
result.push(s[args[i]]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module.exports.__ = __;
|
||||
module.exports.instantiateStructure = instantiateStructure;
|
||||
module.exports.makeStructureConstructor = makeStructureConstructor;
|
||||
module.exports.isSyndicateMeta = isSyndicateMeta;
|
||||
module.exports.isStructure = isStructure;
|
||||
module.exports.structureToArray = structureToArray;
|
|
@ -1,62 +1,8 @@
|
|||
"use strict";
|
||||
|
||||
var Immutable = require("immutable");
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// "Structures": Simple named-tuple-like records.
|
||||
// TODO: shore up $SyndicateMeta$, making it a proper object
|
||||
|
||||
function instantiateStructure($SyndicateMeta$, argvals) {
|
||||
var result = {"$SyndicateMeta$": $SyndicateMeta$};
|
||||
var argnames = $SyndicateMeta$.arguments;
|
||||
for (var i = 0; i < argnames.length; i++) {
|
||||
result[argnames[i]] = argvals[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function makeStructureConstructor(label, argumentNames) {
|
||||
var $SyndicateMeta$ = {
|
||||
label: label,
|
||||
arguments: argumentNames
|
||||
};
|
||||
var ctor = function() {
|
||||
return instantiateStructure($SyndicateMeta$, arguments);
|
||||
};
|
||||
ctor.meta = $SyndicateMeta$;
|
||||
ctor.isClassOf = function (v) { return v && v.$SyndicateMeta$ === $SyndicateMeta$; };
|
||||
ctor.pattern = ctor.apply(null, Immutable.Repeat(__, argumentNames.length).toArray());
|
||||
return ctor;
|
||||
}
|
||||
|
||||
function isSyndicateMeta(m) {
|
||||
// TODO: include more structure in $SyndicateMeta$ objects to make
|
||||
// this judgement less sloppy.
|
||||
return m && m.label && Array.isArray(m.arguments);
|
||||
}
|
||||
|
||||
function isStructure(s) {
|
||||
return (s !== null) && (typeof s === 'object') && ("$SyndicateMeta$" in s);
|
||||
}
|
||||
|
||||
function structureToArray(s, excludeLabel) {
|
||||
var result = excludeLabel ? [] : [s.$SyndicateMeta$.label];
|
||||
var args = s.$SyndicateMeta$.arguments;
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
result.push(s[args[i]]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// $Special: Builder of singletons.
|
||||
|
||||
function $Special(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Misc. utilities
|
||||
var Struct = require('./struct.js');
|
||||
var $Special = require('./special.js');
|
||||
|
||||
function die(message) {
|
||||
throw new Error(message);
|
||||
|
@ -100,7 +46,7 @@ $Branch.prototype.equals = function (other) {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// Patterns, projections and captures
|
||||
|
||||
var __ = new $Special("wildcard"); /* wildcard marker */
|
||||
var __ = Struct.__; /* imported rather than defined here because of cyclic dep in Struct */
|
||||
var SOA = new $Special("array"); /* key for start-of-array */
|
||||
|
||||
function $Embedded(trie, arrayLength) {
|
||||
|
@ -239,7 +185,7 @@ function compilePattern(v, p) {
|
|||
return rseq(p.size, SOA, acc);
|
||||
}
|
||||
|
||||
if (isStructure(p)) {
|
||||
if (Struct.isStructure(p)) {
|
||||
var args = p.$SyndicateMeta$.arguments;
|
||||
for (var i = args.length - 1; i >= 0; i--) {
|
||||
acc = walk(p[args[i]], acc);
|
||||
|
@ -276,7 +222,10 @@ function matchPattern(v, p) {
|
|||
|
||||
if (p === __) return;
|
||||
|
||||
if (isStructure(p) && isStructure(v) && (p.$SyndicateMeta$ === v.$SyndicateMeta$)) {
|
||||
if (Struct.isStructure(p)
|
||||
&& Struct.isStructure(v)
|
||||
&& (p.$SyndicateMeta$ === v.$SyndicateMeta$))
|
||||
{
|
||||
var args = p.$SyndicateMeta$.arguments;
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
walk(v[args[i]], p[args[i]]);
|
||||
|
@ -481,9 +430,9 @@ function matchValue(r, v, failureResultOpt) {
|
|||
if (Array.isArray(v)) {
|
||||
r = rlookup(r, v.length, SOA);
|
||||
vs = Immutable.List(v).concat(vs);
|
||||
} else if (isStructure(v)) {
|
||||
} else if (Struct.isStructure(v)) {
|
||||
r = rlookup(r, v.$SyndicateMeta$.arguments.length, v.$SyndicateMeta$);
|
||||
vs = Immutable.List(structureToArray(v, true)).concat(vs);
|
||||
vs = Immutable.List(Struct.structureToArray(v, true)).concat(vs);
|
||||
} else {
|
||||
r = rlookup(r, 0, v);
|
||||
}
|
||||
|
@ -600,7 +549,7 @@ function projectionNames(p) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (isStructure(p)) {
|
||||
if (Struct.isStructure(p)) {
|
||||
var args = p.$SyndicateMeta$.arguments;
|
||||
for (var i = 0; i < args.length; i++) walk(p[args[i]]);
|
||||
return;
|
||||
|
@ -626,7 +575,7 @@ function projectionToPattern(p) {
|
|||
return result;
|
||||
}
|
||||
|
||||
if (isStructure(p)) {
|
||||
if (Struct.isStructure(p)) {
|
||||
var result = {"$SyndicateMeta$": p.$SyndicateMeta$};
|
||||
var args = p.$SyndicateMeta$.arguments;
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
|
@ -702,12 +651,12 @@ function projectMany(t, wholeSpecs, projectSuccessOpt, combinerOpt) {
|
|||
return target;
|
||||
}
|
||||
|
||||
if (isStructure(spec)) {
|
||||
if (Struct.isStructure(spec)) {
|
||||
var arity = spec.$SyndicateMeta$.arguments.length;
|
||||
var key = spec.$SyndicateMeta$;
|
||||
var intermediate = walk(isCapturing,
|
||||
rlookup(t, arity, key),
|
||||
Immutable.List(structureToArray(spec, true)),
|
||||
Immutable.List(Struct.structureToArray(spec, true)),
|
||||
function (intermediate) {
|
||||
return walk(isCapturing, intermediate, specsRest, kont);
|
||||
});
|
||||
|
@ -738,14 +687,14 @@ function reconstructSequence(key, items) {
|
|||
if (key === SOA) {
|
||||
return items.toArray();
|
||||
} else {
|
||||
return instantiateStructure(key, items);
|
||||
return Struct.instantiateStructure(key, items);
|
||||
}
|
||||
}
|
||||
|
||||
function trieKeys(m, takeCount0) {
|
||||
if (typeof takeCount0 !== 'number') {
|
||||
// Cope with API change which would otherwise silently cause problems
|
||||
die("Missing mandatory argument 'takeCount' to Route.trieKeys");
|
||||
die("Missing mandatory argument 'takeCount' to Trie.trieKeys");
|
||||
}
|
||||
|
||||
if (is_emptyTrie(m)) return Immutable.Set();
|
||||
|
@ -773,7 +722,7 @@ function trieKeys(m, takeCount0) {
|
|||
if (result === false) return false; // break out of iteration
|
||||
|
||||
var piece;
|
||||
if (isSyndicateMeta(key) || key === SOA) { // TODO: this is sloppy
|
||||
if (Struct.isSyndicateMeta(key) || key === SOA) { // TODO: this is sloppy
|
||||
piece = walk(k, arity, Immutable.List(), function (items, m1) {
|
||||
var item = reconstructSequence(key, items);
|
||||
return walk(m1, takeCount - 1, valsRev.unshift(item), kont);
|
||||
|
@ -849,7 +798,7 @@ function prettyTrie(m, initialIndent) {
|
|||
}
|
||||
acc.push(" ");
|
||||
if (key === SOA) key = '<' + arity + '>';
|
||||
else if (isSyndicateMeta(key)) key = key.label + '<' + arity + '>';
|
||||
else if (Struct.isSyndicateMeta(key)) key = key.label + '<' + arity + '>';
|
||||
else if (key instanceof $Special) key = key.name;
|
||||
else if (typeof key === 'undefined') key = 'undefined';
|
||||
else key = JSON.stringify(key);
|
||||
|
@ -870,7 +819,6 @@ module.exports.__ = __;
|
|||
module.exports.SOA = SOA;
|
||||
module.exports.$Capture = $Capture;
|
||||
module.exports.$Special = $Special;
|
||||
module.exports.makeStructureConstructor = makeStructureConstructor;
|
||||
module.exports._$ = _$;
|
||||
module.exports.is_emptyTrie = is_emptyTrie;
|
||||
module.exports.emptyTrie = emptyTrie;
|
|
@ -3,15 +3,15 @@
|
|||
var expect = require('expect.js');
|
||||
var Immutable = require('immutable');
|
||||
|
||||
var Route = require('../src/route.js');
|
||||
var Trie = require('../src/trie.js');
|
||||
var Patch = require('../src/patch.js');
|
||||
var Mux = require('../src/mux.js');
|
||||
|
||||
var __ = Route.__;
|
||||
var _$ = Route._$;
|
||||
var __ = Trie.__;
|
||||
var _$ = Trie._$;
|
||||
|
||||
function checkPrettyTrie(m, expected) {
|
||||
expect(Route.prettyTrie(m)).to.equal(expected.join('\n'));
|
||||
expect(Trie.prettyTrie(m)).to.equal(expected.join('\n'));
|
||||
}
|
||||
|
||||
function checkPrettyPatch(p, expectedAdded, expectedRemoved) {
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
var expect = require('expect.js');
|
||||
var Immutable = require('immutable');
|
||||
|
||||
var Route = require('../src/route.js');
|
||||
var Trie = require('../src/trie.js');
|
||||
var Patch = require('../src/patch.js');
|
||||
|
||||
var __ = Route.__;
|
||||
var _$ = Route._$;
|
||||
var __ = Trie.__;
|
||||
var _$ = Trie._$;
|
||||
|
||||
function checkPrettyPatch(p, expectedAdded, expectedRemoved) {
|
||||
expect(p.pretty()).to.equal(
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
var Immutable = require('immutable');
|
||||
var expect = require('expect.js');
|
||||
var util = require('util');
|
||||
var r = require("../src/route.js");
|
||||
var Struct = require("../src/struct.js");
|
||||
var r = require("../src/trie.js");
|
||||
|
||||
function checkPrettyTrie(m, expected) {
|
||||
expect(r.prettyTrie(m)).to.equal(expected.join('\n'));
|
||||
|
@ -401,7 +402,7 @@ describe("calls to matchPattern", function () {
|
|||
});
|
||||
|
||||
it("matches structures", function () {
|
||||
var ctor = r.makeStructureConstructor('foo', ['bar', 'zot']);
|
||||
var ctor = Struct.makeStructureConstructor('foo', ['bar', 'zot']);
|
||||
expect(r.matchPattern(ctor(123, 234), ctor(r._$("bar"), r._$("zot"))))
|
||||
.to.eql({ bar: 123, zot: 234, length: 2 });
|
||||
// Previously, structures were roughly the same as arrays:
|
||||
|
@ -518,14 +519,14 @@ describe('triePruneBranch', function () {
|
|||
|
||||
describe('makeStructureConstructor', function () {
|
||||
it('should produce the right metadata', function () {
|
||||
var ctor = r.makeStructureConstructor('foo', ['bar', 'zot']);
|
||||
var ctor = Struct.makeStructureConstructor('foo', ['bar', 'zot']);
|
||||
var inst = ctor(123, 234);
|
||||
expect(inst.$SyndicateMeta$.label).to.equal('foo');
|
||||
expect(inst.$SyndicateMeta$.arguments).to.eql(['bar', 'zot']);
|
||||
});
|
||||
|
||||
it('should produce the right instance data', function () {
|
||||
var ctor = r.makeStructureConstructor('foo', ['bar', 'zot']);
|
||||
var ctor = Struct.makeStructureConstructor('foo', ['bar', 'zot']);
|
||||
var inst = ctor(123, 234);
|
||||
expect(inst.bar).to.equal(123);
|
||||
expect(inst.zot).to.equal(234);
|
||||
|
@ -533,7 +534,7 @@ describe('makeStructureConstructor', function () {
|
|||
|
||||
it('should work with compilePattern and matchValue', function () {
|
||||
var sA = Immutable.Set(["A"]);
|
||||
var ctor = r.makeStructureConstructor('foo', ['bar', 'zot']);
|
||||
var ctor = Struct.makeStructureConstructor('foo', ['bar', 'zot']);
|
||||
var inst = ctor(123, 234);
|
||||
var x = r.compilePattern(sA, ctor(123, r.__));
|
||||
checkPrettyTrie(x, [' foo<2> 123 ★ {["A"]}']);
|
||||
|
|
Loading…
Reference in New Issue