ts2workflows 0.8.0 → 0.9.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/expressions.d.ts +9 -0
- package/dist/ast/expressions.d.ts.map +1 -1
- package/dist/ast/expressions.js +43 -19
- package/dist/ast/steps.d.ts +27 -7
- package/dist/ast/steps.d.ts.map +1 -1
- package/dist/ast/steps.js +104 -21
- package/dist/transpiler/expressions.d.ts +0 -1
- package/dist/transpiler/expressions.d.ts.map +1 -1
- package/dist/transpiler/expressions.js +51 -62
- package/dist/transpiler/index.d.ts.map +1 -1
- package/dist/transpiler/index.js +7 -4
- package/dist/transpiler/statements.d.ts +4 -3
- package/dist/transpiler/statements.d.ts.map +1 -1
- package/dist/transpiler/statements.js +369 -96
- package/dist/transpiler/transformations.d.ts +0 -6
- package/dist/transpiler/transformations.d.ts.map +1 -1
- package/dist/transpiler/transformations.js +88 -148
- package/dist/utils.d.ts +1 -5
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +3 -16
- package/language_reference.md +120 -61
- package/package.json +8 -4
|
@@ -1,19 +1,18 @@
|
|
|
1
|
+
import * as R from 'ramda';
|
|
1
2
|
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';
|
|
3
|
-
import { BinaryExpression, FunctionInvocationExpression, PrimitiveExpression, VariableReferenceExpression, isExpression, isFullyQualifiedName, isLiteral, } from '../ast/expressions.js';
|
|
3
|
+
import { AssignStepAST, CallStepAST, ForRangeStepAST, ForStepAST, JumpTargetAST, NextStepAST, ParallelStepAST, RaiseStepAST, ReturnStepAST, StepsStepAST, SwitchStepAST, TryStepAST, } from '../ast/steps.js';
|
|
4
|
+
import { BinaryExpression, FunctionInvocationExpression, MemberExpression, PrimitiveExpression, VariableReferenceExpression, asExpression, isExpression, isFullyQualifiedName, isLiteral, isPure, nullEx, safeAsExpression, trueEx, } from '../ast/expressions.js';
|
|
4
5
|
import { InternalTranspilingError, WorkflowSyntaxError } from '../errors.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { convertExpression, convertMemberExpression, convertObjectExpression, convertObjectAsExpressionValues, isMagicFunction, throwIfSpread, isMagicFunctionStatmentOnly, asExpression, } from './expressions.js';
|
|
6
|
+
import { chainPairs, isRecord } from '../utils.js';
|
|
7
|
+
import { convertExpression, convertMemberExpression, convertObjectExpression, convertObjectAsExpressionValues, isMagicFunction, throwIfSpread, isMagicFunctionStatmentOnly, } from './expressions.js';
|
|
8
8
|
import { blockingFunctions } from './generated/functionMetadata.js';
|
|
9
|
-
export function parseStatement(node, ctx
|
|
10
|
-
|
|
11
|
-
return transformAST(steps.concat(postSteps ?? []));
|
|
9
|
+
export function parseStatement(node, ctx) {
|
|
10
|
+
return parseStatementRecursively(node, undefined, ctx);
|
|
12
11
|
}
|
|
13
12
|
function parseStatementRecursively(node, nextNode, ctx) {
|
|
14
13
|
switch (node.type) {
|
|
15
14
|
case AST_NODE_TYPES.BlockStatement:
|
|
16
|
-
return
|
|
15
|
+
return chainPairs(R.partialRight(parseStatementRecursively, [ctx]), node.body);
|
|
17
16
|
case AST_NODE_TYPES.VariableDeclaration:
|
|
18
17
|
return convertVariableDeclarations(node.declarations, ctx);
|
|
19
18
|
case AST_NODE_TYPES.ExpressionStatement:
|
|
@@ -24,7 +23,7 @@ function parseStatementRecursively(node, nextNode, ctx) {
|
|
|
24
23
|
return callExpressionToStep(node.expression, undefined, ctx);
|
|
25
24
|
}
|
|
26
25
|
else {
|
|
27
|
-
return [generalExpressionToAssignStep(node.expression)];
|
|
26
|
+
return [generalExpressionToAssignStep(node.expression, ctx)];
|
|
28
27
|
}
|
|
29
28
|
case AST_NODE_TYPES.ReturnStatement:
|
|
30
29
|
return [returnStatementToReturnStep(node, ctx)];
|
|
@@ -71,27 +70,279 @@ function parseStatementRecursively(node, nextNode, ctx) {
|
|
|
71
70
|
}
|
|
72
71
|
function convertVariableDeclarations(declarations, ctx) {
|
|
73
72
|
return declarations.flatMap((decl) => {
|
|
74
|
-
if (decl.id.type
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
73
|
+
if (decl.id.type === AST_NODE_TYPES.Identifier) {
|
|
74
|
+
return convertInitializer(decl.id.name, decl.init, ctx);
|
|
75
|
+
}
|
|
76
|
+
else if (decl.id.type === AST_NODE_TYPES.ArrayPattern) {
|
|
77
|
+
return convertArrayDestructuring(decl.id, decl.init, ctx);
|
|
78
|
+
}
|
|
79
|
+
else if (decl.id.type === AST_NODE_TYPES.ObjectPattern) {
|
|
80
|
+
return convertObjectDestructuring(decl.id, decl.init, ctx);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
throw new WorkflowSyntaxError('Unsupported pattern', decl.loc);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function convertInitializer(targetVariableName, initializer, ctx) {
|
|
88
|
+
if (initializer?.type === AST_NODE_TYPES.CallExpression) {
|
|
89
|
+
const calleeName = initializer.callee.type === AST_NODE_TYPES.Identifier
|
|
90
|
+
? initializer.callee.name
|
|
91
|
+
: undefined;
|
|
92
|
+
if (calleeName && isMagicFunctionStatmentOnly(calleeName)) {
|
|
93
|
+
throw new WorkflowSyntaxError(`"${calleeName}" can't be called as part of an expression`, initializer.callee.loc);
|
|
94
|
+
}
|
|
95
|
+
return callExpressionToStep(initializer, targetVariableName, ctx);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
const value = initializer === null ? nullEx : convertExpression(initializer);
|
|
99
|
+
return [new AssignStepAST([[targetVariableName, value]])];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function convertArrayDestructuring(arrayPattern, initializer, ctx) {
|
|
103
|
+
let initExpression;
|
|
104
|
+
const steps = [];
|
|
105
|
+
if (initializer?.type === AST_NODE_TYPES.Identifier ||
|
|
106
|
+
initializer?.type === AST_NODE_TYPES.MemberExpression) {
|
|
107
|
+
// If the initializer is an Identifier or MemberExpression (array variable?),
|
|
108
|
+
// use it directly. This ensures that the recursive variables gets initialized
|
|
109
|
+
// in the correct order. For example:
|
|
110
|
+
// const arr = [1, 2]
|
|
111
|
+
// [arr[1], arr[0]] = arr
|
|
112
|
+
initExpression = convertExpression(initializer);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
// Otherwise, assign the expression to a temporary variable first.
|
|
116
|
+
const initName = tempName(ctx);
|
|
117
|
+
steps.push(...convertInitializer(initName, initializer, ctx));
|
|
118
|
+
initExpression = new VariableReferenceExpression(initName);
|
|
119
|
+
}
|
|
120
|
+
steps.push(...arrayDestructuringSteps(arrayPattern.elements, initExpression, ctx));
|
|
121
|
+
return steps;
|
|
122
|
+
}
|
|
123
|
+
function arrayDestructuringSteps(patterns, initializerExpression, ctx) {
|
|
124
|
+
if (patterns.filter((p) => p !== null).length === 0) {
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
const __temp_len = `${tempName(ctx)}_len`;
|
|
128
|
+
const initializeVariables = [
|
|
129
|
+
[
|
|
130
|
+
__temp_len,
|
|
131
|
+
new FunctionInvocationExpression('len', [initializerExpression]),
|
|
132
|
+
],
|
|
133
|
+
];
|
|
134
|
+
const branches = R.reverse(patterns).flatMap((pat, i) => {
|
|
135
|
+
if (pat === null) {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
return [
|
|
140
|
+
{
|
|
141
|
+
condition: new BinaryExpression(new VariableReferenceExpression(__temp_len), '>=', new PrimitiveExpression(patterns.length - i)),
|
|
142
|
+
steps: arrayElementsDestructuringSteps(patterns, initializerExpression, patterns.length - i, ctx),
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
branches.push({
|
|
148
|
+
condition: trueEx,
|
|
149
|
+
steps: arrayElementsDestructuringSteps(patterns, initializerExpression, 0, ctx),
|
|
150
|
+
});
|
|
151
|
+
return [new AssignStepAST(initializeVariables), new SwitchStepAST(branches)];
|
|
152
|
+
}
|
|
153
|
+
function arrayElementsDestructuringSteps(patterns, initializerExpression, take, ctx) {
|
|
154
|
+
return patterns.flatMap((pat, i) => {
|
|
155
|
+
if (i >= take) {
|
|
156
|
+
return [
|
|
157
|
+
new AssignStepAST(extractDefaultAssignmentsFromDestructuringPattern(pat)),
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
const iElement = new MemberExpression(initializerExpression, new PrimitiveExpression(i), true);
|
|
161
|
+
switch (pat?.type) {
|
|
162
|
+
case AST_NODE_TYPES.MemberExpression:
|
|
163
|
+
case AST_NODE_TYPES.Identifier: {
|
|
164
|
+
const name = convertExpression(pat).toString();
|
|
165
|
+
return [new AssignStepAST([[name, iElement]])];
|
|
166
|
+
}
|
|
167
|
+
case AST_NODE_TYPES.AssignmentPattern: {
|
|
168
|
+
if (pat.left.type !== AST_NODE_TYPES.Identifier) {
|
|
169
|
+
throw new WorkflowSyntaxError('Default value can be used only with an identifier', pat.left.loc);
|
|
170
|
+
}
|
|
171
|
+
return [new AssignStepAST([[pat.left.name, iElement]])];
|
|
172
|
+
}
|
|
173
|
+
case AST_NODE_TYPES.ObjectPattern:
|
|
174
|
+
return objectDestructuringSteps(pat.properties, iElement, ctx);
|
|
175
|
+
case AST_NODE_TYPES.ArrayPattern:
|
|
176
|
+
return arrayDestructuringSteps(pat.elements, iElement, ctx);
|
|
177
|
+
case AST_NODE_TYPES.RestElement:
|
|
178
|
+
return arrayRestDestructuringSteps(patterns, pat, initializerExpression, patterns.length - 1, ctx);
|
|
179
|
+
default: // pat === null
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
function extractDefaultAssignmentsFromDestructuringPattern(pat) {
|
|
185
|
+
if (pat === null) {
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
switch (pat.type) {
|
|
189
|
+
case AST_NODE_TYPES.ArrayPattern:
|
|
190
|
+
return pat.elements.flatMap(extractDefaultAssignmentsFromDestructuringPattern);
|
|
191
|
+
case AST_NODE_TYPES.AssignmentPattern:
|
|
192
|
+
if (pat.left.type !== AST_NODE_TYPES.Identifier) {
|
|
193
|
+
throw new WorkflowSyntaxError('Default value can be used only with an identifier', pat.left.loc);
|
|
84
194
|
}
|
|
85
|
-
return
|
|
195
|
+
return [[pat.left.name, convertExpression(pat.right)]];
|
|
196
|
+
case AST_NODE_TYPES.Identifier:
|
|
197
|
+
return [[pat.name, nullEx]];
|
|
198
|
+
case AST_NODE_TYPES.MemberExpression:
|
|
199
|
+
return [[convertExpression(pat).toString(), nullEx]];
|
|
200
|
+
case AST_NODE_TYPES.ObjectPattern:
|
|
201
|
+
return pat.properties.flatMap((p) => {
|
|
202
|
+
if (p.type === AST_NODE_TYPES.RestElement) {
|
|
203
|
+
return extractDefaultAssignmentsFromDestructuringPattern(p);
|
|
204
|
+
}
|
|
205
|
+
else if (p.value.type === AST_NODE_TYPES.ArrayPattern ||
|
|
206
|
+
p.value.type === AST_NODE_TYPES.AssignmentPattern ||
|
|
207
|
+
p.value.type === AST_NODE_TYPES.Identifier ||
|
|
208
|
+
p.value.type === AST_NODE_TYPES.MemberExpression ||
|
|
209
|
+
p.value.type === AST_NODE_TYPES.ObjectPattern) {
|
|
210
|
+
return extractDefaultAssignmentsFromDestructuringPattern(p.value);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
throw new WorkflowSyntaxError('Destructuring pattern expected', p.value.loc);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
case AST_NODE_TYPES.RestElement:
|
|
217
|
+
if (pat.argument.type !== AST_NODE_TYPES.Identifier) {
|
|
218
|
+
throw new WorkflowSyntaxError('Identifier expected', pat.argument.loc);
|
|
219
|
+
}
|
|
220
|
+
return [[pat.argument.name, new PrimitiveExpression([])]];
|
|
221
|
+
default:
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function throwIfInvalidRestElement(patterns) {
|
|
226
|
+
const i = patterns.findIndex((p) => p?.type === AST_NODE_TYPES.RestElement);
|
|
227
|
+
if (i >= 0 && i !== patterns.length - 1) {
|
|
228
|
+
throw new WorkflowSyntaxError('A rest element must be last in a destructuring pattern', patterns[i].loc);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function arrayRestDestructuringSteps(patterns, rest, initializerExpression, startIndex, ctx) {
|
|
232
|
+
throwIfInvalidRestElement(patterns);
|
|
233
|
+
if (rest.argument.type !== AST_NODE_TYPES.Identifier) {
|
|
234
|
+
throw new WorkflowSyntaxError('Identifier expected', rest.argument.loc);
|
|
235
|
+
}
|
|
236
|
+
const restName = rest.argument.name;
|
|
237
|
+
const __temp_len = new VariableReferenceExpression(`${tempName(ctx)}_len`);
|
|
238
|
+
const __temp_index = `${tempName(ctx)}_index`;
|
|
239
|
+
const one = new PrimitiveExpression(1);
|
|
240
|
+
const emptyArray = new PrimitiveExpression([]);
|
|
241
|
+
const copyLoop = new ForRangeStepAST([
|
|
242
|
+
new AssignStepAST([
|
|
243
|
+
[
|
|
244
|
+
restName,
|
|
245
|
+
new FunctionInvocationExpression('list.concat', [
|
|
246
|
+
new VariableReferenceExpression(restName),
|
|
247
|
+
new MemberExpression(initializerExpression, new VariableReferenceExpression(__temp_index), true),
|
|
248
|
+
]),
|
|
249
|
+
],
|
|
250
|
+
]),
|
|
251
|
+
], __temp_index, startIndex, new BinaryExpression(__temp_len, '-', one));
|
|
252
|
+
return [new AssignStepAST([[restName, emptyArray]]), copyLoop];
|
|
253
|
+
}
|
|
254
|
+
function convertObjectDestructuring(objectPattern, initializer, ctx) {
|
|
255
|
+
let initExpression;
|
|
256
|
+
const steps = [];
|
|
257
|
+
if (initializer?.type === AST_NODE_TYPES.Identifier ||
|
|
258
|
+
(initializer?.type === AST_NODE_TYPES.MemberExpression &&
|
|
259
|
+
isPure(convertExpression(initializer)))) {
|
|
260
|
+
// If the initializer is an Identifier or MemberExpression (object variable?), use it directly.
|
|
261
|
+
initExpression = convertExpression(initializer);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// Otherwise, assign the expression to a temporary variable first.
|
|
265
|
+
const initName = tempName(ctx);
|
|
266
|
+
steps.push(...convertInitializer(initName, initializer, ctx));
|
|
267
|
+
initExpression = new VariableReferenceExpression(initName);
|
|
268
|
+
}
|
|
269
|
+
steps.push(...objectDestructuringSteps(objectPattern.properties, initExpression, ctx));
|
|
270
|
+
return steps;
|
|
271
|
+
}
|
|
272
|
+
function objectDestructuringSteps(properties, initializerExpression, ctx) {
|
|
273
|
+
return properties.flatMap((prop) => {
|
|
274
|
+
if (prop.type === AST_NODE_TYPES.RestElement) {
|
|
275
|
+
return objectDestructuringRestSteps(properties, prop, initializerExpression);
|
|
276
|
+
}
|
|
277
|
+
if (prop.key.type !== AST_NODE_TYPES.Identifier) {
|
|
278
|
+
throw new WorkflowSyntaxError('Identifier expected', prop.key.loc);
|
|
279
|
+
}
|
|
280
|
+
const keyExpression = new MemberExpression(initializerExpression, new VariableReferenceExpression(prop.key.name), false);
|
|
281
|
+
if (prop.value.type === AST_NODE_TYPES.ObjectPattern) {
|
|
282
|
+
return objectDestructuringSteps(prop.value.properties, keyExpression, ctx);
|
|
283
|
+
}
|
|
284
|
+
else if (prop.value.type === AST_NODE_TYPES.ArrayPattern) {
|
|
285
|
+
return arrayDestructuringSteps(prop.value.elements, keyExpression, ctx);
|
|
286
|
+
}
|
|
287
|
+
else if (prop.value.type === AST_NODE_TYPES.Identifier) {
|
|
288
|
+
const safeKeyExpression = new FunctionInvocationExpression('map.get', [
|
|
289
|
+
initializerExpression,
|
|
290
|
+
new PrimitiveExpression(prop.key.name),
|
|
291
|
+
]);
|
|
292
|
+
return [new AssignStepAST([[prop.value.name, safeKeyExpression]])];
|
|
293
|
+
}
|
|
294
|
+
else if (prop.value.type === AST_NODE_TYPES.AssignmentPattern) {
|
|
295
|
+
return objectAssignmentPatternSteps(prop.value, initializerExpression, keyExpression);
|
|
86
296
|
}
|
|
87
297
|
else {
|
|
88
|
-
|
|
89
|
-
? new PrimitiveExpression(null)
|
|
90
|
-
: convertExpression(decl.init);
|
|
91
|
-
return [new AssignStepAST([[targetName, value]])];
|
|
298
|
+
throw new WorkflowSyntaxError(`${prop.value.type} is not allowed in object destructuring`, prop.value.loc);
|
|
92
299
|
}
|
|
93
300
|
});
|
|
94
301
|
}
|
|
302
|
+
function objectAssignmentPatternSteps(pat, initializerExpression, keyExpression) {
|
|
303
|
+
if (pat.left.type !== AST_NODE_TYPES.Identifier) {
|
|
304
|
+
throw new WorkflowSyntaxError('Default value can be used only with an identifier', pat.left.loc);
|
|
305
|
+
}
|
|
306
|
+
// Using Switch step instead of default() because pat.right must be evaluated only
|
|
307
|
+
// in the default value branch (in case it has side effects)
|
|
308
|
+
return [
|
|
309
|
+
new SwitchStepAST([
|
|
310
|
+
{
|
|
311
|
+
condition: new BinaryExpression(new PrimitiveExpression(pat.left.name), 'in', initializerExpression),
|
|
312
|
+
steps: [new AssignStepAST([[pat.left.name, keyExpression]])],
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
condition: trueEx,
|
|
316
|
+
steps: [
|
|
317
|
+
new AssignStepAST([[pat.left.name, convertExpression(pat.right)]]),
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
]),
|
|
321
|
+
];
|
|
322
|
+
}
|
|
323
|
+
function objectDestructuringRestSteps(properties, rest, initializerExpression) {
|
|
324
|
+
throwIfInvalidRestElement(properties);
|
|
325
|
+
if (rest.argument.type !== AST_NODE_TYPES.Identifier) {
|
|
326
|
+
throw new WorkflowSyntaxError('Identifier expected', rest.argument.loc);
|
|
327
|
+
}
|
|
328
|
+
const nonRestProperties = properties.filter((x) => x.type !== AST_NODE_TYPES.RestElement);
|
|
329
|
+
const nonRestKeys = nonRestProperties
|
|
330
|
+
.map((p) => p.key)
|
|
331
|
+
.map((p) => {
|
|
332
|
+
if (p.type !== AST_NODE_TYPES.Identifier) {
|
|
333
|
+
throw new WorkflowSyntaxError('Identifier expected', p.loc);
|
|
334
|
+
}
|
|
335
|
+
return p;
|
|
336
|
+
})
|
|
337
|
+
.map((p) => p.name);
|
|
338
|
+
const value = nonRestKeys.reduce((acc, propertyName) =>
|
|
339
|
+
// map.delete returns a copy of the object and removes the specified property
|
|
340
|
+
new FunctionInvocationExpression('map.delete', [
|
|
341
|
+
acc,
|
|
342
|
+
new PrimitiveExpression(propertyName),
|
|
343
|
+
]), initializerExpression);
|
|
344
|
+
return [new AssignStepAST([[rest.argument.name, value]])];
|
|
345
|
+
}
|
|
95
346
|
function assignmentExpressionToSteps(node, ctx) {
|
|
96
347
|
let compoundOperator = undefined;
|
|
97
348
|
switch (node.operator) {
|
|
@@ -122,6 +373,22 @@ function assignmentExpressionToSteps(node, ctx) {
|
|
|
122
373
|
default:
|
|
123
374
|
throw new WorkflowSyntaxError(`Operator ${node.operator} is not supported in assignment expressions`, node.loc);
|
|
124
375
|
}
|
|
376
|
+
if (node.left.type === AST_NODE_TYPES.ArrayPattern) {
|
|
377
|
+
if (node.operator === '=') {
|
|
378
|
+
return convertArrayDestructuring(node.left, node.right, ctx);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
throw new WorkflowSyntaxError(`Invalid left-hand side in assignment`, node.left.loc);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
else if (node.left.type === AST_NODE_TYPES.ObjectPattern) {
|
|
385
|
+
if (node.operator === '=') {
|
|
386
|
+
return convertObjectDestructuring(node.left, node.right, ctx);
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
throw new WorkflowSyntaxError(`Invalid left-hand side in assignment`, node.left.loc);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
125
392
|
const targetExpression = convertExpression(node.left);
|
|
126
393
|
if (!isFullyQualifiedName(targetExpression)) {
|
|
127
394
|
throw new WorkflowSyntaxError('The left-hand side of an assignment must be an identifier or a property access', node.loc);
|
|
@@ -138,12 +405,12 @@ function assignmentExpressionToSteps(node, ctx) {
|
|
|
138
405
|
}
|
|
139
406
|
const needsTempVariable = compoundOperator === undefined ||
|
|
140
407
|
node.left.type !== AST_NODE_TYPES.Identifier;
|
|
141
|
-
const resultVariable = needsTempVariable ?
|
|
408
|
+
const resultVariable = needsTempVariable ? tempName(ctx) : targetName;
|
|
142
409
|
steps.push(...callExpressionToStep(node.right, resultVariable, ctx));
|
|
143
410
|
if (!needsTempVariable) {
|
|
144
411
|
return steps;
|
|
145
412
|
}
|
|
146
|
-
valueExpression = new VariableReferenceExpression(
|
|
413
|
+
valueExpression = new VariableReferenceExpression(tempName(ctx));
|
|
147
414
|
}
|
|
148
415
|
else {
|
|
149
416
|
valueExpression = convertExpression(node.right);
|
|
@@ -159,7 +426,7 @@ function callExpressionToStep(node, resultVariable, ctx) {
|
|
|
159
426
|
if (isFullyQualifiedName(calleeExpression)) {
|
|
160
427
|
const calleeName = calleeExpression.toString();
|
|
161
428
|
if (calleeName === 'parallel') {
|
|
162
|
-
// A
|
|
429
|
+
// A handle the "parallel" intrinsic
|
|
163
430
|
return [callExpressionToParallelStep(node, ctx)];
|
|
164
431
|
}
|
|
165
432
|
else if (calleeName === 'retry_policy') {
|
|
@@ -176,8 +443,9 @@ function callExpressionToStep(node, resultVariable, ctx) {
|
|
|
176
443
|
];
|
|
177
444
|
}
|
|
178
445
|
else {
|
|
446
|
+
const resultVariable2 = resultVariable ?? tempName(ctx);
|
|
179
447
|
return [
|
|
180
|
-
callExpressionAssignStep(calleeName, node.arguments,
|
|
448
|
+
callExpressionAssignStep(calleeName, node.arguments, resultVariable2),
|
|
181
449
|
];
|
|
182
450
|
}
|
|
183
451
|
}
|
|
@@ -189,7 +457,7 @@ function callExpressionAssignStep(functionName, argumentsNode, resultVariable) {
|
|
|
189
457
|
const argumentExpressions = throwIfSpread(argumentsNode).map(convertExpression);
|
|
190
458
|
return new AssignStepAST([
|
|
191
459
|
[
|
|
192
|
-
resultVariable
|
|
460
|
+
resultVariable,
|
|
193
461
|
new FunctionInvocationExpression(functionName, argumentExpressions),
|
|
194
462
|
],
|
|
195
463
|
]);
|
|
@@ -245,14 +513,19 @@ function callExpressionToParallelStep(node, ctx) {
|
|
|
245
513
|
node.callee.name !== 'parallel') {
|
|
246
514
|
throw new InternalTranspilingError(`The parameter must be a call to "parallel"`);
|
|
247
515
|
}
|
|
516
|
+
const ctx2 = Object.assign({}, ctx, {
|
|
517
|
+
parallelNestingLevel: ctx.parallelNestingLevel
|
|
518
|
+
? ctx.parallelNestingLevel + 1
|
|
519
|
+
: 1,
|
|
520
|
+
});
|
|
248
521
|
let steps = {};
|
|
249
522
|
if (node.arguments.length > 0) {
|
|
250
523
|
switch (node.arguments[0].type) {
|
|
251
524
|
case AST_NODE_TYPES.ArrayExpression:
|
|
252
|
-
steps = parseParallelBranches(node.arguments[0]);
|
|
525
|
+
steps = parseParallelBranches(node.arguments[0], ctx2);
|
|
253
526
|
break;
|
|
254
527
|
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
255
|
-
steps = parseParallelIteration(node.arguments[0],
|
|
528
|
+
steps = parseParallelIteration(node.arguments[0], ctx2);
|
|
256
529
|
break;
|
|
257
530
|
default:
|
|
258
531
|
throw new WorkflowSyntaxError('The first parameter must be an array of functions or an arrow function', node.arguments[0].loc);
|
|
@@ -269,25 +542,21 @@ function callExpressionToParallelStep(node, ctx) {
|
|
|
269
542
|
}
|
|
270
543
|
return new ParallelStepAST(steps, shared, concurrencyLimit, exceptionPolicy);
|
|
271
544
|
}
|
|
272
|
-
function parseParallelBranches(node) {
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
if (arg === null) {
|
|
276
|
-
throw new WorkflowSyntaxError('Argument should be a function call of type () => void', node.loc);
|
|
277
|
-
}
|
|
278
|
-
switch (arg.type) {
|
|
545
|
+
function parseParallelBranches(node, ctx) {
|
|
546
|
+
const branches = node.elements.map((arg) => {
|
|
547
|
+
switch (arg?.type) {
|
|
279
548
|
case AST_NODE_TYPES.Identifier:
|
|
280
|
-
return
|
|
549
|
+
return new StepsStepAST([new CallStepAST(arg.name)]);
|
|
281
550
|
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
282
551
|
if (arg.body.type !== AST_NODE_TYPES.BlockStatement) {
|
|
283
552
|
throw new WorkflowSyntaxError('The body must be a block statement', arg.body.loc);
|
|
284
553
|
}
|
|
285
|
-
return
|
|
554
|
+
return new StepsStepAST(parseStatement(arg.body, ctx));
|
|
286
555
|
default:
|
|
287
|
-
throw new WorkflowSyntaxError('Argument should be a function
|
|
556
|
+
throw new WorkflowSyntaxError('Argument should be a function of type () => void', arg ? arg.loc : node.loc);
|
|
288
557
|
}
|
|
289
558
|
});
|
|
290
|
-
return Object.fromEntries(
|
|
559
|
+
return Object.fromEntries(branches.map((step, i) => [`branch${i + 1}`, step]));
|
|
291
560
|
}
|
|
292
561
|
function parseParallelIteration(node, ctx) {
|
|
293
562
|
if (node.body.type !== AST_NODE_TYPES.BlockStatement ||
|
|
@@ -330,8 +599,8 @@ function parseParallelOptions(node) {
|
|
|
330
599
|
exceptionPolicy,
|
|
331
600
|
};
|
|
332
601
|
}
|
|
333
|
-
function generalExpressionToAssignStep(node) {
|
|
334
|
-
return new AssignStepAST([[
|
|
602
|
+
function generalExpressionToAssignStep(node, ctx) {
|
|
603
|
+
return new AssignStepAST([[tempName(ctx), convertExpression(node)]]);
|
|
335
604
|
}
|
|
336
605
|
function returnStatementToReturnStep(node, ctx) {
|
|
337
606
|
const value = node.argument ? convertExpression(node.argument) : undefined;
|
|
@@ -361,7 +630,7 @@ function flattenIfBranches(ifStatement, ctx) {
|
|
|
361
630
|
}
|
|
362
631
|
else {
|
|
363
632
|
branches.push({
|
|
364
|
-
condition:
|
|
633
|
+
condition: trueEx,
|
|
365
634
|
steps: parseStatement(ifStatement.alternate, ctx),
|
|
366
635
|
});
|
|
367
636
|
}
|
|
@@ -381,10 +650,10 @@ function switchStatementToSteps(node, ctx) {
|
|
|
381
650
|
condition = new BinaryExpression(discriminant, '==', test);
|
|
382
651
|
}
|
|
383
652
|
else {
|
|
384
|
-
condition =
|
|
653
|
+
condition = trueEx;
|
|
385
654
|
}
|
|
386
655
|
const jumpTarget = new JumpTargetAST();
|
|
387
|
-
const body =
|
|
656
|
+
const body = caseNode.consequent.flatMap((x) => parseStatement(x, switchCtx));
|
|
388
657
|
steps.push(jumpTarget);
|
|
389
658
|
steps.push(...body);
|
|
390
659
|
branches.push({
|
|
@@ -416,12 +685,12 @@ function forOfStatementToForStep(node, ctx) {
|
|
|
416
685
|
throw new WorkflowSyntaxError('Initial value not allowed', declaration.init.loc);
|
|
417
686
|
}
|
|
418
687
|
if (declaration.id.type !== AST_NODE_TYPES.Identifier) {
|
|
419
|
-
throw new WorkflowSyntaxError(`
|
|
688
|
+
throw new WorkflowSyntaxError(`Identifier expected, got ${declaration.id.type}`, declaration.id.loc);
|
|
420
689
|
}
|
|
421
690
|
loopVariableName = declaration.id.name;
|
|
422
691
|
}
|
|
423
692
|
else {
|
|
424
|
-
throw new InternalTranspilingError(`
|
|
693
|
+
throw new InternalTranspilingError(`Identifier or VariableDeclaration expected, got ${node.left.type}`);
|
|
425
694
|
}
|
|
426
695
|
const listExpression = convertExpression(node.right);
|
|
427
696
|
if (isLiteral(listExpression) &&
|
|
@@ -443,7 +712,7 @@ function whileStatementSteps(node, ctx) {
|
|
|
443
712
|
breakTarget: endOfLoop.label,
|
|
444
713
|
});
|
|
445
714
|
const postSteps = [new NextStepAST(startOfLoop.label)];
|
|
446
|
-
const steps = parseStatement(node.body, ctx2
|
|
715
|
+
const steps = parseStatement(node.body, ctx2).concat(postSteps);
|
|
447
716
|
return [
|
|
448
717
|
startOfLoop,
|
|
449
718
|
new SwitchStepAST([
|
|
@@ -583,8 +852,8 @@ function extractErrorVariableName(param) {
|
|
|
583
852
|
*/
|
|
584
853
|
function finalizerInitializer(conditionVariable, valueVariable) {
|
|
585
854
|
return new AssignStepAST([
|
|
586
|
-
[conditionVariable,
|
|
587
|
-
[valueVariable,
|
|
855
|
+
[conditionVariable, nullEx],
|
|
856
|
+
[valueVariable, nullEx],
|
|
588
857
|
]);
|
|
589
858
|
}
|
|
590
859
|
/**
|
|
@@ -600,16 +869,18 @@ function finalizerInitializer(conditionVariable, valueVariable) {
|
|
|
600
869
|
* }
|
|
601
870
|
*/
|
|
602
871
|
function finalizerFooter(conditionVariable, valueVariable) {
|
|
872
|
+
const variable = new VariableReferenceExpression(conditionVariable);
|
|
873
|
+
const val = new VariableReferenceExpression(valueVariable);
|
|
874
|
+
const returnString = new PrimitiveExpression('return');
|
|
875
|
+
const raiseString = new PrimitiveExpression('raise');
|
|
603
876
|
return new SwitchStepAST([
|
|
604
877
|
{
|
|
605
|
-
condition: new BinaryExpression(
|
|
606
|
-
steps: [
|
|
607
|
-
new ReturnStepAST(new VariableReferenceExpression(valueVariable)),
|
|
608
|
-
],
|
|
878
|
+
condition: new BinaryExpression(variable, '==', returnString),
|
|
879
|
+
steps: [new ReturnStepAST(val)],
|
|
609
880
|
},
|
|
610
881
|
{
|
|
611
|
-
condition: new BinaryExpression(
|
|
612
|
-
steps: [new RaiseStepAST(
|
|
882
|
+
condition: new BinaryExpression(variable, '==', raiseString),
|
|
883
|
+
steps: [new RaiseStepAST(val)],
|
|
613
884
|
},
|
|
614
885
|
]);
|
|
615
886
|
}
|
|
@@ -631,7 +902,7 @@ function delayedReturnAndJumpToFinalizer(value, ctx) {
|
|
|
631
902
|
const [conditionVariable, valueVariable] = finalizerVariables(ctx);
|
|
632
903
|
return new AssignStepAST([
|
|
633
904
|
[conditionVariable, new PrimitiveExpression('return')],
|
|
634
|
-
[valueVariable, value ??
|
|
905
|
+
[valueVariable, value ?? nullEx],
|
|
635
906
|
], finalizerTarget);
|
|
636
907
|
}
|
|
637
908
|
function labeledStep(node, ctx) {
|
|
@@ -664,43 +935,45 @@ function parseRetryPolicy(node) {
|
|
|
664
935
|
}
|
|
665
936
|
}
|
|
666
937
|
function retryPolicyFromParams(paramsObject, argsLoc) {
|
|
667
|
-
const params =
|
|
668
|
-
if ('backoff' in params) {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
938
|
+
const params = R.map(asExpression, paramsObject);
|
|
939
|
+
if (!('backoff' in params)) {
|
|
940
|
+
throw new WorkflowSyntaxError('Required parameter "backoff" missing', argsLoc);
|
|
941
|
+
}
|
|
942
|
+
else if (params.backoff.expressionType !== 'primitive' ||
|
|
943
|
+
!isRecord(params.backoff.value)) {
|
|
944
|
+
throw new WorkflowSyntaxError('Expected "backoff" to be an object literal', argsLoc);
|
|
945
|
+
}
|
|
946
|
+
const backoff = params.backoff.value;
|
|
947
|
+
return {
|
|
948
|
+
predicate: predicateFromRetryParams(params, argsLoc),
|
|
949
|
+
maxRetries: params.max_retries,
|
|
950
|
+
backoff: {
|
|
951
|
+
initialDelay: safeAsExpression(backoff.initial_delay),
|
|
952
|
+
maxDelay: safeAsExpression(backoff.max_delay),
|
|
953
|
+
multiplier: safeAsExpression(backoff.multiplier),
|
|
954
|
+
},
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
function predicateFromRetryParams(params, argsLoc) {
|
|
958
|
+
if (!('predicate' in params)) {
|
|
959
|
+
return undefined;
|
|
960
|
+
}
|
|
961
|
+
else if (isFullyQualifiedName(params.predicate)) {
|
|
962
|
+
return params.predicate.toString();
|
|
963
|
+
}
|
|
964
|
+
else {
|
|
965
|
+
throw new WorkflowSyntaxError('"predicate" must be a function name', argsLoc);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
function tempName(ctx) {
|
|
969
|
+
if (ctx.parallelNestingLevel !== undefined) {
|
|
970
|
+
// Temporary variable inside a parallel step can not be the same as temporary
|
|
971
|
+
// variables on the outside. Sharing the variable name would cause deployment
|
|
972
|
+
// error, if the variable is not marked as shared by including it in the
|
|
973
|
+
// "shared" array.
|
|
974
|
+
return `__temp_parallel${ctx.parallelNestingLevel ?? 0}`;
|
|
702
975
|
}
|
|
703
976
|
else {
|
|
704
|
-
|
|
977
|
+
return '__temp';
|
|
705
978
|
}
|
|
706
979
|
}
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import { WorkflowStepAST } from '../ast/steps.js';
|
|
2
|
-
/**
|
|
3
|
-
* Performs various transformations on the AST.
|
|
4
|
-
*
|
|
5
|
-
* This flat list of steps and does not recurse into nested steps. This gets
|
|
6
|
-
* called on each nesting level separately.
|
|
7
|
-
*/
|
|
8
2
|
export declare function transformAST(steps: WorkflowStepAST[]): WorkflowStepAST[];
|
|
9
3
|
/**
|
|
10
4
|
* Merge a next step to the previous step.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformations.d.ts","sourceRoot":"","sources":["../../src/transpiler/transformations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transformations.d.ts","sourceRoot":"","sources":["../../src/transpiler/transformations.ts"],"names":[],"mappings":"AACA,OAAO,EAQL,eAAe,EAChB,MAAM,iBAAiB,CAAA;AA6BxB,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAExE;AAiCD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,eAAe,EAAE,GACvB,eAAe,EAAE,CAqBnB"}
|