Switch to Preserves for Record and Bytes
This commit is contained in:
parent
ea907c5aee
commit
44c1d425b3
|
@ -21,6 +21,7 @@
|
||||||
"nyc": "^13.1.0"
|
"nyc": "^13.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"immutable": "^3.8.2"
|
"immutable": "^3.8.2",
|
||||||
|
"preserves": "^0.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,10 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
var Struct = require('./struct.js');
|
var { Record } = require('preserves');
|
||||||
|
|
||||||
function Seal(contents) {
|
function Seal(contents) {
|
||||||
if (this === void 0) {
|
if (!(this instanceof Seal)) return new Seal(contents);
|
||||||
return new Seal(contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.contents = contents;
|
this.contents = contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +32,12 @@ Seal.prototype.toJSON = function () {
|
||||||
return { '@seal': 0 };
|
return { '@seal': 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.Discard = Struct.makeConstructor('discard', []);
|
module.exports.Discard = Record.makeConstructor('discard', []);
|
||||||
module.exports.Capture = Struct.makeConstructor('capture', ['specification']);
|
module.exports.Capture = Record.makeConstructor('capture', ['specification']);
|
||||||
module.exports.Observe = Struct.makeConstructor('observe', ['specification']);
|
module.exports.Observe = Record.makeConstructor('observe', ['specification']);
|
||||||
|
|
||||||
|
module.exports.Inbound = Record.makeConstructor('inbound', ['assertion']);
|
||||||
|
module.exports.Outbound = Record.makeConstructor('outbound', ['assertion']);
|
||||||
|
module.exports.Instance = Record.makeConstructor('instance', ['uniqueId']);
|
||||||
|
|
||||||
module.exports.Seal = Seal;
|
module.exports.Seal = Seal;
|
||||||
module.exports.Inbound = Struct.makeConstructor('inbound', ['assertion']);
|
|
||||||
module.exports.Outbound = Struct.makeConstructor('outbound', ['assertion']);
|
|
||||||
module.exports.Instance = Struct.makeConstructor('instance', ['uniqueId']);
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
// Bags and Deltas (which are Bags where item-counts can be negative).
|
// Bags and Deltas (which are Bags where item-counts can be negative).
|
||||||
|
|
||||||
const Immutable = require("immutable");
|
const Immutable = require("immutable");
|
||||||
|
const { fromJS } = require("preserves");
|
||||||
|
|
||||||
const PRESENT_TO_ABSENT = -1;
|
const PRESENT_TO_ABSENT = -1;
|
||||||
const ABSENT_TO_ABSENT = 0;
|
const ABSENT_TO_ABSENT = 0;
|
||||||
|
@ -77,7 +78,7 @@ const Bag = Immutable.Map;
|
||||||
function fromSet(s) {
|
function fromSet(s) {
|
||||||
return Bag().withMutations(function (b) {
|
return Bag().withMutations(function (b) {
|
||||||
for (let v of Immutable.Set(s)) {
|
for (let v of Immutable.Set(s)) {
|
||||||
b = b.set(Immutable.fromJS(v), 1);
|
b = b.set(fromJS(v), 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const Immutable = require("immutable");
|
const Immutable = require("immutable");
|
||||||
const Struct = require('./struct.js');
|
const { fromJS } = require("preserves");
|
||||||
|
|
||||||
const Skeleton = require('./skeleton.js');
|
const Skeleton = require('./skeleton.js');
|
||||||
const $Special = require('./special.js');
|
const $Special = require('./special.js');
|
||||||
const Bag = require('./bag.js');
|
const Bag = require('./bag.js');
|
||||||
|
@ -343,14 +344,14 @@ Actor.prototype.assert = function (a) { this.pendingPatch().adjust(a, +1); };
|
||||||
Actor.prototype.retract = function (a) { this.pendingPatch().adjust(a, -1); };
|
Actor.prototype.retract = function (a) { this.pendingPatch().adjust(a, -1); };
|
||||||
|
|
||||||
Actor.prototype.adhocRetract = function (a) {
|
Actor.prototype.adhocRetract = function (a) {
|
||||||
a = Immutable.fromJS(a);
|
a = fromJS(a);
|
||||||
if (this.adhocAssertions.change(a, -1, true) === Bag.PRESENT_TO_ABSENT) {
|
if (this.adhocAssertions.change(a, -1, true) === Bag.PRESENT_TO_ABSENT) {
|
||||||
this.retract(a);
|
this.retract(a);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Actor.prototype.adhocAssert = function (a) {
|
Actor.prototype.adhocAssert = function (a) {
|
||||||
a = Immutable.fromJS(a);
|
a = fromJS(a);
|
||||||
if (this.adhocAssertions.change(a, +1) === Bag.ABSENT_TO_PRESENT) {
|
if (this.adhocAssertions.change(a, +1) === Bag.ABSENT_TO_PRESENT) {
|
||||||
this.assert(a);
|
this.assert(a);
|
||||||
}
|
}
|
||||||
|
@ -371,8 +372,10 @@ Patch.prototype.perform = function (ds, ac) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Patch.prototype.adjust = function (a, count) {
|
Patch.prototype.adjust = function (a, count) {
|
||||||
var _net;
|
if (a !== void 0) {
|
||||||
({bag: this.changes, net: _net} = Bag.change(this.changes, Immutable.fromJS(a), count));
|
var _net;
|
||||||
|
({bag: this.changes, net: _net} = Bag.change(this.changes, fromJS(a), count));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function Message(body) {
|
function Message(body) {
|
||||||
|
@ -381,7 +384,7 @@ function Message(body) {
|
||||||
|
|
||||||
Message.prototype.perform = function (ds, ac) {
|
Message.prototype.perform = function (ds, ac) {
|
||||||
if (this.body !== void 0) {
|
if (this.body !== void 0) {
|
||||||
ds.sendMessage(Immutable.fromJS(this.body));
|
ds.sendMessage(fromJS(this.body));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -612,7 +615,7 @@ Endpoint.prototype._uninstall = function (ds, ac, emitPatches) {
|
||||||
|
|
||||||
Endpoint.prototype.refresh = function (ds, ac, facet) {
|
Endpoint.prototype.refresh = function (ds, ac, facet) {
|
||||||
let [newAssertion, newHandler] = this.updateFun.call(facet.fields);
|
let [newAssertion, newHandler] = this.updateFun.call(facet.fields);
|
||||||
newAssertion = Immutable.fromJS(newAssertion);
|
if (newAssertion !== void 0) newAssertion = fromJS(newAssertion);
|
||||||
if (!Immutable.is(newAssertion, this.assertion)) {
|
if (!Immutable.is(newAssertion, this.assertion)) {
|
||||||
this._uninstall(ds, ac, true);
|
this._uninstall(ds, ac, true);
|
||||||
this._install(ds, ac, newAssertion, newHandler);
|
this._install(ds, ac, newAssertion, newHandler);
|
||||||
|
|
|
@ -19,6 +19,7 @@ Ground.prototype = new Dataspace(null);
|
||||||
Ground._resolved = Promise.resolve();
|
Ground._resolved = Promise.resolve();
|
||||||
Ground.laterCall = function (thunk) {
|
Ground.laterCall = function (thunk) {
|
||||||
Ground._resolved.then(() => {
|
Ground._resolved.then(() => {
|
||||||
|
Error.stackTraceLimit = 100;
|
||||||
try {
|
try {
|
||||||
thunk();
|
thunk();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const Struct = require('./struct.js');
|
|
||||||
const Skeleton = require('./skeleton.js');
|
const Skeleton = require('./skeleton.js');
|
||||||
const RandomID = require('./randomid.js');
|
const RandomID = require('./randomid.js');
|
||||||
const Dataspace = require('./dataspace.js');
|
const Dataspace = require('./dataspace.js');
|
||||||
|
@ -25,11 +24,12 @@ const Ground = require('./ground.js');
|
||||||
const Assertions = require('./assertions.js');
|
const Assertions = require('./assertions.js');
|
||||||
const Relay = require('./relay.js');
|
const Relay = require('./relay.js');
|
||||||
|
|
||||||
|
Object.assign(module.exports, require("preserves"));
|
||||||
|
|
||||||
module.exports.Immutable = require('immutable');
|
module.exports.Immutable = require('immutable');
|
||||||
// ^ for use by import machinery in syntactic extensions
|
// ^ for use by import machinery in syntactic extensions
|
||||||
|
|
||||||
module.exports.Bag = require("./bag.js");
|
module.exports.Bag = require("./bag.js");
|
||||||
module.exports.Struct = Struct;
|
|
||||||
module.exports.Skeleton = Skeleton;
|
module.exports.Skeleton = Skeleton;
|
||||||
module.exports.RandomID = RandomID;
|
module.exports.RandomID = RandomID;
|
||||||
|
|
||||||
|
|
|
@ -47,18 +47,18 @@ NestedDataspace.prototype.sendMessage = function (m) {
|
||||||
NestedDataspace.prototype.endpointHook = function (facet, innerEp) {
|
NestedDataspace.prototype.endpointHook = function (facet, innerEp) {
|
||||||
const innerDs = this;
|
const innerDs = this;
|
||||||
Dataspace.prototype.endpointHook.call(this, facet, innerEp);
|
Dataspace.prototype.endpointHook.call(this, facet, innerEp);
|
||||||
if (Observe.isClassOf(innerEp.assertion) && Inbound.isClassOf(innerEp.assertion[0])) {
|
if (Observe.isClassOf(innerEp.assertion) && Inbound.isClassOf(innerEp.assertion.get(0))) {
|
||||||
// We know that innerEp.assertion is an Observe(Inbound(...)).
|
// We know that innerEp.assertion is an Observe(Inbound(...)).
|
||||||
// Also, if innerEp.handler exists, it will be consonant with innerEp.assertion.
|
// Also, if innerEp.handler exists, it will be consonant with innerEp.assertion.
|
||||||
// Beware of completely-constant patterns, which cause skeleton to be null!
|
// Beware of completely-constant patterns, which cause skeleton to be null!
|
||||||
this.hookEndpointLifecycle(innerEp, this.outerFacet.addEndpoint(() => {
|
this.hookEndpointLifecycle(innerEp, this.outerFacet.addEndpoint(() => {
|
||||||
const h = innerEp.handler;
|
const h = innerEp.handler;
|
||||||
return [Observe(innerEp.assertion[0][0]),
|
return [Observe(innerEp.assertion.get(0).get(0)),
|
||||||
h && (h.skeleton === null
|
h && (h.skeleton === null
|
||||||
? {
|
? {
|
||||||
skeleton: null,
|
skeleton: null,
|
||||||
constPaths: h.constPaths,
|
constPaths: h.constPaths,
|
||||||
constVals: h.constVals.map((v) => v[0]),
|
constVals: h.constVals.map((v) => v.get(0)),
|
||||||
capturePaths: h.capturePaths.map((p) => p.shift()),
|
capturePaths: h.capturePaths.map((p) => p.shift()),
|
||||||
callback: function (evt, captures) {
|
callback: function (evt, captures) {
|
||||||
h.callback.call(this, evt, captures);
|
h.callback.call(this, evt, captures);
|
||||||
|
@ -85,13 +85,13 @@ NestedDataspace.prototype.adjustIndex = function (a, count) {
|
||||||
switch (net) {
|
switch (net) {
|
||||||
case Bag.ABSENT_TO_PRESENT:
|
case Bag.ABSENT_TO_PRESENT:
|
||||||
this.outerFacet.actor.pushScript(() => {
|
this.outerFacet.actor.pushScript(() => {
|
||||||
this.outerFacet.actor.adhocAssert(a[0]);
|
this.outerFacet.actor.adhocAssert(a.get(0));
|
||||||
});
|
});
|
||||||
this.outerFacet.actor.dataspace.start();
|
this.outerFacet.actor.dataspace.start();
|
||||||
break;
|
break;
|
||||||
case Bag.PRESENT_TO_ABSENT:
|
case Bag.PRESENT_TO_ABSENT:
|
||||||
this.outerFacet.actor.pushScript(() => {
|
this.outerFacet.actor.pushScript(() => {
|
||||||
this.outerFacet.actor.adhocRetract(a[0]);
|
this.outerFacet.actor.adhocRetract(a.get(0));
|
||||||
});
|
});
|
||||||
this.outerFacet.actor.dataspace.start();
|
this.outerFacet.actor.dataspace.start();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const Immutable = require("immutable");
|
const Immutable = require("immutable");
|
||||||
const Struct = require('./struct.js');
|
const { Record } = require("preserves");
|
||||||
|
|
||||||
const $Special = require('./special.js');
|
const $Special = require('./special.js');
|
||||||
const Bag = require('./bag.js');
|
const Bag = require('./bag.js');
|
||||||
const { Capture, Discard } = require('./assertions.js');
|
const { Capture, Discard } = require('./assertions.js');
|
||||||
|
@ -66,8 +67,8 @@ function Handler(cachedCaptures) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function classOf(v) {
|
function classOf(v) {
|
||||||
if (v instanceof Struct.Structure) {
|
if (v instanceof Record) {
|
||||||
return v.meta;
|
return v.getConstructorInfo();
|
||||||
} else if (v instanceof Immutable.List) {
|
} else if (v instanceof Immutable.List) {
|
||||||
return v.size;
|
return v.size;
|
||||||
} else {
|
} else {
|
||||||
|
@ -104,7 +105,7 @@ Node.prototype.extend = function(skeleton) {
|
||||||
if (!nextNode) {
|
if (!nextNode) {
|
||||||
nextNode = new Node(new Continuation(
|
nextNode = new Node(new Continuation(
|
||||||
node.continuation.cachedAssertions.filter(
|
node.continuation.cachedAssertions.filter(
|
||||||
(a) => classOf(projectPath(a, path)) === cls)));
|
(a) => Immutable.is(classOf(projectPath(a, path)), cls))));
|
||||||
table = table.set(cls, nextNode);
|
table = table.set(cls, nextNode);
|
||||||
node.edges = node.edges.set(selector, table);
|
node.edges = node.edges.set(selector, table);
|
||||||
}
|
}
|
||||||
|
@ -191,8 +192,7 @@ Node.prototype.modify = function(outerValue, m_cont, m_leaf, m_handler) {
|
||||||
while (i--) { mutable.pop(); }
|
while (i--) { mutable.pop(); }
|
||||||
});
|
});
|
||||||
let nextValue = step(nextStack.first(), selector.index);
|
let nextValue = step(nextStack.first(), selector.index);
|
||||||
let cls = classOf(nextValue);
|
let nextNode = table.get(classOf(nextValue), false);
|
||||||
let nextNode = table.get(cls, false);
|
|
||||||
if (nextNode) {
|
if (nextNode) {
|
||||||
walkNode(nextNode, nextStack.push(nextValue));
|
walkNode(nextNode, nextStack.push(nextValue));
|
||||||
}
|
}
|
||||||
|
@ -279,6 +279,15 @@ function analyzeAssertion(a) {
|
||||||
let capturePaths = Immutable.List();
|
let capturePaths = Immutable.List();
|
||||||
|
|
||||||
function walk(path, a) {
|
function walk(path, a) {
|
||||||
|
if (Capture.isClassOf(a)) {
|
||||||
|
capturePaths = capturePaths.push(path);
|
||||||
|
return walk(path, a.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Discard.isClassOf(a)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
let cls = classOf(a);
|
let cls = classOf(a);
|
||||||
if (cls !== null) {
|
if (cls !== null) {
|
||||||
let arity = (typeof cls === 'number') ? cls : cls.arity;
|
let arity = (typeof cls === 'number') ? cls : cls.arity;
|
||||||
|
@ -287,18 +296,11 @@ function analyzeAssertion(a) {
|
||||||
result.push(walk(path.push(i), step(a, i)));
|
result.push(walk(path.push(i), step(a, i)));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else {
|
|
||||||
if (Capture.isClassOf(a)) {
|
|
||||||
capturePaths = capturePaths.push(path);
|
|
||||||
return walk(path, a.get(0));
|
|
||||||
} else if (Discard.isClassOf(a)) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
constPaths = constPaths.push(path);
|
|
||||||
constVals = constVals.push(a);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constPaths = constPaths.push(path);
|
||||||
|
constVals = constVals.push(a);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let skeleton = walk(Immutable.List(), a);
|
let skeleton = walk(Immutable.List(), a);
|
||||||
|
|
|
@ -1,169 +0,0 @@
|
||||||
"use strict";
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// @syndicate-lang/core, an implementation of Syndicate dataspaces for JS.
|
|
||||||
// Copyright (C) 2016-2018 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// "Structures": Simple named-tuple-like records.
|
|
||||||
|
|
||||||
const Immutable = require("immutable");
|
|
||||||
const $Special = require('./special.js');
|
|
||||||
|
|
||||||
function StructureType(label, arity) {
|
|
||||||
this.label = label;
|
|
||||||
this.arity = arity;
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
this.ctor = function () {
|
|
||||||
return self.instantiate(Array.prototype.slice.call(arguments));
|
|
||||||
};
|
|
||||||
this.ctor.meta = this;
|
|
||||||
this.ctor.isClassOf = function (v) { return self.isClassOf(v); };
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeConstructor(label, fieldNames) {
|
|
||||||
return new StructureType(label, fieldNames.length).ctor;
|
|
||||||
}
|
|
||||||
|
|
||||||
StructureType.prototype.equals = function (other) {
|
|
||||||
if (!(other instanceof StructureType)) return false;
|
|
||||||
return this.arity === other.arity && this.label === other.label;
|
|
||||||
};
|
|
||||||
|
|
||||||
StructureType.prototype.hashCode = function () {
|
|
||||||
return Immutable.List([this.label, this.arity]).hashCode();
|
|
||||||
};
|
|
||||||
|
|
||||||
StructureType.prototype.instantiate = function (fields) {
|
|
||||||
return new Structure(this, fields);
|
|
||||||
};
|
|
||||||
|
|
||||||
StructureType.prototype.isClassOf = function (v) {
|
|
||||||
return v && (v instanceof Structure) && (v.meta.equals(this));
|
|
||||||
};
|
|
||||||
|
|
||||||
function Structure(meta, fields) {
|
|
||||||
if (!isStructureType(meta)) {
|
|
||||||
throw new Error("Structure: requires structure type");
|
|
||||||
}
|
|
||||||
if (fields.length !== meta.arity) {
|
|
||||||
throw new Error("Structure: cannot instantiate meta "+JSON.stringify(meta.label)+
|
|
||||||
" expecting "+meta.arity+" fields with "+fields.length+" fields");
|
|
||||||
}
|
|
||||||
fields = fields.slice(0);
|
|
||||||
this.meta = meta;
|
|
||||||
this.length = meta.arity;
|
|
||||||
this.fields = fields;
|
|
||||||
for (var i = 0; i < fields.length; i++) {
|
|
||||||
this[i] = fields[i] = Immutable.fromJS(fields[i]);
|
|
||||||
if (this[i] === void 0) {
|
|
||||||
throw new Error("Structure: cannot contain undefined value at field " + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Structure.prototype.clone = function () {
|
|
||||||
return new Structure(this.meta, this.fields);
|
|
||||||
};
|
|
||||||
|
|
||||||
Structure.prototype.get = function (index) {
|
|
||||||
return this[index];
|
|
||||||
};
|
|
||||||
|
|
||||||
Structure.prototype.set = function (index, value) {
|
|
||||||
var s = this.clone();
|
|
||||||
s[index] = s.fields[index] = value;
|
|
||||||
return s;
|
|
||||||
};
|
|
||||||
|
|
||||||
Structure.prototype.equals = function (other) {
|
|
||||||
if (!other) return false;
|
|
||||||
if (!(other instanceof Structure)) return false;
|
|
||||||
if (!other.meta.equals(this.meta)) return false;
|
|
||||||
for (let i = 0; i < this.length; i++) {
|
|
||||||
const a = this[i];
|
|
||||||
const b = other[i];
|
|
||||||
if (a === b) continue;
|
|
||||||
if (!a || typeof a.equals !== 'function') return false;
|
|
||||||
if (!a.equals(b)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
Structure.prototype.hashCode = function () {
|
|
||||||
return Immutable.List(this.fields).unshift(this.meta).hashCode();
|
|
||||||
};
|
|
||||||
|
|
||||||
Structure.prototype.toString = function () {
|
|
||||||
let b = this.meta.label + "(";
|
|
||||||
let needComma = false;
|
|
||||||
for (let v of this.fields) {
|
|
||||||
if (needComma) b = b + ", ";
|
|
||||||
needComma = true;
|
|
||||||
b = b + JSON.stringify(v);
|
|
||||||
}
|
|
||||||
return b + ")";
|
|
||||||
};
|
|
||||||
|
|
||||||
function reviveStructs(j) {
|
|
||||||
if (Array.isArray(j)) {
|
|
||||||
return j.map(reviveStructs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((j !== null) && typeof j === 'object') {
|
|
||||||
if ((typeof j['@type'] === 'string') && Array.isArray(j['fields'])) {
|
|
||||||
return (new StructureType(j['@type'], j['fields'].length)).instantiate(j['fields']);
|
|
||||||
} else {
|
|
||||||
for (var k in j) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(j, k)) {
|
|
||||||
j[k] = reviveStructs(j[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
|
|
||||||
function reviver(k, v) {
|
|
||||||
if (k === '') {
|
|
||||||
return reviveStructs(v);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
};
|
|
||||||
|
|
||||||
Structure.prototype.toJSON = function () {
|
|
||||||
return { '@type': this.meta.label, 'fields': this.fields };
|
|
||||||
};
|
|
||||||
|
|
||||||
function isStructureType(v) {
|
|
||||||
return v && (v instanceof StructureType);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isStructure(v) {
|
|
||||||
return v && (v instanceof Structure);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
module.exports.StructureType = StructureType;
|
|
||||||
module.exports.makeConstructor = makeConstructor;
|
|
||||||
module.exports.Structure = Structure;
|
|
||||||
module.exports.reviveStructs = reviveStructs;
|
|
||||||
module.exports.reviver = reviver;
|
|
||||||
module.exports.isStructureType = isStructureType;
|
|
||||||
module.exports.isStructure = isStructure;
|
|
|
@ -24,28 +24,27 @@ chai.use(require('chai-immutable'));
|
||||||
const Immutable = require('immutable');
|
const Immutable = require('immutable');
|
||||||
|
|
||||||
const Syndicate = require('../src/index.js');
|
const Syndicate = require('../src/index.js');
|
||||||
const Skeleton = Syndicate.Skeleton;
|
const { Skeleton, Dataspace, Observe, Capture, Discard } = Syndicate;
|
||||||
const Dataspace = Syndicate.Dataspace;
|
|
||||||
const Struct = Syndicate.Struct;
|
|
||||||
const __ = Syndicate.__;
|
|
||||||
const _$ = Syndicate._$;
|
|
||||||
|
|
||||||
describe('dataspace', () => {
|
describe('dataspace', () => {
|
||||||
it('should boot and run', () => {
|
it('should boot and run', () => {
|
||||||
// TODO: convert this into even a rudimentary somewhat-real test case
|
// TODO: convert this into even a rudimentary somewhat-real test case
|
||||||
// (change console.log into gathering a trace)
|
// (change console.log into gathering a trace)
|
||||||
let ds = new Dataspace(null, () => {
|
let ds = new Dataspace(() => {
|
||||||
// console.log('boot');
|
// console.log('boot');
|
||||||
Dataspace.currentFacet().addEndpoint(() => {
|
Dataspace.currentFacet().addEndpoint(() => {
|
||||||
let handler = Skeleton.analyzeAssertion(_$);
|
let handler = Skeleton.analyzeAssertion(Capture(Discard()));
|
||||||
handler.callback = (evt, vs) => {
|
handler.callback = (evt, vs) => {
|
||||||
if (Syndicate.Observe.isClassOf(vs.get(0))) {
|
if (Observe.isClassOf(vs.get(0))) {
|
||||||
// console.log('OBSERVATION EVENT', evt, vs, vs.get(0).get(0) === _$);
|
// console.log('OBSERVATION EVENT',
|
||||||
|
// evt,
|
||||||
|
// vs,
|
||||||
|
// Immutable.is(vs.get(0).get(0), Capture(Discard())));
|
||||||
} else {
|
} else {
|
||||||
// console.log('EVENT', evt, vs);
|
// console.log('EVENT', evt, vs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return [Syndicate.Observe(_$), handler];
|
return [Observe(Capture(Discard())), handler];
|
||||||
});
|
});
|
||||||
Dataspace.deferTurn(() => {
|
Dataspace.deferTurn(() => {
|
||||||
// console.log('after defer');
|
// console.log('after defer');
|
||||||
|
|
|
@ -24,12 +24,12 @@ chai.use(require('chai-immutable'));
|
||||||
const Immutable = require('immutable');
|
const Immutable = require('immutable');
|
||||||
|
|
||||||
const Syndicate = require('../src/index.js');
|
const Syndicate = require('../src/index.js');
|
||||||
const Skeleton = Syndicate.Skeleton;
|
const { Seal, Skeleton, Capture, Discard, Record } = Syndicate;
|
||||||
const Struct = Syndicate.Struct;
|
|
||||||
const __ = Syndicate.__;
|
|
||||||
const _$ = Syndicate._$;
|
|
||||||
|
|
||||||
const Event = Struct.makeConstructor('Event', ['label', 'type', 'values']);
|
const __ = Discard();
|
||||||
|
const _$ = Capture(Discard());
|
||||||
|
|
||||||
|
const Event = Record.makeConstructor('Event', ['label', 'type', 'values']);
|
||||||
|
|
||||||
function eventCallback(traceHolder, label) {
|
function eventCallback(traceHolder, label) {
|
||||||
return (e, vs) => { traceHolder.push(Event(label, e, vs)) };
|
return (e, vs) => { traceHolder.push(Event(label, e, vs)) };
|
||||||
|
@ -51,21 +51,21 @@ function _analyzeAssertion(a) {
|
||||||
|
|
||||||
describe('skeleton', () => {
|
describe('skeleton', () => {
|
||||||
|
|
||||||
const A = Struct.makeConstructor('A', ['x', 'y']);
|
const A = Record.makeConstructor('A', ['x', 'y']);
|
||||||
const B = Struct.makeConstructor('B', ['v']);
|
const B = Record.makeConstructor('B', ['v']);
|
||||||
const C = Struct.makeConstructor('C', ['v']);
|
const C = Record.makeConstructor('C', ['v']);
|
||||||
|
|
||||||
describe('pattern analysis', () => {
|
describe('pattern analysis', () => {
|
||||||
it('should handle leaf captures', () => {
|
it('should handle leaf captures', () => {
|
||||||
expect(Immutable.fromJS(_analyzeAssertion(A(B(_$), _$))))
|
expect(Immutable.fromJS(_analyzeAssertion(A(B(_$), _$))))
|
||||||
.to.equal(Immutable.fromJS({skeleton: [A.meta, [B.meta, null], null],
|
.to.equal(Immutable.fromJS({skeleton: [A.constructorInfo, [B.constructorInfo, null], null],
|
||||||
constPaths: Immutable.fromJS([]),
|
constPaths: Immutable.fromJS([]),
|
||||||
constVals: Immutable.fromJS([]),
|
constVals: Immutable.fromJS([]),
|
||||||
capturePaths: Immutable.fromJS([[0, 0], [1]])}));
|
capturePaths: Immutable.fromJS([[0, 0], [1]])}));
|
||||||
});
|
});
|
||||||
it('should handle atomic constants', () => {
|
it('should handle atomic constants', () => {
|
||||||
expect(Immutable.fromJS(_analyzeAssertion(A(B("x"), _$))))
|
expect(Immutable.fromJS(_analyzeAssertion(A(B("x"), _$))))
|
||||||
.to.equal(Immutable.fromJS({skeleton: [A.meta, [B.meta, null], null],
|
.to.equal(Immutable.fromJS({skeleton: [A.constructorInfo, [B.constructorInfo, null], null],
|
||||||
constPaths: Immutable.fromJS([[0, 0]]),
|
constPaths: Immutable.fromJS([[0, 0]]),
|
||||||
constVals: Immutable.fromJS(["x"]),
|
constVals: Immutable.fromJS(["x"]),
|
||||||
capturePaths: Immutable.fromJS([[1]])}));
|
capturePaths: Immutable.fromJS([[1]])}));
|
||||||
|
@ -77,12 +77,15 @@ describe('skeleton', () => {
|
||||||
// will end up being complex at runtime. We can't properly test
|
// will end up being complex at runtime. We can't properly test
|
||||||
// that situation without the static analysis half of the code.
|
// that situation without the static analysis half of the code.
|
||||||
// TODO later.
|
// TODO later.
|
||||||
let complexPlaceholder = new Object();
|
const complexPlaceholder = new Object();
|
||||||
expect(Immutable.fromJS(_analyzeAssertion(A(complexPlaceholder, C(_$)))))
|
const analysis = Immutable.fromJS(_analyzeAssertion(A(complexPlaceholder, C(_$))));
|
||||||
.to.equal(Immutable.fromJS({skeleton: [A.meta, null, [C.meta, null]],
|
const expected = Immutable.fromJS({
|
||||||
constPaths: Immutable.fromJS([[0]]),
|
skeleton: [A.constructorInfo, null, [C.constructorInfo, null]],
|
||||||
constVals: Immutable.fromJS([complexPlaceholder]),
|
constPaths: Immutable.fromJS([[0]]),
|
||||||
capturePaths: Immutable.fromJS([[1, 0]])}));
|
constVals: Immutable.List([complexPlaceholder]),
|
||||||
|
capturePaths: Immutable.fromJS([[1, 0]]),
|
||||||
|
});
|
||||||
|
expect(analysis).to.equal(expected);
|
||||||
});
|
});
|
||||||
it('should handle complex constants (2)', () => {
|
it('should handle complex constants (2)', () => {
|
||||||
// Marker: (***)
|
// Marker: (***)
|
||||||
|
@ -91,8 +94,10 @@ describe('skeleton', () => {
|
||||||
// will end up being complex at runtime. We can't properly test
|
// will end up being complex at runtime. We can't properly test
|
||||||
// that situation without the static analysis half of the code.
|
// that situation without the static analysis half of the code.
|
||||||
// TODO later.
|
// TODO later.
|
||||||
expect(Immutable.fromJS(_analyzeAssertion(A(B(B("y")), _$("rhs", C(__))))))
|
expect(Immutable.fromJS(_analyzeAssertion(A(B(B("y")), Capture(C(__))))))
|
||||||
.to.equal(Immutable.fromJS({skeleton: [A.meta, [B.meta, [B.meta, null]], [C.meta, null]],
|
.to.equal(Immutable.fromJS({skeleton: [A.constructorInfo,
|
||||||
|
[B.constructorInfo, [B.constructorInfo, null]],
|
||||||
|
[C.constructorInfo, null]],
|
||||||
constPaths: Immutable.fromJS([[0, 0, 0]]),
|
constPaths: Immutable.fromJS([[0, 0, 0]]),
|
||||||
constVals: Immutable.fromJS(["y"]),
|
constVals: Immutable.fromJS(["y"]),
|
||||||
capturePaths: Immutable.fromJS([[1]])}));
|
capturePaths: Immutable.fromJS([[1]])}));
|
||||||
|
@ -117,13 +122,15 @@ describe('skeleton', () => {
|
||||||
let trace = skeletonTrace((i, traceHolder) => {
|
let trace = skeletonTrace((i, traceHolder) => {
|
||||||
i.addHandler(_analyzeAssertion(A(B(_$), _$)), eventCallback(traceHolder, "AB"));
|
i.addHandler(_analyzeAssertion(A(B(_$), _$)), eventCallback(traceHolder, "AB"));
|
||||||
i.addHandler(_analyzeAssertion(A(B("x"), _$)), eventCallback(traceHolder, "ABx"));
|
i.addHandler(_analyzeAssertion(A(B("x"), _$)), eventCallback(traceHolder, "ABx"));
|
||||||
let complexConstantPattern1 = {skeleton: [A.meta, null, [C.meta, null]],
|
let complexConstantPattern1 = {skeleton: [A.constructorInfo, null, [C.constructorInfo, null]],
|
||||||
constPaths: Immutable.fromJS([[0]]),
|
constPaths: Immutable.fromJS([[0]]),
|
||||||
constVals: Immutable.fromJS([B("y")]),
|
constVals: Immutable.fromJS([B("y")]),
|
||||||
capturePaths: Immutable.fromJS([[1, 0]])};
|
capturePaths: Immutable.fromJS([[1, 0]])};
|
||||||
// ^ See comment in 'should handle complex constants (1)' test above (marked (***)).
|
// ^ See comment in 'should handle complex constants (1)' test above (marked (***)).
|
||||||
i.addHandler(complexConstantPattern1, eventCallback(traceHolder, "AByC"));
|
i.addHandler(complexConstantPattern1, eventCallback(traceHolder, "AByC"));
|
||||||
let complexConstantPattern2 = {skeleton: [A.meta, [B.meta, null], [C.meta, null]],
|
let complexConstantPattern2 = {skeleton: [A.constructorInfo,
|
||||||
|
[B.constructorInfo, null],
|
||||||
|
[C.constructorInfo, null]],
|
||||||
constPaths: Immutable.fromJS([[0, 0]]),
|
constPaths: Immutable.fromJS([[0, 0]]),
|
||||||
constVals: Immutable.fromJS([B("y")]),
|
constVals: Immutable.fromJS([B("y")]),
|
||||||
capturePaths: Immutable.fromJS([[1]])};
|
capturePaths: Immutable.fromJS([[1]])};
|
||||||
|
@ -135,7 +142,7 @@ describe('skeleton', () => {
|
||||||
i.addAssertion(Immutable.fromJS(A(B("z"),C(3))));
|
i.addAssertion(Immutable.fromJS(A(B("z"),C(3))));
|
||||||
});
|
});
|
||||||
|
|
||||||
// trace.forEach((e) => { console.log(e.toString()) });
|
// trace.forEach((e) => { console.log(e) });
|
||||||
|
|
||||||
expect(trace)
|
expect(trace)
|
||||||
.to.equal(Immutable.List([
|
.to.equal(Immutable.List([
|
||||||
|
@ -236,7 +243,7 @@ describe('skeleton', () => {
|
||||||
expect(trace.size).to.equal(8);
|
expect(trace.size).to.equal(8);
|
||||||
});
|
});
|
||||||
it('should have a correct 3-EVENT subtrace', () => {
|
it('should have a correct 3-EVENT subtrace', () => {
|
||||||
expect(trace.filter((e) => { return e[0] === "3-EVENT"; }))
|
expect(trace.filter((e) => { return e.get(0) === "3-EVENT"; }))
|
||||||
.to.equal(Immutable.List([
|
.to.equal(Immutable.List([
|
||||||
Event("3-EVENT", Skeleton.EVENT_ADDED, [123, 234]),
|
Event("3-EVENT", Skeleton.EVENT_ADDED, [123, 234]),
|
||||||
Event("3-EVENT", Skeleton.EVENT_ADDED, [999, 999]),
|
Event("3-EVENT", Skeleton.EVENT_ADDED, [999, 999]),
|
||||||
|
@ -245,7 +252,7 @@ describe('skeleton', () => {
|
||||||
Event("3-EVENT", Skeleton.EVENT_REMOVED, [123, 234])]));
|
Event("3-EVENT", Skeleton.EVENT_REMOVED, [123, 234])]));
|
||||||
});
|
});
|
||||||
it('should have a correct 2-EVENT subtrace', () => {
|
it('should have a correct 2-EVENT subtrace', () => {
|
||||||
expect(trace.filter((e) => { return e[0] === "2-EVENT"; }))
|
expect(trace.filter((e) => { return e.get(0) === "2-EVENT"; }))
|
||||||
.to.equal(Immutable.List([
|
.to.equal(Immutable.List([
|
||||||
Event("2-EVENT", Skeleton.EVENT_ADDED, []),
|
Event("2-EVENT", Skeleton.EVENT_ADDED, []),
|
||||||
Event("2-EVENT", Skeleton.EVENT_MESSAGE, []),
|
Event("2-EVENT", Skeleton.EVENT_MESSAGE, []),
|
||||||
|
|
|
@ -57,17 +57,18 @@ export function htmlToString(j) {
|
||||||
|
|
||||||
function walk(j) {
|
function walk(j) {
|
||||||
if (htmlTag.isClassOf(j)) {
|
if (htmlTag.isClassOf(j)) {
|
||||||
pieces.push('<', j[0]);
|
pieces.push('<', j.get(0));
|
||||||
j[1].forEach((p) => pieces.push(' ', escapeHtml(p[0]), '="', escapeHtml(p[1]), '"'));
|
j.get(1).forEach(
|
||||||
|
(p) => pieces.push(' ', escapeHtml(p.get(0)), '="', escapeHtml(p.get(1)), '"'));
|
||||||
pieces.push('>');
|
pieces.push('>');
|
||||||
j[2].forEach(walk);
|
j.get(2).forEach(walk);
|
||||||
if (!(j[0] in emptyHtmlElements)) {
|
if (!(j.get(0) in emptyHtmlElements)) {
|
||||||
pieces.push('</', j[0], '>');
|
pieces.push('</', j.get(0), '>');
|
||||||
}
|
}
|
||||||
} else if (htmlFragment.isClassOf(j)) {
|
} else if (htmlFragment.isClassOf(j)) {
|
||||||
j[0].forEach(walk);
|
j.get(0).forEach(walk);
|
||||||
} else if (htmlLiteral.isClassOf(j)) {
|
} else if (htmlLiteral.isClassOf(j)) {
|
||||||
pieces.push(j[0]);
|
pieces.push(j.get(0));
|
||||||
} else if (typeof j === 'object' && j && typeof j[Symbol.iterator] === 'function') {
|
} else if (typeof j === 'object' && j && typeof j[Symbol.iterator] === 'function') {
|
||||||
for (let k of j) { walk(k); }
|
for (let k of j) { walk(k); }
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
import { genUuid, Seal, Capture, Observe, Dataspace, currentFacet } from "@syndicate-lang/core";
|
import { genUuid, Seal, Capture, Observe, Dataspace, currentFacet, Bytes } from "@syndicate-lang/core";
|
||||||
import { parse as parseUrl } from "url";
|
import { parse as parseUrl } from "url";
|
||||||
|
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
|
@ -40,14 +40,14 @@ Object.assign(module.exports, {
|
||||||
Response, DataOut,
|
Response, DataOut,
|
||||||
});
|
});
|
||||||
|
|
||||||
spawn named 'HttpServerFactory' {
|
spawn named 'driver/HttpServerFactory' {
|
||||||
during Observe(Request(_, HttpServer($h, $p), _, _, _, _)) assert HttpServer(h, p);
|
during Observe(Request(_, HttpServer($h, $p), _, _, _, _)) assert HttpServer(h, p);
|
||||||
during Observe(Request(_, HttpsServer($h, $p, $o), _, _, _, _)) assert HttpsServer(h, p, o);
|
during Observe(Request(_, HttpsServer($h, $p, $o), _, _, _, _)) assert HttpsServer(h, p, o);
|
||||||
|
|
||||||
during HttpServer($host, $port) spawn named ['HttpServer', host, port] {
|
during HttpServer($host, $port) spawn named ['driver/HttpServer', host, port] {
|
||||||
_server.call(this, host, port, null);
|
_server.call(this, host, port, null);
|
||||||
}
|
}
|
||||||
during HttpsServer($host, $port, $options) spawn named ['HttpsServer', host, port] {
|
during HttpsServer($host, $port, $options) spawn named ['driver/HttpsServer', host, port] {
|
||||||
_server.call(this, host, port, options);
|
_server.call(this, host, port, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ function _server(host, port, httpsOptions) {
|
||||||
facet.stop();
|
facet.stop();
|
||||||
}
|
}
|
||||||
on message DataOut(id, $chunk) {
|
on message DataOut(id, $chunk) {
|
||||||
res.write(chunk);
|
res.write(Bytes.toIO(chunk));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,12 +218,12 @@ function _server(host, port, httpsOptions) {
|
||||||
|
|
||||||
on asserted Observe(DataIn(id, _)) {
|
on asserted Observe(DataIn(id, _)) {
|
||||||
ws.on('message', Dataspace.wrapExternal((message) => {
|
ws.on('message', Dataspace.wrapExternal((message) => {
|
||||||
^ DataIn(id, message);
|
^ DataIn(id, Bytes.fromIO(message));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
on message DataOut(id, $message) {
|
on message DataOut(id, $message) {
|
||||||
ws.send(message);
|
ws.send(Bytes.toIO(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
stop on retracted Observe(WebSocket(_, server, pathPattern, _));
|
stop on retracted Observe(WebSocket(_, server, pathPattern, _));
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
import { currentFacet, Observe, Dataspace, genUuid } from "@syndicate-lang/core";
|
import { currentFacet, Observe, Dataspace, genUuid, Bytes } from "@syndicate-lang/core";
|
||||||
const net = require('net');
|
const net = require('net');
|
||||||
|
|
||||||
const { sleep } = activate require("@syndicate-lang/driver-timer");
|
const { sleep } = activate require("@syndicate-lang/driver-timer");
|
||||||
|
@ -38,14 +38,14 @@ export {
|
||||||
TcpAddress, TcpListener,
|
TcpAddress, TcpListener,
|
||||||
};
|
};
|
||||||
|
|
||||||
spawn named 'TcpDriver' {
|
spawn named 'driver/TcpDriver' {
|
||||||
during Observe(TcpConnection(_, TcpListener($port))) spawn named ['TcpListener', port] {
|
during Observe(TcpConnection(_, TcpListener($port))) spawn named ['driver/TcpListener', port] {
|
||||||
let finish = Dataspace.backgroundTask();
|
let finish = Dataspace.backgroundTask();
|
||||||
on stop finish();
|
on stop finish();
|
||||||
|
|
||||||
let server = net.createServer(Dataspace.wrapExternal((socket) => {
|
let server = net.createServer(Dataspace.wrapExternal((socket) => {
|
||||||
let id = genUuid('tcp' + port);
|
let id = genUuid('tcp' + port);
|
||||||
spawn named ['TcpInbound', id] {
|
spawn named ['driver/TcpInbound', id] {
|
||||||
assert TcpConnection(id, TcpListener(port));
|
assert TcpConnection(id, TcpListener(port));
|
||||||
on asserted TcpAccepted(id) _connectionCommon.call(this, currentFacet(), id, socket, true);
|
on asserted TcpAccepted(id) _connectionCommon.call(this, currentFacet(), id, socket, true);
|
||||||
stop on retracted TcpAccepted(id);
|
stop on retracted TcpAccepted(id);
|
||||||
|
@ -57,7 +57,8 @@ spawn named 'TcpDriver' {
|
||||||
on stop try { server.close() } catch (e) { console.error(e); }
|
on stop try { server.close() } catch (e) { console.error(e); }
|
||||||
}
|
}
|
||||||
|
|
||||||
during TcpConnection($id, TcpAddress($host, $port)) spawn named ['TcpOutbound', id, host, port] {
|
during TcpConnection($id, TcpAddress($host, $port))
|
||||||
|
spawn named ['driver/TcpOutbound', id, host, port] {
|
||||||
let finish = Dataspace.backgroundTask();
|
let finish = Dataspace.backgroundTask();
|
||||||
on stop finish();
|
on stop finish();
|
||||||
|
|
||||||
|
@ -69,9 +70,9 @@ spawn named 'TcpDriver' {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
during Observe(LineIn($id, _)) spawn named ['TcpLineReader', id] {
|
during Observe(LineIn($id, _)) spawn named ['driver/TcpLineReader', id] {
|
||||||
field this.buffer = Buffer.alloc(0);
|
field this.buffer = Bytes();
|
||||||
on message DataIn(id, $data) this.buffer = Buffer.concat([this.buffer, data]);
|
on message DataIn(id, $data) this.buffer = Bytes.concat([this.buffer, data]);
|
||||||
dataflow {
|
dataflow {
|
||||||
const pos = this.buffer.indexOf(10);
|
const pos = this.buffer.indexOf(10);
|
||||||
if (pos !== -1) {
|
if (pos !== -1) {
|
||||||
|
@ -107,12 +108,12 @@ function _connectionCommon(rootFacet, id, socket, established) {
|
||||||
|
|
||||||
on start react stop on asserted Observe(DataIn(id, _)) {
|
on start react stop on asserted Observe(DataIn(id, _)) {
|
||||||
socket.on('data', Dataspace.wrapExternal((data) => {
|
socket.on('data', Dataspace.wrapExternal((data) => {
|
||||||
^ DataIn(id, data);
|
^ DataIn(id, Bytes.fromIO(data));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
on message DataOut(id, $data) {
|
on message DataOut(id, $data) {
|
||||||
socket.write(data);
|
socket.write(Bytes.toIO(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
import { currentFacet, Observe, Dataspace } from "@syndicate-lang/core";
|
import { currentFacet, Observe, Dataspace, Bytes } from "@syndicate-lang/core";
|
||||||
import { createSocket } from "dgram";
|
import { createSocket } from "dgram";
|
||||||
|
|
||||||
const { sleep } = activate require("@syndicate-lang/driver-timer");
|
const { sleep } = activate require("@syndicate-lang/driver-timer");
|
||||||
|
@ -70,7 +70,7 @@ function _socket(addr, port) {
|
||||||
|
|
||||||
socket.on('listening', Dataspace.wrapExternal(() => { this.connected = true; }));
|
socket.on('listening', Dataspace.wrapExternal(() => { this.connected = true; }));
|
||||||
socket.on('message', Dataspace.wrapExternal((message, rinfo) => {
|
socket.on('message', Dataspace.wrapExternal((message, rinfo) => {
|
||||||
^ UdpPacket(UdpPeer(rinfo.address, rinfo.port), addr, message);
|
^ UdpPacket(UdpPeer(rinfo.address, rinfo.port), addr, Bytes.fromIO(message));
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ function _socket(addr, port) {
|
||||||
assert addr when (this.connected);
|
assert addr when (this.connected);
|
||||||
|
|
||||||
on message UdpPacket(addr, UdpPeer($host, $port), $payload) {
|
on message UdpPacket(addr, UdpPeer($host, $port), $payload) {
|
||||||
|
payload = Bytes.toIO(payload);
|
||||||
socket.send(payload, 0, payload.length, port, host, Dataspace.wrapExternal((err) => {
|
socket.send(payload, 0, payload.length, port, host, Dataspace.wrapExternal((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
import { currentFacet, Observe, Dataspace } from "@syndicate-lang/core";
|
import { currentFacet, Bytes, Observe, Dataspace } from "@syndicate-lang/core";
|
||||||
const { sleep } = activate require("@syndicate-lang/driver-timer");
|
const { sleep } = activate require("@syndicate-lang/driver-timer");
|
||||||
|
|
||||||
const _WebSocket = require('isomorphic-ws');
|
const _WebSocket = require('isomorphic-ws');
|
||||||
|
@ -52,7 +52,7 @@ spawn named 'WebSocketFactory' {
|
||||||
|
|
||||||
ws.onopen = Dataspace.wrapExternal(() => { this.connected = true; });
|
ws.onopen = Dataspace.wrapExternal(() => { this.connected = true; });
|
||||||
ws.onclose = Dataspace.wrapExternal(() => { if (this.connected) { connect(); }});
|
ws.onclose = Dataspace.wrapExternal(() => { if (this.connected) { connect(); }});
|
||||||
ws.onmessage = Dataspace.wrapExternal((data) => { ^ DataIn(id, data.data); });
|
ws.onmessage = Dataspace.wrapExternal((data) => { ^ DataIn(id, Bytes.fromIO(data.data)); });
|
||||||
};
|
};
|
||||||
|
|
||||||
const disconnect = () => {
|
const disconnect = () => {
|
||||||
|
@ -70,7 +70,7 @@ spawn named 'WebSocketFactory' {
|
||||||
|
|
||||||
on message DataOut(id, $data) {
|
on message DataOut(id, $data) {
|
||||||
if (this.connected) {
|
if (this.connected) {
|
||||||
ws.send(data);
|
ws.send(Bytes.toIO(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
import { currentFacet, genUuid } from "@syndicate-lang/core";
|
import { currentFacet, genUuid, Bytes } from "@syndicate-lang/core";
|
||||||
|
|
||||||
const WS = activate require("@syndicate-lang/driver-websocket");
|
const WS = activate require("@syndicate-lang/driver-websocket");
|
||||||
const { PeriodicTick } = activate require("@syndicate-lang/driver-timer");
|
const { PeriodicTick } = activate require("@syndicate-lang/driver-timer");
|
||||||
|
@ -34,7 +34,7 @@ spawn named 'demo' {
|
||||||
}
|
}
|
||||||
|
|
||||||
on message PeriodicTick(1000) {
|
on message PeriodicTick(1000) {
|
||||||
^ WS.DataOut(wsId, genUuid('timestamp'));
|
^ WS.DataOut(wsId, Bytes.from(genUuid('timestamp')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ spawn named 'multicast_demo' {
|
||||||
assert U.UdpMulticastLoopback(HANDLE, true);
|
assert U.UdpMulticastLoopback(HANDLE, true);
|
||||||
|
|
||||||
on message U.UdpPacket(U.UdpPeer($host, $port), HANDLE, $body) {
|
on message U.UdpPacket(U.UdpPeer($host, $port), HANDLE, $body) {
|
||||||
console.log('Got', body.toString(), 'from', host, port);
|
console.log('Got', body, 'from', host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
on message PeriodicTick(2000) {
|
on message PeriodicTick(2000) {
|
||||||
|
|
|
@ -74,6 +74,15 @@ function counter() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spawn named 'serverLogger' {
|
||||||
|
on asserted Http.Request(_, server, $method, $path, $query, $req) {
|
||||||
|
console.log(method, path.toJS(), query.toJS());
|
||||||
|
}
|
||||||
|
on asserted Http.WebSocket(_, server, $path, $query) {
|
||||||
|
console.log(path.toJS(), query.toJS());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spawn named 'rootServer' {
|
spawn named 'rootServer' {
|
||||||
let counters = {};
|
let counters = {};
|
||||||
on asserted Counter($id) counters[id] = true;
|
on asserted Counter($id) counters[id] = true;
|
||||||
|
|
|
@ -66,9 +66,9 @@ function discardAst(state) {
|
||||||
return _discardAst({ SYNDICATE: state.SyndicateID });
|
return _discardAst({ SYNDICATE: state.SyndicateID });
|
||||||
}
|
}
|
||||||
|
|
||||||
const _listAst = template.expression(`IMMUTABLE.fromJS(VS)`);
|
const _listAst = template.expression(`SYNDICATE.fromJS(VS)`);
|
||||||
function listAst(state, vs) {
|
function listAst(state, vs) {
|
||||||
return _listAst({ IMMUTABLE: state.ImmutableID, VS: vs });
|
return _listAst({ SYNDICATE: state.SyndicateID, VS: vs });
|
||||||
}
|
}
|
||||||
|
|
||||||
function captureWrap(state, ast) {
|
function captureWrap(state, ast) {
|
||||||
|
@ -123,7 +123,7 @@ function compilePattern(state, patternPath) {
|
||||||
// constPaths/constVals.
|
// constPaths/constVals.
|
||||||
if (hasCapturesOrDiscards(patternPath)) {
|
if (hasCapturesOrDiscards(patternPath)) {
|
||||||
let arity = pattern.arguments.length;
|
let arity = pattern.arguments.length;
|
||||||
let skel = [t.memberExpression(pattern.callee, t.identifier('meta'), false, false)];
|
let skel = [t.memberExpression(pattern.callee, t.identifier('constructorInfo'), false, false)];
|
||||||
let assn = [];
|
let assn = [];
|
||||||
for (let i = 0; i < arity; i++) {
|
for (let i = 0; i < arity; i++) {
|
||||||
syndicatePath.push(i);
|
syndicatePath.push(i);
|
||||||
|
@ -295,25 +295,22 @@ export default declare((api, options) => {
|
||||||
visitor: {
|
visitor: {
|
||||||
Program(path, state) {
|
Program(path, state) {
|
||||||
let savedGlobalFacetUid = path.scope.generateUidIdentifier("savedGlobalFacet");
|
let savedGlobalFacetUid = path.scope.generateUidIdentifier("savedGlobalFacet");
|
||||||
state.ImmutableID = path.scope.generateUidIdentifier("Immutable");
|
|
||||||
state.SyndicateID = path.scope.generateUidIdentifier("Syndicate");
|
state.SyndicateID = path.scope.generateUidIdentifier("Syndicate");
|
||||||
state.DataspaceID = path.scope.generateUidIdentifier("Dataspace");
|
state.DataspaceID = path.scope.generateUidIdentifier("Dataspace");
|
||||||
state.SkeletonID = path.scope.generateUidIdentifier("Skeleton");
|
state.SkeletonID = path.scope.generateUidIdentifier("Skeleton");
|
||||||
state.StructID = path.scope.generateUidIdentifier("Struct");
|
state.RecordID = path.scope.generateUidIdentifier("Record");
|
||||||
path.unshiftContainer(
|
path.unshiftContainer(
|
||||||
'body',
|
'body',
|
||||||
template(`const SYNDICATE = require("@syndicate-lang/core");
|
template(`const SYNDICATE = require("@syndicate-lang/core");
|
||||||
const IMMUTABLE = SYNDICATE.Immutable;
|
|
||||||
const DATASPACE = SYNDICATE.Dataspace;
|
const DATASPACE = SYNDICATE.Dataspace;
|
||||||
const SKELETON = SYNDICATE.Skeleton;
|
const SKELETON = SYNDICATE.Skeleton;
|
||||||
const STRUCT = SYNDICATE.Struct;
|
const RECORD = SYNDICATE.Record;
|
||||||
let SAVEDGLOBALFACET = DATASPACE._currentFacet;
|
let SAVEDGLOBALFACET = DATASPACE._currentFacet;
|
||||||
DATASPACE._currentFacet = new SYNDICATE._Dataspace.ActionCollector();`)({
|
DATASPACE._currentFacet = new SYNDICATE._Dataspace.ActionCollector();`)({
|
||||||
IMMUTABLE: state.ImmutableID,
|
|
||||||
SYNDICATE: state.SyndicateID,
|
SYNDICATE: state.SyndicateID,
|
||||||
DATASPACE: state.DataspaceID,
|
DATASPACE: state.DataspaceID,
|
||||||
SKELETON: state.SkeletonID,
|
SKELETON: state.SkeletonID,
|
||||||
STRUCT: state.StructID,
|
RECORD: state.RecordID,
|
||||||
SAVEDGLOBALFACET: savedGlobalFacetUid,
|
SAVEDGLOBALFACET: savedGlobalFacetUid,
|
||||||
}));
|
}));
|
||||||
path.pushContainer(
|
path.pushContainer(
|
||||||
|
@ -346,8 +343,8 @@ export default declare((api, options) => {
|
||||||
PROC: node.bootProc
|
PROC: node.bootProc
|
||||||
}),
|
}),
|
||||||
ASSERTIONS: node.initialAssertions.length === 0 ? null :
|
ASSERTIONS: node.initialAssertions.length === 0 ? null :
|
||||||
template.expression(`IMMUTABLE.Set(SEQ)`)({
|
template.expression(`SYNDICATE.Set(SEQ)`)({
|
||||||
IMMUTABLE: state.ImmutableID,
|
SYNDICATE: state.SyndicateID,
|
||||||
SEQ: t.arrayExpression(node.initialAssertions)
|
SEQ: t.arrayExpression(node.initialAssertions)
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
@ -453,9 +450,9 @@ export default declare((api, options) => {
|
||||||
|
|
||||||
SyndicateTypeDefinition(path, state) {
|
SyndicateTypeDefinition(path, state) {
|
||||||
const { node } = path;
|
const { node } = path;
|
||||||
path.replaceWith(template(`const ID = STRUCT.makeConstructor(WIRE, FORMALS);`)({
|
path.replaceWith(template(`const ID = RECORD.makeConstructor(WIRE, FORMALS);`)({
|
||||||
ID: node.id,
|
ID: node.id,
|
||||||
STRUCT: state.StructID,
|
RECORD: state.RecordID,
|
||||||
WIRE: node.wireName || t.stringLiteral(node.id.name),
|
WIRE: node.wireName || t.stringLiteral(node.id.name),
|
||||||
FORMALS: t.arrayExpression(node.formals.map((f) => t.stringLiteral(f.name))),
|
FORMALS: t.arrayExpression(node.formals.map((f) => t.stringLiteral(f.name))),
|
||||||
}));
|
}));
|
||||||
|
|
Loading…
Reference in New Issue