Syntax support for initial assertions on spawn
This commit is contained in:
parent
2688c09639
commit
a1d57e61f1
|
@ -20,13 +20,19 @@ import * as t from "@babel/types";
|
|||
|
||||
export function SpawnStatement(node) {
|
||||
this.word("spawn");
|
||||
this.space();
|
||||
if (node.name) {
|
||||
this.space();
|
||||
this.word("named");
|
||||
this.space();
|
||||
this.print(node.name, node);
|
||||
this.space();
|
||||
}
|
||||
for (let a of node.initialAssertions) {
|
||||
this.space();
|
||||
this.token(":asserting");
|
||||
this.space();
|
||||
this.print(a, node);
|
||||
}
|
||||
this.space();
|
||||
this.printBlock(node);
|
||||
}
|
||||
|
||||
|
|
|
@ -199,6 +199,12 @@ export default class SyndicateParser extends _original_Parser {
|
|||
this.next();
|
||||
node.name = this.parseExpression();
|
||||
}
|
||||
node.initialAssertions = [];
|
||||
while (this.match(tt.colon)) {
|
||||
this.next();
|
||||
this.expectContextual("asserting");
|
||||
node.initialAssertions.push(this.parseExpression());
|
||||
}
|
||||
node.body = this.parseStatement();
|
||||
return this.finishNode(node, "SpawnStatement");
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ function discardAst(state) {
|
|||
return _discardAst({ SYNDICATE: state.SyndicateID });
|
||||
}
|
||||
|
||||
const _listAst = template.expression(`IMMUTABLE.List(VS)`);
|
||||
const _listAst = template.expression(`IMMUTABLE.fromJS(VS)`);
|
||||
function listAst(state, vs) {
|
||||
return _listAst({ IMMUTABLE: state.ImmutableID, VS: vs });
|
||||
}
|
||||
|
@ -149,6 +149,25 @@ function compilePattern(state, patternPath) {
|
|||
return [t.nullLiteral(), pattern];
|
||||
}
|
||||
|
||||
case 'ArrayExpression': {
|
||||
if (hasCapturesOrDiscards(patternPath)) {
|
||||
let arity = pattern.elements.length;
|
||||
let skel = [t.numericLiteral(arity)];
|
||||
let assn = [];
|
||||
for (let i = 0; i < arity; i++) {
|
||||
syndicatePath.push(i);
|
||||
let [s, a] = walk(patternPath.get('elements.' + i));
|
||||
skel.push(s);
|
||||
assn.push(a);
|
||||
syndicatePath.pop();
|
||||
}
|
||||
return [t.arrayExpression(skel), t.arrayExpression(assn)];
|
||||
} else {
|
||||
pushConstant(pattern);
|
||||
return [t.nullLiteral(), pattern];
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
if (!isLiteral(pattern)) {
|
||||
console.error('Unsupported pattern node type', pattern);
|
||||
|
@ -286,10 +305,15 @@ export default declare((api, options) => {
|
|||
|
||||
SpawnStatement(path, state) {
|
||||
const { node } = path;
|
||||
path.replaceWith(template(`DATASPACE.spawn(NAME, function () { BODY })`)({
|
||||
path.replaceWith(template(`DATASPACE.spawn(NAME, function () { BODY }, ASSERTIONS)`)({
|
||||
DATASPACE: state.DataspaceID,
|
||||
NAME: node.name || t.nullLiteral(),
|
||||
BODY: node.body
|
||||
BODY: node.body,
|
||||
ASSERTIONS: node.initialAssertions.length === 0 ? null :
|
||||
template.expression(`IMMUTABLE.Set(SEQ)`)({
|
||||
IMMUTABLE: state.ImmutableID,
|
||||
SEQ: t.arrayExpression(node.initialAssertions)
|
||||
}),
|
||||
}));
|
||||
},
|
||||
|
||||
|
@ -410,6 +434,26 @@ export default declare((api, options) => {
|
|||
if (node.body.type === "SpawnStatement") {
|
||||
let idId = path.scope.generateUidIdentifier("id");
|
||||
let instId = path.scope.generateUidIdentifier("inst");
|
||||
let bodyPath = path.get('body');
|
||||
bodyPath.unshiftContainer('initialAssertions', [
|
||||
template.expression(`I`)({
|
||||
I: instId
|
||||
}),
|
||||
template.expression(`S.Observe(S.Observe(I))`)({
|
||||
S: state.SyndicateID,
|
||||
I: instId
|
||||
}),
|
||||
]);
|
||||
bodyPath.get('body').replaceWithMultiple([
|
||||
syndicateTemplate(`assert I;`)({
|
||||
I: instId
|
||||
}),
|
||||
syndicateTemplate(`stop on retracted S.Observe(I);`)({
|
||||
S: state.SyndicateID,
|
||||
I: instId
|
||||
}),
|
||||
node.body.body,
|
||||
]);
|
||||
path.replaceWith(syndicateTemplate(
|
||||
`on asserted PATTERN1 {
|
||||
let IDID = SYNDICATE.genUuid();
|
||||
|
@ -423,16 +467,11 @@ export default declare((api, options) => {
|
|||
stop on asserted INSTID;
|
||||
}
|
||||
}
|
||||
spawn named NAME {
|
||||
assert INSTID;
|
||||
stop on retracted SYNDICATE.Observe(INSTID);
|
||||
BODY
|
||||
}
|
||||
BODY
|
||||
}`)({
|
||||
PATTERN1: node.pattern,
|
||||
PATTERN2: instantiatePatternToPattern(state, path.get('pattern')),
|
||||
NAME: node.body.name || t.nullLiteral(),
|
||||
BODY: node.body.body, // the body of the SPAWN, which is itself the body of `node`
|
||||
BODY: node.body,
|
||||
SYNDICATE: state.SyndicateID,
|
||||
IDID: idId,
|
||||
INSTID: instId,
|
||||
|
|
|
@ -25,14 +25,20 @@ import defineType, {
|
|||
} from "@babel/types/lib/definitions/utils";
|
||||
|
||||
defineType("SpawnStatement", {
|
||||
builder: ["name", "body"],
|
||||
visitor: ["name", "body"],
|
||||
builder: ["name", "initialAssertions", "body"],
|
||||
visitor: ["name", "initialAssertions", "body"],
|
||||
aliases: ["Statement"],
|
||||
fields: {
|
||||
name: {
|
||||
validate: assertNodeType("Expression"),
|
||||
optional: true,
|
||||
},
|
||||
initialAssertions: {
|
||||
validate: chain(
|
||||
assertValueType("array"),
|
||||
assertEach(assertNodeType("Expression")),
|
||||
),
|
||||
},
|
||||
body: {
|
||||
validate: assertNodeType("Statement"),
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue