@faicad/cq-compat 0.13.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 (41) hide show
  1. package/dist/assembly-compare.d.ts +135 -0
  2. package/dist/assembly-compare.d.ts.map +1 -0
  3. package/dist/assembly-compare.js +266 -0
  4. package/dist/assembly-compare.js.map +1 -0
  5. package/dist/assembly.d.ts +102 -0
  6. package/dist/assembly.d.ts.map +1 -0
  7. package/dist/assembly.js +403 -0
  8. package/dist/assembly.js.map +1 -0
  9. package/dist/browser.d.ts +13 -0
  10. package/dist/browser.d.ts.map +1 -0
  11. package/dist/browser.js +13 -0
  12. package/dist/browser.js.map +1 -0
  13. package/dist/gear-test-harness.d.ts +79 -0
  14. package/dist/gear-test-harness.d.ts.map +1 -0
  15. package/dist/gear-test-harness.js +112 -0
  16. package/dist/gear-test-harness.js.map +1 -0
  17. package/dist/gears.d.ts +226 -0
  18. package/dist/gears.d.ts.map +1 -0
  19. package/dist/gears.js +274 -0
  20. package/dist/gears.js.map +1 -0
  21. package/dist/geom-types.d.ts +7 -0
  22. package/dist/geom-types.d.ts.map +1 -0
  23. package/dist/geom-types.js +2 -0
  24. package/dist/geom-types.js.map +1 -0
  25. package/dist/index.d.ts +26 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +23 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/step-compare.d.ts +83 -0
  30. package/dist/step-compare.d.ts.map +1 -0
  31. package/dist/step-compare.js +140 -0
  32. package/dist/step-compare.js.map +1 -0
  33. package/dist/transpile.d.ts +42 -0
  34. package/dist/transpile.d.ts.map +1 -0
  35. package/dist/transpile.js +557 -0
  36. package/dist/transpile.js.map +1 -0
  37. package/dist/workplane.d.ts +1216 -0
  38. package/dist/workplane.d.ts.map +1 -0
  39. package/dist/workplane.js +4026 -0
  40. package/dist/workplane.js.map +1 -0
  41. package/package.json +48 -0
