ts2workflows 0.10.0 → 0.12.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.
Files changed (53) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +36 -9
  3. package/dist/ast/expressions.d.ts +37 -41
  4. package/dist/ast/expressions.d.ts.map +1 -1
  5. package/dist/ast/expressions.js +124 -255
  6. package/dist/ast/statements.d.ts +132 -0
  7. package/dist/ast/statements.d.ts.map +1 -0
  8. package/dist/ast/statements.js +197 -0
  9. package/dist/ast/steps.d.ts +82 -194
  10. package/dist/ast/steps.d.ts.map +1 -1
  11. package/dist/ast/steps.js +862 -521
  12. package/dist/ast/workflows.d.ts +14 -12
  13. package/dist/ast/workflows.d.ts.map +1 -1
  14. package/dist/ast/workflows.js +20 -35
  15. package/dist/cli.js +45 -32
  16. package/dist/errors.d.ts +4 -0
  17. package/dist/errors.d.ts.map +1 -1
  18. package/dist/errors.js +7 -0
  19. package/dist/transpiler/index.d.ts +19 -1
  20. package/dist/transpiler/index.d.ts.map +1 -1
  21. package/dist/transpiler/index.js +158 -31
  22. package/dist/transpiler/linker.d.ts +3 -0
  23. package/dist/transpiler/linker.d.ts.map +1 -0
  24. package/dist/transpiler/linker.js +41 -0
  25. package/dist/transpiler/parseexpressions.d.ts +11 -0
  26. package/dist/transpiler/parseexpressions.d.ts.map +1 -0
  27. package/dist/transpiler/{expressions.js → parseexpressions.js} +90 -103
  28. package/dist/transpiler/parsestatement.d.ts +7 -0
  29. package/dist/transpiler/parsestatement.d.ts.map +1 -0
  30. package/dist/transpiler/parsestatement.js +862 -0
  31. package/dist/transpiler/stepnames.d.ts +3 -0
  32. package/dist/transpiler/stepnames.d.ts.map +1 -0
  33. package/dist/transpiler/stepnames.js +17 -0
  34. package/dist/transpiler/transformations.d.ts +3 -19
  35. package/dist/transpiler/transformations.d.ts.map +1 -1
  36. package/dist/transpiler/transformations.js +267 -322
  37. package/language_reference.md +53 -17
  38. package/package.json +15 -11
  39. package/types/workflowslib.d.ts +58 -74
  40. package/dist/ast/stepnames.d.ts +0 -9
  41. package/dist/ast/stepnames.d.ts.map +0 -1
  42. package/dist/ast/stepnames.js +0 -280
  43. package/dist/ast/validation.d.ts +0 -20
  44. package/dist/ast/validation.d.ts.map +0 -1
  45. package/dist/ast/validation.js +0 -214
  46. package/dist/transpiler/expressions.d.ts +0 -11
  47. package/dist/transpiler/expressions.d.ts.map +0 -1
  48. package/dist/transpiler/statements.d.ts +0 -10
  49. package/dist/transpiler/statements.d.ts.map +0 -1
  50. package/dist/transpiler/statements.js +0 -1100
  51. package/dist/utils.d.ts +0 -9
  52. package/dist/utils.d.ts.map +0 -1
  53. package/dist/utils.js +0 -13
