From 6f929e43306c711f6da7573ef3072946114082c4 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 5 Nov 2018 16:47:45 +0000 Subject: [PATCH] Avoid this-scoping problem with spawn by having body be a FunctionExpression --- packages/syntax/src/generators.js | 2 +- packages/syntax/src/parser.js | 17 ++++++++++++++++- packages/syntax/src/plugin.js | 15 ++++++++++----- packages/syntax/src/types.js | 8 ++++---- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/syntax/src/generators.js b/packages/syntax/src/generators.js index 0d9748b..40ec24c 100644 --- a/packages/syntax/src/generators.js +++ b/packages/syntax/src/generators.js @@ -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) { diff --git a/packages/syntax/src/parser.js b/packages/syntax/src/parser.js index b3b7092..d5eb62a 100644 --- a/packages/syntax/src/parser.js +++ b/packages/syntax/src/parser.js @@ -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(); diff --git a/packages/syntax/src/plugin.js b/packages/syntax/src/plugin.js index ff9e6bb..a3221f8 100644 --- a/packages/syntax/src/plugin.js +++ b/packages/syntax/src/plugin.js @@ -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) { diff --git a/packages/syntax/src/types.js b/packages/syntax/src/types.js index a8789e5..f452a64 100644 --- a/packages/syntax/src/types.js +++ b/packages/syntax/src/types.js @@ -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"), }, }, });