@@ -0,0 +1,557 @@
1
+ /**
2
+ * CadQuery Python → .fai.js transpiler.
3
+ *
4
+ * Handles the patterns found in real-world CadQuery projects:
5
+ * - import cadquery as cq / import config / import math
6
+ * - chained Workplane calls: wp.faces(">Z").workplane().hole(d)
7
+ * - config constant references (inlined from config.py)
8
+ * - function definitions (def pin_holes(wp): ...)
9
+ * - list comprehensions, math.cos/radians, slicing
10
+ * - if __name__ == "__main__" blocks (dropped)
11
+ *
12
+ * Not a general Python transpiler — targeted at CadQuery scripts.
13
+ */
14
+ // ── Config extraction ──────────────────────────────────────────────────────
15
+ /**
16
+ * extractConfig
17
+ * @param ast - AstNode
18
+ * @returns {
19
+ consts: Map<string, string>
20
+ fns: Map<string, { params: string[]; body: string[] }>
21
+ }
22
+ */
23
+ export function extractConfig(ast) {
24
+ const consts = new Map();
25
+ const fns = new Map();
26
+ // First pass: extract all constants
27
+ for (const stmt of ast.body ?? []) {
28
+ if (stmt._type === 'Assign') {
29
+ const targets = stmt.targets;
30
+ const value = stmt.value;
31
+ if (targets.length === 1 && targets[0]._type === 'Name') {
32
+ const name = targets[0].id;
33
+ consts.set(name, transpileExpr(value, makeCtxWithConsts(consts)));
34
+ }
35
+ }
36
+ }
37
+ // Second pass: extract functions with constants inlined
38
+ const fnCtx = { ...makeCtxWithConsts(consts), inFunction: true };
39
+ for (const stmt of ast.body ?? []) {
40
+ if (stmt._type === 'FunctionDef') {
41
+ const name = stmt.name;
42
+ const args = stmt.args.args ?? [];
43
+ const params = args.map((a) => a.arg);
44
+ const body = stmt.body ?? [];
45
+ const bodyLines = body.map((s) => transpileStmt(s, fnCtx)).filter((l) => l !== null);
46
+ fns.set(name, { params, body: bodyLines });
47
+ }
48
+ }
49
+ return { consts, fns };
50
+ }
51
+ function makeCtxWithConsts(consts) {
52
+ return { configConsts: new Map(consts), configFns: new Map(), partName: 'result', declared: new Set() };
53
+ }
54
+ // ── Main entry ─────────────────────────────────────────────────────────────
55
+ /**
56
+ * transpile
57
+ * @param ast - AstNode
58
+ * @param config - ReturnType<typeof extractConfig>
59
+ * @param partName - string
60
+ * @returns string
61
+ */
62
+ export function transpile(ast, config, partName) {
63
+ const ctx = {
64
+ configConsts: config.consts,
65
+ configFns: config.fns,
66
+ partName,
67
+ declared: new Set(),
68
+ };
69
+ const lines = [];
70
+ lines.push("import * as cq from '@faicad/cq-compat'");
71
+ lines.push('');
72
+ // Inline config constants
73
+ if (config.consts.size > 0) {
74
+ for (const [name, value] of config.consts) {
75
+ lines.push(`const ${name} = ${value}`);
76
+ }
77
+ lines.push('');
78
+ }
79
+ // Inline config functions
80
+ for (const [name, fn] of config.fns) {
81
+ lines.push(`async function ${name}(${fn.params.join(', ')}) {`);
82
+ for (const l of fn.body)
83
+ lines.push(` ${l}`);
84
+ lines.push('}');
85
+ lines.push('');
86
+ }
87
+ // Transpile module body
88
+ const bodyLines = [];
89
+ let lastAssignName = null;
90
+ for (const stmt of ast.body ?? []) {
91
+ const line = transpileStmt(stmt, ctx);
92
+ if (line !== null) {
93
+ bodyLines.push(line);
94
+ // Track last variable assignment (for terminal extraction)
95
+ if (stmt._type === 'Assign') {
96
+ const targets = stmt.targets;
97
+ if (targets.length === 1 && targets[0]._type === 'Name') {
98
+ lastAssignName = targets[0].id;
99
+ }
100
+ }
101
+ }
102
+ }
103
+ lines.push(...bodyLines);
104
+ // Terminal extraction: if last assignment is a Workplane, extract its shape
105
+ if (lastAssignName) {
106
+ lines.push('');
107
+ lines.push(`let result = cq.val(${lastAssignName})`);
108
+ }
109
+ return lines.join('\n');
110
+ }
111
+ // ── Statement transpilation ────────────────────────────────────────────────
112
+ function transpileStmt(stmt, ctx) {
113
+ switch (stmt._type) {
114
+ case 'Import':
115
+ case 'ImportFrom':
116
+ return null; // imports handled by header
117
+ case 'If':
118
+ return transpileIf(stmt, ctx);
119
+ case 'Assign':
120
+ return transpileAssign(stmt, ctx);
121
+ case 'Expr':
122
+ return transpileExpr(stmt.value, ctx);
123
+ case 'FunctionDef':
124
+ return transpileFunctionDef(stmt, ctx);
125
+ case 'Return':
126
+ return `return ${transpileExpr(stmt.value, ctx)}`;
127
+ case 'Pass':
128
+ return null;
129
+ default:
130
+ return `// [unhandled stmt: ${stmt._type}]`;
131
+ }
132
+ }
133
+ function transpileIf(stmt, ctx) {
134
+ const test = stmt.test;
135
+ // Detect `if __name__ == "__main__":` or `if True or ...` → drop
136
+ if (isMainCheck(test) || isTrueLiteral(test) || isShowObjectGuard(test)) {
137
+ return null;
138
+ }
139
+ // Generic if (rare in practice)
140
+ const body = stmt.body.map((s) => transpileStmt(s, ctx)).filter((l) => l !== null);
141
+ const testStr = transpileExpr(test, ctx);
142
+ return [`if (${testStr}) {`, ...body.map((l) => ` ${l}`), '}'].join('\n');
143
+ }
144
+ /** Detect `"x" not in globals()` guard (cadquery vis import pattern). */
145
+ function isShowObjectGuard(test) {
146
+ if (test._type !== 'Compare')
147
+ return false;
148
+ const ops = test.ops;
149
+ if (ops.length !== 1 || ops[0]._type !== 'NotIn')
150
+ return false;
151
+ return true;
152
+ }
153
+ function isMainCheck(test) {
154
+ if (test._type !== 'Compare')
155
+ return false;
156
+ const left = test.left;
157
+ if (left._type !== 'Name' || left.id !== '__name__')
158
+ return false;
159
+ const ops = test.ops;
160
+ if (ops.length !== 1 || ops[0]._type !== 'Eq')
161
+ return false;
162
+ const comps = test.comparators;
163
+ if (comps.length !== 1 || comps[0]._type !== 'Constant')
164
+ return false;
165
+ return comps[0].value === '__main__';
166
+ }
167
+ function isTrueLiteral(test) {
168
+ if (test._type === 'Constant' && test.value === true)
169
+ return true;
170
+ // `True or ...` — always true
171
+ if (test._type === 'BoolOp' && test.op._type === 'Or') {
172
+ const values = test.values;
173
+ return values.some((v) => v._type === 'Constant' && v.value === true);
174
+ }
175
+ return false;
176
+ }
177
+ function transpileAssign(stmt, ctx) {
178
+ const targets = stmt.targets;
179
+ const value = stmt.value;
180
+ if (targets.length !== 1)
181
+ return `// [unhandled multi-target assign]`;
182
+ const target = targets[0];
183
+ if (target._type !== 'Name')
184
+ return `// [unhandled assign target: ${target._type}]`;
185
+ const name = target.id;
186
+ const valueStr = transpileExpr(value, ctx);
187
+ const isNew = !ctx.declared.has(name);
188
+ if (isNew)
189
+ ctx.declared.add(name);
190
+ return isNew ? `let ${name} = ${valueStr}` : `${name} = ${valueStr}`;
191
+ }
192
+ function transpileFunctionDef(stmt, ctx) {
193
+ const name = stmt.name;
194
+ const args = stmt.args.args ?? [];
195
+ const params = args.map((a) => a.arg);
196
+ const fnCtx = { ...ctx, inFunction: true };
197
+ const body = stmt.body.map((s) => transpileStmt(s, fnCtx)).filter((l) => l !== null);
198
+ return [`async function ${name}(${params.join(', ')}) {`, ...body.map((l) => ` ${l}`), '}'].join('\n');
199
+ }
200
+ // ── Expression transpilation ───────────────────────────────────────────────
201
+ function transpileExpr(node, ctx) {
202
+ switch (node._type) {
203
+ case 'Constant':
204
+ return transpileConstant(node);
205
+ case 'Name':
206
+ return transpileName(node, ctx);
207
+ case 'Attribute':
208
+ return transpileAttribute(node, ctx);
209
+ case 'Call':
210
+ return transpileCall(node, ctx);
211
+ case 'BinOp':
212
+ return transpileBinOp(node, ctx);
213
+ case 'UnaryOp':
214
+ return transpileUnaryOp(node, ctx);
215
+ case 'List':
216
+ return transpileList(node, ctx);
217
+ case 'Subscript':
218
+ return transpileSubscript(node, ctx);
219
+ case 'ListComp':
220
+ return transpileListComp(node, ctx);
221
+ case 'Tuple':
222
+ return `[${(node.elts ?? []).map((e) => transpileExpr(e, ctx)).join(', ')}]`;
223
+ case 'Compare':
224
+ return transpileCompare(node, ctx);
225
+ case 'BoolOp':
226
+ return transpileBoolOp(node, ctx);
227
+ default:
228
+ return `/* [unhandled expr: ${node._type}] */`;
229
+ }
230
+ }
231
+ function transpileCompare(node, ctx) {
232
+ const left = transpileExpr(node.left, ctx);
233
+ const ops = node.ops;
234
+ const comparators = node.comparators;
235
+ const opMap = {
236
+ Eq: '===', NotEq: '!==', Lt: '<', LtE: '<=', Gt: '>', GtE: '>=',
237
+ Is: '===', IsNot: '!==', In: 'in', NotIn: '!in',
238
+ };
239
+ const parts = [left];
240
+ for (let i = 0; i < ops.length; i++) {
241
+ const op = opMap[ops[i]._type] ?? `/* ${ops[i]._type} */`;
242
+ const comp = transpileExpr(comparators[i], ctx);
243
+ parts.push(op, comp);
244
+ }
245
+ return `(${parts.join(' ')})`;
246
+ }
247
+ function transpileBoolOp(node, ctx) {
248
+ const op = node.op;
249
+ const values = node.values.map((v) => transpileExpr(v, ctx));
250
+ const joiner = op._type === 'And' ? '&&' : '||';
251
+ return `(${values.join(` ${joiner} `)})`;
252
+ }
253
+ function transpileConstant(node) {
254
+ const v = node.value;
255
+ if (typeof v === 'string')
256
+ return JSON.stringify(v);
257
+ if (v === null)
258
+ return 'null';
259
+ return String(v);
260
+ }
261
+ function transpileName(node, ctx) {
262
+ const id = node.id;
263
+ // math module → Math
264
+ if (id === 'math')
265
+ return 'Math';
266
+ // config constant inlining
267
+ if (ctx.configConsts.has(id))
268
+ return ctx.configConsts.get(id);
269
+ return id;
270
+ }
271
+ function transpileAttribute(node, ctx) {
272
+ const value = node.value;
273
+ const attr = node.attr;
274
+ // math.cos → Math.cos, math.radians → (x => x * Math.PI / 180)
275
+ if (value._type === 'Name' && value.id === 'math') {
276
+ if (attr === 'radians')
277
+ return '(x => x * Math.PI / 180)';
278
+ if (attr === 'cos')
279
+ return 'Math.cos';
280
+ if (attr === 'sin')
281
+ return 'Math.sin';
282
+ if (attr === 'sqrt')
283
+ return 'Math.sqrt';
284
+ return `Math.${attr}`;
285
+ }
286
+ // config.X → inlined constant
287
+ if (value._type === 'Name' && value.id === 'config' && ctx.configConsts.has(attr)) {
288
+ return ctx.configConsts.get(attr);
289
+ }
290
+ // Generic attribute: a.b — but for chained calls this is handled by transpileCall
291
+ return `${transpileExpr(value, ctx)}.${attr}`;
292
+ }
293
+ function transpileCall(node, ctx) {
294
+ const func = node.func;
295
+ const args = node.args ?? [];
296
+ const keywords = node.keywords ?? [];
297
+ let result;
298
+ let needsAwait = false;
299
+ // Chained method call: wp.method(args)
300
+ if (func._type === 'Attribute') {
301
+ result = transpileMethodCall(func, args, keywords, ctx);
302
+ // cq/workplane methods are async; Math.xxx is not.
303
+ // For chained calls, the outermost receiver may be a Call, so check method name.
304
+ const method = func.attr;
305
+ const mathMethods = new Set(['cos', 'sin', 'sqrt', 'radians', 'degrees', 'tan', 'atan', 'asin', 'acos', 'pow', 'abs', 'floor', 'ceil', 'round']);
306
+ if (!mathMethods.has(method)) {
307
+ needsAwait = true;
308
+ }
309
+ }
310
+ else if (func._type === 'Name') {
311
+ // Direct function call: fn(args)
312
+ const name = func.id;
313
+ const argStrs = args.map((a) => transpileExpr(a, ctx));
314
+ result = `${name}(${argStrs.join(', ')})`;
315
+ if (ctx.configFns.has(name))
316
+ needsAwait = true;
317
+ }
318
+ else {
319
+ // Call result of another expression (e.g. (lambda)(...))
320
+ result = `${transpileExpr(func, ctx)}(${args.map((a) => transpileExpr(a, ctx)).join(', ')})`;
321
+ }
322
+ // Inside async function body, await cq/config calls (they return Promises)
323
+ if (ctx.inFunction && needsAwait) {
324
+ result = `await ${result}`;
325
+ }
326
+ return result;
327
+ }
328
+ /**
329
+ * Convert chained method calls to function calls:
330
+ * wp.faces(">Z").workplane().hole(d)
331
+ * → cq.hole(cq.workplane(cq.faces(wp, ">Z")), d)
332
+ *
333
+ * Also handles cq.Workplane("XY") (constructor, not method).
334
+ */
335
+ function transpileMethodCall(func, args, keywords, ctx) {
336
+ const method = func.attr;
337
+ const receiver = func.value;
338
+ const argStrs = args.map((a) => transpileExpr(a, ctx));
339
+ const kwStr = transpileKeywords(keywords, ctx);
340
+ // config.fn(args) → fn(args) (config functions are inlined as global functions)
341
+ if (receiver._type === 'Name' && receiver.id === 'config' && ctx.configFns.has(method)) {
342
+ return `${method}(${argStrs.join(', ')})`;
343
+ }
344
+ // config.CONSTANT → inlined constant (handled in transpileAttribute, but here for call)
345
+ if (receiver._type === 'Name' && receiver.id === 'config' && ctx.configConsts.has(method)) {
346
+ return ctx.configConsts.get(method);
347
+ }
348
+ // math.cos(x), math.sin(x), math.sqrt(x), math.radians(x) → JS Math
349
+ if (receiver._type === 'Name' && receiver.id === 'math') {
350
+ if (method === 'radians')
351
+ return `(${argStrs[0]} * Math.PI / 180)`;
352
+ if (method === 'degrees')
353
+ return `(${argStrs[0]} * 180 / Math.PI)`;
354
+ return `Math.${method}(${argStrs.join(', ')})`;
355
+ }
356
+ // cq.Workplane("XY") — constructor call
357
+ if (receiver._type === 'Name' && receiver.id === 'cq' && method === 'Workplane') {
358
+ return `cq.Workplane(${argStrs.join(', ')})`;
359
+ }
360
+ // wp.export("file.step") — drop (CLI handles export)
361
+ if (method === 'export')
362
+ return 'null';
363
+ // wp.val() → cq.val(wp)
364
+ if (method === 'val')
365
+ return `cq.val(${transpileExpr(receiver, ctx)})`;
366
+ // wp.vals() → cq.vals(wp)
367
+ if (method === 'vals')
368
+ return `cq.vals(${transpileExpr(receiver, ctx)})`;
369
+ // wp.transformed(offset=(x,y,z)) → cq.transformed(wp, { offset: [x,y,z] })
370
+ if (method === 'transformed') {
371
+ const recv = transpileExpr(receiver, ctx);
372
+ return `cq.transformed(${recv}, { ${kwStr} })`;
373
+ }
374
+ // wp.rect(w, h, forConstruction=True) → cq.rect(wp, w, h, { forConstruction: true })
375
+ if (method === 'rect') {
376
+ const recv = transpileExpr(receiver, ctx);
377
+ const allArgs = kwStr ? [...argStrs, `{ ${kwStr} }`] : argStrs;
378
+ return `cq.rect(${recv}, ${allArgs.join(', ')})`;
379
+ }
380
+ // wp.circle(r) → cq.circle(wp, r)
381
+ if (method === 'circle') {
382
+ return `cq.circle(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
383
+ }
384
+ // wp.extrude(d) → cq.extrude(wp, d)
385
+ if (method === 'extrude') {
386
+ return `cq.extrude(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
387
+ }
388
+ // wp.faces(sel) → cq.faces(wp, sel)
389
+ if (method === 'faces') {
390
+ return `cq.faces(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
391
+ }
392
+ // wp.workplane(offset=?) → cq.workplane(wp) or cq.workplane(wp, { offset })
393
+ if (method === 'workplane') {
394
+ const recv = transpileExpr(receiver, ctx);
395
+ return kwStr ? `cq.workplane(${recv}, { ${kwStr} })` : `cq.workplane(${recv})`;
396
+ }
397
+ // wp.hole(d) → cq.hole(wp, d)
398
+ if (method === 'hole') {
399
+ return `cq.hole(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
400
+ }
401
+ // wp.cutBlind(d) → cq.cutBlind(wp, d)
402
+ if (method === 'cutBlind') {
403
+ return `cq.cutBlind(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
404
+ }
405
+ // wp.fillet(r) → cq.fillet(wp, r)
406
+ if (method === 'fillet') {
407
+ return `cq.fillet(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
408
+ }
409
+ // wp.edges(sel) → cq.edges(wp, sel)
410
+ if (method === 'edges') {
411
+ const recv = transpileExpr(receiver, ctx);
412
+ return argStrs.length > 0 ? `cq.edges(${recv}, ${argStrs.join(', ')})` : `cq.edges(${recv})`;
413
+ }
414
+ // wp.vertices() → cq.vertices(wp)
415
+ if (method === 'vertices') {
416
+ return `cq.vertices(${transpileExpr(receiver, ctx)})`;
417
+ }
418
+ // wp.pushPoints(pts) → cq.pushPoints(wp, pts)
419
+ if (method === 'pushPoints') {
420
+ return `cq.pushPoints(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
421
+ }
422
+ // wp.union(other) → cq.union(wp, other)
423
+ if (method === 'union') {
424
+ return `cq.union(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
425
+ }
426
+ // wp.cut(other) → cq.cut(wp, other)
427
+ if (method === 'cut') {
428
+ return `cq.cut(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
429
+ }
430
+ // wp.mirror(plane) → cq.mirror(wp, plane)
431
+ if (method === 'mirror') {
432
+ return `cq.mirror(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
433
+ }
434
+ // wp.rotate(start, end, angle) → cq.rotate(wp, axis, angle) (simplified)
435
+ if (method === 'rotate') {
436
+ return `cq.rotate(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
437
+ }
438
+ // wp.translate(v) → cq.translate(wp, v)
439
+ if (method === 'translate') {
440
+ return `cq.translate(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
441
+ }
442
+ // wp.polygon(n, d) → cq.polygon(wp, n, d)
443
+ if (method === 'polygon') {
444
+ return `cq.polygon(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
445
+ }
446
+ // wp.cboreHole(d, cboreD, cboreH) → cq.cboreHole(wp, d, cboreD, cboreH)
447
+ if (method === 'cboreHole') {
448
+ return `cq.cboreHole(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
449
+ }
450
+ // wp.cskHole(d, cskD, cskAng) → cq.cskHole(wp, d, cskD, cskAng)
451
+ if (method === 'cskHole') {
452
+ return `cq.cskHole(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
453
+ }
454
+ // wp.threadedHole(d) → cq.threadedHole(wp, d)
455
+ if (method === 'threadedHole') {
456
+ return `cq.threadedHole(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
457
+ }
458
+ // wp.shell(t) → cq.shell(wp, t)
459
+ if (method === 'shell') {
460
+ return `cq.shell(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
461
+ }
462
+ // wp.intersect(other) → cq.intersect(wp, other)
463
+ if (method === 'intersect') {
464
+ return `cq.intersect(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
465
+ }
466
+ // Generic fallback: cq.method(receiver, args...)
467
+ return `cq.${method}(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`;
468
+ }
469
+ function transpileKeywords(keywords, ctx) {
470
+ const parts = [];
471
+ for (const kw of keywords) {
472
+ const arg = kw.arg;
473
+ const value = transpileExpr(kw.value, ctx);
474
+ if (arg) {
475
+ // Python True/False → JS true/false
476
+ const v = value === 'True' ? 'true' : value === 'False' ? 'false' : value;
477
+ parts.push(`${arg}: ${v}`);
478
+ }
479
+ else {
480
+ parts.push(`...${value}`);
481
+ }
482
+ }
483
+ return parts.join(', ');
484
+ }
485
+ function transpileBinOp(node, ctx) {
486
+ const left = transpileExpr(node.left, ctx);
487
+ const right = transpileExpr(node.right, ctx);
488
+ const op = node.op;
489
+ const opMap = {
490
+ Add: '+', Sub: '-', Mult: '*', Div: '/', Mod: '%', Pow: '**',
491
+ LShift: '<<', RShift: '>>', BitOr: '|', BitXor: '^', BitAnd: '&',
492
+ FloorDiv: '/',
493
+ };
494
+ const opStr = opMap[op._type] ?? `/* ${op._type} */`;
495
+ return `(${left} ${opStr} ${right})`;
496
+ }
497
+ function transpileUnaryOp(node, ctx) {
498
+ const operand = transpileExpr(node.operand, ctx);
499
+ const op = node.op;
500
+ if (op._type === 'USub')
501
+ return `(-${operand})`;
502
+ if (op._type === 'UAdd')
503
+ return `(+${operand})`;
504
+ if (op._type === 'Not')
505
+ return `(!${operand})`;
506
+ return `(${operand})`;
507
+ }
508
+ function transpileList(node, ctx) {
509
+ const elts = node.elts ?? [];
510
+ return `[${elts.map((e) => transpileExpr(e, ctx)).join(', ')}]`;
511
+ }
512
+ function transpileSubscript(node, ctx) {
513
+ const valueNode = node.value;
514
+ // Handle .vertices()[start:end] and .edges()[start:end] — merge slice into call
515
+ if (valueNode._type === 'Call' && valueNode.func._type === 'Attribute') {
516
+ const method = valueNode.func.attr;
517
+ if (method === 'vertices' || method === 'edges') {
518
+ const baseCall = transpileCall(valueNode, ctx);
519
+ const slice = node.slice;
520
+ if (slice._type === 'Slice') {
521
+ const lower = slice.lower ? transpileExpr(slice.lower, ctx) : null;
522
+ const upper = slice.upper ? transpileExpr(slice.upper, ctx) : null;
523
+ const parts = [];
524
+ if (lower !== null)
525
+ parts.push(lower);
526
+ if (upper !== null)
527
+ parts.push(upper);
528
+ return baseCall.replace(/\)$/, `, { slice: [${parts.join(', ')}] })`);
529
+ }
530
+ // Single index: .vertices()[-1]
531
+ const idx = transpileExpr(slice, ctx);
532
+ return baseCall.replace(/\)$/, `, { index: ${idx} })`);
533
+ }
534
+ }
535
+ const value = transpileExpr(valueNode, ctx);
536
+ const slice = node.slice;
537
+ if (slice._type === 'Slice') {
538
+ const lower = slice.lower ? transpileExpr(slice.lower, ctx) : '';
539
+ const upper = slice.upper ? transpileExpr(slice.upper, ctx) : '';
540
+ return `${value}.slice(${lower}, ${upper})`;
541
+ }
542
+ // Index
543
+ return `${value}[${transpileExpr(slice, ctx)}]`;
544
+ }
545
+ function transpileListComp(node, ctx) {
546
+ const elt = transpileExpr(node.elt, ctx);
547
+ const generators = node.generators ?? [];
548
+ // Simple single-generator: [expr for x in list]
549
+ if (generators.length === 1) {
550
+ const gen = generators[0];
551
+ const target = transpileExpr(gen.target, ctx);
552
+ const iter = transpileExpr(gen.iter, ctx);
553
+ return `${iter}.map((${target}) => ${elt})`;
554
+ }
555
+ return `[${elt} /* listcomp */]`;
556
+ }
557
+ //# sourceMappingURL=transpile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transpile.js","sourceRoot":"","sources":["../src/transpile.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CadQuery Python → .fai.js transpiler.\n *\n * Handles the patterns found in real-world CadQuery projects:\n * - import cadquery as cq / import config / import math\n * - chained Workplane calls: wp.faces(\">Z\").workplane().hole(d)\n * - config constant references (inlined from config.py)\n * - function definitions (def pin_holes(wp): ...)\n * - list comprehensions, math.cos/radians, slicing\n * - if __name__ == \"__main__\" blocks (dropped)\n *\n * Not a general Python transpiler — targeted at CadQuery scripts.\n */\n\n// ── AST types (subset) ─────────────────────────────────────────────────────\n\ninterface AstNode {\n _type: string\n [key: string]: unknown\n}\n\ninterface TranspileCtx {\n /** Inlined config constants: name → JS expression string */\n configConsts: Map<string, string>\n /** Inlined config functions: name → JS function body lines */\n configFns: Map<string, { params: string[]; body: string[] }>\n /** Part name (from output filename, used for terminal variable) */\n partName: string\n /** Variables already declared (to avoid duplicate `let`) */\n declared: Set<string>\n /** When true, Name nodes matching config constants are inlined. */\n inlineConfigNames?: boolean\n /** When true, we're inside a function body — cq calls need await. */\n inFunction?: boolean\n}\n\n// ── Config extraction ──────────────────────────────────────────────────────\n\n/**\n * extractConfig\n * @param ast - AstNode\n * @returns {\n consts: Map<string, string>\n fns: Map<string, { params: string[]; body: string[] }>\n}\n */\nexport function extractConfig(ast: AstNode): {\n consts: Map<string, string>\n fns: Map<string, { params: string[]; body: string[] }>\n} {\n const consts = new Map<string, string>()\n const fns = new Map<string, { params: string[]; body: string[] }>()\n\n // First pass: extract all constants\n for (const stmt of (ast.body as AstNode[]) ?? []) {\n if (stmt._type === 'Assign') {\n const targets = stmt.targets as AstNode[]\n const value = stmt.value as AstNode\n if (targets.length === 1 && targets[0]._type === 'Name') {\n const name = (targets[0] as AstNode).id as string\n consts.set(name, transpileExpr(value, makeCtxWithConsts(consts)))\n }\n }\n }\n\n // Second pass: extract functions with constants inlined\n const fnCtx: TranspileCtx = { ...makeCtxWithConsts(consts), inFunction: true }\n for (const stmt of (ast.body as AstNode[]) ?? []) {\n if (stmt._type === 'FunctionDef') {\n const name = stmt.name as string\n const args = ((stmt.args as AstNode).args as AstNode[]) ?? []\n const params = args.map((a) => (a as AstNode).arg as string)\n const body = (stmt.body as AstNode[]) ?? []\n const bodyLines = body.map((s) => transpileStmt(s, fnCtx)).filter((l) => l !== null) as string[]\n fns.set(name, { params, body: bodyLines })\n }\n }\n return { consts, fns }\n}\n\nfunction makeCtxWithConsts(consts: Map<string, string>): TranspileCtx {\n return { configConsts: new Map(consts), configFns: new Map(), partName: 'result', declared: new Set() }\n}\n\n// ── Main entry ─────────────────────────────────────────────────────────────\n\n/**\n * transpile\n * @param ast - AstNode\n * @param config - ReturnType<typeof extractConfig>\n * @param partName - string\n * @returns string\n */\nexport function transpile(ast: AstNode, config: ReturnType<typeof extractConfig>, partName: string): string {\n const ctx: TranspileCtx = {\n configConsts: config.consts,\n configFns: config.fns,\n partName,\n declared: new Set(),\n }\n\n const lines: string[] = []\n lines.push(\"import * as cq from '@faicad/cq-compat'\")\n lines.push('')\n\n // Inline config constants\n if (config.consts.size > 0) {\n for (const [name, value] of config.consts) {\n lines.push(`const ${name} = ${value}`)\n }\n lines.push('')\n }\n\n // Inline config functions\n for (const [name, fn] of config.fns) {\n lines.push(`async function ${name}(${fn.params.join(', ')}) {`)\n for (const l of fn.body) lines.push(` ${l}`)\n lines.push('}')\n lines.push('')\n }\n\n // Transpile module body\n const bodyLines: string[] = []\n let lastAssignName: string | null = null\n for (const stmt of (ast.body as AstNode[]) ?? []) {\n const line = transpileStmt(stmt, ctx)\n if (line !== null) {\n bodyLines.push(line)\n // Track last variable assignment (for terminal extraction)\n if (stmt._type === 'Assign') {\n const targets = stmt.targets as AstNode[]\n if (targets.length === 1 && targets[0]._type === 'Name') {\n lastAssignName = (targets[0] as AstNode).id as string\n }\n }\n }\n }\n lines.push(...bodyLines)\n\n // Terminal extraction: if last assignment is a Workplane, extract its shape\n if (lastAssignName) {\n lines.push('')\n lines.push(`let result = cq.val(${lastAssignName})`)\n }\n\n return lines.join('\\n')\n}\n\n// ── Statement transpilation ────────────────────────────────────────────────\n\nfunction transpileStmt(stmt: AstNode, ctx: TranspileCtx): string | null {\n switch (stmt._type) {\n case 'Import':\n case 'ImportFrom':\n return null // imports handled by header\n case 'If':\n return transpileIf(stmt, ctx)\n case 'Assign':\n return transpileAssign(stmt, ctx)\n case 'Expr':\n return transpileExpr(stmt.value as AstNode, ctx)\n case 'FunctionDef':\n return transpileFunctionDef(stmt, ctx)\n case 'Return':\n return `return ${transpileExpr(stmt.value as AstNode, ctx)}`\n case 'Pass':\n return null\n default:\n return `// [unhandled stmt: ${stmt._type}]`\n }\n}\n\nfunction transpileIf(stmt: AstNode, ctx: TranspileCtx): string | null {\n const test = stmt.test as AstNode\n // Detect `if __name__ == \"__main__\":` or `if True or ...` → drop\n if (isMainCheck(test) || isTrueLiteral(test) || isShowObjectGuard(test)) {\n return null\n }\n // Generic if (rare in practice)\n const body = (stmt.body as AstNode[]).map((s) => transpileStmt(s, ctx)).filter((l) => l !== null) as string[]\n const testStr = transpileExpr(test, ctx)\n return [`if (${testStr}) {`, ...body.map((l) => ` ${l}`), '}'].join('\\n')\n}\n\n/** Detect `\"x\" not in globals()` guard (cadquery vis import pattern). */\nfunction isShowObjectGuard(test: AstNode): boolean {\n if (test._type !== 'Compare') return false\n const ops = test.ops as AstNode[]\n if (ops.length !== 1 || ops[0]._type !== 'NotIn') return false\n return true\n}\n\nfunction isMainCheck(test: AstNode): boolean {\n if (test._type !== 'Compare') return false\n const left = test.left as AstNode\n if (left._type !== 'Name' || left.id !== '__name__') return false\n const ops = test.ops as AstNode[]\n if (ops.length !== 1 || ops[0]._type !== 'Eq') return false\n const comps = test.comparators as AstNode[]\n if (comps.length !== 1 || comps[0]._type !== 'Constant') return false\n return (comps[0] as AstNode).value === '__main__'\n}\n\nfunction isTrueLiteral(test: AstNode): boolean {\n if (test._type === 'Constant' && test.value === true) return true\n // `True or ...` — always true\n if (test._type === 'BoolOp' && (test.op as AstNode)._type === 'Or') {\n const values = test.values as AstNode[]\n return values.some((v) => v._type === 'Constant' && v.value === true)\n }\n return false\n}\n\nfunction transpileAssign(stmt: AstNode, ctx: TranspileCtx): string | null {\n const targets = stmt.targets as AstNode[]\n const value = stmt.value as AstNode\n if (targets.length !== 1) return `// [unhandled multi-target assign]`\n const target = targets[0]\n if (target._type !== 'Name') return `// [unhandled assign target: ${target._type}]`\n const name = target.id as string\n const valueStr = transpileExpr(value, ctx)\n const isNew = !ctx.declared.has(name)\n if (isNew) ctx.declared.add(name)\n return isNew ? `let ${name} = ${valueStr}` : `${name} = ${valueStr}`\n}\n\nfunction transpileFunctionDef(stmt: AstNode, ctx: TranspileCtx): string | null {\n const name = stmt.name as string\n const args = ((stmt.args as AstNode).args as AstNode[]) ?? []\n const params = args.map((a) => (a as AstNode).arg as string)\n const fnCtx: TranspileCtx = { ...ctx, inFunction: true }\n const body = (stmt.body as AstNode[]).map((s) => transpileStmt(s, fnCtx)).filter((l) => l !== null) as string[]\n return [`async function ${name}(${params.join(', ')}) {`, ...body.map((l) => ` ${l}`), '}'].join('\\n')\n}\n\n// ── Expression transpilation ───────────────────────────────────────────────\n\nfunction transpileExpr(node: AstNode, ctx: TranspileCtx): string {\n switch (node._type) {\n case 'Constant':\n return transpileConstant(node)\n case 'Name':\n return transpileName(node, ctx)\n case 'Attribute':\n return transpileAttribute(node, ctx)\n case 'Call':\n return transpileCall(node, ctx)\n case 'BinOp':\n return transpileBinOp(node, ctx)\n case 'UnaryOp':\n return transpileUnaryOp(node, ctx)\n case 'List':\n return transpileList(node, ctx)\n case 'Subscript':\n return transpileSubscript(node, ctx)\n case 'ListComp':\n return transpileListComp(node, ctx)\n case 'Tuple':\n return `[${((node.elts as AstNode[]) ?? []).map((e) => transpileExpr(e, ctx)).join(', ')}]`\n case 'Compare':\n return transpileCompare(node, ctx)\n case 'BoolOp':\n return transpileBoolOp(node, ctx)\n default:\n return `/* [unhandled expr: ${node._type}] */`\n }\n}\n\nfunction transpileCompare(node: AstNode, ctx: TranspileCtx): string {\n const left = transpileExpr(node.left as AstNode, ctx)\n const ops = node.ops as AstNode[]\n const comparators = node.comparators as AstNode[]\n const opMap: Record<string, string> = {\n Eq: '===', NotEq: '!==', Lt: '<', LtE: '<=', Gt: '>', GtE: '>=',\n Is: '===', IsNot: '!==', In: 'in', NotIn: '!in',\n }\n const parts: string[] = [left]\n for (let i = 0; i < ops.length; i++) {\n const op = opMap[ops[i]._type] ?? `/* ${ops[i]._type} */`\n const comp = transpileExpr(comparators[i], ctx)\n parts.push(op, comp)\n }\n return `(${parts.join(' ')})`\n}\n\nfunction transpileBoolOp(node: AstNode, ctx: TranspileCtx): string {\n const op = node.op as AstNode\n const values = (node.values as AstNode[]).map((v) => transpileExpr(v, ctx))\n const joiner = op._type === 'And' ? '&&' : '||'\n return `(${values.join(` ${joiner} `)})`\n}\n\nfunction transpileConstant(node: AstNode): string {\n const v = node.value\n if (typeof v === 'string') return JSON.stringify(v)\n if (v === null) return 'null'\n return String(v)\n}\n\nfunction transpileName(node: AstNode, ctx: TranspileCtx): string {\n const id = node.id as string\n // math module → Math\n if (id === 'math') return 'Math'\n // config constant inlining\n if (ctx.configConsts.has(id)) return ctx.configConsts.get(id)!\n return id\n}\n\nfunction transpileAttribute(node: AstNode, ctx: TranspileCtx): string {\n const value = node.value as AstNode\n const attr = node.attr as string\n // math.cos → Math.cos, math.radians → (x => x * Math.PI / 180)\n if (value._type === 'Name' && value.id === 'math') {\n if (attr === 'radians') return '(x => x * Math.PI / 180)'\n if (attr === 'cos') return 'Math.cos'\n if (attr === 'sin') return 'Math.sin'\n if (attr === 'sqrt') return 'Math.sqrt'\n return `Math.${attr}`\n }\n // config.X → inlined constant\n if (value._type === 'Name' && value.id === 'config' && ctx.configConsts.has(attr)) {\n return ctx.configConsts.get(attr)!\n }\n // Generic attribute: a.b — but for chained calls this is handled by transpileCall\n return `${transpileExpr(value, ctx)}.${attr}`\n}\n\nfunction transpileCall(node: AstNode, ctx: TranspileCtx): string {\n const func = node.func as AstNode\n const args = (node.args as AstNode[]) ?? []\n const keywords = (node.keywords as AstNode[]) ?? []\n\n let result: string\n let needsAwait = false\n\n // Chained method call: wp.method(args)\n if (func._type === 'Attribute') {\n result = transpileMethodCall(func, args, keywords, ctx)\n // cq/workplane methods are async; Math.xxx is not.\n // For chained calls, the outermost receiver may be a Call, so check method name.\n const method = (func as AstNode).attr as string\n const mathMethods = new Set(['cos', 'sin', 'sqrt', 'radians', 'degrees', 'tan', 'atan', 'asin', 'acos', 'pow', 'abs', 'floor', 'ceil', 'round'])\n if (!mathMethods.has(method)) {\n needsAwait = true\n }\n } else if (func._type === 'Name') {\n // Direct function call: fn(args)\n const name = func.id as string\n const argStrs = args.map((a) => transpileExpr(a, ctx))\n result = `${name}(${argStrs.join(', ')})`\n if (ctx.configFns.has(name)) needsAwait = true\n } else {\n // Call result of another expression (e.g. (lambda)(...))\n result = `${transpileExpr(func, ctx)}(${args.map((a) => transpileExpr(a, ctx)).join(', ')})`\n }\n\n // Inside async function body, await cq/config calls (they return Promises)\n if (ctx.inFunction && needsAwait) {\n result = `await ${result}`\n }\n return result\n}\n\n/**\n * Convert chained method calls to function calls:\n * wp.faces(\">Z\").workplane().hole(d)\n * → cq.hole(cq.workplane(cq.faces(wp, \">Z\")), d)\n *\n * Also handles cq.Workplane(\"XY\") (constructor, not method).\n */\nfunction transpileMethodCall(\n func: AstNode,\n args: AstNode[],\n keywords: AstNode[],\n ctx: TranspileCtx,\n): string {\n const method = func.attr as string\n const receiver = func.value as AstNode\n const argStrs = args.map((a) => transpileExpr(a, ctx))\n const kwStr = transpileKeywords(keywords, ctx)\n\n // config.fn(args) → fn(args) (config functions are inlined as global functions)\n if (receiver._type === 'Name' && receiver.id === 'config' && ctx.configFns.has(method)) {\n return `${method}(${argStrs.join(', ')})`\n }\n\n // config.CONSTANT → inlined constant (handled in transpileAttribute, but here for call)\n if (receiver._type === 'Name' && receiver.id === 'config' && ctx.configConsts.has(method)) {\n return ctx.configConsts.get(method)!\n }\n\n // math.cos(x), math.sin(x), math.sqrt(x), math.radians(x) → JS Math\n if (receiver._type === 'Name' && receiver.id === 'math') {\n if (method === 'radians') return `(${argStrs[0]} * Math.PI / 180)`\n if (method === 'degrees') return `(${argStrs[0]} * 180 / Math.PI)`\n return `Math.${method}(${argStrs.join(', ')})`\n }\n\n // cq.Workplane(\"XY\") — constructor call\n if (receiver._type === 'Name' && receiver.id === 'cq' && method === 'Workplane') {\n return `cq.Workplane(${argStrs.join(', ')})`\n }\n\n // wp.export(\"file.step\") — drop (CLI handles export)\n if (method === 'export') return 'null'\n\n // wp.val() → cq.val(wp)\n if (method === 'val') return `cq.val(${transpileExpr(receiver, ctx)})`\n\n // wp.vals() → cq.vals(wp)\n if (method === 'vals') return `cq.vals(${transpileExpr(receiver, ctx)})`\n\n // wp.transformed(offset=(x,y,z)) → cq.transformed(wp, { offset: [x,y,z] })\n if (method === 'transformed') {\n const recv = transpileExpr(receiver, ctx)\n return `cq.transformed(${recv}, { ${kwStr} })`\n }\n\n // wp.rect(w, h, forConstruction=True) → cq.rect(wp, w, h, { forConstruction: true })\n if (method === 'rect') {\n const recv = transpileExpr(receiver, ctx)\n const allArgs = kwStr ? [...argStrs, `{ ${kwStr} }`] : argStrs\n return `cq.rect(${recv}, ${allArgs.join(', ')})`\n }\n\n // wp.circle(r) → cq.circle(wp, r)\n if (method === 'circle') {\n return `cq.circle(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.extrude(d) → cq.extrude(wp, d)\n if (method === 'extrude') {\n return `cq.extrude(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.faces(sel) → cq.faces(wp, sel)\n if (method === 'faces') {\n return `cq.faces(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.workplane(offset=?) → cq.workplane(wp) or cq.workplane(wp, { offset })\n if (method === 'workplane') {\n const recv = transpileExpr(receiver, ctx)\n return kwStr ? `cq.workplane(${recv}, { ${kwStr} })` : `cq.workplane(${recv})`\n }\n\n // wp.hole(d) → cq.hole(wp, d)\n if (method === 'hole') {\n return `cq.hole(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.cutBlind(d) → cq.cutBlind(wp, d)\n if (method === 'cutBlind') {\n return `cq.cutBlind(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.fillet(r) → cq.fillet(wp, r)\n if (method === 'fillet') {\n return `cq.fillet(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.edges(sel) → cq.edges(wp, sel)\n if (method === 'edges') {\n const recv = transpileExpr(receiver, ctx)\n return argStrs.length > 0 ? `cq.edges(${recv}, ${argStrs.join(', ')})` : `cq.edges(${recv})`\n }\n\n // wp.vertices() → cq.vertices(wp)\n if (method === 'vertices') {\n return `cq.vertices(${transpileExpr(receiver, ctx)})`\n }\n\n // wp.pushPoints(pts) → cq.pushPoints(wp, pts)\n if (method === 'pushPoints') {\n return `cq.pushPoints(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.union(other) → cq.union(wp, other)\n if (method === 'union') {\n return `cq.union(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.cut(other) → cq.cut(wp, other)\n if (method === 'cut') {\n return `cq.cut(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.mirror(plane) → cq.mirror(wp, plane)\n if (method === 'mirror') {\n return `cq.mirror(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.rotate(start, end, angle) → cq.rotate(wp, axis, angle) (simplified)\n if (method === 'rotate') {\n return `cq.rotate(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.translate(v) → cq.translate(wp, v)\n if (method === 'translate') {\n return `cq.translate(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.polygon(n, d) → cq.polygon(wp, n, d)\n if (method === 'polygon') {\n return `cq.polygon(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.cboreHole(d, cboreD, cboreH) → cq.cboreHole(wp, d, cboreD, cboreH)\n if (method === 'cboreHole') {\n return `cq.cboreHole(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.cskHole(d, cskD, cskAng) → cq.cskHole(wp, d, cskD, cskAng)\n if (method === 'cskHole') {\n return `cq.cskHole(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.threadedHole(d) → cq.threadedHole(wp, d)\n if (method === 'threadedHole') {\n return `cq.threadedHole(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.shell(t) → cq.shell(wp, t)\n if (method === 'shell') {\n return `cq.shell(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // wp.intersect(other) → cq.intersect(wp, other)\n if (method === 'intersect') {\n return `cq.intersect(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n }\n\n // Generic fallback: cq.method(receiver, args...)\n return `cq.${method}(${transpileExpr(receiver, ctx)}, ${argStrs.join(', ')})`\n}\n\nfunction transpileKeywords(keywords: AstNode[], ctx: TranspileCtx): string {\n const parts: string[] = []\n for (const kw of keywords) {\n const arg = kw.arg as string | null\n const value = transpileExpr(kw.value as AstNode, ctx)\n if (arg) {\n // Python True/False → JS true/false\n const v = value === 'True' ? 'true' : value === 'False' ? 'false' : value\n parts.push(`${arg}: ${v}`)\n } else {\n parts.push(`...${value}`)\n }\n }\n return parts.join(', ')\n}\n\nfunction transpileBinOp(node: AstNode, ctx: TranspileCtx): string {\n const left = transpileExpr(node.left as AstNode, ctx)\n const right = transpileExpr(node.right as AstNode, ctx)\n const op = node.op as AstNode\n const opMap: Record<string, string> = {\n Add: '+', Sub: '-', Mult: '*', Div: '/', Mod: '%', Pow: '**',\n LShift: '<<', RShift: '>>', BitOr: '|', BitXor: '^', BitAnd: '&',\n FloorDiv: '/',\n }\n const opStr = opMap[op._type] ?? `/* ${op._type} */`\n return `(${left} ${opStr} ${right})`\n}\n\nfunction transpileUnaryOp(node: AstNode, ctx: TranspileCtx): string {\n const operand = transpileExpr(node.operand as AstNode, ctx)\n const op = node.op as AstNode\n if (op._type === 'USub') return `(-${operand})`\n if (op._type === 'UAdd') return `(+${operand})`\n if (op._type === 'Not') return `(!${operand})`\n return `(${operand})`\n}\n\nfunction transpileList(node: AstNode, ctx: TranspileCtx): string {\n const elts = (node.elts as AstNode[]) ?? []\n return `[${elts.map((e) => transpileExpr(e, ctx)).join(', ')}]`\n}\n\nfunction transpileSubscript(node: AstNode, ctx: TranspileCtx): string {\n const valueNode = node.value as AstNode\n // Handle .vertices()[start:end] and .edges()[start:end] — merge slice into call\n if (valueNode._type === 'Call' && (valueNode.func as AstNode)._type === 'Attribute') {\n const method = ((valueNode.func as AstNode).attr as string)\n if (method === 'vertices' || method === 'edges') {\n const baseCall = transpileCall(valueNode, ctx)\n const slice = node.slice as AstNode\n if (slice._type === 'Slice') {\n const lower = slice.lower ? transpileExpr(slice.lower as AstNode, ctx) : null\n const upper = slice.upper ? transpileExpr(slice.upper as AstNode, ctx) : null\n const parts: string[] = []\n if (lower !== null) parts.push(lower)\n if (upper !== null) parts.push(upper)\n return baseCall.replace(/\\)$/, `, { slice: [${parts.join(', ')}] })`)\n }\n // Single index: .vertices()[-1]\n const idx = transpileExpr(slice, ctx)\n return baseCall.replace(/\\)$/, `, { index: ${idx} })`)\n }\n }\n const value = transpileExpr(valueNode, ctx)\n const slice = node.slice as AstNode\n if (slice._type === 'Slice') {\n const lower = slice.lower ? transpileExpr(slice.lower as AstNode, ctx) : ''\n const upper = slice.upper ? transpileExpr(slice.upper as AstNode, ctx) : ''\n return `${value}.slice(${lower}, ${upper})`\n }\n // Index\n return `${value}[${transpileExpr(slice, ctx)}]`\n}\n\nfunction transpileListComp(node: AstNode, ctx: TranspileCtx): string {\n const elt = transpileExpr(node.elt as AstNode, ctx)\n const generators = (node.generators as AstNode[]) ?? []\n // Simple single-generator: [expr for x in list]\n if (generators.length === 1) {\n const gen = generators[0]\n const target = transpileExpr(gen.target as AstNode, ctx)\n const iter = transpileExpr(gen.iter as AstNode, ctx)\n return `${iter}.map((${target}) => ${elt})`\n }\n return `[${elt} /* listcomp */]`\n}\n"]}