Avoid this-scoping problem with spawn by having body be a FunctionExpression

This commit is contained in:
Tony Garnock-Jones 2018-11-05 16:47:45 +00:00
parent 4ee225b9dd
commit 6f929e4330
4 changed files with 31 additions and 11 deletions

View File

@ -33,7 +33,7 @@ export function SpawnStatement(node) {
this.print(a, node);
}
this.space();
this.printBlock(node);
this.printBlock(node.bootProc);
}
export function FieldDeclarationStatement(node) {

View File

@ -207,10 +207,25 @@ export default class SyndicateParser extends _original_Parser {
this.expectContextual("asserting");
node.initialAssertions.push(this.parseExpression());
}
node.body = this.parseStatement();
node.bootProc = this.parseSyntheticFunctionStatement();
return this.finishNode(node, "SpawnStatement");
}
parseSyntheticFunctionStatement() {
const node = this.startNode();
node.params = [];
const stmt = this.parseStatement();
if (stmt.type === "BlockStatement") {
node.body = stmt;
} else {
const blk = this.startNode();
blk.directives = [];
blk.body = [stmt];
node.body = this.finishNode(blk, "BlockStatement");
}
return this.finishNode(node, "FunctionExpression");
}
parseEventHandlerEndpoint(terminal, pseudoEventsAllowed) {
this.expectContextual("on");
const node = this.startNode();

View File

@ -23,6 +23,9 @@ import template from "@babel/template";
import traverse from "@babel/traverse";
import builder from "@babel/types/lib/builders/builder";
import generate from "@babel/generator";
function _GEN(x) { console.log(generate(x).code); }
function syndicateTemplate(str) {
return template(str, { plugins: [ "syndicate" ] });
}
@ -215,6 +218,7 @@ function instantiatePatternToPattern(state, patternPath) {
const bindingRegistrationVisitor = {
EventHandlerEndpoint(path, state) {
if (Array.isArray(path.node.captureIds)) return;
switch (path.node.triggerType) {
case "dataflow":
break;
@ -230,6 +234,7 @@ const bindingRegistrationVisitor = {
},
DuringStatement(path, state) {
if (Array.isArray(path.node.captureIds)) return;
let info = compilePattern(state, path.get('pattern'));
path.node.captureIds = info.captureIds;
path.scope.registerBinding('let', path);
@ -333,10 +338,10 @@ export default declare((api, options) => {
SpawnStatement(path, state) {
const { node } = path;
path.replaceWith(template(`DATASPACE.spawn(NAME, function () { BODY }, ASSERTIONS)`)({
path.replaceWith(template(`DATASPACE.spawn(NAME, PROC, ASSERTIONS)`)({
DATASPACE: state.DataspaceID,
NAME: node.name || t.nullLiteral(),
BODY: node.body,
PROC: node.bootProc,
ASSERTIONS: node.initialAssertions.length === 0 ? null :
template.expression(`IMMUTABLE.Set(SEQ)`)({
IMMUTABLE: state.ImmutableID,
@ -474,7 +479,7 @@ export default declare((api, options) => {
I: instId
}),
]);
bodyPath.get('body').replaceWithMultiple([
bodyPath.get('bootProc.body').replaceWithMultiple([
syndicateTemplate(`assert I;`)({
I: instId
}),
@ -482,7 +487,7 @@ export default declare((api, options) => {
S: state.SyndicateID,
I: instId
}),
node.body.body,
node.body.bootProc.body,
]);
path.replaceWith(syndicateTemplate(
`on asserted PATTERN1 {
@ -507,7 +512,6 @@ export default declare((api, options) => {
INSTID: instId,
}));
} else {
// during
path.replaceWith(syndicateTemplate(
`on asserted PATTERN1 react {
stop on retracted :snapshot PATTERN2;
@ -518,6 +522,7 @@ export default declare((api, options) => {
BODY: node.body,
}));
}
path.parentPath.traverse(bindingRegistrationVisitor, state);
},
SyndicateReactStatement(path, state) {

View File

@ -25,8 +25,8 @@ import defineType, {
} from "@babel/types/lib/definitions/utils";
defineType("SpawnStatement", {
builder: ["name", "initialAssertions", "body"],
visitor: ["name", "initialAssertions", "body"],
builder: ["name", "initialAssertions", "bootProc"],
visitor: ["name", "initialAssertions", "bootProc"],
aliases: ["Statement"],
fields: {
name: {
@ -39,8 +39,8 @@ defineType("SpawnStatement", {
assertEach(assertNodeType("Expression")),
),
},
body: {
validate: assertNodeType("Statement"),
bootProc: {
validate: assertNodeType("FunctionExpression"),
},
},
});