@@ -1,1100 +0,0 @@
1
- import * as R from 'ramda';
2
- import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
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';
5
- import { InternalTranspilingError, WorkflowSyntaxError } from '../errors.js';
6
- import { chainPairs, isRecord } from '../utils.js';
7
- import { convertExpression, convertMemberExpression, convertObjectExpression, convertObjectAsExpressionValues, isIntrinsic, throwIfSpread, isIntrinsicStatment as isIntrinsicStatement, convertVariableNameExpression, } from './expressions.js';
8
- import { blockingFunctions } from './generated/functionMetadata.js';
9
- export function parseStatement(node, ctx) {
10
- return parseStatementRecursively(node, undefined, ctx);
11
- }
12
- function parseStatementRecursively(node, nextNode, ctx) {
13
- switch (node.type) {
14
- case AST_NODE_TYPES.BlockStatement:
15
- return chainPairs(R.partialRight(parseStatementRecursively, [ctx]), node.body);
16
- case AST_NODE_TYPES.VariableDeclaration:
17
- return convertVariableDeclarations(node.declarations, ctx);
18
- case AST_NODE_TYPES.ExpressionStatement:
19
- if (node.expression.type === AST_NODE_TYPES.AssignmentExpression) {
20
- return assignmentExpressionToSteps(node.expression, ctx);
21
- }
22
- else if (node.expression.type === AST_NODE_TYPES.CallExpression) {
23
- return callExpressionToStep(node.expression, undefined, ctx);
24
- }
25
- else {
26
- return [generalExpressionToAssignStep(node.expression, ctx)];
27
- }
28
- case AST_NODE_TYPES.ReturnStatement:
29
- return [returnStatementToReturnStep(node, ctx)];
30
- case AST_NODE_TYPES.ThrowStatement:
31
- return [throwStatementToRaiseStep(node)];
32
- case AST_NODE_TYPES.IfStatement:
33
- return [ifStatementToSwitchStep(node, ctx)];
34
- case AST_NODE_TYPES.SwitchStatement:
35
- return switchStatementToSteps(node, ctx);
36
- case AST_NODE_TYPES.ForInStatement:
37
- throw new WorkflowSyntaxError('for...in is not a supported construct. Use for...of.', node.loc);
38
- case AST_NODE_TYPES.ForOfStatement:
39
- return [forOfStatementToForStep(node, ctx)];
40
- case AST_NODE_TYPES.DoWhileStatement:
41
- return doWhileStatementSteps(node, ctx);
42
- case AST_NODE_TYPES.WhileStatement:
43
- return whileStatementSteps(node, ctx);
44
- case AST_NODE_TYPES.BreakStatement:
45
- return [breakStatementToNextStep(node, ctx)];
46
- case AST_NODE_TYPES.ContinueStatement:
47
- return [continueStatementToNextStep(node, ctx)];
48
- case AST_NODE_TYPES.TryStatement: {
49
- let retryPolicy = undefined;
50
- if (nextNode?.type === AST_NODE_TYPES.ExpressionStatement &&
51
- nextNode.expression.type === AST_NODE_TYPES.CallExpression) {
52
- retryPolicy = parseRetryPolicy(nextNode.expression);
53
- }
54
- return tryStatementToTrySteps(node, retryPolicy, ctx);
55
- }
56
- case AST_NODE_TYPES.LabeledStatement:
57
- return labeledStep(node, ctx);
58
- case AST_NODE_TYPES.EmptyStatement:
59
- return [];
60
- case AST_NODE_TYPES.FunctionDeclaration:
61
- throw new WorkflowSyntaxError('Functions must be defined at the top level of a source file', node.loc);
62
- case AST_NODE_TYPES.TSInterfaceDeclaration:
63
- case AST_NODE_TYPES.TSTypeAliasDeclaration:
64
- case AST_NODE_TYPES.TSDeclareFunction:
65
- // Ignore "type", "interface" and "declare function"
66
- return [];
67
- default:
68
- throw new WorkflowSyntaxError(`TODO: encountered unsupported type: ${node.type}`, node.loc);
69
- }
70
- }
71
- function convertVariableDeclarations(declarations, ctx) {
72
- return declarations.flatMap((decl) => {
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 && isIntrinsicStatement(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 name = new VariableReferenceExpression(targetVariableName);
99
- const value = initializer === null ? nullEx : convertExpression(initializer);
100
- return [new AssignStepAST([{ name, value }])];
101
- }
102
- }
103
- function convertArrayDestructuring(arrayPattern, initializer, ctx) {
104
- let initExpression;
105
- const steps = [];
106
- if (initializer?.type === AST_NODE_TYPES.Identifier ||
107
- initializer?.type === AST_NODE_TYPES.MemberExpression) {
108
- // If the initializer is an Identifier or MemberExpression (array variable?),
109
- // use it directly. This ensures that the recursive variables gets initialized
110
- // in the correct order. For example:
111
- // const arr = [1, 2]
112
- // [arr[1], arr[0]] = arr
113
- initExpression = convertExpression(initializer);
114
- }
115
- else {
116
- // Otherwise, assign the expression to a temporary variable first.
117
- const initName = tempName(ctx);
118
- steps.push(...convertInitializer(initName, initializer, ctx));
119
- initExpression = new VariableReferenceExpression(initName);
120
- }
121
- steps.push(...arrayDestructuringSteps(arrayPattern.elements, initExpression, ctx));
122
- return steps;
123
- }
124
- function arrayDestructuringSteps(patterns, initializerExpression, ctx) {
125
- if (patterns.filter((p) => p !== null).length === 0) {
126
- return [];
127
- }
128
- const __temp_len = new VariableReferenceExpression(`${tempName(ctx)}_len`);
129
- const initializeVariables = [
130
- {
131
- name: __temp_len,
132
- value: new FunctionInvocationExpression('len', [initializerExpression]),
133
- },
134
- ];
135
- const branches = R.reverse(patterns).flatMap((pat, i) => {
136
- if (pat === null) {
137
- return [];
138
- }
139
- else {
140
- return [
141
- {
142
- condition: new BinaryExpression(__temp_len, '>=', new PrimitiveExpression(patterns.length - i)),
143
- steps: arrayElementsDestructuringSteps(patterns, initializerExpression, patterns.length - i, ctx),
144
- },
145
- ];
146
- }
147
- });
148
- branches.push({
149
- condition: trueEx,
150
- steps: arrayElementsDestructuringSteps(patterns, initializerExpression, 0, ctx),
151
- });
152
- return [new AssignStepAST(initializeVariables), new SwitchStepAST(branches)];
153
- }
154
- function arrayElementsDestructuringSteps(patterns, initializerExpression, take, ctx) {
155
- return patterns.flatMap((pat, i) => {
156
- if (i >= take) {
157
- return [
158
- new AssignStepAST(extractDefaultAssignmentsFromDestructuringPattern(pat)),
159
- ];
160
- }
161
- const iElement = new MemberExpression(initializerExpression, new PrimitiveExpression(i), true);
162
- switch (pat?.type) {
163
- case AST_NODE_TYPES.MemberExpression:
164
- case AST_NODE_TYPES.Identifier: {
165
- const name = convertVariableNameExpression(pat);
166
- return [new AssignStepAST([{ name, value: iElement }])];
167
- }
168
- case AST_NODE_TYPES.AssignmentPattern: {
169
- if (pat.left.type !== AST_NODE_TYPES.Identifier) {
170
- throw new WorkflowSyntaxError('Default value can be used only with an identifier', pat.left.loc);
171
- }
172
- const name = new VariableReferenceExpression(pat.left.name);
173
- return [new AssignStepAST([{ name, value: iElement }])];
174
- }
175
- case AST_NODE_TYPES.ObjectPattern:
176
- return objectDestructuringSteps(pat.properties, iElement, ctx);
177
- case AST_NODE_TYPES.ArrayPattern:
178
- return arrayDestructuringSteps(pat.elements, iElement, ctx);
179
- case AST_NODE_TYPES.RestElement:
180
- return arrayRestDestructuringSteps(patterns, pat, initializerExpression, patterns.length - 1, ctx);
181
- default: // pat === null
182
- return [];
183
- }
184
- });
185
- }
186
- function extractDefaultAssignmentsFromDestructuringPattern(pat) {
187
- if (pat === null) {
188
- return [];
189
- }
190
- switch (pat.type) {
191
- case AST_NODE_TYPES.ArrayPattern:
192
- return pat.elements.flatMap(extractDefaultAssignmentsFromDestructuringPattern);
193
- case AST_NODE_TYPES.AssignmentPattern:
194
- if (pat.left.type !== AST_NODE_TYPES.Identifier) {
195
- throw new WorkflowSyntaxError('Default value can be used only with an identifier', pat.left.loc);
196
- }
197
- return [
198
- {
199
- name: new VariableReferenceExpression(pat.left.name),
200
- value: convertExpression(pat.right),
201
- },
202
- ];
203
- case AST_NODE_TYPES.Identifier:
204
- return [
205
- { name: new VariableReferenceExpression(pat.name), value: nullEx },
206
- ];
207
- case AST_NODE_TYPES.MemberExpression:
208
- return [{ name: convertVariableNameExpression(pat), value: nullEx }];
209
- case AST_NODE_TYPES.ObjectPattern:
210
- return pat.properties.flatMap((p) => {
211
- if (p.type === AST_NODE_TYPES.RestElement) {
212
- return extractDefaultAssignmentsFromDestructuringPattern(p);
213
- }
214
- else if (p.value.type === AST_NODE_TYPES.ArrayPattern ||
215
- p.value.type === AST_NODE_TYPES.AssignmentPattern ||
216
- p.value.type === AST_NODE_TYPES.Identifier ||
217
- p.value.type === AST_NODE_TYPES.MemberExpression ||
218
- p.value.type === AST_NODE_TYPES.ObjectPattern) {
219
- return extractDefaultAssignmentsFromDestructuringPattern(p.value);
220
- }
221
- else {
222
- throw new WorkflowSyntaxError('Destructuring pattern expected', p.value.loc);
223
- }
224
- });
225
- case AST_NODE_TYPES.RestElement:
226
- if (pat.argument.type !== AST_NODE_TYPES.Identifier) {
227
- throw new WorkflowSyntaxError('Identifier expected', pat.argument.loc);
228
- }
229
- return [
230
- {
231
- name: new VariableReferenceExpression(pat.argument.name),
232
- value: new PrimitiveExpression([]),
233
- },
234
- ];
235
- default:
236
- return [];
237
- }
238
- }
239
- function throwIfInvalidRestElement(patterns) {
240
- const i = patterns.findIndex((p) => p?.type === AST_NODE_TYPES.RestElement);
241
- if (i >= 0 && i !== patterns.length - 1) {
242
- throw new WorkflowSyntaxError('A rest element must be last in a destructuring pattern', patterns[i].loc);
243
- }
244
- }
245
- function arrayRestDestructuringSteps(patterns, rest, initializerExpression, startIndex, ctx) {
246
- throwIfInvalidRestElement(patterns);
247
- if (rest.argument.type !== AST_NODE_TYPES.Identifier) {
248
- throw new WorkflowSyntaxError('Identifier expected', rest.argument.loc);
249
- }
250
- const restName = new VariableReferenceExpression(rest.argument.name);
251
- const __temp_len = new VariableReferenceExpression(`${tempName(ctx)}_len`);
252
- const __temp_index = `${tempName(ctx)}_index`;
253
- const one = new PrimitiveExpression(1);
254
- const emptyArray = new PrimitiveExpression([]);
255
- const copyLoop = new ForRangeStepAST([
256
- new AssignStepAST([
257
- {
258
- name: restName,
259
- value: new FunctionInvocationExpression('list.concat', [
260
- restName,
261
- new MemberExpression(initializerExpression, new VariableReferenceExpression(__temp_index), true),
262
- ]),
263
- },
264
- ]),
265
- ], __temp_index, startIndex, new BinaryExpression(__temp_len, '-', one));
266
- return [new AssignStepAST([{ name: restName, value: emptyArray }]), copyLoop];
267
- }
268
- function convertObjectDestructuring(objectPattern, initializer, ctx) {
269
- let initExpression;
270
- const steps = [];
271
- if (initializer?.type === AST_NODE_TYPES.Identifier ||
272
- (initializer?.type === AST_NODE_TYPES.MemberExpression &&
273
- isPure(convertExpression(initializer)))) {
274
- // If the initializer is an Identifier or MemberExpression (object variable?), use it directly.
275
- initExpression = convertExpression(initializer);
276
- }
277
- else {
278
- // Otherwise, assign the expression to a temporary variable first.
279
- const initName = tempName(ctx);
280
- steps.push(...convertInitializer(initName, initializer, ctx));
281
- initExpression = new VariableReferenceExpression(initName);
282
- }
283
- steps.push(...objectDestructuringSteps(objectPattern.properties, initExpression, ctx));
284
- return steps;
285
- }
286
- function objectDestructuringSteps(properties, initializerExpression, ctx) {
287
- return properties.flatMap((prop) => {
288
- if (prop.type === AST_NODE_TYPES.RestElement) {
289
- return objectDestructuringRestSteps(properties, prop, initializerExpression);
290
- }
291
- if (prop.key.type !== AST_NODE_TYPES.Identifier) {
292
- throw new WorkflowSyntaxError('Identifier expected', prop.key.loc);
293
- }
294
- const keyExpression = new MemberExpression(initializerExpression, new VariableReferenceExpression(prop.key.name), false);
295
- if (prop.value.type === AST_NODE_TYPES.ObjectPattern) {
296
- return objectDestructuringSteps(prop.value.properties, keyExpression, ctx);
297
- }
298
- else if (prop.value.type === AST_NODE_TYPES.ArrayPattern) {
299
- return arrayDestructuringSteps(prop.value.elements, keyExpression, ctx);
300
- }
301
- else if (prop.value.type === AST_NODE_TYPES.Identifier) {
302
- const safeKeyExpression = new FunctionInvocationExpression('map.get', [
303
- initializerExpression,
304
- new PrimitiveExpression(prop.key.name),
305
- ]);
306
- return [
307
- new AssignStepAST([
308
- {
309
- name: new VariableReferenceExpression(prop.value.name),
310
- value: safeKeyExpression,
311
- },
312
- ]),
313
- ];
314
- }
315
- else if (prop.value.type === AST_NODE_TYPES.AssignmentPattern) {
316
- return objectAssignmentPatternSteps(prop.value, initializerExpression, keyExpression);
317
- }
318
- else {
319
- throw new WorkflowSyntaxError(`${prop.value.type} is not allowed in object destructuring`, prop.value.loc);
320
- }
321
- });
322
- }
323
- function objectAssignmentPatternSteps(pat, initializerExpression, keyExpression) {
324
- if (pat.left.type !== AST_NODE_TYPES.Identifier) {
325
- throw new WorkflowSyntaxError('Default value can be used only with an identifier', pat.left.loc);
326
- }
327
- // Using Switch step instead of default() because pat.right must be evaluated only
328
- // in the default value branch (in case it has side effects)
329
- const name = new VariableReferenceExpression(pat.left.name);
330
- return [
331
- new SwitchStepAST([
332
- {
333
- condition: new BinaryExpression(new PrimitiveExpression(pat.left.name), 'in', initializerExpression),
334
- steps: [new AssignStepAST([{ name, value: keyExpression }])],
335
- },
336
- {
337
- condition: trueEx,
338
- steps: [
339
- new AssignStepAST([{ name, value: convertExpression(pat.right) }]),
340
- ],
341
- },
342
- ]),
343
- ];
344
- }
345
- function objectDestructuringRestSteps(properties, rest, initializerExpression) {
346
- throwIfInvalidRestElement(properties);
347
- if (rest.argument.type !== AST_NODE_TYPES.Identifier) {
348
- throw new WorkflowSyntaxError('Identifier expected', rest.argument.loc);
349
- }
350
- const nonRestProperties = properties.filter((x) => x.type !== AST_NODE_TYPES.RestElement);
351
- const nonRestKeys = nonRestProperties
352
- .map((p) => p.key)
353
- .map((p) => {
354
- if (p.type !== AST_NODE_TYPES.Identifier) {
355
- throw new WorkflowSyntaxError('Identifier expected', p.loc);
356
- }
357
- return p;
358
- })
359
- .map((p) => p.name);
360
- const name = new VariableReferenceExpression(rest.argument.name);
361
- const value = nonRestKeys.reduce((acc, propertyName) =>
362
- // map.delete returns a copy of the object and removes the specified property
363
- new FunctionInvocationExpression('map.delete', [
364
- acc,
365
- new PrimitiveExpression(propertyName),
366
- ]), initializerExpression);
367
- return [new AssignStepAST([{ name, value }])];
368
- }
369
- function assignmentExpressionToSteps(node, ctx) {
370
- let compoundOperator = undefined;
371
- switch (node.operator) {
372
- case '=':
373
- compoundOperator = undefined;
374
- break;
375
- case '+=':
376
- compoundOperator = '+';
377
- break;
378
- case '-=':
379
- compoundOperator = '-';
380
- break;
381
- case '*=':
382
- compoundOperator = '*';
383
- break;
384
- case '/=':
385
- compoundOperator = '/';
386
- break;
387
- case '%=':
388
- compoundOperator = '%';
389
- break;
390
- case '&&=':
391
- compoundOperator = 'and';
392
- break;
393
- case '||=':
394
- compoundOperator = 'or';
395
- break;
396
- default:
397
- throw new WorkflowSyntaxError(`Operator ${node.operator} is not supported in assignment expressions`, node.loc);
398
- }
399
- if (compoundOperator === undefined) {
400
- return assignmentSteps(node.left, node.right, ctx);
401
- }
402
- else {
403
- return compoundAssignmentSteps(node.left, node.right, compoundOperator, ctx);
404
- }
405
- }
406
- function assignmentSteps(left, right, ctx) {
407
- let valueExpression;
408
- const steps = [];
409
- if (left.type === AST_NODE_TYPES.ArrayPattern) {
410
- return convertArrayDestructuring(left, right, ctx);
411
- }
412
- else if (left.type === AST_NODE_TYPES.ObjectPattern) {
413
- return convertObjectDestructuring(left, right, ctx);
414
- }
415
- if (right.type === AST_NODE_TYPES.CallExpression &&
416
- right.callee.type === AST_NODE_TYPES.Identifier &&
417
- isIntrinsic(right.callee.name)) {
418
- const tr = convertAssignmentExpressionIntrinsicRHS(right, ctx);
419
- steps.push(...tr.steps);
420
- valueExpression = tr.tempVariable;
421
- }
422
- else {
423
- valueExpression = convertExpression(right);
424
- }
425
- const targetExpression = convertVariableNameExpression(left);
426
- steps.push(new AssignStepAST([{ name: targetExpression, value: valueExpression }]));
427
- return steps;
428
- }
429
- function compoundAssignmentSteps(left, right, operator, ctx) {
430
- let valueExpression;
431
- const { expression: targetExpression, steps } = convertCompoundAssignmentLeftHandSide(left, ctx);
432
- if (right.type === AST_NODE_TYPES.CallExpression &&
433
- right.callee.type === AST_NODE_TYPES.Identifier &&
434
- isIntrinsic(right.callee.name)) {
435
- const tr = convertAssignmentExpressionIntrinsicRHS(right, ctx);
436
- steps.push(...tr.steps);
437
- valueExpression = tr.tempVariable;
438
- }
439
- else {
440
- valueExpression = convertExpression(right);
441
- }
442
- valueExpression = new BinaryExpression(targetExpression, operator, valueExpression);
443
- steps.push(new AssignStepAST([{ name: targetExpression, value: valueExpression }]));
444
- return steps;
445
- }
446
- function convertCompoundAssignmentLeftHandSide(left, ctx) {
447
- if (left.type === AST_NODE_TYPES.ArrayPattern ||
448
- left.type === AST_NODE_TYPES.ObjectPattern) {
449
- throw new WorkflowSyntaxError(`Invalid left-hand side in assignment`, left.loc);
450
- }
451
- const leftEx = convertVariableNameExpression(left);
452
- if (leftEx.expressionType === 'member') {
453
- const { transformed, assignments } = extractSideEffectsFromMemberExpression(leftEx, tempName(ctx), 0);
454
- const steps = [new AssignStepAST(assignments)];
455
- return { expression: transformed, steps };
456
- }
457
- else {
458
- return {
459
- expression: leftEx,
460
- steps: [],
461
- };
462
- }
463
- }
464
- /**
465
- * Extract side-effecting computed properties into temporary variable assignments.
466
- *
467
- * This is used on the left-hand side of a compound assignment expression, which
468
- * should only be evaluted once.
469
- */
470
- function extractSideEffectsFromMemberExpression(ex, tempPrefix, tempIndex) {
471
- if (ex.computed && !isPure(ex.property)) {
472
- let transformedObject;
473
- let objectAssignments;
474
- if (ex.object.expressionType === 'member') {
475
- const object2 = extractSideEffectsFromMemberExpression(ex.object, tempPrefix, tempIndex + 1);
476
- transformedObject = object2.transformed;
477
- objectAssignments = object2.assignments;
478
- }
479
- else {
480
- transformedObject = ex.object;
481
- objectAssignments = [];
482
- }
483
- const tmp = new VariableReferenceExpression(`${tempPrefix}${tempIndex}`);
484
- const transformed = new MemberExpression(transformedObject, tmp, true);
485
- const assignments = objectAssignments;
486
- assignments.push({
487
- name: tmp,
488
- value: ex.property,
489
- });
490
- return { transformed, assignments };
491
- }
492
- else if (ex.object.expressionType === 'member') {
493
- const { transformed: object2, assignments: assignments } = extractSideEffectsFromMemberExpression(ex.object, tempPrefix, tempIndex);
494
- const transformed = new MemberExpression(object2, ex.property, ex.computed);
495
- return {
496
- transformed,
497
- assignments,
498
- };
499
- }
500
- else {
501
- return {
502
- transformed: ex,
503
- assignments: [],
504
- };
505
- }
506
- }
507
- /**
508
- * Special case for handling call_step() RHS in assignment expressions.
509
- *
510
- * This can be removed once the generic convertExpression() is able to handle call_step.
511
- */
512
- function convertAssignmentExpressionIntrinsicRHS(callEx, ctx) {
513
- if (callEx.callee.type !== AST_NODE_TYPES.Identifier) {
514
- throw new InternalTranspilingError('The callee should be an identifier');
515
- }
516
- const calleeName = callEx.callee.name;
517
- if (isIntrinsicStatement(calleeName)) {
518
- throw new WorkflowSyntaxError(`"${calleeName}" can't be called as part of an expression`, callEx.callee.loc);
519
- }
520
- const resultVariable = tempName(ctx);
521
- const steps = callExpressionToStep(callEx, resultVariable, ctx);
522
- const tempVariable = new VariableReferenceExpression(resultVariable);
523
- return { steps, tempVariable };
524
- }
525
- function callExpressionToStep(node, resultVariable, ctx) {
526
- const calleeExpression = convertExpression(node.callee);
527
- if (isFullyQualifiedName(calleeExpression)) {
528
- const calleeName = calleeExpression.toString();
529
- if (calleeName === 'parallel') {
530
- // A handle the "parallel" intrinsic
531
- return [callExpressionToParallelStep(node, ctx)];
532
- }
533
- else if (calleeName === 'retry_policy') {
534
- // retry_policy() is handled by AST_NODE_TYPES.TryStatement and therefore ignored here
535
- return [];
536
- }
537
- else if (calleeName === 'call_step') {
538
- return [createCallStep(node, node.arguments, resultVariable)];
539
- }
540
- else if (blockingFunctions.has(calleeName)) {
541
- const argumentNames = blockingFunctions.get(calleeName) ?? [];
542
- return [
543
- blockingFunctionCallStep(calleeName, argumentNames, node.arguments, resultVariable),
544
- ];
545
- }
546
- else {
547
- const resultVariable2 = resultVariable ?? tempName(ctx);
548
- return [
549
- callExpressionAssignStep(calleeName, node.arguments, resultVariable2),
550
- ];
551
- }
552
- }
553
- else {
554
- throw new WorkflowSyntaxError('Expeced a subworkflow or a standard library function name', node.callee.loc);
555
- }
556
- }
557
- function callExpressionAssignStep(functionName, argumentsNode, resultVariable) {
558
- const argumentExpressions = throwIfSpread(argumentsNode).map(convertExpression);
559
- return new AssignStepAST([
560
- {
561
- name: new VariableReferenceExpression(resultVariable),
562
- value: new FunctionInvocationExpression(functionName, argumentExpressions),
563
- },
564
- ]);
565
- }
566
- function createCallStep(node, argumentsNode, resultVariable) {
567
- if (argumentsNode.length < 1) {
568
- throw new WorkflowSyntaxError('The first argument must be a Function', node.loc);
569
- }
570
- let functionName;
571
- const argNode = argumentsNode[0].type === AST_NODE_TYPES.TSInstantiationExpression
572
- ? argumentsNode[0].expression
573
- : argumentsNode[0];
574
- if (argNode.type === AST_NODE_TYPES.Identifier) {
575
- functionName = argNode.name;
576
- }
577
- else if (argNode.type === AST_NODE_TYPES.MemberExpression) {
578
- const memberExp = convertMemberExpression(argNode);
579
- if (!isFullyQualifiedName(memberExp)) {
580
- throw new WorkflowSyntaxError('Function name must be a fully-qualified name', argNode.loc);
581
- }
582
- functionName = memberExp.toString();
583
- }
584
- else {
585
- throw new WorkflowSyntaxError('Expected an identifier or a member expression', argNode.loc);
586
- }
587
- let args = {};
588
- if (argumentsNode.length >= 2) {
589
- if (argumentsNode[1].type !== AST_NODE_TYPES.ObjectExpression) {
590
- throw new WorkflowSyntaxError('The second argument must be an object', argumentsNode[1].loc);
591
- }
592
- args = convertObjectAsExpressionValues(argumentsNode[1]);
593
- }
594
- return new CallStepAST(functionName, args, resultVariable);
595
- }
596
- function blockingFunctionCallStep(functionName, argumentNames, argumentsNode, resultName) {
597
- const argumentExpressions = throwIfSpread(argumentsNode).map(convertExpression);
598
- const args = Object.fromEntries(argumentNames.flatMap((argName, i) => {
599
- if (i >= argumentExpressions.length) {
600
- return [];
601
- }
602
- else if (argumentsNode[i].type === AST_NODE_TYPES.Identifier &&
603
- argumentsNode[i].name === 'undefined') {
604
- return [];
605
- }
606
- else {
607
- return [[argName, argumentExpressions[i]]];
608
- }
609
- }));
610
- return new CallStepAST(functionName, args, resultName);
611
- }
612
- function callExpressionToParallelStep(node, ctx) {
613
- if (node.callee.type !== AST_NODE_TYPES.Identifier ||
614
- node.callee.name !== 'parallel') {
615
- throw new InternalTranspilingError(`The parameter must be a call to "parallel"`);
616
- }
617
- const ctx2 = Object.assign({}, ctx, {
618
- parallelNestingLevel: ctx.parallelNestingLevel
619
- ? ctx.parallelNestingLevel + 1
620
- : 1,
621
- });
622
- let steps = {};
623
- if (node.arguments.length > 0) {
624
- switch (node.arguments[0].type) {
625
- case AST_NODE_TYPES.ArrayExpression:
626
- steps = parseParallelBranches(node.arguments[0], ctx2);
627
- break;
628
- case AST_NODE_TYPES.ArrowFunctionExpression:
629
- steps = parseParallelIteration(node.arguments[0], ctx2);
630
- break;
631
- default:
632
- throw new WorkflowSyntaxError('The first parameter must be an array of functions or an arrow function', node.arguments[0].loc);
633
- }
634
- }
635
- let shared = undefined;
636
- let concurrencyLimit = undefined;
637
- let exceptionPolicy = undefined;
638
- if (node.arguments.length > 1) {
639
- const options = parseParallelOptions(node.arguments[1]);
640
- shared = options.shared;
641
- concurrencyLimit = options.concurrencyLimit;
642
- exceptionPolicy = options.exceptionPolicy;
643
- }
644
- return new ParallelStepAST(steps, shared, concurrencyLimit, exceptionPolicy);
645
- }
646
- function parseParallelBranches(node, ctx) {
647
- const branches = node.elements.map((arg) => {
648
- switch (arg?.type) {
649
- case AST_NODE_TYPES.Identifier:
650
- return new StepsStepAST([new CallStepAST(arg.name)]);
651
- case AST_NODE_TYPES.ArrowFunctionExpression:
652
- if (arg.body.type !== AST_NODE_TYPES.BlockStatement) {
653
- throw new WorkflowSyntaxError('The body must be a block statement', arg.body.loc);
654
- }
655
- return new StepsStepAST(parseStatement(arg.body, ctx));
656
- default:
657
- throw new WorkflowSyntaxError('Argument should be a function of type () => void', arg ? arg.loc : node.loc);
658
- }
659
- });
660
- return Object.fromEntries(branches.map((step, i) => [`branch${i + 1}`, step]));
661
- }
662
- function parseParallelIteration(node, ctx) {
663
- if (node.body.type !== AST_NODE_TYPES.BlockStatement ||
664
- node.body.body.length !== 1 ||
665
- node.body.body[0].type !== AST_NODE_TYPES.ForOfStatement) {
666
- throw new WorkflowSyntaxError('The parallel function body must be a single for...of statement', node.body.loc);
667
- }
668
- return forOfStatementToForStep(node.body.body[0], ctx);
669
- }
670
- function parseParallelOptions(node) {
671
- if (node.type !== AST_NODE_TYPES.ObjectExpression) {
672
- throw new WorkflowSyntaxError('The second parameter must be an object', node.loc);
673
- }
674
- const parallelOptions = convertObjectExpression(node);
675
- const sharedExpression = parallelOptions.shared;
676
- if (!Array.isArray(sharedExpression)) {
677
- throw new WorkflowSyntaxError('"shared" must be an array or strings', node.loc);
678
- }
679
- const shared = sharedExpression.map((x) => {
680
- if (isExpression(x) || typeof x !== 'string') {
681
- throw new WorkflowSyntaxError('"shared" must be an array of strings', node.loc);
682
- }
683
- return x;
684
- });
685
- const concurrencyLimitExpression = parallelOptions.concurrency_limit;
686
- if (typeof concurrencyLimitExpression !== 'number' &&
687
- typeof concurrencyLimitExpression !== 'undefined') {
688
- throw new WorkflowSyntaxError('"concurrency_limit" must be a number', node.loc);
689
- }
690
- const concurrencyLimit = concurrencyLimitExpression;
691
- const exceptionPolicyExpression = parallelOptions.exception_policy;
692
- if (typeof exceptionPolicyExpression !== 'string' &&
693
- typeof exceptionPolicyExpression !== 'undefined') {
694
- throw new WorkflowSyntaxError('"exception_policy" must be a string', node.loc);
695
- }
696
- const exceptionPolicy = exceptionPolicyExpression;
697
- return {
698
- shared,
699
- concurrencyLimit,
700
- exceptionPolicy,
701
- };
702
- }
703
- function generalExpressionToAssignStep(node, ctx) {
704
- return new AssignStepAST([
705
- {
706
- name: new VariableReferenceExpression(tempName(ctx)),
707
- value: convertExpression(node),
708
- },
709
- ]);
710
- }
711
- function returnStatementToReturnStep(node, ctx) {
712
- const value = node.argument ? convertExpression(node.argument) : undefined;
713
- if (ctx.finalizerTargets && ctx.finalizerTargets.length > 0) {
714
- // If we are in try statement with a finally block, return statements are
715
- // replaced by a jump to finally back with a captured return value.
716
- return delayedReturnAndJumpToFinalizer(value, ctx);
717
- }
718
- return new ReturnStepAST(value);
719
- }
720
- function throwStatementToRaiseStep(node) {
721
- return new RaiseStepAST(convertExpression(node.argument));
722
- }
723
- function ifStatementToSwitchStep(node, ctx) {
724
- return new SwitchStepAST(flattenIfBranches(node, ctx));
725
- }
726
- function flattenIfBranches(ifStatement, ctx) {
727
- const branches = [
728
- {
729
- condition: convertExpression(ifStatement.test),
730
- steps: parseStatement(ifStatement.consequent, ctx),
731
- },
732
- ];
733
- if (ifStatement.alternate) {
734
- if (ifStatement.alternate.type === AST_NODE_TYPES.IfStatement) {
735
- branches.push(...flattenIfBranches(ifStatement.alternate, ctx));
736
- }
737
- else {
738
- branches.push({
739
- condition: trueEx,
740
- steps: parseStatement(ifStatement.alternate, ctx),
741
- });
742
- }
743
- }
744
- return branches;
745
- }
746
- function switchStatementToSteps(node, ctx) {
747
- const endOfSwitch = new JumpTargetAST();
748
- const switchCtx = Object.assign({}, ctx, { breakTarget: endOfSwitch.label });
749
- const steps = [];
750
- const branches = [];
751
- const discriminant = convertExpression(node.discriminant);
752
- node.cases.forEach((caseNode) => {
753
- let condition;
754
- if (caseNode.test) {
755
- const test = convertExpression(caseNode.test);
756
- condition = new BinaryExpression(discriminant, '==', test);
757
- }
758
- else {
759
- condition = trueEx;
760
- }
761
- const jumpTarget = new JumpTargetAST();
762
- const body = caseNode.consequent.flatMap((x) => parseStatement(x, switchCtx));
763
- steps.push(jumpTarget);
764
- steps.push(...body);
765
- branches.push({
766
- condition,
767
- steps: [],
768
- next: jumpTarget.label,
769
- });
770
- });
771
- steps.unshift(new SwitchStepAST(branches));
772
- steps.push(endOfSwitch);
773
- return steps;
774
- }
775
- function forOfStatementToForStep(node, ctx) {
776
- const bodyCtx = Object.assign({}, ctx, {
777
- continueTarget: undefined,
778
- breakTarget: undefined,
779
- });
780
- const steps = parseStatement(node.body, bodyCtx);
781
- let loopVariableName;
782
- if (node.left.type === AST_NODE_TYPES.Identifier) {
783
- loopVariableName = node.left.name;
784
- }
785
- else if (node.left.type === AST_NODE_TYPES.VariableDeclaration) {
786
- if (node.left.declarations.length !== 1) {
787
- throw new WorkflowSyntaxError('Only one variable can be declared here', node.left.loc);
788
- }
789
- const declaration = node.left.declarations[0];
790
- if (declaration.init !== null) {
791
- throw new WorkflowSyntaxError('Initial value not allowed', declaration.init.loc);
792
- }
793
- if (declaration.id.type !== AST_NODE_TYPES.Identifier) {
794
- throw new WorkflowSyntaxError(`Identifier expected, got ${declaration.id.type}`, declaration.id.loc);
795
- }
796
- loopVariableName = declaration.id.name;
797
- }
798
- else {
799
- throw new InternalTranspilingError(`Identifier or VariableDeclaration expected, got ${node.left.type}`);
800
- }
801
- const listExpression = convertExpression(node.right);
802
- if (isLiteral(listExpression) &&
803
- listExpression.expressionType === 'primitive' &&
804
- (isRecord(listExpression.value) ||
805
- typeof listExpression.value === 'number' ||
806
- typeof listExpression.value === 'string' ||
807
- typeof listExpression.value === 'boolean' ||
808
- listExpression.value === null)) {
809
- throw new WorkflowSyntaxError('Must be a list expression', node.right.loc);
810
- }
811
- return new ForStepAST(steps, loopVariableName, listExpression);
812
- }
813
- function whileStatementSteps(node, ctx) {
814
- const startOfLoop = new JumpTargetAST();
815
- const endOfLoop = new JumpTargetAST();
816
- const ctx2 = Object.assign({}, ctx, {
817
- continueTarget: startOfLoop.label,
818
- breakTarget: endOfLoop.label,
819
- });
820
- const postSteps = [new NextStepAST(startOfLoop.label)];
821
- const steps = parseStatement(node.body, ctx2).concat(postSteps);
822
- return [
823
- startOfLoop,
824
- new SwitchStepAST([
825
- {
826
- condition: convertExpression(node.test),
827
- steps,
828
- },
829
- ]),
830
- endOfLoop,
831
- ];
832
- }
833
- function doWhileStatementSteps(node, ctx) {
834
- const startOfLoop = new JumpTargetAST();
835
- const endOfLoop = new JumpTargetAST();
836
- const ctx2 = Object.assign({}, ctx, {
837
- continueTarget: startOfLoop.label,
838
- breakTarget: endOfLoop.label,
839
- });
840
- const steps = [startOfLoop];
841
- steps.push(...parseStatement(node.body, ctx2));
842
- steps.push(new SwitchStepAST([
843
- {
844
- condition: convertExpression(node.test),
845
- steps: [],
846
- next: startOfLoop.label,
847
- },
848
- ]));
849
- steps.push(endOfLoop);
850
- return steps;
851
- }
852
- function breakStatementToNextStep(node, ctx) {
853
- if (ctx.finalizerTargets) {
854
- // TODO: would need to detect if this breaks out of the try or catch block,
855
- // execute the finally block first and then do the break.
856
- throw new WorkflowSyntaxError('break is not supported inside a try-finally block', node.loc);
857
- }
858
- let target;
859
- if (node.label) {
860
- target = node.label.name;
861
- }
862
- else if (ctx.breakTarget) {
863
- target = ctx.breakTarget;
864
- }
865
- else {
866
- target = 'break';
867
- }
868
- return new NextStepAST(target);
869
- }
870
- function continueStatementToNextStep(node, ctx) {
871
- if (ctx.finalizerTargets) {
872
- // TODO: would need to detect if continue breaks out of the try or catch block,
873
- // execute the finally block first and then do the continue.
874
- throw new WorkflowSyntaxError('continue is not supported inside a try-finally block', node.loc);
875
- }
876
- let target;
877
- if (node.label) {
878
- target = node.label.name;
879
- }
880
- else if (ctx.continueTarget) {
881
- target = ctx.continueTarget;
882
- }
883
- else {
884
- target = 'continue';
885
- }
886
- return new NextStepAST(target);
887
- }
888
- function tryStatementToTrySteps(node, retryPolicy, ctx) {
889
- if (!node.finalizer) {
890
- // Basic try-catch without a finally block
891
- const baseTryStep = parseTryCatchRetry(node, ctx, retryPolicy);
892
- return [baseTryStep];
893
- }
894
- else {
895
- // Try-finally is translated to two nested try blocks. The innermost try is
896
- // the actual try body with control flow statements (return, in the future
897
- // also break/continue) replaced by jumps to the finally block.
898
- //
899
- // The outer try's catch block saved the exception and continues to the
900
- // finally block.
901
- //
902
- // The nested try blocks are followed by the finally block and a swith for
903
- // checking if we need to perform a delayed return/raise.
904
- const startOfFinalizer = new JumpTargetAST();
905
- const targets = ctx.finalizerTargets ?? [];
906
- targets.push(startOfFinalizer.label);
907
- ctx = Object.assign({}, ctx, { finalizerTargets: targets });
908
- const [conditionVariable, valueVariable] = finalizerVariables(ctx);
909
- const innerTry = parseTryCatchRetry(node, ctx, retryPolicy);
910
- const outerTry = new TryStepAST([innerTry], finalizerDelayedException('__fin_exc', conditionVariable, valueVariable), undefined, '__fin_exc');
911
- // Reset ctx before parsing the finally block because we don't want to
912
- // transform returns in finally block in to delayed returns
913
- if (ctx.finalizerTargets && ctx.finalizerTargets.length <= 1) {
914
- delete ctx.finalizerTargets;
915
- }
916
- else {
917
- ctx.finalizerTargets?.pop();
918
- }
919
- const finallyBlock = parseStatement(node.finalizer, ctx);
920
- return [
921
- finalizerInitializer(conditionVariable, valueVariable),
922
- outerTry,
923
- startOfFinalizer,
924
- ...finallyBlock,
925
- finalizerFooter(conditionVariable, valueVariable),
926
- ];
927
- }
928
- }
929
- function finalizerVariables(ctx) {
930
- const targets = ctx.finalizerTargets ?? [];
931
- const nestingLevel = targets.length > 0 ? `${targets.length}` : '';
932
- const conditionVariable = `__t2w_finally_condition${nestingLevel}`;
933
- const valueVariable = `__t2w_finally_value${nestingLevel}`;
934
- return [conditionVariable, valueVariable];
935
- }
936
- function parseTryCatchRetry(node, ctx, retryPolicy) {
937
- const trySteps = parseStatement(node.block, ctx);
938
- let exceptSteps = undefined;
939
- let errorVariable = undefined;
940
- if (node.handler) {
941
- exceptSteps = parseStatement(node.handler.body, ctx);
942
- errorVariable = extractErrorVariableName(node.handler.param);
943
- }
944
- const baseTryStep = new TryStepAST(trySteps, exceptSteps, retryPolicy, errorVariable);
945
- return baseTryStep;
946
- }
947
- function extractErrorVariableName(param) {
948
- if (!param) {
949
- return undefined;
950
- }
951
- if (param.type !== AST_NODE_TYPES.Identifier) {
952
- throw new WorkflowSyntaxError('The error variable must be an identifier', param.loc);
953
- }
954
- return param.name;
955
- }
956
- /**
957
- * The shared header for try-finally for initializing the temp variables
958
- */
959
- function finalizerInitializer(conditionVariable, valueVariable) {
960
- return new AssignStepAST([
961
- {
962
- name: new VariableReferenceExpression(conditionVariable),
963
- value: nullEx,
964
- },
965
- {
966
- name: new VariableReferenceExpression(valueVariable),
967
- value: nullEx,
968
- },
969
- ]);
970
- }
971
- /**
972
- * The shared footer of a finally block that re-throws the exception or
973
- * returns the value returned by the try body.
974
- *
975
- * The footer code in TypeScript:
976
- *
977
- * if (__t2w_finally_condition == "return") {
978
- * return __t2w_finally_value
979
- * } elseif (__t2w_finally_condition == "raise") {
980
- * throw __t2w_finally_value
981
- * }
982
- */
983
- function finalizerFooter(conditionVariable, valueVariable) {
984
- const variable = new VariableReferenceExpression(conditionVariable);
985
- const val = new VariableReferenceExpression(valueVariable);
986
- const returnString = new PrimitiveExpression('return');
987
- const raiseString = new PrimitiveExpression('raise');
988
- return new SwitchStepAST([
989
- {
990
- condition: new BinaryExpression(variable, '==', returnString),
991
- steps: [new ReturnStepAST(val)],
992
- },
993
- {
994
- condition: new BinaryExpression(variable, '==', raiseString),
995
- steps: [new RaiseStepAST(val)],
996
- },
997
- ]);
998
- }
999
- function finalizerDelayedException(exceptionVariableName, conditionVariableName, valueVariableName) {
1000
- return [
1001
- new AssignStepAST([
1002
- {
1003
- name: new VariableReferenceExpression(conditionVariableName),
1004
- value: new PrimitiveExpression('raise'),
1005
- },
1006
- {
1007
- name: new VariableReferenceExpression(valueVariableName),
1008
- value: new VariableReferenceExpression(exceptionVariableName),
1009
- },
1010
- ]),
1011
- ];
1012
- }
1013
- function delayedReturnAndJumpToFinalizer(value, ctx) {
1014
- const finalizerTarget = ctx.finalizerTargets && ctx.finalizerTargets.length > 0
1015
- ? ctx.finalizerTargets[ctx.finalizerTargets.length - 1]
1016
- : undefined;
1017
- const [conditionVariable, valueVariable] = finalizerVariables(ctx);
1018
- return new AssignStepAST([
1019
- {
1020
- name: new VariableReferenceExpression(conditionVariable),
1021
- value: new PrimitiveExpression('return'),
1022
- },
1023
- {
1024
- name: new VariableReferenceExpression(valueVariable),
1025
- value: value ?? nullEx,
1026
- },
1027
- ], finalizerTarget);
1028
- }
1029
- function labeledStep(node, ctx) {
1030
- const steps = parseStatement(node.body, ctx);
1031
- if (steps.length > 0 && steps[0].tag !== 'jumptarget') {
1032
- steps[0] = steps[0].withLabel(node.label.name);
1033
- }
1034
- return steps;
1035
- }
1036
- function parseRetryPolicy(node) {
1037
- const callee = node.callee;
1038
- if (callee.type !== AST_NODE_TYPES.Identifier ||
1039
- callee.name !== 'retry_policy') {
1040
- // Ignore everything else besides retry_policy()
1041
- return undefined;
1042
- }
1043
- if (node.arguments.length < 1) {
1044
- throw new WorkflowSyntaxError('Required argument missing', node.loc);
1045
- }
1046
- const arg0 = throwIfSpread(node.arguments).map(convertExpression)[0];
1047
- const argsLoc = node.arguments[0].loc;
1048
- if (isFullyQualifiedName(arg0)) {
1049
- return arg0.toString();
1050
- }
1051
- else if (arg0.expressionType === 'primitive' && isRecord(arg0.value)) {
1052
- return retryPolicyFromParams(arg0.value, argsLoc);
1053
- }
1054
- else {
1055
- throw new WorkflowSyntaxError('Unexpected type', argsLoc);
1056
- }
1057
- }
1058
- function retryPolicyFromParams(paramsObject, argsLoc) {
1059
- const params = R.map(asExpression, paramsObject);
1060
- if (!('backoff' in params)) {
1061
- throw new WorkflowSyntaxError('Required parameter "backoff" missing', argsLoc);
1062
- }
1063
- else if (params.backoff.expressionType !== 'primitive' ||
1064
- !isRecord(params.backoff.value)) {
1065
- throw new WorkflowSyntaxError('Expected "backoff" to be an object literal', argsLoc);
1066
- }
1067
- const backoff = params.backoff.value;
1068
- return {
1069
- predicate: predicateFromRetryParams(params, argsLoc),
1070
- maxRetries: params.max_retries,
1071
- backoff: {
1072
- initialDelay: safeAsExpression(backoff.initial_delay),
1073
- maxDelay: safeAsExpression(backoff.max_delay),
1074
- multiplier: safeAsExpression(backoff.multiplier),
1075
- },
1076
- };
1077
- }
1078
- function predicateFromRetryParams(params, argsLoc) {
1079
- if (!('predicate' in params)) {
1080
- return undefined;
1081
- }
1082
- else if (isFullyQualifiedName(params.predicate)) {
1083
- return params.predicate.toString();
1084
- }
1085
- else {
1086
- throw new WorkflowSyntaxError('"predicate" must be a function name', argsLoc);
1087
- }
1088
- }
1089
- function tempName(ctx) {
1090
- if (ctx.parallelNestingLevel !== undefined) {
1091
- // Temporary variable inside a parallel step can not be the same as temporary
1092
- // variables on the outside. Sharing the variable name would cause deployment
1093
- // error, if the variable is not marked as shared by including it in the
1094
- // "shared" array.
1095
- return `__temp_parallel${ctx.parallelNestingLevel ?? 0}`;
1096
- }
1097
- else {
1098
- return '__temp';
1099
- }
1100
- }