during, during/spawn and react; not quite working yet
This commit is contained in:
parent
95f8e881d2
commit
8f7907fa3e
|
@ -27,3 +27,4 @@ module.exports.Observe = Struct.makeConstructor('Observe', ['specification']);
|
||||||
module.exports.Seal = Seal;
|
module.exports.Seal = Seal;
|
||||||
module.exports.Inbound = Struct.makeConstructor('Inbound', ['assertion']);
|
module.exports.Inbound = Struct.makeConstructor('Inbound', ['assertion']);
|
||||||
module.exports.Outbound = Struct.makeConstructor('Outbound', ['assertion']);
|
module.exports.Outbound = Struct.makeConstructor('Outbound', ['assertion']);
|
||||||
|
module.exports.Instance = Struct.makeConstructor('Instance', ['uniqueId']);
|
||||||
|
|
|
@ -41,5 +41,10 @@ module.exports.Observe = Assertions.Observe;
|
||||||
module.exports.Seal = Assertions.Seal;
|
module.exports.Seal = Assertions.Seal;
|
||||||
module.exports.Inbound = Assertions.Inbound;
|
module.exports.Inbound = Assertions.Inbound;
|
||||||
module.exports.Outbound = Assertions.Outbound;
|
module.exports.Outbound = Assertions.Outbound;
|
||||||
|
module.exports.Instance = Assertions.Instance;
|
||||||
|
|
||||||
module.exports.bootModule = Ground.bootModule;
|
module.exports.bootModule = Ground.bootModule;
|
||||||
|
|
||||||
|
module.exports.genUuid = function () {
|
||||||
|
return Symbol('@syndicate-lang/core');
|
||||||
|
};
|
||||||
|
|
|
@ -78,6 +78,10 @@ export function EventHandlerEndpoint(node) {
|
||||||
} else {
|
} else {
|
||||||
this.word(node.triggerType);
|
this.word(node.triggerType);
|
||||||
this.space();
|
this.space();
|
||||||
|
if (!node.isDynamic) {
|
||||||
|
this.word(":snapshot");
|
||||||
|
this.space();
|
||||||
|
}
|
||||||
this.print(node.pattern, node);
|
this.print(node.pattern, node);
|
||||||
}
|
}
|
||||||
this.space();
|
this.space();
|
||||||
|
@ -122,3 +126,17 @@ export function ActivationExpression(node) {
|
||||||
this.space();
|
this.space();
|
||||||
this.print(node.moduleExpr, node);
|
this.print(node.moduleExpr, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function DuringStatement(node) {
|
||||||
|
this.word("during");
|
||||||
|
this.space();
|
||||||
|
this.print(node.pattern, node);
|
||||||
|
this.space();
|
||||||
|
this.print(node.body, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SyndicateReactStatement(node) {
|
||||||
|
this.word("react");
|
||||||
|
this.space();
|
||||||
|
this.print(node.body, node);
|
||||||
|
}
|
||||||
|
|
|
@ -88,14 +88,7 @@ export default class SyndicateParser extends _original_Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isContextual("spawn")) {
|
if (this.isContextual("spawn")) {
|
||||||
this.next();
|
return this.parseSpawnStatement();
|
||||||
const node = this.startNode();
|
|
||||||
if (this.isContextual("named")) {
|
|
||||||
this.next();
|
|
||||||
node.name = this.parseExpression();
|
|
||||||
}
|
|
||||||
node.body = this.parseStatement();
|
|
||||||
return this.finishNode(node, "SpawnStatement");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isContextual("assert")) {
|
if (this.isContextual("assert")) {
|
||||||
|
@ -127,6 +120,25 @@ export default class SyndicateParser extends _original_Parser {
|
||||||
return this.parseEventHandlerEndpoint(false, true);
|
return this.parseEventHandlerEndpoint(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.isContextual("during")) {
|
||||||
|
this.next();
|
||||||
|
const node = this.startNode();
|
||||||
|
node.pattern = this.parseExpression();
|
||||||
|
if (this.isContextual("spawn")) {
|
||||||
|
node.body = this.parseSpawnStatement();
|
||||||
|
} else {
|
||||||
|
node.body = this.parseStatement();
|
||||||
|
}
|
||||||
|
return this.finishNode(node, "DuringStatement");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isContextual("react")) {
|
||||||
|
this.next();
|
||||||
|
const node = this.startNode();
|
||||||
|
node.body = this.parseStatement();
|
||||||
|
return this.finishNode(node, "SyndicateReactStatement");
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isContextual("assertion") || this.isContextual("message")) {
|
if (this.isContextual("assertion") || this.isContextual("message")) {
|
||||||
const node = this.startNode();
|
const node = this.startNode();
|
||||||
node.expectedUse = this.state.value;
|
node.expectedUse = this.state.value;
|
||||||
|
@ -180,6 +192,17 @@ export default class SyndicateParser extends _original_Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseSpawnStatement() {
|
||||||
|
this.next();
|
||||||
|
const node = this.startNode();
|
||||||
|
if (this.isContextual("named")) {
|
||||||
|
this.next();
|
||||||
|
node.name = this.parseExpression();
|
||||||
|
}
|
||||||
|
node.body = this.parseStatement();
|
||||||
|
return this.finishNode(node, "SpawnStatement");
|
||||||
|
}
|
||||||
|
|
||||||
parseEventHandlerEndpoint(terminal, pseudoEventsAllowed) {
|
parseEventHandlerEndpoint(terminal, pseudoEventsAllowed) {
|
||||||
this.expectContextual("on");
|
this.expectContextual("on");
|
||||||
const node = this.startNode();
|
const node = this.startNode();
|
||||||
|
@ -187,6 +210,7 @@ export default class SyndicateParser extends _original_Parser {
|
||||||
if (this.match(tt.parenL)) {
|
if (this.match(tt.parenL)) {
|
||||||
node.terminal = terminal;
|
node.terminal = terminal;
|
||||||
node.triggerType = "dataflow";
|
node.triggerType = "dataflow";
|
||||||
|
node.isDynamic = true;
|
||||||
node.pattern = this.parseExpression();
|
node.pattern = this.parseExpression();
|
||||||
node.body = this.parseStatement();
|
node.body = this.parseStatement();
|
||||||
return this.finishNode(node, "EventHandlerEndpoint");
|
return this.finishNode(node, "EventHandlerEndpoint");
|
||||||
|
@ -213,6 +237,7 @@ export default class SyndicateParser extends _original_Parser {
|
||||||
case "message":
|
case "message":
|
||||||
node.triggerType = this.state.value;
|
node.triggerType = this.state.value;
|
||||||
this.next();
|
this.next();
|
||||||
|
node.isDynamic = this.parseMaybeSnapshot();
|
||||||
node.terminal = terminal;
|
node.terminal = terminal;
|
||||||
node.pattern = this.parseExpression();
|
node.pattern = this.parseExpression();
|
||||||
node.body = this.parseStatement();
|
node.body = this.parseStatement();
|
||||||
|
@ -222,4 +247,14 @@ export default class SyndicateParser extends _original_Parser {
|
||||||
this.unexpected(null, "Unknown event handler trigger type");
|
this.unexpected(null, "Unknown event handler trigger type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseMaybeSnapshot() {
|
||||||
|
if (this.match(tt.colon)) {
|
||||||
|
this.next();
|
||||||
|
this.expectContextual("snapshot");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,14 @@
|
||||||
|
|
||||||
import { declare } from "@babel/helper-plugin-utils";
|
import { declare } from "@babel/helper-plugin-utils";
|
||||||
import { types as t } from "@babel/core";
|
import { types as t } from "@babel/core";
|
||||||
import { cloneDeep } from "@babel/types";
|
import { cloneDeep, isLiteral } from "@babel/types";
|
||||||
import template from "@babel/template";
|
import template from "@babel/template";
|
||||||
import traverse from "@babel/traverse";
|
import traverse from "@babel/traverse";
|
||||||
|
import builder from "@babel/types/lib/builders/builder";
|
||||||
|
|
||||||
|
function syndicateTemplate(str) {
|
||||||
|
return template(str, { plugins: [ "syndicate" ] });
|
||||||
|
}
|
||||||
|
|
||||||
function maybeTerminalWrap(state, terminal, ast) {
|
function maybeTerminalWrap(state, terminal, ast) {
|
||||||
if (terminal) {
|
if (terminal) {
|
||||||
|
@ -125,7 +130,7 @@ function compilePattern(state, patternPath) {
|
||||||
assn.push(a);
|
assn.push(a);
|
||||||
syndicatePath.pop();
|
syndicatePath.pop();
|
||||||
}
|
}
|
||||||
return [t.arrayExpression(skel), t.callExpression(pattern.callee, assn)];
|
return [t.arrayExpression(skel), t.callExpression(cloneDeep(pattern.callee), assn)];
|
||||||
} else {
|
} else {
|
||||||
pushConstant(pattern);
|
pushConstant(pattern);
|
||||||
return [t.nullLiteral(), pattern];
|
return [t.nullLiteral(), pattern];
|
||||||
|
@ -145,7 +150,9 @@ function compilePattern(state, patternPath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.error('Unsupported pattern node type', pattern);
|
if (!isLiteral(pattern)) {
|
||||||
|
console.error('Unsupported pattern node type', pattern);
|
||||||
|
}
|
||||||
pushConstant(pattern);
|
pushConstant(pattern);
|
||||||
return [t.nullLiteral(), pattern];
|
return [t.nullLiteral(), pattern];
|
||||||
}
|
}
|
||||||
|
@ -166,6 +173,25 @@ function compilePattern(state, patternPath) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function instantiatePatternToPattern(state, patternPath) {
|
||||||
|
patternPath.node = cloneDeep(patternPath.node);
|
||||||
|
patternPath.traverse({
|
||||||
|
CallExpression(path) {
|
||||||
|
if (isCaptureIdentifier(path.node.callee)) {
|
||||||
|
path.replaceWith(t.identifier(path.node.callee.name.slice(1)));
|
||||||
|
path.skip();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Identifier(path) {
|
||||||
|
if (isCaptureIdentifier(path.node)) {
|
||||||
|
path.replaceWith(t.identifier(path.node.name.slice(1)));
|
||||||
|
path.skip();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return patternPath.node;
|
||||||
|
}
|
||||||
|
|
||||||
function translateEndpoint(state, path, expectedEvt) {
|
function translateEndpoint(state, path, expectedEvt) {
|
||||||
const { node } = path;
|
const { node } = path;
|
||||||
let info = compilePattern(state, path.get('pattern'));
|
let info = compilePattern(state, path.get('pattern'));
|
||||||
|
@ -188,7 +214,7 @@ function translateEndpoint(state, path, expectedEvt) {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
return [ASSERTION, HANDLER];
|
return [ASSERTION, HANDLER];
|
||||||
});`)({
|
}, ISDYNAMIC);`)({
|
||||||
DATASPACE: state.DataspaceID,
|
DATASPACE: state.DataspaceID,
|
||||||
HANDLER: path.scope.generateUidIdentifier("handler"),
|
HANDLER: path.scope.generateUidIdentifier("handler"),
|
||||||
SKELETON: info.skeletonAst,
|
SKELETON: info.skeletonAst,
|
||||||
|
@ -205,6 +231,7 @@ function translateEndpoint(state, path, expectedEvt) {
|
||||||
})),
|
})),
|
||||||
BODY: maybeTerminalWrap(state, node.terminal, node.body),
|
BODY: maybeTerminalWrap(state, node.terminal, node.body),
|
||||||
ASSERTION: info.assertionAst,
|
ASSERTION: info.assertionAst,
|
||||||
|
ISDYNAMIC: t.booleanLiteral(node.isDynamic),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,13 +338,10 @@ export default declare((api, options) => {
|
||||||
const { node } = path;
|
const { node } = path;
|
||||||
switch (node.triggerType) {
|
switch (node.triggerType) {
|
||||||
case "dataflow":
|
case "dataflow":
|
||||||
path.replaceWith(template(`DATASPACE._currentFacet.addDataflow(function () {
|
path.replaceWith(syndicateTemplate(`dataflow { if (PATTERN) { BODY } }`)({
|
||||||
if (PATTERN) { BODY }
|
PATTERN: node.pattern,
|
||||||
});`)({
|
BODY: maybeTerminalWrap(state, node.terminal, node.body),
|
||||||
DATASPACE: state.DataspaceID,
|
}));
|
||||||
PATTERN: node.pattern,
|
|
||||||
BODY: maybeTerminalWrap(state, node.terminal, node.body),
|
|
||||||
}));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "asserted":
|
case "asserted":
|
||||||
|
@ -380,6 +404,60 @@ export default declare((api, options) => {
|
||||||
MODULE: node.moduleExpr,
|
MODULE: node.moduleExpr,
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
DuringStatement(path, state) {
|
||||||
|
const { node } = path;
|
||||||
|
if (node.body.type === "SpawnStatement") {
|
||||||
|
let idId = path.scope.generateUidIdentifier("id");
|
||||||
|
let instId = path.scope.generateUidIdentifier("inst");
|
||||||
|
path.replaceWith(syndicateTemplate(
|
||||||
|
`on asserted PATTERN1 {
|
||||||
|
let IDID = SYNDICATE.genUuid();
|
||||||
|
let INSTID = SYNDICATE.Instance(IDID);
|
||||||
|
react {
|
||||||
|
stop on asserted INSTID react {
|
||||||
|
stop on retracted INSTID;
|
||||||
|
stop on retracted :snapshot PATTERN2;
|
||||||
|
}
|
||||||
|
stop on retracted :snapshot PATTERN2 react {
|
||||||
|
stop on asserted INSTID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spawn {
|
||||||
|
assert INSTID;
|
||||||
|
stop on retracted SYNDICATE.Observe(INSTID);
|
||||||
|
BODY
|
||||||
|
}
|
||||||
|
}`)({
|
||||||
|
PATTERN1: node.pattern,
|
||||||
|
PATTERN2: instantiatePatternToPattern(state, path.get('pattern')),
|
||||||
|
BODY: node.body,
|
||||||
|
SYNDICATE: state.SyndicateID,
|
||||||
|
IDID: idId,
|
||||||
|
INSTID: instId,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
// during
|
||||||
|
path.replaceWith(syndicateTemplate(
|
||||||
|
`on asserted PATTERN1 react on retracted :snapshot PATTERN2 BODY`)({
|
||||||
|
PATTERN1: node.pattern,
|
||||||
|
PATTERN2: instantiatePatternToPattern(state, path.get('pattern')),
|
||||||
|
BODY: node.body,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
SyndicateReactStatement(path, state) {
|
||||||
|
const { node } = path;
|
||||||
|
path.replaceWith(template(
|
||||||
|
`DATASPACE._currentFacet.actor.addFacet(
|
||||||
|
DATASPACE._currentFacet,
|
||||||
|
function () { BODY },
|
||||||
|
true);`)({
|
||||||
|
DATASPACE: state.DataspaceID,
|
||||||
|
BODY: node.body,
|
||||||
|
}));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -81,8 +81,8 @@ defineType("DataflowStatement", {
|
||||||
});
|
});
|
||||||
|
|
||||||
defineType("EventHandlerEndpoint", {
|
defineType("EventHandlerEndpoint", {
|
||||||
builder: ["terminal", "triggerType", "pattern", "body"],
|
builder: ["terminal", "triggerType", "isDynamic", "pattern", "body"],
|
||||||
visitor: ["terminal", "triggerType", "pattern", "body"],
|
visitor: ["terminal", "triggerType", "isDynamic", "pattern", "body"],
|
||||||
aliases: ["Statement"],
|
aliases: ["Statement"],
|
||||||
fields: {
|
fields: {
|
||||||
terminal: {
|
terminal: {
|
||||||
|
@ -91,6 +91,9 @@ defineType("EventHandlerEndpoint", {
|
||||||
triggerType: {
|
triggerType: {
|
||||||
validate: assertOneOf("asserted", "retracted", "message", "dataflow"),
|
validate: assertOneOf("asserted", "retracted", "message", "dataflow"),
|
||||||
},
|
},
|
||||||
|
isDynamic: {
|
||||||
|
validate: assertOneOf(true, false),
|
||||||
|
},
|
||||||
pattern: {
|
pattern: {
|
||||||
validate: assertNodeType("Expression"),
|
validate: assertNodeType("Expression"),
|
||||||
},
|
},
|
||||||
|
@ -159,3 +162,28 @@ defineType("ActivationExpression", {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
defineType("DuringStatement", {
|
||||||
|
builder: ["pattern", "body"],
|
||||||
|
visitor: ["pattern", "body"],
|
||||||
|
aliases: ["Statement"],
|
||||||
|
fields: {
|
||||||
|
pattern: {
|
||||||
|
validate: assertNodeType("Expression"),
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
validate: assertNodeType("Statement"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
defineType("SyndicateReactStatement", {
|
||||||
|
builder: ["body"],
|
||||||
|
visitor: ["body"],
|
||||||
|
aliases: ["Statement"],
|
||||||
|
fields: {
|
||||||
|
body: {
|
||||||
|
validate: assertNodeType("Statement"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue