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.Inbound = Struct.makeConstructor('Inbound', ['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.Inbound = Assertions.Inbound;
|
||||
module.exports.Outbound = Assertions.Outbound;
|
||||
module.exports.Instance = Assertions.Instance;
|
||||
|
||||
module.exports.bootModule = Ground.bootModule;
|
||||
|
||||
module.exports.genUuid = function () {
|
||||
return Symbol('@syndicate-lang/core');
|
||||
};
|
||||
|
|
|
@ -78,6 +78,10 @@ export function EventHandlerEndpoint(node) {
|
|||
} else {
|
||||
this.word(node.triggerType);
|
||||
this.space();
|
||||
if (!node.isDynamic) {
|
||||
this.word(":snapshot");
|
||||
this.space();
|
||||
}
|
||||
this.print(node.pattern, node);
|
||||
}
|
||||
this.space();
|
||||
|
@ -122,3 +126,17 @@ export function ActivationExpression(node) {
|
|||
this.space();
|
||||
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")) {
|
||||
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");
|
||||
return this.parseSpawnStatement();
|
||||
}
|
||||
|
||||
if (this.isContextual("assert")) {
|
||||
|
@ -127,6 +120,25 @@ export default class SyndicateParser extends _original_Parser {
|
|||
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")) {
|
||||
const node = this.startNode();
|
||||
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) {
|
||||
this.expectContextual("on");
|
||||
const node = this.startNode();
|
||||
|
@ -187,6 +210,7 @@ export default class SyndicateParser extends _original_Parser {
|
|||
if (this.match(tt.parenL)) {
|
||||
node.terminal = terminal;
|
||||
node.triggerType = "dataflow";
|
||||
node.isDynamic = true;
|
||||
node.pattern = this.parseExpression();
|
||||
node.body = this.parseStatement();
|
||||
return this.finishNode(node, "EventHandlerEndpoint");
|
||||
|
@ -213,6 +237,7 @@ export default class SyndicateParser extends _original_Parser {
|
|||
case "message":
|
||||
node.triggerType = this.state.value;
|
||||
this.next();
|
||||
node.isDynamic = this.parseMaybeSnapshot();
|
||||
node.terminal = terminal;
|
||||
node.pattern = this.parseExpression();
|
||||
node.body = this.parseStatement();
|
||||
|
@ -222,4 +247,14 @@ export default class SyndicateParser extends _original_Parser {
|
|||
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 { types as t } from "@babel/core";
|
||||
import { cloneDeep } from "@babel/types";
|
||||
import { cloneDeep, isLiteral } from "@babel/types";
|
||||
import template from "@babel/template";
|
||||
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) {
|
||||
if (terminal) {
|
||||
|
@ -125,7 +130,7 @@ function compilePattern(state, patternPath) {
|
|||
assn.push(a);
|
||||
syndicatePath.pop();
|
||||
}
|
||||
return [t.arrayExpression(skel), t.callExpression(pattern.callee, assn)];
|
||||
return [t.arrayExpression(skel), t.callExpression(cloneDeep(pattern.callee), assn)];
|
||||
} else {
|
||||
pushConstant(pattern);
|
||||
return [t.nullLiteral(), pattern];
|
||||
|
@ -145,7 +150,9 @@ function compilePattern(state, patternPath) {
|
|||
}
|
||||
|
||||
default:
|
||||
console.error('Unsupported pattern node type', pattern);
|
||||
if (!isLiteral(pattern)) {
|
||||
console.error('Unsupported pattern node type', pattern);
|
||||
}
|
||||
pushConstant(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) {
|
||||
const { node } = path;
|
||||
let info = compilePattern(state, path.get('pattern'));
|
||||
|
@ -188,7 +214,7 @@ function translateEndpoint(state, path, expectedEvt) {
|
|||
})
|
||||
};
|
||||
return [ASSERTION, HANDLER];
|
||||
});`)({
|
||||
}, ISDYNAMIC);`)({
|
||||
DATASPACE: state.DataspaceID,
|
||||
HANDLER: path.scope.generateUidIdentifier("handler"),
|
||||
SKELETON: info.skeletonAst,
|
||||
|
@ -205,6 +231,7 @@ function translateEndpoint(state, path, expectedEvt) {
|
|||
})),
|
||||
BODY: maybeTerminalWrap(state, node.terminal, node.body),
|
||||
ASSERTION: info.assertionAst,
|
||||
ISDYNAMIC: t.booleanLiteral(node.isDynamic),
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -311,13 +338,10 @@ export default declare((api, options) => {
|
|||
const { node } = path;
|
||||
switch (node.triggerType) {
|
||||
case "dataflow":
|
||||
path.replaceWith(template(`DATASPACE._currentFacet.addDataflow(function () {
|
||||
if (PATTERN) { BODY }
|
||||
});`)({
|
||||
DATASPACE: state.DataspaceID,
|
||||
PATTERN: node.pattern,
|
||||
BODY: maybeTerminalWrap(state, node.terminal, node.body),
|
||||
}));
|
||||
path.replaceWith(syndicateTemplate(`dataflow { if (PATTERN) { BODY } }`)({
|
||||
PATTERN: node.pattern,
|
||||
BODY: maybeTerminalWrap(state, node.terminal, node.body),
|
||||
}));
|
||||
break;
|
||||
|
||||
case "asserted":
|
||||
|
@ -380,6 +404,60 @@ export default declare((api, options) => {
|
|||
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", {
|
||||
builder: ["terminal", "triggerType", "pattern", "body"],
|
||||
visitor: ["terminal", "triggerType", "pattern", "body"],
|
||||
builder: ["terminal", "triggerType", "isDynamic", "pattern", "body"],
|
||||
visitor: ["terminal", "triggerType", "isDynamic", "pattern", "body"],
|
||||
aliases: ["Statement"],
|
||||
fields: {
|
||||
terminal: {
|
||||
|
@ -91,6 +91,9 @@ defineType("EventHandlerEndpoint", {
|
|||
triggerType: {
|
||||
validate: assertOneOf("asserted", "retracted", "message", "dataflow"),
|
||||
},
|
||||
isDynamic: {
|
||||
validate: assertOneOf(true, false),
|
||||
},
|
||||
pattern: {
|
||||
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