ts2workflows 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/ast/expressions.d.ts.map +1 -1
- package/dist/ast/expressions.js +7 -10
- package/dist/ast/stepnames.d.ts.map +1 -1
- package/dist/ast/stepnames.js +11 -1
- package/dist/ast/steps.d.ts +24 -13
- package/dist/ast/steps.d.ts.map +1 -1
- package/dist/ast/steps.js +54 -38
- package/dist/transpiler/expressions.d.ts +8 -4
- package/dist/transpiler/expressions.d.ts.map +1 -1
- package/dist/transpiler/expressions.js +162 -42
- package/dist/transpiler/index.d.ts.map +1 -1
- package/dist/transpiler/index.js +29 -28
- package/dist/transpiler/statements.d.ts +2 -1
- package/dist/transpiler/statements.d.ts.map +1 -1
- package/dist/transpiler/statements.js +137 -155
- package/dist/transpiler/transformations.d.ts.map +1 -1
- package/dist/transpiler/transformations.js +216 -110
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +6 -0
- package/language_reference.md +55 -33
- package/package.json +11 -4
- package/types/global.d.ts +124 -0
- package/dist/transpiler/asserts.d.ts +0 -7
- package/dist/transpiler/asserts.d.ts.map +0 -1
- package/dist/transpiler/asserts.js +0 -11
|
@@ -1,105 +1,92 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { AssignStepAST, CallStepAST, ForStepAST, JumpTargetAST, NextStepAST, ParallelStepAST, RaiseStepAST, ReturnStepAST, StepsStepAST, SwitchStepAST, TryStepAST, stepWithLabel, } from '../ast/steps.js';
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
|
|
2
|
+
import { AssignStepAST, CallStepAST, ForStepAST, JumpTargetAST, NextStepAST, ParallelStepAST, RaiseStepAST, ReturnStepAST, StepsStepAST, SwitchStepAST, TryStepAST, } from '../ast/steps.js';
|
|
4
3
|
import { BinaryExpression, FunctionInvocationExpression, PrimitiveExpression, VariableReferenceExpression, isExpression, isFullyQualifiedName, isLiteral, } from '../ast/expressions.js';
|
|
5
4
|
import { InternalTranspilingError, WorkflowSyntaxError } from '../errors.js';
|
|
6
5
|
import { isRecord } from '../utils.js';
|
|
7
6
|
import { transformAST } from './transformations.js';
|
|
8
|
-
import {
|
|
9
|
-
import { convertExpression, convertMemberExpression, convertObjectExpression, convertObjectAsExpressionValues, } from './expressions.js';
|
|
7
|
+
import { convertExpression, convertMemberExpression, convertObjectExpression, convertObjectAsExpressionValues, isMagicFunction, throwIfSpread, isMagicFunctionStatmentOnly, } from './expressions.js';
|
|
10
8
|
import { blockingFunctions } from './generated/functionMetadata.js';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const body = node.body;
|
|
15
|
-
return transformAST(body.flatMap((x) => parseStep(x, ctx)));
|
|
9
|
+
export function parseStatement(node, ctx, postSteps) {
|
|
10
|
+
const steps = parseStatementRecursively(node, ctx);
|
|
11
|
+
return transformAST(steps.concat(postSteps ?? []));
|
|
16
12
|
}
|
|
17
|
-
function
|
|
13
|
+
function parseStatementRecursively(node, ctx) {
|
|
18
14
|
switch (node.type) {
|
|
19
|
-
case
|
|
20
|
-
return
|
|
21
|
-
case
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
case AST_NODE_TYPES.BlockStatement:
|
|
16
|
+
return node.body.flatMap((statement) => parseStatementRecursively(statement, ctx));
|
|
17
|
+
case AST_NODE_TYPES.VariableDeclaration:
|
|
18
|
+
return convertVariableDeclarations(node.declarations, ctx);
|
|
19
|
+
case AST_NODE_TYPES.ExpressionStatement:
|
|
20
|
+
if (node.expression.type === AST_NODE_TYPES.AssignmentExpression) {
|
|
21
|
+
return assignmentExpressionToSteps(node.expression, ctx);
|
|
24
22
|
}
|
|
25
|
-
else if (node.expression.type === CallExpression) {
|
|
26
|
-
return [callExpressionToStep(node.expression, ctx)];
|
|
23
|
+
else if (node.expression.type === AST_NODE_TYPES.CallExpression) {
|
|
24
|
+
return [callExpressionToStep(node.expression, undefined, ctx)];
|
|
27
25
|
}
|
|
28
26
|
else {
|
|
29
27
|
return [generalExpressionToAssignStep(node.expression)];
|
|
30
28
|
}
|
|
31
|
-
case ReturnStatement:
|
|
29
|
+
case AST_NODE_TYPES.ReturnStatement:
|
|
32
30
|
return [returnStatementToReturnStep(node)];
|
|
33
|
-
case ThrowStatement:
|
|
31
|
+
case AST_NODE_TYPES.ThrowStatement:
|
|
34
32
|
return [throwStatementToRaiseStep(node)];
|
|
35
|
-
case IfStatement:
|
|
33
|
+
case AST_NODE_TYPES.IfStatement:
|
|
36
34
|
return [ifStatementToSwitchStep(node, ctx)];
|
|
37
|
-
case SwitchStatement:
|
|
35
|
+
case AST_NODE_TYPES.SwitchStatement:
|
|
38
36
|
return switchStatementToSteps(node, ctx);
|
|
39
|
-
case ForInStatement:
|
|
37
|
+
case AST_NODE_TYPES.ForInStatement:
|
|
40
38
|
throw new WorkflowSyntaxError('for...in is not a supported construct. Use for...of.', node.loc);
|
|
41
|
-
case ForOfStatement:
|
|
39
|
+
case AST_NODE_TYPES.ForOfStatement:
|
|
42
40
|
return [forOfStatementToForStep(node, ctx)];
|
|
43
|
-
case DoWhileStatement:
|
|
41
|
+
case AST_NODE_TYPES.DoWhileStatement:
|
|
44
42
|
return doWhileStatementSteps(node, ctx);
|
|
45
|
-
case WhileStatement:
|
|
43
|
+
case AST_NODE_TYPES.WhileStatement:
|
|
46
44
|
return whileStatementSteps(node, ctx);
|
|
47
|
-
case BreakStatement:
|
|
45
|
+
case AST_NODE_TYPES.BreakStatement:
|
|
48
46
|
return [breakStatementToNextStep(node, ctx)];
|
|
49
|
-
case ContinueStatement:
|
|
47
|
+
case AST_NODE_TYPES.ContinueStatement:
|
|
50
48
|
return [continueStatementToNextStep(node, ctx)];
|
|
51
|
-
case TryStatement:
|
|
49
|
+
case AST_NODE_TYPES.TryStatement:
|
|
52
50
|
return [tryStatementToTryStep(node, ctx)];
|
|
53
|
-
case LabeledStatement:
|
|
51
|
+
case AST_NODE_TYPES.LabeledStatement:
|
|
54
52
|
return labeledStep(node, ctx);
|
|
55
|
-
case EmptyStatement:
|
|
53
|
+
case AST_NODE_TYPES.EmptyStatement:
|
|
56
54
|
return [];
|
|
57
|
-
case FunctionDeclaration:
|
|
55
|
+
case AST_NODE_TYPES.FunctionDeclaration:
|
|
58
56
|
throw new WorkflowSyntaxError('Functions must be defined at the top level of a source file', node.loc);
|
|
59
|
-
case TSInterfaceDeclaration:
|
|
60
|
-
case TSTypeAliasDeclaration:
|
|
61
|
-
case TSDeclareFunction:
|
|
57
|
+
case AST_NODE_TYPES.TSInterfaceDeclaration:
|
|
58
|
+
case AST_NODE_TYPES.TSTypeAliasDeclaration:
|
|
59
|
+
case AST_NODE_TYPES.TSDeclareFunction:
|
|
62
60
|
// Ignore "type", "interface" and "declare function"
|
|
63
61
|
return [];
|
|
64
62
|
default:
|
|
65
63
|
throw new WorkflowSyntaxError(`TODO: encountered unsupported type: ${node.type}`, node.loc);
|
|
66
64
|
}
|
|
67
65
|
}
|
|
68
|
-
function convertVariableDeclarations(declarations) {
|
|
66
|
+
function convertVariableDeclarations(declarations, ctx) {
|
|
69
67
|
return declarations.map((decl) => {
|
|
70
|
-
if (decl.type !==
|
|
71
|
-
throw new WorkflowSyntaxError('Not a VariableDeclarator', decl.loc);
|
|
72
|
-
}
|
|
73
|
-
if (decl.id.type !== Identifier) {
|
|
68
|
+
if (decl.id.type !== AST_NODE_TYPES.Identifier) {
|
|
74
69
|
throw new WorkflowSyntaxError('Expected Identifier', decl.loc);
|
|
75
70
|
}
|
|
76
71
|
const targetName = decl.id.name;
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// This branch could be removed. The transform step for extracting
|
|
84
|
-
// blocking function would take care of this, but it creates an
|
|
85
|
-
// unnecessary temporary variable assignment step.
|
|
86
|
-
return blockingFunctionCallStep(maybeBlockingcall.functionName, maybeBlockingcall.argumentNames, decl.init.arguments, targetName);
|
|
87
|
-
}
|
|
88
|
-
else if (decl.init.callee.type === Identifier &&
|
|
89
|
-
decl.init.callee.name === 'call_step') {
|
|
90
|
-
return createCallStep(decl.init.arguments, targetName);
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
return new AssignStepAST([[targetName, convertExpression(decl.init)]]);
|
|
72
|
+
if (decl.init?.type === AST_NODE_TYPES.CallExpression) {
|
|
73
|
+
const calleeName = decl.init.callee.type === AST_NODE_TYPES.Identifier
|
|
74
|
+
? decl.init.callee.name
|
|
75
|
+
: undefined;
|
|
76
|
+
if (calleeName && isMagicFunctionStatmentOnly(calleeName)) {
|
|
77
|
+
throw new WorkflowSyntaxError(`"${calleeName}" can't be called as part of an expression`, decl.init.callee.loc);
|
|
94
78
|
}
|
|
79
|
+
return callExpressionToStep(decl.init, targetName, ctx);
|
|
95
80
|
}
|
|
96
81
|
else {
|
|
97
|
-
|
|
82
|
+
const value = decl.init == null
|
|
83
|
+
? new PrimitiveExpression(null)
|
|
84
|
+
: convertExpression(decl.init);
|
|
85
|
+
return new AssignStepAST([[targetName, value]]);
|
|
98
86
|
}
|
|
99
87
|
});
|
|
100
88
|
}
|
|
101
|
-
function assignmentExpressionToSteps(node) {
|
|
102
|
-
assertType(node, AssignmentExpression);
|
|
89
|
+
function assignmentExpressionToSteps(node, ctx) {
|
|
103
90
|
let compoundOperator = undefined;
|
|
104
91
|
switch (node.operator) {
|
|
105
92
|
case '=':
|
|
@@ -133,25 +120,35 @@ function assignmentExpressionToSteps(node) {
|
|
|
133
120
|
if (!isFullyQualifiedName(targetExpression)) {
|
|
134
121
|
throw new WorkflowSyntaxError('The left-hand side of an assignment must be an identifier or a property access', node.loc);
|
|
135
122
|
}
|
|
123
|
+
let valueExpression;
|
|
124
|
+
const steps = [];
|
|
136
125
|
const targetName = targetExpression.toString();
|
|
137
|
-
|
|
126
|
+
if (node.right.type === AST_NODE_TYPES.CallExpression &&
|
|
127
|
+
node.right.callee.type === AST_NODE_TYPES.Identifier &&
|
|
128
|
+
isMagicFunction(node.right.callee.name)) {
|
|
129
|
+
const calleeName = node.right.callee.name;
|
|
130
|
+
if (isMagicFunctionStatmentOnly(calleeName)) {
|
|
131
|
+
throw new WorkflowSyntaxError(`"${calleeName}" can't be called as part of an expression`, node.right.callee.loc);
|
|
132
|
+
}
|
|
133
|
+
const needsTempVariable = compoundOperator === undefined ||
|
|
134
|
+
node.left.type !== AST_NODE_TYPES.Identifier;
|
|
135
|
+
const resultVariable = needsTempVariable ? '__temp' : targetName;
|
|
136
|
+
steps.push(callExpressionToStep(node.right, resultVariable, ctx));
|
|
137
|
+
if (!needsTempVariable) {
|
|
138
|
+
return steps;
|
|
139
|
+
}
|
|
140
|
+
valueExpression = new VariableReferenceExpression('__temp');
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
valueExpression = convertExpression(node.right);
|
|
144
|
+
}
|
|
138
145
|
if (compoundOperator) {
|
|
139
146
|
valueExpression = new BinaryExpression(new VariableReferenceExpression(targetName), compoundOperator, valueExpression);
|
|
140
147
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
function getBlockingCallParameters(node) {
|
|
144
|
-
if (node?.type === CallExpression) {
|
|
145
|
-
const functionName = convertExpression(node.callee).toString();
|
|
146
|
-
const argumentNames = blockingFunctions.get(functionName);
|
|
147
|
-
if (argumentNames) {
|
|
148
|
-
return { isBlockingCall: true, functionName, argumentNames };
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return { isBlockingCall: false };
|
|
148
|
+
steps.push(new AssignStepAST([[targetName, valueExpression]]));
|
|
149
|
+
return steps;
|
|
152
150
|
}
|
|
153
|
-
function callExpressionToStep(node, ctx) {
|
|
154
|
-
assertType(node, CallExpression);
|
|
151
|
+
function callExpressionToStep(node, resultVariable, ctx) {
|
|
155
152
|
const calleeExpression = convertExpression(node.callee);
|
|
156
153
|
if (isFullyQualifiedName(calleeExpression)) {
|
|
157
154
|
const calleeName = calleeExpression.toString();
|
|
@@ -160,48 +157,49 @@ function callExpressionToStep(node, ctx) {
|
|
|
160
157
|
return callExpressionToParallelStep(node, ctx);
|
|
161
158
|
}
|
|
162
159
|
else if (calleeName === 'retry_policy') {
|
|
163
|
-
return callExpressionToCallStep(calleeName, node.arguments);
|
|
160
|
+
return callExpressionToCallStep(calleeName, node.arguments, resultVariable);
|
|
164
161
|
}
|
|
165
162
|
else if (calleeName === 'call_step') {
|
|
166
|
-
return createCallStep(node.arguments);
|
|
163
|
+
return createCallStep(node.arguments, resultVariable);
|
|
167
164
|
}
|
|
168
165
|
else if (blockingFunctions.has(calleeName)) {
|
|
169
166
|
const argumentNames = blockingFunctions.get(calleeName) ?? [];
|
|
170
|
-
return blockingFunctionCallStep(calleeName, argumentNames, node.arguments);
|
|
167
|
+
return blockingFunctionCallStep(calleeName, argumentNames, node.arguments, resultVariable);
|
|
171
168
|
}
|
|
172
169
|
else {
|
|
173
|
-
return callExpressionAssignStep(calleeName, node.arguments);
|
|
170
|
+
return callExpressionAssignStep(calleeName, node.arguments, resultVariable);
|
|
174
171
|
}
|
|
175
172
|
}
|
|
176
173
|
else {
|
|
177
174
|
throw new WorkflowSyntaxError('Expeced a subworkflow or a standard library function name', node.callee.loc);
|
|
178
175
|
}
|
|
179
176
|
}
|
|
180
|
-
function callExpressionAssignStep(functionName, argumentsNode) {
|
|
181
|
-
const argumentExpressions = argumentsNode.map(convertExpression);
|
|
177
|
+
function callExpressionAssignStep(functionName, argumentsNode, resultVariable) {
|
|
178
|
+
const argumentExpressions = throwIfSpread(argumentsNode).map(convertExpression);
|
|
182
179
|
return new AssignStepAST([
|
|
183
180
|
[
|
|
184
|
-
'__temp',
|
|
181
|
+
resultVariable ?? '__temp',
|
|
185
182
|
new FunctionInvocationExpression(functionName, argumentExpressions),
|
|
186
183
|
],
|
|
187
184
|
]);
|
|
188
185
|
}
|
|
189
|
-
function callExpressionToCallStep(functionName, argumentsNode) {
|
|
190
|
-
if (argumentsNode.length < 1 ||
|
|
186
|
+
function callExpressionToCallStep(functionName, argumentsNode, resultVariable) {
|
|
187
|
+
if (argumentsNode.length < 1 ||
|
|
188
|
+
argumentsNode[0].type !== AST_NODE_TYPES.ObjectExpression) {
|
|
191
189
|
throw new WorkflowSyntaxError('Expected one object parameter', argumentsNode[0].loc);
|
|
192
190
|
}
|
|
193
191
|
const workflowArguments = convertObjectAsExpressionValues(argumentsNode[0]);
|
|
194
|
-
return new CallStepAST(functionName, workflowArguments);
|
|
192
|
+
return new CallStepAST(functionName, workflowArguments, resultVariable);
|
|
195
193
|
}
|
|
196
194
|
function createCallStep(argumentsNode, resultVariable) {
|
|
197
195
|
if (argumentsNode.length < 1) {
|
|
198
196
|
throw new WorkflowSyntaxError('The first argument must be a Function', argumentsNode[0].loc);
|
|
199
197
|
}
|
|
200
198
|
let functionName;
|
|
201
|
-
if (argumentsNode[0].type === Identifier) {
|
|
199
|
+
if (argumentsNode[0].type === AST_NODE_TYPES.Identifier) {
|
|
202
200
|
functionName = argumentsNode[0].name;
|
|
203
201
|
}
|
|
204
|
-
else if (argumentsNode[0].type === MemberExpression) {
|
|
202
|
+
else if (argumentsNode[0].type === AST_NODE_TYPES.MemberExpression) {
|
|
205
203
|
const memberExp = convertMemberExpression(argumentsNode[0]);
|
|
206
204
|
if (!isFullyQualifiedName(memberExp)) {
|
|
207
205
|
throw new WorkflowSyntaxError('Function name must be a fully-qualified name', argumentsNode[0].loc);
|
|
@@ -213,7 +211,7 @@ function createCallStep(argumentsNode, resultVariable) {
|
|
|
213
211
|
}
|
|
214
212
|
let args = {};
|
|
215
213
|
if (argumentsNode.length >= 2) {
|
|
216
|
-
if (argumentsNode[1].type !== ObjectExpression) {
|
|
214
|
+
if (argumentsNode[1].type !== AST_NODE_TYPES.ObjectExpression) {
|
|
217
215
|
throw new WorkflowSyntaxError('The second argument must be an object', argumentsNode[1].loc);
|
|
218
216
|
}
|
|
219
217
|
args = convertObjectAsExpressionValues(argumentsNode[1]);
|
|
@@ -221,12 +219,12 @@ function createCallStep(argumentsNode, resultVariable) {
|
|
|
221
219
|
return new CallStepAST(functionName, args, resultVariable);
|
|
222
220
|
}
|
|
223
221
|
function blockingFunctionCallStep(functionName, argumentNames, argumentsNode, resultName) {
|
|
224
|
-
const argumentExpressions = argumentsNode.map(convertExpression);
|
|
222
|
+
const argumentExpressions = throwIfSpread(argumentsNode).map(convertExpression);
|
|
225
223
|
const args = Object.fromEntries(argumentNames.flatMap((argName, i) => {
|
|
226
224
|
if (i >= argumentExpressions.length) {
|
|
227
225
|
return [];
|
|
228
226
|
}
|
|
229
|
-
else if (argumentsNode[i].type === Identifier &&
|
|
227
|
+
else if (argumentsNode[i].type === AST_NODE_TYPES.Identifier &&
|
|
230
228
|
argumentsNode[i].name === 'undefined') {
|
|
231
229
|
return [];
|
|
232
230
|
}
|
|
@@ -237,18 +235,17 @@ function blockingFunctionCallStep(functionName, argumentNames, argumentsNode, re
|
|
|
237
235
|
return new CallStepAST(functionName, args, resultName);
|
|
238
236
|
}
|
|
239
237
|
function callExpressionToParallelStep(node, ctx) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
throw new TypeError(`The parameter must be a call to "parallel"`);
|
|
238
|
+
if (node.callee.type !== AST_NODE_TYPES.Identifier ||
|
|
239
|
+
node.callee.name !== 'parallel') {
|
|
240
|
+
throw new InternalTranspilingError(`The parameter must be a call to "parallel"`);
|
|
244
241
|
}
|
|
245
242
|
let steps = {};
|
|
246
243
|
if (node.arguments.length > 0) {
|
|
247
244
|
switch (node.arguments[0].type) {
|
|
248
|
-
case ArrayExpression:
|
|
245
|
+
case AST_NODE_TYPES.ArrayExpression:
|
|
249
246
|
steps = parseParallelBranches(node.arguments[0]);
|
|
250
247
|
break;
|
|
251
|
-
case ArrowFunctionExpression:
|
|
248
|
+
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
252
249
|
steps = parseParallelIteration(node.arguments[0], ctx);
|
|
253
250
|
break;
|
|
254
251
|
default:
|
|
@@ -267,18 +264,19 @@ function callExpressionToParallelStep(node, ctx) {
|
|
|
267
264
|
return new ParallelStepAST(steps, shared, concurrencyLimit, exceptionPolicy);
|
|
268
265
|
}
|
|
269
266
|
function parseParallelBranches(node) {
|
|
270
|
-
|
|
271
|
-
const nodeElements = node.elements;
|
|
272
|
-
const stepsArray = nodeElements.map((arg, idx) => {
|
|
267
|
+
const stepsArray = node.elements.map((arg, idx) => {
|
|
273
268
|
const branchName = `branch${idx + 1}`;
|
|
269
|
+
if (arg === null) {
|
|
270
|
+
throw new WorkflowSyntaxError('Argument should be a function call of type () => void', node.loc);
|
|
271
|
+
}
|
|
274
272
|
switch (arg.type) {
|
|
275
|
-
case Identifier:
|
|
273
|
+
case AST_NODE_TYPES.Identifier:
|
|
276
274
|
return [branchName, new StepsStepAST([new CallStepAST(arg.name)])];
|
|
277
|
-
case ArrowFunctionExpression:
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
];
|
|
275
|
+
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
276
|
+
if (arg.body.type !== AST_NODE_TYPES.BlockStatement) {
|
|
277
|
+
throw new WorkflowSyntaxError('The body must be a block statement', arg.body.loc);
|
|
278
|
+
}
|
|
279
|
+
return [branchName, new StepsStepAST(parseStatement(arg.body, {}))];
|
|
282
280
|
default:
|
|
283
281
|
throw new WorkflowSyntaxError('Argument should be a function call of type () => void', arg.loc);
|
|
284
282
|
}
|
|
@@ -286,15 +284,15 @@ function parseParallelBranches(node) {
|
|
|
286
284
|
return Object.fromEntries(stepsArray);
|
|
287
285
|
}
|
|
288
286
|
function parseParallelIteration(node, ctx) {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
node.body.body[0].type !== ForOfStatement) {
|
|
287
|
+
if (node.body.type !== AST_NODE_TYPES.BlockStatement ||
|
|
288
|
+
node.body.body.length !== 1 ||
|
|
289
|
+
node.body.body[0].type !== AST_NODE_TYPES.ForOfStatement) {
|
|
292
290
|
throw new WorkflowSyntaxError('The parallel function body must be a single for...of statement', node.body.loc);
|
|
293
291
|
}
|
|
294
292
|
return forOfStatementToForStep(node.body.body[0], ctx);
|
|
295
293
|
}
|
|
296
294
|
function parseParallelOptions(node) {
|
|
297
|
-
if (node.type !== ObjectExpression) {
|
|
295
|
+
if (node.type !== AST_NODE_TYPES.ObjectExpression) {
|
|
298
296
|
throw new WorkflowSyntaxError('The second parameter must be an object', node.loc);
|
|
299
297
|
}
|
|
300
298
|
const parallelOptions = convertObjectExpression(node);
|
|
@@ -330,53 +328,42 @@ function generalExpressionToAssignStep(node) {
|
|
|
330
328
|
return new AssignStepAST([['__temp', convertExpression(node)]]);
|
|
331
329
|
}
|
|
332
330
|
function returnStatementToReturnStep(node) {
|
|
333
|
-
assertType(node, ReturnStatement);
|
|
334
331
|
const value = node.argument ? convertExpression(node.argument) : undefined;
|
|
335
332
|
return new ReturnStepAST(value);
|
|
336
333
|
}
|
|
337
334
|
function throwStatementToRaiseStep(node) {
|
|
338
|
-
assertType(node, ThrowStatement);
|
|
339
335
|
return new RaiseStepAST(convertExpression(node.argument));
|
|
340
336
|
}
|
|
341
337
|
function ifStatementToSwitchStep(node, ctx) {
|
|
342
|
-
assertType(node, IfStatement);
|
|
343
338
|
return new SwitchStepAST(flattenIfBranches(node, ctx));
|
|
344
339
|
}
|
|
345
340
|
function flattenIfBranches(ifStatement, ctx) {
|
|
346
|
-
assertType(ifStatement, IfStatement);
|
|
347
|
-
assertType(ifStatement.consequent, BlockStatement);
|
|
348
341
|
const branches = [
|
|
349
342
|
{
|
|
350
343
|
condition: convertExpression(ifStatement.test),
|
|
351
|
-
steps:
|
|
344
|
+
steps: parseStatement(ifStatement.consequent, ctx),
|
|
352
345
|
},
|
|
353
346
|
];
|
|
354
347
|
if (ifStatement.alternate) {
|
|
355
|
-
if (ifStatement.alternate.type ===
|
|
356
|
-
branches.push({
|
|
357
|
-
condition: new PrimitiveExpression(true),
|
|
358
|
-
steps: parseBlockStatement(ifStatement.alternate, ctx),
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
else if (ifStatement.alternate.type === IfStatement) {
|
|
348
|
+
if (ifStatement.alternate.type === AST_NODE_TYPES.IfStatement) {
|
|
362
349
|
branches.push(...flattenIfBranches(ifStatement.alternate, ctx));
|
|
363
350
|
}
|
|
364
351
|
else {
|
|
365
|
-
|
|
352
|
+
branches.push({
|
|
353
|
+
condition: new PrimitiveExpression(true),
|
|
354
|
+
steps: parseStatement(ifStatement.alternate, ctx),
|
|
355
|
+
});
|
|
366
356
|
}
|
|
367
357
|
}
|
|
368
358
|
return branches;
|
|
369
359
|
}
|
|
370
360
|
function switchStatementToSteps(node, ctx) {
|
|
371
|
-
assertType(node, SwitchStatement);
|
|
372
361
|
const endOfSwitch = new JumpTargetAST();
|
|
373
362
|
const switchCtx = Object.assign({}, ctx, { breakTarget: endOfSwitch.label });
|
|
374
363
|
const steps = [];
|
|
375
364
|
const branches = [];
|
|
376
365
|
const discriminant = convertExpression(node.discriminant);
|
|
377
|
-
|
|
378
|
-
cases.forEach((caseNode) => {
|
|
379
|
-
assertType(caseNode, SwitchCase);
|
|
366
|
+
node.cases.forEach((caseNode) => {
|
|
380
367
|
let condition;
|
|
381
368
|
if (caseNode.test) {
|
|
382
369
|
const test = convertExpression(caseNode.test);
|
|
@@ -386,8 +373,7 @@ function switchStatementToSteps(node, ctx) {
|
|
|
386
373
|
condition = new PrimitiveExpression(true);
|
|
387
374
|
}
|
|
388
375
|
const jumpTarget = new JumpTargetAST();
|
|
389
|
-
const
|
|
390
|
-
const body = transformAST(consequent.flatMap((x) => parseStep(x, switchCtx)));
|
|
376
|
+
const body = transformAST(caseNode.consequent.flatMap((x) => parseStatement(x, switchCtx)));
|
|
391
377
|
steps.push(jumpTarget);
|
|
392
378
|
steps.push(...body);
|
|
393
379
|
branches.push({
|
|
@@ -401,18 +387,16 @@ function switchStatementToSteps(node, ctx) {
|
|
|
401
387
|
return steps;
|
|
402
388
|
}
|
|
403
389
|
function forOfStatementToForStep(node, ctx) {
|
|
404
|
-
assertType(node, ForOfStatement);
|
|
405
|
-
assertType(node.body, BlockStatement);
|
|
406
390
|
const bodyCtx = Object.assign({}, ctx, {
|
|
407
391
|
continueTarget: undefined,
|
|
408
392
|
breakTarget: undefined,
|
|
409
393
|
});
|
|
410
|
-
const steps =
|
|
394
|
+
const steps = parseStatement(node.body, bodyCtx);
|
|
411
395
|
let loopVariableName;
|
|
412
|
-
if (node.left.type === Identifier) {
|
|
396
|
+
if (node.left.type === AST_NODE_TYPES.Identifier) {
|
|
413
397
|
loopVariableName = node.left.name;
|
|
414
398
|
}
|
|
415
|
-
else if (node.left.type === VariableDeclaration) {
|
|
399
|
+
else if (node.left.type === AST_NODE_TYPES.VariableDeclaration) {
|
|
416
400
|
if (node.left.declarations.length !== 1) {
|
|
417
401
|
throw new WorkflowSyntaxError('Only one variable can be declared here', node.left.loc);
|
|
418
402
|
}
|
|
@@ -420,7 +404,9 @@ function forOfStatementToForStep(node, ctx) {
|
|
|
420
404
|
if (declaration.init !== null) {
|
|
421
405
|
throw new WorkflowSyntaxError('Initial value not allowed', declaration.init.loc);
|
|
422
406
|
}
|
|
423
|
-
|
|
407
|
+
if (declaration.id.type !== AST_NODE_TYPES.Identifier) {
|
|
408
|
+
throw new WorkflowSyntaxError(`Expected identifier, got ${declaration.id.type}`, declaration.id.loc);
|
|
409
|
+
}
|
|
424
410
|
loopVariableName = declaration.id.name;
|
|
425
411
|
}
|
|
426
412
|
else {
|
|
@@ -439,15 +425,14 @@ function forOfStatementToForStep(node, ctx) {
|
|
|
439
425
|
return new ForStepAST(steps, loopVariableName, listExpression);
|
|
440
426
|
}
|
|
441
427
|
function whileStatementSteps(node, ctx) {
|
|
442
|
-
assertType(node, WhileStatement);
|
|
443
428
|
const startOfLoop = new JumpTargetAST();
|
|
444
429
|
const endOfLoop = new JumpTargetAST();
|
|
445
430
|
const ctx2 = Object.assign({}, ctx, {
|
|
446
431
|
continueTarget: startOfLoop.label,
|
|
447
432
|
breakTarget: endOfLoop.label,
|
|
448
433
|
});
|
|
449
|
-
const
|
|
450
|
-
steps
|
|
434
|
+
const postSteps = [new NextStepAST(startOfLoop.label)];
|
|
435
|
+
const steps = parseStatement(node.body, ctx2, postSteps);
|
|
451
436
|
return [
|
|
452
437
|
startOfLoop,
|
|
453
438
|
new SwitchStepAST([
|
|
@@ -460,7 +445,6 @@ function whileStatementSteps(node, ctx) {
|
|
|
460
445
|
];
|
|
461
446
|
}
|
|
462
447
|
function doWhileStatementSteps(node, ctx) {
|
|
463
|
-
assertType(node, DoWhileStatement);
|
|
464
448
|
const startOfLoop = new JumpTargetAST();
|
|
465
449
|
const endOfLoop = new JumpTargetAST();
|
|
466
450
|
const ctx2 = Object.assign({}, ctx, {
|
|
@@ -468,7 +452,7 @@ function doWhileStatementSteps(node, ctx) {
|
|
|
468
452
|
breakTarget: endOfLoop.label,
|
|
469
453
|
});
|
|
470
454
|
const steps = [startOfLoop];
|
|
471
|
-
steps.push(...
|
|
455
|
+
steps.push(...parseStatement(node.body, ctx2));
|
|
472
456
|
steps.push(new SwitchStepAST([
|
|
473
457
|
{
|
|
474
458
|
condition: convertExpression(node.test),
|
|
@@ -480,10 +464,8 @@ function doWhileStatementSteps(node, ctx) {
|
|
|
480
464
|
return steps;
|
|
481
465
|
}
|
|
482
466
|
function breakStatementToNextStep(node, ctx) {
|
|
483
|
-
assertType(node, BreakStatement);
|
|
484
467
|
let target;
|
|
485
468
|
if (node.label) {
|
|
486
|
-
assertType(node.label, Identifier);
|
|
487
469
|
target = node.label.name;
|
|
488
470
|
}
|
|
489
471
|
else if (ctx.breakTarget) {
|
|
@@ -495,10 +477,8 @@ function breakStatementToNextStep(node, ctx) {
|
|
|
495
477
|
return new NextStepAST(target);
|
|
496
478
|
}
|
|
497
479
|
function continueStatementToNextStep(node, ctx) {
|
|
498
|
-
assertType(node, ContinueStatement);
|
|
499
480
|
let target;
|
|
500
481
|
if (node.label) {
|
|
501
|
-
assertType(node.label, Identifier);
|
|
502
482
|
target = node.label.name;
|
|
503
483
|
}
|
|
504
484
|
else if (ctx.continueTarget) {
|
|
@@ -510,14 +490,18 @@ function continueStatementToNextStep(node, ctx) {
|
|
|
510
490
|
return new NextStepAST(target);
|
|
511
491
|
}
|
|
512
492
|
function tryStatementToTryStep(node, ctx) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
const exceptSteps = parseBlockStatement(node.handler.body, ctx);
|
|
493
|
+
const steps = parseStatement(node.block, ctx);
|
|
494
|
+
let exceptSteps = [];
|
|
516
495
|
let errorVariable = undefined;
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
496
|
+
if (node.handler) {
|
|
497
|
+
exceptSteps = parseStatement(node.handler.body, ctx);
|
|
498
|
+
const handlerParam = node.handler.param;
|
|
499
|
+
if (handlerParam) {
|
|
500
|
+
if (handlerParam.type !== AST_NODE_TYPES.Identifier) {
|
|
501
|
+
throw new WorkflowSyntaxError('The error variable must be an identifier', handlerParam.loc);
|
|
502
|
+
}
|
|
503
|
+
errorVariable = handlerParam.name;
|
|
504
|
+
}
|
|
521
505
|
}
|
|
522
506
|
if (node.finalizer !== null) {
|
|
523
507
|
// TODO
|
|
@@ -526,11 +510,9 @@ function tryStatementToTryStep(node, ctx) {
|
|
|
526
510
|
return new TryStepAST(steps, exceptSteps, undefined, errorVariable);
|
|
527
511
|
}
|
|
528
512
|
function labeledStep(node, ctx) {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
steps[0] = stepWithLabel(steps[0], node.label.name);
|
|
533
|
-
return steps;
|
|
513
|
+
const steps = parseStatement(node.body, ctx);
|
|
514
|
+
if (steps.length > 0 && steps[0].tag !== 'jumptarget') {
|
|
515
|
+
steps[0] = steps[0].withLabel(node.label.name);
|
|
534
516
|
}
|
|
535
517
|
return steps;
|
|
536
518
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformations.d.ts","sourceRoot":"","sources":["../../src/transpiler/transformations.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"transformations.d.ts","sourceRoot":"","sources":["../../src/transpiler/transformations.ts"],"names":[],"mappings":"AAAA,OAAO,EAWL,eAAe,EAChB,MAAM,iBAAiB,CAAA;AAwBxB;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAUxE;AA6JD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,eAAe,EAAE,GACvB,eAAe,EAAE,CAqBnB"}
|