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.print(a, node);
} }
this.space(); this.space();
this.printBlock(node); this.printBlock(node.bootProc);
} }
export function FieldDeclarationStatement(node) { export function FieldDeclarationStatement(node) {

View File

@ -207,10 +207,25 @@ export default class SyndicateParser extends _original_Parser {
this.expectContextual("asserting"); this.expectContextual("asserting");
node.initialAssertions.push(this.parseExpression()); node.initialAssertions.push(this.parseExpression());
} }
node.body = this.parseStatement(); node.bootProc = this.parseSyntheticFunctionStatement();
return this.finishNode(node, "SpawnStatement"); 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) { parseEventHandlerEndpoint(terminal, pseudoEventsAllowed) {
this.expectContextual("on"); this.expectContextual("on");
const node = this.startNode(); const node = this.startNode();

View File

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

View File

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