From 43b5987e8b00482782df766d1b726404f4e4b2a9 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 5 Nov 2018 17:48:26 +0000 Subject: [PATCH] spawn :let ID = INIT :let ID = INIT ... { ... } --- TODO.md | 1 + packages/syntax/src/generators.js | 10 ++++++++++ packages/syntax/src/index.js | 1 + packages/syntax/src/parser.js | 18 ++++++++++++++++-- packages/syntax/src/plugin.js | 10 ++++++++++ packages/syntax/src/types.js | 12 +++++++++--- 6 files changed, 47 insertions(+), 5 deletions(-) diff --git a/TODO.md b/TODO.md index fff8a20..bb04014 100644 --- a/TODO.md +++ b/TODO.md @@ -5,6 +5,7 @@ - [DONE] `spawn*` or similar - looks like `spawn on start { ... }` will do the trick - [DONE] activation - [DONE] remove ground dataspace syntax + - [DONE] `spawn :let childVal = parentCalculation { ... }` - `defer` statement - `define/query` diff --git a/packages/syntax/src/generators.js b/packages/syntax/src/generators.js index 40ec24c..c57c71b 100644 --- a/packages/syntax/src/generators.js +++ b/packages/syntax/src/generators.js @@ -32,6 +32,16 @@ export function SpawnStatement(node) { this.space(); this.print(a, node); } + for (let i = 0; i < node.parentIds.length; i++) { + this.space(); + this.token(":let"); + this.space(); + this.print(node.parentIds[i], node); + this.space(); + this.token("="); + this.space(); + this.print(node.parentInits[i], node); + } this.space(); this.printBlock(node.bootProc); } diff --git a/packages/syntax/src/index.js b/packages/syntax/src/index.js index e069a6a..5f74427 100644 --- a/packages/syntax/src/index.js +++ b/packages/syntax/src/index.js @@ -89,6 +89,7 @@ Array.prototype.push.apply(Types.TYPES, Object.keys(Types.DEPRECATED_KEYS)); // Types.getBindingIdentifiers.keys.EventHandlerEndpoint = ["captureIds"]; Types.getBindingIdentifiers.keys.DuringStatement = ["captureIds"]; +Types.getBindingIdentifiers.keys.SpawnStatement = ["parentIds"]; //--------------------------------------------------------------------------- // (3) Install our modified parser in place of the core parser. diff --git a/packages/syntax/src/parser.js b/packages/syntax/src/parser.js index d5eb62a..8f27274 100644 --- a/packages/syntax/src/parser.js +++ b/packages/syntax/src/parser.js @@ -202,10 +202,24 @@ export default class SyndicateParser extends _original_Parser { node.name = this.parseExpression(); } node.initialAssertions = []; + node.parentIds = []; + node.parentInits = []; while (this.match(tt.colon)) { this.next(); - this.expectContextual("asserting"); - node.initialAssertions.push(this.parseExpression()); + if (this.isContextual("asserting")) { + this.next(); + node.initialAssertions.push(this.parseExpression()); + } else if (this.state.type === tt._let) { + this.next(); + const id = this.parseBindingAtom(); + this.checkLVal(id, true, undefined, "spawn :let declaration"); + this.expect(tt.eq); + const init = this.parseMaybeAssign(false); + node.parentIds.push(id); + node.parentInits.push(init); + } else { + this.unexpected(); + } } node.bootProc = this.parseSyntheticFunctionStatement(); return this.finishNode(node, "SpawnStatement"); diff --git a/packages/syntax/src/plugin.js b/packages/syntax/src/plugin.js index a3221f8..16e258c 100644 --- a/packages/syntax/src/plugin.js +++ b/packages/syntax/src/plugin.js @@ -348,6 +348,16 @@ export default declare((api, options) => { SEQ: t.arrayExpression(node.initialAssertions) }), })); + if (node.parentIds.length > 0) { + const stmts = []; + for (let i = 0; i < node.parentIds.length; i++) { + const id = node.parentIds[i]; + const init = node.parentInits[i]; + stmts.push(template(`const ID = INIT;`)({ ID: id, INIT: init })); + } + stmts.push(path.node); + path.replaceWith(t.blockStatement(stmts, [])); + } }, FieldDeclarationStatement(path, state) { diff --git a/packages/syntax/src/types.js b/packages/syntax/src/types.js index f452a64..9ce1cd4 100644 --- a/packages/syntax/src/types.js +++ b/packages/syntax/src/types.js @@ -25,9 +25,9 @@ import defineType, { } from "@babel/types/lib/definitions/utils"; defineType("SpawnStatement", { - builder: ["name", "initialAssertions", "bootProc"], - visitor: ["name", "initialAssertions", "bootProc"], - aliases: ["Statement"], + builder: ["name", "initialAssertions", "parentIds", "parentInits", "bootProc"], + visitor: ["name", "initialAssertions", "parentIds", "parentInits", "bootProc"], + aliases: ["Statement", "Scopable"], fields: { name: { validate: assertNodeType("Expression"), @@ -39,6 +39,12 @@ defineType("SpawnStatement", { assertEach(assertNodeType("Expression")), ), }, + parentIds: { + validate: chain(assertValueType("array"), assertEach(assertNodeType("Identifier")),), + }, + parentInits: { + validate: chain(assertValueType("array"), assertEach(assertNodeType("Expression")),), + }, bootProc: { validate: assertNodeType("FunctionExpression"), },