@mondaydotcomorg/atp-compiler 0.17.16 → 0.18.4-rc.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/__tests__/unit/default-compiler.test.ts +259 -0
- package/__tests__/unit/plugin-system.test.ts +401 -0
- package/dist/atp-compiler/src/index.d.ts +8 -0
- package/dist/atp-compiler/src/index.d.ts.map +1 -1
- package/dist/atp-compiler/src/index.js +9 -0
- package/dist/atp-compiler/src/index.js.map +1 -1
- package/dist/atp-compiler/src/plugin-system/create-default-compiler.d.ts +40 -0
- package/dist/atp-compiler/src/plugin-system/create-default-compiler.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/create-default-compiler.js +40 -0
- package/dist/atp-compiler/src/plugin-system/create-default-compiler.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/array-transformer-plugin.d.ts +18 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/array-transformer-plugin.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/array-transformer-plugin.js +45 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/array-transformer-plugin.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/detection-plugin.d.ts +17 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/detection-plugin.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/detection-plugin.js +33 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/detection-plugin.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/index.d.ts +11 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/index.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/index.js +11 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/index.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/loop-transformer-plugin.d.ts +17 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/loop-transformer-plugin.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/loop-transformer-plugin.js +36 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/loop-transformer-plugin.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/promise-transformer-plugin.d.ts +19 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/promise-transformer-plugin.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/promise-transformer-plugin.js +49 -0
- package/dist/atp-compiler/src/plugin-system/default-plugins/promise-transformer-plugin.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/examples/loop-transformer-plugin.d.ts +31 -0
- package/dist/atp-compiler/src/plugin-system/examples/loop-transformer-plugin.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/examples/loop-transformer-plugin.js +60 -0
- package/dist/atp-compiler/src/plugin-system/examples/loop-transformer-plugin.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/examples/security-validator-plugin.d.ts +48 -0
- package/dist/atp-compiler/src/plugin-system/examples/security-validator-plugin.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/examples/security-validator-plugin.js +108 -0
- package/dist/atp-compiler/src/plugin-system/examples/security-validator-plugin.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/examples/timeout-plugin.d.ts +53 -0
- package/dist/atp-compiler/src/plugin-system/examples/timeout-plugin.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/examples/timeout-plugin.js +106 -0
- package/dist/atp-compiler/src/plugin-system/examples/timeout-plugin.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/index.d.ts +14 -0
- package/dist/atp-compiler/src/plugin-system/index.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/index.js +16 -0
- package/dist/atp-compiler/src/plugin-system/index.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/pluggable-compiler.d.ts +102 -0
- package/dist/atp-compiler/src/plugin-system/pluggable-compiler.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/pluggable-compiler.js +280 -0
- package/dist/atp-compiler/src/plugin-system/pluggable-compiler.js.map +1 -0
- package/dist/atp-compiler/src/plugin-system/plugin-api.d.ts +165 -0
- package/dist/atp-compiler/src/plugin-system/plugin-api.d.ts.map +1 -0
- package/dist/atp-compiler/src/plugin-system/plugin-api.js +180 -0
- package/dist/atp-compiler/src/plugin-system/plugin-api.js.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer-utils.d.ts +2 -2
- package/dist/atp-compiler/src/transformer/array-transformer-utils.d.ts.map +1 -1
- package/dist/atp-compiler/src/transformer/array-transformer-utils.js +2 -2
- package/dist/atp-compiler/src/transformer/array-transformer-utils.js.map +1 -1
- package/dist/atp-compiler/src/transformer/index.d.ts +15 -1
- package/dist/atp-compiler/src/transformer/index.d.ts.map +1 -1
- package/dist/atp-compiler/src/transformer/index.js +17 -0
- package/dist/atp-compiler/src/transformer/index.js.map +1 -1
- package/dist/atp-compiler/src/transformer/loop-transformer.d.ts +0 -4
- package/dist/atp-compiler/src/transformer/loop-transformer.d.ts.map +1 -1
- package/dist/atp-compiler/src/transformer/loop-transformer.js +5 -60
- package/dist/atp-compiler/src/transformer/loop-transformer.js.map +1 -1
- package/dist/atp-compiler/src/transformer/utils.d.ts +4 -0
- package/dist/atp-compiler/src/transformer/utils.d.ts.map +1 -1
- package/dist/atp-compiler/src/transformer/utils.js +15 -0
- package/dist/atp-compiler/src/transformer/utils.js.map +1 -1
- package/dist/atp-compiler/src/types/compiler-interface.d.ts +61 -0
- package/dist/atp-compiler/src/types/compiler-interface.d.ts.map +1 -0
- package/dist/atp-compiler/src/types/compiler-interface.js +18 -0
- package/dist/atp-compiler/src/types/compiler-interface.js.map +1 -0
- package/dist/runtime/src/approval/index.js +2 -1
- package/dist/runtime/src/approval/index.js.map +1 -1
- package/dist/runtime/src/index.d.ts +1 -1
- package/dist/runtime/src/index.d.ts.map +1 -1
- package/dist/runtime/src/index.js +1 -1
- package/dist/runtime/src/index.js.map +1 -1
- package/dist/runtime/src/llm/index.d.ts +1 -1
- package/dist/runtime/src/llm/index.d.ts.map +1 -1
- package/dist/runtime/src/llm/index.js +1 -1
- package/dist/runtime/src/llm/index.js.map +1 -1
- package/dist/runtime/src/llm/replay.d.ts +75 -0
- package/dist/runtime/src/llm/replay.d.ts.map +1 -1
- package/dist/runtime/src/llm/replay.js +187 -5
- package/dist/runtime/src/llm/replay.js.map +1 -1
- package/dist/runtime/src/metadata/generated.d.ts.map +1 -1
- package/dist/runtime/src/metadata/generated.js +189 -189
- package/dist/runtime/src/metadata/generated.js.map +1 -1
- package/dist/runtime/src/metadata/index.js +2 -2
- package/dist/runtime/src/metadata/index.js.map +1 -1
- package/dist/runtime/src/metadata/types.d.ts +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +14 -5
- package/project.json +1 -3
- package/src/index.ts +26 -0
- package/src/plugin-system/create-default-compiler.ts +57 -0
- package/src/plugin-system/default-plugins/array-transformer-plugin.ts +57 -0
- package/src/plugin-system/default-plugins/detection-plugin.ts +41 -0
- package/src/plugin-system/default-plugins/index.ts +12 -0
- package/src/plugin-system/default-plugins/loop-transformer-plugin.ts +47 -0
- package/src/plugin-system/default-plugins/promise-transformer-plugin.ts +63 -0
- package/src/plugin-system/examples/loop-transformer-plugin.ts +76 -0
- package/src/plugin-system/examples/security-validator-plugin.ts +168 -0
- package/src/plugin-system/examples/timeout-plugin.ts +158 -0
- package/src/plugin-system/index.ts +19 -0
- package/src/plugin-system/pluggable-compiler.ts +318 -0
- package/src/plugin-system/plugin-api.ts +330 -0
- package/src/transformer/array-transformer-utils.ts +3 -7
- package/src/transformer/index.ts +21 -1
- package/src/transformer/loop-transformer.ts +5 -66
- package/src/transformer/utils.ts +14 -0
- package/src/types/compiler-interface.ts +79 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATP Compiler Plugin API
|
|
3
|
+
*
|
|
4
|
+
* Extensible plugin system for custom transformations and detections
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { NodePath } from '@babel/traverse';
|
|
8
|
+
import type * as t from '@babel/types';
|
|
9
|
+
import type { CompilerConfig, DetectionResult, TransformMetadata, AsyncPattern } from '../types.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Base plugin interface
|
|
13
|
+
*/
|
|
14
|
+
export interface CompilerPlugin {
|
|
15
|
+
/**
|
|
16
|
+
* Unique plugin name
|
|
17
|
+
*/
|
|
18
|
+
name: string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Plugin version (semver)
|
|
22
|
+
*/
|
|
23
|
+
version: string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Plugin priority (higher = runs first)
|
|
27
|
+
* Built-in plugins: 100
|
|
28
|
+
* User plugins: 50 (default)
|
|
29
|
+
* Low priority: 10
|
|
30
|
+
*/
|
|
31
|
+
priority?: number;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Plugin initialization (optional)
|
|
35
|
+
* Called once when plugin is registered
|
|
36
|
+
*/
|
|
37
|
+
initialize?(config: CompilerConfig): void | Promise<void>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Plugin cleanup (optional)
|
|
41
|
+
* Called when compiler is disposed
|
|
42
|
+
*/
|
|
43
|
+
dispose?(): void | Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Detection plugin - detects patterns that need transformation
|
|
48
|
+
*/
|
|
49
|
+
export interface DetectionPlugin extends CompilerPlugin {
|
|
50
|
+
/**
|
|
51
|
+
* Detect patterns in code
|
|
52
|
+
*/
|
|
53
|
+
detect(code: string, ast: t.File): DetectionResult | Promise<DetectionResult>;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Custom async patterns this plugin can detect
|
|
57
|
+
*/
|
|
58
|
+
patterns: AsyncPattern[];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Transformation plugin - transforms AST nodes
|
|
63
|
+
*/
|
|
64
|
+
export interface TransformationPlugin extends CompilerPlugin {
|
|
65
|
+
/**
|
|
66
|
+
* Visitor pattern for AST traversal
|
|
67
|
+
* Return visitor object compatible with @babel/traverse
|
|
68
|
+
*/
|
|
69
|
+
getVisitor(config: CompilerConfig): BabelVisitor;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get transformation metadata after transform
|
|
73
|
+
*/
|
|
74
|
+
getMetadata(): Partial<TransformMetadata>;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Reset plugin state (called before each transform)
|
|
78
|
+
*/
|
|
79
|
+
reset(): void;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Optimizer plugin - optimizes transformed code
|
|
84
|
+
*/
|
|
85
|
+
export interface OptimizerPlugin extends CompilerPlugin {
|
|
86
|
+
/**
|
|
87
|
+
* Optimize AST after all transformations
|
|
88
|
+
*/
|
|
89
|
+
optimize(ast: t.File, config: CompilerConfig): t.File | Promise<t.File>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Validator plugin - validates code before/after transformation
|
|
94
|
+
*/
|
|
95
|
+
export interface ValidatorPlugin extends CompilerPlugin {
|
|
96
|
+
/**
|
|
97
|
+
* Validate code (throw error if invalid)
|
|
98
|
+
*/
|
|
99
|
+
validate(code: string, ast: t.File, phase: 'pre' | 'post'): void | Promise<void>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Babel visitor type (simplified)
|
|
104
|
+
*/
|
|
105
|
+
export interface BabelVisitor {
|
|
106
|
+
[key: string]: (path: NodePath<any>) => void;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Plugin context - shared state during transformation
|
|
111
|
+
*/
|
|
112
|
+
export interface PluginContext {
|
|
113
|
+
config: CompilerConfig;
|
|
114
|
+
executionId?: string;
|
|
115
|
+
metadata: TransformMetadata;
|
|
116
|
+
patterns: Set<AsyncPattern>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Plugin registry for managing plugins
|
|
121
|
+
*/
|
|
122
|
+
export class PluginRegistry {
|
|
123
|
+
private detectors: DetectionPlugin[] = [];
|
|
124
|
+
private transformers: TransformationPlugin[] = [];
|
|
125
|
+
private optimizers: OptimizerPlugin[] = [];
|
|
126
|
+
private validators: ValidatorPlugin[] = [];
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Register a plugin
|
|
130
|
+
*/
|
|
131
|
+
register(plugin: CompilerPlugin): void {
|
|
132
|
+
// Check for name conflicts
|
|
133
|
+
if (this.findPlugin(plugin.name)) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`Plugin "${plugin.name}" is already registered. ` +
|
|
136
|
+
`Please use a unique name or unregister the existing plugin first.`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Type guards to determine plugin type
|
|
141
|
+
if (this.isDetectionPlugin(plugin)) {
|
|
142
|
+
this.detectors.push(plugin);
|
|
143
|
+
this.detectors.sort((a, b) => (b.priority || 50) - (a.priority || 50));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (this.isTransformationPlugin(plugin)) {
|
|
147
|
+
this.transformers.push(plugin);
|
|
148
|
+
this.transformers.sort((a, b) => (b.priority || 50) - (a.priority || 50));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (this.isOptimizerPlugin(plugin)) {
|
|
152
|
+
this.optimizers.push(plugin);
|
|
153
|
+
this.optimizers.sort((a, b) => (b.priority || 50) - (a.priority || 50));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (this.isValidatorPlugin(plugin)) {
|
|
157
|
+
this.validators.push(plugin);
|
|
158
|
+
this.validators.sort((a, b) => (b.priority || 50) - (a.priority || 50));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Find a plugin by name
|
|
164
|
+
*/
|
|
165
|
+
findPlugin(name: string): CompilerPlugin | undefined {
|
|
166
|
+
const allPlugins = [
|
|
167
|
+
...this.detectors,
|
|
168
|
+
...this.transformers,
|
|
169
|
+
...this.optimizers,
|
|
170
|
+
...this.validators,
|
|
171
|
+
];
|
|
172
|
+
return allPlugins.find((p) => p.name === name);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Unregister a plugin by name
|
|
177
|
+
*/
|
|
178
|
+
unregister(name: string): boolean {
|
|
179
|
+
let removed = false;
|
|
180
|
+
|
|
181
|
+
this.detectors = this.detectors.filter((p) => {
|
|
182
|
+
if (p.name === name) {
|
|
183
|
+
removed = true;
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
return true;
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
this.transformers = this.transformers.filter((p) => {
|
|
190
|
+
if (p.name === name) {
|
|
191
|
+
removed = true;
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
return true;
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
this.optimizers = this.optimizers.filter((p) => {
|
|
198
|
+
if (p.name === name) {
|
|
199
|
+
removed = true;
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
return true;
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
this.validators = this.validators.filter((p) => {
|
|
206
|
+
if (p.name === name) {
|
|
207
|
+
removed = true;
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
return true;
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
return removed;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get all detection plugins
|
|
218
|
+
*/
|
|
219
|
+
getDetectors(): DetectionPlugin[] {
|
|
220
|
+
return this.detectors;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get all transformation plugins
|
|
225
|
+
*/
|
|
226
|
+
getTransformers(): TransformationPlugin[] {
|
|
227
|
+
return this.transformers;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Get all optimizer plugins
|
|
232
|
+
*/
|
|
233
|
+
getOptimizers(): OptimizerPlugin[] {
|
|
234
|
+
return this.optimizers;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Get all validator plugins
|
|
239
|
+
*/
|
|
240
|
+
getValidators(): ValidatorPlugin[] {
|
|
241
|
+
return this.validators;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Initialize all plugins
|
|
246
|
+
*/
|
|
247
|
+
async initializeAll(config: CompilerConfig): Promise<void> {
|
|
248
|
+
const allPlugins = [
|
|
249
|
+
...this.detectors,
|
|
250
|
+
...this.transformers,
|
|
251
|
+
...this.optimizers,
|
|
252
|
+
...this.validators,
|
|
253
|
+
];
|
|
254
|
+
|
|
255
|
+
for (const plugin of allPlugins) {
|
|
256
|
+
if (plugin.initialize) {
|
|
257
|
+
await plugin.initialize(config);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Dispose all plugins
|
|
264
|
+
*/
|
|
265
|
+
async disposeAll(): Promise<void> {
|
|
266
|
+
const allPlugins = [
|
|
267
|
+
...this.detectors,
|
|
268
|
+
...this.transformers,
|
|
269
|
+
...this.optimizers,
|
|
270
|
+
...this.validators,
|
|
271
|
+
];
|
|
272
|
+
|
|
273
|
+
for (const plugin of allPlugins) {
|
|
274
|
+
if (plugin.dispose) {
|
|
275
|
+
await plugin.dispose();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Type guards
|
|
282
|
+
*/
|
|
283
|
+
private isDetectionPlugin(plugin: CompilerPlugin): plugin is DetectionPlugin {
|
|
284
|
+
return 'detect' in plugin && 'patterns' in plugin;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
private isTransformationPlugin(plugin: CompilerPlugin): plugin is TransformationPlugin {
|
|
288
|
+
return 'getVisitor' in plugin && 'getMetadata' in plugin && 'reset' in plugin;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private isOptimizerPlugin(plugin: CompilerPlugin): plugin is OptimizerPlugin {
|
|
292
|
+
return 'optimize' in plugin;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
private isValidatorPlugin(plugin: CompilerPlugin): plugin is ValidatorPlugin {
|
|
296
|
+
return 'validate' in plugin;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Utility function to create a simple transformation plugin
|
|
302
|
+
*/
|
|
303
|
+
export function createTransformPlugin(config: {
|
|
304
|
+
name: string;
|
|
305
|
+
version: string;
|
|
306
|
+
priority?: number;
|
|
307
|
+
visitor: BabelVisitor;
|
|
308
|
+
getMetadata?: () => Partial<TransformMetadata>;
|
|
309
|
+
}): TransformationPlugin {
|
|
310
|
+
let transformCount = 0;
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
name: config.name,
|
|
314
|
+
version: config.version,
|
|
315
|
+
priority: config.priority || 50,
|
|
316
|
+
|
|
317
|
+
getVisitor() {
|
|
318
|
+
return config.visitor;
|
|
319
|
+
},
|
|
320
|
+
|
|
321
|
+
getMetadata() {
|
|
322
|
+
return config.getMetadata ? config.getMetadata() : { loopCount: transformCount };
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
reset() {
|
|
326
|
+
transformCount = 0;
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as t from '@babel/types';
|
|
2
|
+
import { isArrayMethod } from './utils.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
|
-
* Find LLM call expression in
|
|
5
|
+
* Find LLM call expression in AST node
|
|
5
6
|
*/
|
|
6
|
-
export function findLLMCallExpression(
|
|
7
|
-
body: t.BlockStatement | t.Expression
|
|
8
|
-
): t.CallExpression | null {
|
|
7
|
+
export function findLLMCallExpression(body: t.Node): t.CallExpression | null {
|
|
9
8
|
let found: t.CallExpression | null = null;
|
|
10
9
|
|
|
11
10
|
const visit = (node: t.Node) => {
|
|
@@ -42,9 +41,6 @@ export function findLLMCallExpression(
|
|
|
42
41
|
*/
|
|
43
42
|
export function getArrayMethodName(node: t.CallExpression): string | null {
|
|
44
43
|
const arrayMethods = ['map', 'forEach', 'filter', 'reduce', 'find', 'some', 'every', 'flatMap'];
|
|
45
|
-
|
|
46
|
-
const { isArrayMethod } = require('./utils.js');
|
|
47
|
-
|
|
48
44
|
for (const method of arrayMethods) {
|
|
49
45
|
if (isArrayMethod(node, method)) {
|
|
50
46
|
return method;
|
package/src/transformer/index.ts
CHANGED
|
@@ -12,8 +12,13 @@ import type { TransformResult, CompilerConfig, TransformMetadata } from '../type
|
|
|
12
12
|
import { DEFAULT_COMPILER_CONFIG } from '../types.js';
|
|
13
13
|
import { TransformationError } from '../runtime/errors.js';
|
|
14
14
|
import { resetIdCounter } from '../runtime/context.js';
|
|
15
|
+
import type { ICompiler } from '../types/compiler-interface.js';
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
/**
|
|
18
|
+
* ATP Compiler - Standard compiler for transforming code to support resumability
|
|
19
|
+
* Implements ICompiler interface for consistency and dependency injection support
|
|
20
|
+
*/
|
|
21
|
+
export class ATPCompiler implements ICompiler {
|
|
17
22
|
private config: CompilerConfig;
|
|
18
23
|
private detector: AsyncIterationDetector;
|
|
19
24
|
private loopTransformer: LoopTransformer;
|
|
@@ -144,6 +149,21 @@ export class ATPCompiler {
|
|
|
144
149
|
t.isIdentifier(callee.property, { name: 'allSettled' })
|
|
145
150
|
);
|
|
146
151
|
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Get the compiler type identifier (ICompiler interface requirement)
|
|
155
|
+
*/
|
|
156
|
+
getType(): string {
|
|
157
|
+
return 'ATPCompiler';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Get cache statistics (ICompiler interface requirement)
|
|
162
|
+
* ATPCompiler doesn't cache ASTs, so returns null
|
|
163
|
+
*/
|
|
164
|
+
getCacheStats() {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
147
167
|
}
|
|
148
168
|
|
|
149
169
|
export * from './detector.js';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as t from '@babel/types';
|
|
2
2
|
import { generateUniqueId } from '../runtime/context.js';
|
|
3
|
-
import { containsAwait } from './utils.js';
|
|
3
|
+
import { containsAwait, extractForOfParamName } from './utils.js';
|
|
4
4
|
import { BatchOptimizer } from './batch-optimizer.js';
|
|
5
5
|
import { BatchParallelDetector } from './batch-detector.js';
|
|
6
|
+
import { findLLMCallExpression } from './array-transformer-utils.js';
|
|
6
7
|
|
|
7
8
|
export class LoopTransformer {
|
|
8
9
|
private transformCount = 0;
|
|
@@ -46,27 +47,10 @@ export class LoopTransformer {
|
|
|
46
47
|
*/
|
|
47
48
|
private transformForOfToBatch(path: any, node: t.ForOfStatement): boolean {
|
|
48
49
|
const loopId = generateUniqueId('for_of_batch');
|
|
49
|
-
const left = node.left;
|
|
50
50
|
const right = node.right;
|
|
51
|
+
const paramName = extractForOfParamName(node.left);
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
if (t.isVariableDeclaration(left)) {
|
|
54
|
-
const id = left.declarations[0]?.id;
|
|
55
|
-
paramName = t.isIdentifier(id) ? id.name : 'item';
|
|
56
|
-
} else if (t.isIdentifier(left)) {
|
|
57
|
-
paramName = left.name;
|
|
58
|
-
} else {
|
|
59
|
-
paramName = 'item';
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const bodyStatements = t.isBlockStatement(node.body) ? node.body.body : [node.body];
|
|
63
|
-
const callback = t.arrowFunctionExpression(
|
|
64
|
-
[t.identifier(paramName)],
|
|
65
|
-
t.blockStatement(bodyStatements),
|
|
66
|
-
true
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
const llmCall = this.findLLMCallInBody(node.body);
|
|
53
|
+
const llmCall = findLLMCallExpression(node.body);
|
|
70
54
|
if (!llmCall) {
|
|
71
55
|
return this.transformForOfToSequential(path, node);
|
|
72
56
|
}
|
|
@@ -109,18 +93,8 @@ export class LoopTransformer {
|
|
|
109
93
|
*/
|
|
110
94
|
private transformForOfToSequential(path: any, node: t.ForOfStatement): boolean {
|
|
111
95
|
const loopId = generateUniqueId('for_of');
|
|
112
|
-
const left = node.left;
|
|
113
96
|
const right = node.right;
|
|
114
|
-
|
|
115
|
-
let paramName: string;
|
|
116
|
-
if (t.isVariableDeclaration(left)) {
|
|
117
|
-
const id = left.declarations[0]?.id;
|
|
118
|
-
paramName = t.isIdentifier(id) ? id.name : 'item';
|
|
119
|
-
} else if (t.isIdentifier(left)) {
|
|
120
|
-
paramName = left.name;
|
|
121
|
-
} else {
|
|
122
|
-
paramName = 'item';
|
|
123
|
-
}
|
|
97
|
+
const paramName = extractForOfParamName(node.left);
|
|
124
98
|
|
|
125
99
|
const bodyStatements = t.isBlockStatement(node.body) ? node.body.body : [node.body];
|
|
126
100
|
|
|
@@ -142,41 +116,6 @@ export class LoopTransformer {
|
|
|
142
116
|
return true;
|
|
143
117
|
}
|
|
144
118
|
|
|
145
|
-
/**
|
|
146
|
-
* Find LLM call in loop body
|
|
147
|
-
*/
|
|
148
|
-
private findLLMCallInBody(body: t.Statement | t.BlockStatement): t.CallExpression | null {
|
|
149
|
-
let found: t.CallExpression | null = null;
|
|
150
|
-
|
|
151
|
-
const visit = (node: t.Node) => {
|
|
152
|
-
if (found) return;
|
|
153
|
-
|
|
154
|
-
if (t.isAwaitExpression(node) && t.isCallExpression(node.argument)) {
|
|
155
|
-
const call = node.argument;
|
|
156
|
-
if (t.isMemberExpression(call.callee)) {
|
|
157
|
-
found = call;
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
Object.keys(node).forEach((key) => {
|
|
163
|
-
const value = (node as any)[key];
|
|
164
|
-
if (Array.isArray(value)) {
|
|
165
|
-
value.forEach((item) => {
|
|
166
|
-
if (item && typeof item === 'object' && item.type) {
|
|
167
|
-
visit(item);
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
} else if (value && typeof value === 'object' && value.type) {
|
|
171
|
-
visit(value);
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
visit(body);
|
|
177
|
-
return found;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
119
|
transformWhileLoop(path: any): boolean {
|
|
181
120
|
const node = path.node as t.WhileStatement;
|
|
182
121
|
|
package/src/transformer/utils.ts
CHANGED
|
@@ -145,3 +145,17 @@ export function isArrayMethod(node: t.Node, methodName: string): boolean {
|
|
|
145
145
|
|
|
146
146
|
return t.isIdentifier(callee.property) && callee.property.name === methodName;
|
|
147
147
|
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Extract parameter name from ForOfStatement left side
|
|
151
|
+
*/
|
|
152
|
+
export function extractForOfParamName(left: t.VariableDeclaration | t.LVal): string {
|
|
153
|
+
if (t.isVariableDeclaration(left)) {
|
|
154
|
+
const id = left.declarations[0]?.id;
|
|
155
|
+
return t.isIdentifier(id) ? id.name : 'item';
|
|
156
|
+
} else if (t.isIdentifier(left)) {
|
|
157
|
+
return left.name;
|
|
158
|
+
} else {
|
|
159
|
+
return 'item';
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core compiler interface for ATP
|
|
3
|
+
* All ATP compilers must implement this interface to ensure consistency
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { DetectionResult, TransformResult } from '../types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* ICompiler - The core interface that all ATP compilers must implement
|
|
10
|
+
*
|
|
11
|
+
* This interface defines the contract for any compiler in the ATP system,
|
|
12
|
+
* enabling dependency injection and easy extensibility.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* class MyCustomCompiler implements ICompiler {
|
|
17
|
+
* detect(code: string): DetectionResult {
|
|
18
|
+
* // Detection logic
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* transform(code: string): TransformResult {
|
|
22
|
+
* // Transformation logic
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* getType(): string {
|
|
26
|
+
* return 'MyCustomCompiler';
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export interface ICompiler {
|
|
32
|
+
/**
|
|
33
|
+
* Detect if code needs transformation and what patterns it contains
|
|
34
|
+
* Can be synchronous or asynchronous
|
|
35
|
+
*/
|
|
36
|
+
detect(code: string): DetectionResult | Promise<DetectionResult>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Transform the code based on detected patterns
|
|
40
|
+
* Can be synchronous or asynchronous
|
|
41
|
+
*/
|
|
42
|
+
transform(code: string): TransformResult | Promise<TransformResult>;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the compiler type identifier
|
|
46
|
+
*/
|
|
47
|
+
getType(): string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get cache statistics (optional)
|
|
51
|
+
* Useful for performance monitoring and debugging
|
|
52
|
+
*/
|
|
53
|
+
getCacheStats?(): CacheStats | null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Cache statistics structure
|
|
58
|
+
*/
|
|
59
|
+
export interface CacheStats {
|
|
60
|
+
size: number;
|
|
61
|
+
enabled: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Type guard to check if an object implements ICompiler
|
|
66
|
+
*/
|
|
67
|
+
export function isCompiler(obj: unknown): obj is ICompiler {
|
|
68
|
+
return (
|
|
69
|
+
typeof obj === 'object' &&
|
|
70
|
+
obj !== null &&
|
|
71
|
+
'detect' in obj &&
|
|
72
|
+
'transform' in obj &&
|
|
73
|
+
'getType' in obj &&
|
|
74
|
+
typeof (obj as any).detect === 'function' &&
|
|
75
|
+
typeof (obj as any).transform === 'function' &&
|
|
76
|
+
typeof (obj as any).getType === 'function'
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|