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) {
|
export function SpawnStatement(node) {
|
||||||
this.word("spawn");
|
this.word("spawn");
|
||||||
this.space();
|
|
||||||
if (node.name) {
|
if (node.name) {
|
||||||
|
this.space();
|
||||||
this.word("named");
|
this.word("named");
|
||||||
this.space();
|
this.space();
|
||||||
this.print(node.name, node);
|
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);
|
this.printBlock(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,12 @@ export default class SyndicateParser extends _original_Parser {
|
||||||
this.next();
|
this.next();
|
||||||
node.name = this.parseExpression();
|
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();
|
node.body = this.parseStatement();
|
||||||
return this.finishNode(node, "SpawnStatement");
|
return this.finishNode(node, "SpawnStatement");
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ function discardAst(state) {
|
||||||
return _discardAst({ SYNDICATE: state.SyndicateID });
|
return _discardAst({ SYNDICATE: state.SyndicateID });
|
||||||
}
|
}
|
||||||
|
|
||||||
const _listAst = template.expression(`IMMUTABLE.List(VS)`);
|
const _listAst = template.expression(`IMMUTABLE.fromJS(VS)`);
|
||||||
function listAst(state, vs) {
|
function listAst(state, vs) {
|
||||||
return _listAst({ IMMUTABLE: state.ImmutableID, VS: vs });
|
return _listAst({ IMMUTABLE: state.ImmutableID, VS: vs });
|
||||||
}
|
}
|
||||||
|
@ -149,6 +149,25 @@ function compilePattern(state, patternPath) {
|
||||||
return [t.nullLiteral(), pattern];
|
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:
|
default:
|
||||||
if (!isLiteral(pattern)) {
|
if (!isLiteral(pattern)) {
|
||||||
console.error('Unsupported pattern node type', pattern);
|
console.error('Unsupported pattern node type', pattern);
|
||||||
|
@ -286,10 +305,15 @@ export default declare((api, options) => {
|
||||||
|
|
||||||
SpawnStatement(path, state) {
|
SpawnStatement(path, state) {
|
||||||
const { node } = path;
|
const { node } = path;
|
||||||
path.replaceWith(template(`DATASPACE.spawn(NAME, function () { BODY })`)({
|
path.replaceWith(template(`DATASPACE.spawn(NAME, function () { BODY }, ASSERTIONS)`)({
|
||||||
DATASPACE: state.DataspaceID,
|
DATASPACE: state.DataspaceID,
|
||||||
NAME: node.name || t.nullLiteral(),
|
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") {
|
if (node.body.type === "SpawnStatement") {
|
||||||
let idId = path.scope.generateUidIdentifier("id");
|
let idId = path.scope.generateUidIdentifier("id");
|
||||||
let instId = path.scope.generateUidIdentifier("inst");
|
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(
|
path.replaceWith(syndicateTemplate(
|
||||||
`on asserted PATTERN1 {
|
`on asserted PATTERN1 {
|
||||||
let IDID = SYNDICATE.genUuid();
|
let IDID = SYNDICATE.genUuid();
|
||||||
|
@ -423,16 +467,11 @@ export default declare((api, options) => {
|
||||||
stop on asserted INSTID;
|
stop on asserted INSTID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spawn named NAME {
|
BODY
|
||||||
assert INSTID;
|
|
||||||
stop on retracted SYNDICATE.Observe(INSTID);
|
|
||||||
BODY
|
|
||||||
}
|
|
||||||
}`)({
|
}`)({
|
||||||
PATTERN1: node.pattern,
|
PATTERN1: node.pattern,
|
||||||
PATTERN2: instantiatePatternToPattern(state, path.get('pattern')),
|
PATTERN2: instantiatePatternToPattern(state, path.get('pattern')),
|
||||||
NAME: node.body.name || t.nullLiteral(),
|
BODY: node.body,
|
||||||
BODY: node.body.body, // the body of the SPAWN, which is itself the body of `node`
|
|
||||||
SYNDICATE: state.SyndicateID,
|
SYNDICATE: state.SyndicateID,
|
||||||
IDID: idId,
|
IDID: idId,
|
||||||
INSTID: instId,
|
INSTID: instId,
|
||||||
|
|
|
@ -25,14 +25,20 @@ import defineType, {
|
||||||
} from "@babel/types/lib/definitions/utils";
|
} from "@babel/types/lib/definitions/utils";
|
||||||
|
|
||||||
defineType("SpawnStatement", {
|
defineType("SpawnStatement", {
|
||||||
builder: ["name", "body"],
|
builder: ["name", "initialAssertions", "body"],
|
||||||
visitor: ["name", "body"],
|
visitor: ["name", "initialAssertions", "body"],
|
||||||
aliases: ["Statement"],
|
aliases: ["Statement"],
|
||||||
fields: {
|
fields: {
|
||||||
name: {
|
name: {
|
||||||
validate: assertNodeType("Expression"),
|
validate: assertNodeType("Expression"),
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
initialAssertions: {
|
||||||
|
validate: chain(
|
||||||
|
assertValueType("array"),
|
||||||
|
assertEach(assertNodeType("Expression")),
|
||||||
|
),
|
||||||
|
},
|
||||||
body: {
|
body: {
|
||||||
validate: assertNodeType("Statement"),
|
validate: assertNodeType("Statement"),
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue