ts2workflows 0.3.0 → 0.4.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/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 +42 -27
- package/dist/transpiler/expressions.d.ts +7 -4
- package/dist/transpiler/expressions.d.ts.map +1 -1
- package/dist/transpiler/expressions.js +156 -37
- 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 +129 -154
- package/dist/transpiler/transformations.d.ts.map +1 -1
- package/dist/transpiler/transformations.js +25 -21
- package/language_reference.md +55 -33
- package/package.json +10 -3
- package/types/global.d.ts +116 -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,89 @@
|
|
|
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, } 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 !== VariableDeclarator) {
|
|
68
|
+
if (decl.type !== AST_NODE_TYPES.VariableDeclarator) {
|
|
71
69
|
throw new WorkflowSyntaxError('Not a VariableDeclarator', decl.loc);
|
|
72
70
|
}
|
|
73
|
-
if (decl.id.type !== Identifier) {
|
|
71
|
+
if (decl.id.type !== AST_NODE_TYPES.Identifier) {
|
|
74
72
|
throw new WorkflowSyntaxError('Expected Identifier', decl.loc);
|
|
75
73
|
}
|
|
76
74
|
const targetName = decl.id.name;
|
|
77
|
-
if (
|
|
78
|
-
return
|
|
79
|
-
}
|
|
80
|
-
else if (decl.init.type === CallExpression) {
|
|
81
|
-
const maybeBlockingcall = getBlockingCallParameters(decl.init);
|
|
82
|
-
if (maybeBlockingcall.isBlockingCall) {
|
|
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)]]);
|
|
94
|
-
}
|
|
75
|
+
if (decl.init?.type === AST_NODE_TYPES.CallExpression) {
|
|
76
|
+
return callExpressionToStep(decl.init, targetName, ctx);
|
|
95
77
|
}
|
|
96
78
|
else {
|
|
97
|
-
|
|
79
|
+
const value = decl.init == null
|
|
80
|
+
? new PrimitiveExpression(null)
|
|
81
|
+
: convertExpression(decl.init);
|
|
82
|
+
return new AssignStepAST([[targetName, value]]);
|
|
98
83
|
}
|
|
99
84
|
});
|
|
100
85
|
}
|
|
101
|
-
function assignmentExpressionToSteps(node) {
|
|
102
|
-
assertType(node, AssignmentExpression);
|
|
86
|
+
function assignmentExpressionToSteps(node, ctx) {
|
|
103
87
|
let compoundOperator = undefined;
|
|
104
88
|
switch (node.operator) {
|
|
105
89
|
case '=':
|
|
@@ -133,25 +117,31 @@ function assignmentExpressionToSteps(node) {
|
|
|
133
117
|
if (!isFullyQualifiedName(targetExpression)) {
|
|
134
118
|
throw new WorkflowSyntaxError('The left-hand side of an assignment must be an identifier or a property access', node.loc);
|
|
135
119
|
}
|
|
120
|
+
let valueExpression;
|
|
121
|
+
const steps = [];
|
|
136
122
|
const targetName = targetExpression.toString();
|
|
137
|
-
|
|
123
|
+
if (node.right.type === AST_NODE_TYPES.CallExpression &&
|
|
124
|
+
node.right.callee.type === AST_NODE_TYPES.Identifier &&
|
|
125
|
+
isMagicFunction(node.right.callee.name)) {
|
|
126
|
+
const needsTempVariable = compoundOperator === undefined ||
|
|
127
|
+
node.left.type !== AST_NODE_TYPES.Identifier;
|
|
128
|
+
const resultVariable = needsTempVariable ? '__temp' : targetName;
|
|
129
|
+
steps.push(callExpressionToStep(node.right, resultVariable, ctx));
|
|
130
|
+
if (!needsTempVariable) {
|
|
131
|
+
return steps;
|
|
132
|
+
}
|
|
133
|
+
valueExpression = new VariableReferenceExpression('__temp');
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
valueExpression = convertExpression(node.right);
|
|
137
|
+
}
|
|
138
138
|
if (compoundOperator) {
|
|
139
139
|
valueExpression = new BinaryExpression(new VariableReferenceExpression(targetName), compoundOperator, valueExpression);
|
|
140
140
|
}
|
|
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 };
|
|
141
|
+
steps.push(new AssignStepAST([[targetName, valueExpression]]));
|
|
142
|
+
return steps;
|
|
152
143
|
}
|
|
153
|
-
function callExpressionToStep(node, ctx) {
|
|
154
|
-
assertType(node, CallExpression);
|
|
144
|
+
function callExpressionToStep(node, resultVariable, ctx) {
|
|
155
145
|
const calleeExpression = convertExpression(node.callee);
|
|
156
146
|
if (isFullyQualifiedName(calleeExpression)) {
|
|
157
147
|
const calleeName = calleeExpression.toString();
|
|
@@ -160,48 +150,49 @@ function callExpressionToStep(node, ctx) {
|
|
|
160
150
|
return callExpressionToParallelStep(node, ctx);
|
|
161
151
|
}
|
|
162
152
|
else if (calleeName === 'retry_policy') {
|
|
163
|
-
return callExpressionToCallStep(calleeName, node.arguments);
|
|
153
|
+
return callExpressionToCallStep(calleeName, node.arguments, resultVariable);
|
|
164
154
|
}
|
|
165
155
|
else if (calleeName === 'call_step') {
|
|
166
|
-
return createCallStep(node.arguments);
|
|
156
|
+
return createCallStep(node.arguments, resultVariable);
|
|
167
157
|
}
|
|
168
158
|
else if (blockingFunctions.has(calleeName)) {
|
|
169
159
|
const argumentNames = blockingFunctions.get(calleeName) ?? [];
|
|
170
|
-
return blockingFunctionCallStep(calleeName, argumentNames, node.arguments);
|
|
160
|
+
return blockingFunctionCallStep(calleeName, argumentNames, node.arguments, resultVariable);
|
|
171
161
|
}
|
|
172
162
|
else {
|
|
173
|
-
return callExpressionAssignStep(calleeName, node.arguments);
|
|
163
|
+
return callExpressionAssignStep(calleeName, node.arguments, resultVariable);
|
|
174
164
|
}
|
|
175
165
|
}
|
|
176
166
|
else {
|
|
177
167
|
throw new WorkflowSyntaxError('Expeced a subworkflow or a standard library function name', node.callee.loc);
|
|
178
168
|
}
|
|
179
169
|
}
|
|
180
|
-
function callExpressionAssignStep(functionName, argumentsNode) {
|
|
181
|
-
const argumentExpressions = argumentsNode.map(convertExpression);
|
|
170
|
+
function callExpressionAssignStep(functionName, argumentsNode, resultVariable) {
|
|
171
|
+
const argumentExpressions = throwIfSpread(argumentsNode).map(convertExpression);
|
|
182
172
|
return new AssignStepAST([
|
|
183
173
|
[
|
|
184
|
-
'__temp',
|
|
174
|
+
resultVariable ?? '__temp',
|
|
185
175
|
new FunctionInvocationExpression(functionName, argumentExpressions),
|
|
186
176
|
],
|
|
187
177
|
]);
|
|
188
178
|
}
|
|
189
|
-
function callExpressionToCallStep(functionName, argumentsNode) {
|
|
190
|
-
if (argumentsNode.length < 1 ||
|
|
179
|
+
function callExpressionToCallStep(functionName, argumentsNode, resultVariable) {
|
|
180
|
+
if (argumentsNode.length < 1 ||
|
|
181
|
+
argumentsNode[0].type !== AST_NODE_TYPES.ObjectExpression) {
|
|
191
182
|
throw new WorkflowSyntaxError('Expected one object parameter', argumentsNode[0].loc);
|
|
192
183
|
}
|
|
193
184
|
const workflowArguments = convertObjectAsExpressionValues(argumentsNode[0]);
|
|
194
|
-
return new CallStepAST(functionName, workflowArguments);
|
|
185
|
+
return new CallStepAST(functionName, workflowArguments, resultVariable);
|
|
195
186
|
}
|
|
196
187
|
function createCallStep(argumentsNode, resultVariable) {
|
|
197
188
|
if (argumentsNode.length < 1) {
|
|
198
189
|
throw new WorkflowSyntaxError('The first argument must be a Function', argumentsNode[0].loc);
|
|
199
190
|
}
|
|
200
191
|
let functionName;
|
|
201
|
-
if (argumentsNode[0].type === Identifier) {
|
|
192
|
+
if (argumentsNode[0].type === AST_NODE_TYPES.Identifier) {
|
|
202
193
|
functionName = argumentsNode[0].name;
|
|
203
194
|
}
|
|
204
|
-
else if (argumentsNode[0].type === MemberExpression) {
|
|
195
|
+
else if (argumentsNode[0].type === AST_NODE_TYPES.MemberExpression) {
|
|
205
196
|
const memberExp = convertMemberExpression(argumentsNode[0]);
|
|
206
197
|
if (!isFullyQualifiedName(memberExp)) {
|
|
207
198
|
throw new WorkflowSyntaxError('Function name must be a fully-qualified name', argumentsNode[0].loc);
|
|
@@ -213,7 +204,7 @@ function createCallStep(argumentsNode, resultVariable) {
|
|
|
213
204
|
}
|
|
214
205
|
let args = {};
|
|
215
206
|
if (argumentsNode.length >= 2) {
|
|
216
|
-
if (argumentsNode[1].type !== ObjectExpression) {
|
|
207
|
+
if (argumentsNode[1].type !== AST_NODE_TYPES.ObjectExpression) {
|
|
217
208
|
throw new WorkflowSyntaxError('The second argument must be an object', argumentsNode[1].loc);
|
|
218
209
|
}
|
|
219
210
|
args = convertObjectAsExpressionValues(argumentsNode[1]);
|
|
@@ -221,12 +212,12 @@ function createCallStep(argumentsNode, resultVariable) {
|
|
|
221
212
|
return new CallStepAST(functionName, args, resultVariable);
|
|
222
213
|
}
|
|
223
214
|
function blockingFunctionCallStep(functionName, argumentNames, argumentsNode, resultName) {
|
|
224
|
-
const argumentExpressions = argumentsNode.map(convertExpression);
|
|
215
|
+
const argumentExpressions = throwIfSpread(argumentsNode).map(convertExpression);
|
|
225
216
|
const args = Object.fromEntries(argumentNames.flatMap((argName, i) => {
|
|
226
217
|
if (i >= argumentExpressions.length) {
|
|
227
218
|
return [];
|
|
228
219
|
}
|
|
229
|
-
else if (argumentsNode[i].type === Identifier &&
|
|
220
|
+
else if (argumentsNode[i].type === AST_NODE_TYPES.Identifier &&
|
|
230
221
|
argumentsNode[i].name === 'undefined') {
|
|
231
222
|
return [];
|
|
232
223
|
}
|
|
@@ -237,18 +228,17 @@ function blockingFunctionCallStep(functionName, argumentNames, argumentsNode, re
|
|
|
237
228
|
return new CallStepAST(functionName, args, resultName);
|
|
238
229
|
}
|
|
239
230
|
function callExpressionToParallelStep(node, ctx) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
throw new TypeError(`The parameter must be a call to "parallel"`);
|
|
231
|
+
if (node.callee.type !== AST_NODE_TYPES.Identifier ||
|
|
232
|
+
node.callee.name !== 'parallel') {
|
|
233
|
+
throw new InternalTranspilingError(`The parameter must be a call to "parallel"`);
|
|
244
234
|
}
|
|
245
235
|
let steps = {};
|
|
246
236
|
if (node.arguments.length > 0) {
|
|
247
237
|
switch (node.arguments[0].type) {
|
|
248
|
-
case ArrayExpression:
|
|
238
|
+
case AST_NODE_TYPES.ArrayExpression:
|
|
249
239
|
steps = parseParallelBranches(node.arguments[0]);
|
|
250
240
|
break;
|
|
251
|
-
case ArrowFunctionExpression:
|
|
241
|
+
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
252
242
|
steps = parseParallelIteration(node.arguments[0], ctx);
|
|
253
243
|
break;
|
|
254
244
|
default:
|
|
@@ -267,18 +257,19 @@ function callExpressionToParallelStep(node, ctx) {
|
|
|
267
257
|
return new ParallelStepAST(steps, shared, concurrencyLimit, exceptionPolicy);
|
|
268
258
|
}
|
|
269
259
|
function parseParallelBranches(node) {
|
|
270
|
-
|
|
271
|
-
const nodeElements = node.elements;
|
|
272
|
-
const stepsArray = nodeElements.map((arg, idx) => {
|
|
260
|
+
const stepsArray = node.elements.map((arg, idx) => {
|
|
273
261
|
const branchName = `branch${idx + 1}`;
|
|
262
|
+
if (arg === null) {
|
|
263
|
+
throw new WorkflowSyntaxError('Argument should be a function call of type () => void', node.loc);
|
|
264
|
+
}
|
|
274
265
|
switch (arg.type) {
|
|
275
|
-
case Identifier:
|
|
266
|
+
case AST_NODE_TYPES.Identifier:
|
|
276
267
|
return [branchName, new StepsStepAST([new CallStepAST(arg.name)])];
|
|
277
|
-
case ArrowFunctionExpression:
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
];
|
|
268
|
+
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
269
|
+
if (arg.body.type !== AST_NODE_TYPES.BlockStatement) {
|
|
270
|
+
throw new WorkflowSyntaxError('The body must be a block statement', arg.body.loc);
|
|
271
|
+
}
|
|
272
|
+
return [branchName, new StepsStepAST(parseStatement(arg.body, {}))];
|
|
282
273
|
default:
|
|
283
274
|
throw new WorkflowSyntaxError('Argument should be a function call of type () => void', arg.loc);
|
|
284
275
|
}
|
|
@@ -286,15 +277,15 @@ function parseParallelBranches(node) {
|
|
|
286
277
|
return Object.fromEntries(stepsArray);
|
|
287
278
|
}
|
|
288
279
|
function parseParallelIteration(node, ctx) {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
node.body.body[0].type !== ForOfStatement) {
|
|
280
|
+
if (node.body.type !== AST_NODE_TYPES.BlockStatement ||
|
|
281
|
+
node.body.body.length !== 1 ||
|
|
282
|
+
node.body.body[0].type !== AST_NODE_TYPES.ForOfStatement) {
|
|
292
283
|
throw new WorkflowSyntaxError('The parallel function body must be a single for...of statement', node.body.loc);
|
|
293
284
|
}
|
|
294
285
|
return forOfStatementToForStep(node.body.body[0], ctx);
|
|
295
286
|
}
|
|
296
287
|
function parseParallelOptions(node) {
|
|
297
|
-
if (node.type !== ObjectExpression) {
|
|
288
|
+
if (node.type !== AST_NODE_TYPES.ObjectExpression) {
|
|
298
289
|
throw new WorkflowSyntaxError('The second parameter must be an object', node.loc);
|
|
299
290
|
}
|
|
300
291
|
const parallelOptions = convertObjectExpression(node);
|
|
@@ -330,53 +321,42 @@ function generalExpressionToAssignStep(node) {
|
|
|
330
321
|
return new AssignStepAST([['__temp', convertExpression(node)]]);
|
|
331
322
|
}
|
|
332
323
|
function returnStatementToReturnStep(node) {
|
|
333
|
-
assertType(node, ReturnStatement);
|
|
334
324
|
const value = node.argument ? convertExpression(node.argument) : undefined;
|
|
335
325
|
return new ReturnStepAST(value);
|
|
336
326
|
}
|
|
337
327
|
function throwStatementToRaiseStep(node) {
|
|
338
|
-
assertType(node, ThrowStatement);
|
|
339
328
|
return new RaiseStepAST(convertExpression(node.argument));
|
|
340
329
|
}
|
|
341
330
|
function ifStatementToSwitchStep(node, ctx) {
|
|
342
|
-
assertType(node, IfStatement);
|
|
343
331
|
return new SwitchStepAST(flattenIfBranches(node, ctx));
|
|
344
332
|
}
|
|
345
333
|
function flattenIfBranches(ifStatement, ctx) {
|
|
346
|
-
assertType(ifStatement, IfStatement);
|
|
347
|
-
assertType(ifStatement.consequent, BlockStatement);
|
|
348
334
|
const branches = [
|
|
349
335
|
{
|
|
350
336
|
condition: convertExpression(ifStatement.test),
|
|
351
|
-
steps:
|
|
337
|
+
steps: parseStatement(ifStatement.consequent, ctx),
|
|
352
338
|
},
|
|
353
339
|
];
|
|
354
340
|
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) {
|
|
341
|
+
if (ifStatement.alternate.type === AST_NODE_TYPES.IfStatement) {
|
|
362
342
|
branches.push(...flattenIfBranches(ifStatement.alternate, ctx));
|
|
363
343
|
}
|
|
364
344
|
else {
|
|
365
|
-
|
|
345
|
+
branches.push({
|
|
346
|
+
condition: new PrimitiveExpression(true),
|
|
347
|
+
steps: parseStatement(ifStatement.alternate, ctx),
|
|
348
|
+
});
|
|
366
349
|
}
|
|
367
350
|
}
|
|
368
351
|
return branches;
|
|
369
352
|
}
|
|
370
353
|
function switchStatementToSteps(node, ctx) {
|
|
371
|
-
assertType(node, SwitchStatement);
|
|
372
354
|
const endOfSwitch = new JumpTargetAST();
|
|
373
355
|
const switchCtx = Object.assign({}, ctx, { breakTarget: endOfSwitch.label });
|
|
374
356
|
const steps = [];
|
|
375
357
|
const branches = [];
|
|
376
358
|
const discriminant = convertExpression(node.discriminant);
|
|
377
|
-
|
|
378
|
-
cases.forEach((caseNode) => {
|
|
379
|
-
assertType(caseNode, SwitchCase);
|
|
359
|
+
node.cases.forEach((caseNode) => {
|
|
380
360
|
let condition;
|
|
381
361
|
if (caseNode.test) {
|
|
382
362
|
const test = convertExpression(caseNode.test);
|
|
@@ -386,8 +366,7 @@ function switchStatementToSteps(node, ctx) {
|
|
|
386
366
|
condition = new PrimitiveExpression(true);
|
|
387
367
|
}
|
|
388
368
|
const jumpTarget = new JumpTargetAST();
|
|
389
|
-
const
|
|
390
|
-
const body = transformAST(consequent.flatMap((x) => parseStep(x, switchCtx)));
|
|
369
|
+
const body = transformAST(caseNode.consequent.flatMap((x) => parseStatement(x, switchCtx)));
|
|
391
370
|
steps.push(jumpTarget);
|
|
392
371
|
steps.push(...body);
|
|
393
372
|
branches.push({
|
|
@@ -401,18 +380,16 @@ function switchStatementToSteps(node, ctx) {
|
|
|
401
380
|
return steps;
|
|
402
381
|
}
|
|
403
382
|
function forOfStatementToForStep(node, ctx) {
|
|
404
|
-
assertType(node, ForOfStatement);
|
|
405
|
-
assertType(node.body, BlockStatement);
|
|
406
383
|
const bodyCtx = Object.assign({}, ctx, {
|
|
407
384
|
continueTarget: undefined,
|
|
408
385
|
breakTarget: undefined,
|
|
409
386
|
});
|
|
410
|
-
const steps =
|
|
387
|
+
const steps = parseStatement(node.body, bodyCtx);
|
|
411
388
|
let loopVariableName;
|
|
412
|
-
if (node.left.type === Identifier) {
|
|
389
|
+
if (node.left.type === AST_NODE_TYPES.Identifier) {
|
|
413
390
|
loopVariableName = node.left.name;
|
|
414
391
|
}
|
|
415
|
-
else if (node.left.type === VariableDeclaration) {
|
|
392
|
+
else if (node.left.type === AST_NODE_TYPES.VariableDeclaration) {
|
|
416
393
|
if (node.left.declarations.length !== 1) {
|
|
417
394
|
throw new WorkflowSyntaxError('Only one variable can be declared here', node.left.loc);
|
|
418
395
|
}
|
|
@@ -420,7 +397,9 @@ function forOfStatementToForStep(node, ctx) {
|
|
|
420
397
|
if (declaration.init !== null) {
|
|
421
398
|
throw new WorkflowSyntaxError('Initial value not allowed', declaration.init.loc);
|
|
422
399
|
}
|
|
423
|
-
|
|
400
|
+
if (declaration.id.type !== AST_NODE_TYPES.Identifier) {
|
|
401
|
+
throw new WorkflowSyntaxError(`Expected identifier, got ${declaration.id.type}`, declaration.id.loc);
|
|
402
|
+
}
|
|
424
403
|
loopVariableName = declaration.id.name;
|
|
425
404
|
}
|
|
426
405
|
else {
|
|
@@ -439,15 +418,14 @@ function forOfStatementToForStep(node, ctx) {
|
|
|
439
418
|
return new ForStepAST(steps, loopVariableName, listExpression);
|
|
440
419
|
}
|
|
441
420
|
function whileStatementSteps(node, ctx) {
|
|
442
|
-
assertType(node, WhileStatement);
|
|
443
421
|
const startOfLoop = new JumpTargetAST();
|
|
444
422
|
const endOfLoop = new JumpTargetAST();
|
|
445
423
|
const ctx2 = Object.assign({}, ctx, {
|
|
446
424
|
continueTarget: startOfLoop.label,
|
|
447
425
|
breakTarget: endOfLoop.label,
|
|
448
426
|
});
|
|
449
|
-
const
|
|
450
|
-
steps
|
|
427
|
+
const postSteps = [new NextStepAST(startOfLoop.label)];
|
|
428
|
+
const steps = parseStatement(node.body, ctx2, postSteps);
|
|
451
429
|
return [
|
|
452
430
|
startOfLoop,
|
|
453
431
|
new SwitchStepAST([
|
|
@@ -460,7 +438,6 @@ function whileStatementSteps(node, ctx) {
|
|
|
460
438
|
];
|
|
461
439
|
}
|
|
462
440
|
function doWhileStatementSteps(node, ctx) {
|
|
463
|
-
assertType(node, DoWhileStatement);
|
|
464
441
|
const startOfLoop = new JumpTargetAST();
|
|
465
442
|
const endOfLoop = new JumpTargetAST();
|
|
466
443
|
const ctx2 = Object.assign({}, ctx, {
|
|
@@ -468,7 +445,7 @@ function doWhileStatementSteps(node, ctx) {
|
|
|
468
445
|
breakTarget: endOfLoop.label,
|
|
469
446
|
});
|
|
470
447
|
const steps = [startOfLoop];
|
|
471
|
-
steps.push(...
|
|
448
|
+
steps.push(...parseStatement(node.body, ctx2));
|
|
472
449
|
steps.push(new SwitchStepAST([
|
|
473
450
|
{
|
|
474
451
|
condition: convertExpression(node.test),
|
|
@@ -480,10 +457,8 @@ function doWhileStatementSteps(node, ctx) {
|
|
|
480
457
|
return steps;
|
|
481
458
|
}
|
|
482
459
|
function breakStatementToNextStep(node, ctx) {
|
|
483
|
-
assertType(node, BreakStatement);
|
|
484
460
|
let target;
|
|
485
461
|
if (node.label) {
|
|
486
|
-
assertType(node.label, Identifier);
|
|
487
462
|
target = node.label.name;
|
|
488
463
|
}
|
|
489
464
|
else if (ctx.breakTarget) {
|
|
@@ -495,10 +470,8 @@ function breakStatementToNextStep(node, ctx) {
|
|
|
495
470
|
return new NextStepAST(target);
|
|
496
471
|
}
|
|
497
472
|
function continueStatementToNextStep(node, ctx) {
|
|
498
|
-
assertType(node, ContinueStatement);
|
|
499
473
|
let target;
|
|
500
474
|
if (node.label) {
|
|
501
|
-
assertType(node.label, Identifier);
|
|
502
475
|
target = node.label.name;
|
|
503
476
|
}
|
|
504
477
|
else if (ctx.continueTarget) {
|
|
@@ -510,14 +483,18 @@ function continueStatementToNextStep(node, ctx) {
|
|
|
510
483
|
return new NextStepAST(target);
|
|
511
484
|
}
|
|
512
485
|
function tryStatementToTryStep(node, ctx) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
const exceptSteps = parseBlockStatement(node.handler.body, ctx);
|
|
486
|
+
const steps = parseStatement(node.block, ctx);
|
|
487
|
+
let exceptSteps = [];
|
|
516
488
|
let errorVariable = undefined;
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
489
|
+
if (node.handler) {
|
|
490
|
+
exceptSteps = parseStatement(node.handler.body, ctx);
|
|
491
|
+
const handlerParam = node.handler.param;
|
|
492
|
+
if (handlerParam) {
|
|
493
|
+
if (handlerParam.type !== AST_NODE_TYPES.Identifier) {
|
|
494
|
+
throw new WorkflowSyntaxError('The error variable must be an identifier', handlerParam.loc);
|
|
495
|
+
}
|
|
496
|
+
errorVariable = handlerParam.name;
|
|
497
|
+
}
|
|
521
498
|
}
|
|
522
499
|
if (node.finalizer !== null) {
|
|
523
500
|
// TODO
|
|
@@ -526,11 +503,9 @@ function tryStatementToTryStep(node, ctx) {
|
|
|
526
503
|
return new TryStepAST(steps, exceptSteps, undefined, errorVariable);
|
|
527
504
|
}
|
|
528
505
|
function labeledStep(node, ctx) {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
steps[0] = stepWithLabel(steps[0], node.label.name);
|
|
533
|
-
return steps;
|
|
506
|
+
const steps = parseStatement(node.body, ctx);
|
|
507
|
+
if (steps.length > 0 && steps[0].tag !== 'jumptarget') {
|
|
508
|
+
steps[0] = steps[0].withLabel(node.label.name);
|
|
534
509
|
}
|
|
535
510
|
return steps;
|
|
536
511
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformations.d.ts","sourceRoot":"","sources":["../../src/transpiler/transformations.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,eAAe,EAChB,MAAM,iBAAiB,CAAA;AAuBxB;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAUxE;
|
|
1
|
+
{"version":3,"file":"transformations.d.ts","sourceRoot":"","sources":["../../src/transpiler/transformations.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,eAAe,EAChB,MAAM,iBAAiB,CAAA;AAuBxB;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAUxE;AA4JD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,eAAe,EAAE,GACvB,eAAe,EAAE,CAqBnB"}
|
|
@@ -23,8 +23,9 @@ function mergeAssignSteps(steps) {
|
|
|
23
23
|
const prev = acc.length > 0 ? acc[acc.length - 1] : null;
|
|
24
24
|
if (current.tag === 'assign' &&
|
|
25
25
|
prev?.tag === 'assign' &&
|
|
26
|
-
prev.assignments.length < 50
|
|
27
|
-
|
|
26
|
+
prev.assignments.length < 50 &&
|
|
27
|
+
!prev.next) {
|
|
28
|
+
const merged = new AssignStepAST(prev.assignments.concat(current.assignments), current.next);
|
|
28
29
|
acc.pop();
|
|
29
30
|
acc.push(merged);
|
|
30
31
|
}
|
|
@@ -142,26 +143,29 @@ function parseRetryPolicyNumber(record, keyName) {
|
|
|
142
143
|
* next: target1
|
|
143
144
|
*/
|
|
144
145
|
export function flattenPlainNextConditions(steps) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
146
|
+
return steps.reduce((acc, step) => {
|
|
147
|
+
if (acc.length > 0 && step.tag === 'next') {
|
|
148
|
+
// Merge a "next" to the previous "assign" step
|
|
149
|
+
const prev = acc[acc.length - 1];
|
|
150
|
+
if (prev.tag === 'assign' && !prev.next) {
|
|
151
|
+
acc.pop();
|
|
152
|
+
acc.push(prev.withNext(step.target));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
acc.push(step);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else if (step.tag === 'switch') {
|
|
159
|
+
// If the condition steps consists of a single "next", merge it with the condition
|
|
160
|
+
acc.push(flattenNextToCondition(step));
|
|
155
161
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
*/
|
|
162
|
-
return steps.map((step) => (step.tag === 'switch' ? flattenNext(step) : step));
|
|
162
|
+
else {
|
|
163
|
+
acc.push(step);
|
|
164
|
+
}
|
|
165
|
+
return acc;
|
|
166
|
+
}, []);
|
|
163
167
|
}
|
|
164
|
-
function
|
|
168
|
+
function flattenNextToCondition(step) {
|
|
165
169
|
const transformedBranches = step.branches.map((cond) => {
|
|
166
170
|
if (!cond.next && cond.steps.length === 1 && cond.steps[0].tag === 'next') {
|
|
167
171
|
const nextStep = cond.steps[0];
|
|
@@ -287,7 +291,7 @@ function transformExpressionsAssign(step, transform) {
|
|
|
287
291
|
newSteps.push(...steps2);
|
|
288
292
|
return [name, ex2];
|
|
289
293
|
});
|
|
290
|
-
newSteps.push(new AssignStepAST(newAssignments, step.label));
|
|
294
|
+
newSteps.push(new AssignStepAST(newAssignments, step.next, step.label));
|
|
291
295
|
return newSteps;
|
|
292
296
|
}
|
|
293
297
|
else {
|