gofront 0.0.4 → 0.0.5
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/README.md +104 -126
- package/package.json +2 -3
- package/src/codegen/expressions.js +448 -256
- package/src/codegen/statements.js +193 -6
- package/src/codegen.js +89 -3
- package/src/dts-parser.js +1 -1
- package/src/index.js +13 -12
- package/src/lexer.js +24 -1
- package/src/minifier.js +698 -0
- package/src/parser/expressions.js +115 -15
- package/src/parser/statements.js +4 -4
- package/src/parser/types.js +108 -3
- package/src/parser.js +57 -4
- package/src/typechecker/expressions.js +279 -10
- package/src/typechecker/statements.js +64 -3
- package/src/typechecker/types.js +96 -10
- package/src/typechecker.js +482 -16
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// CodeGen expression methods and helpers — installed as a mixin on CodeGen.prototype.
|
|
2
2
|
|
|
3
|
+
import { ERROR, isComplex } from "../typechecker/types.js";
|
|
4
|
+
|
|
5
|
+
const globalError = ERROR;
|
|
6
|
+
|
|
3
7
|
const INT_TYPE_NAMES = new Set([
|
|
4
8
|
"int",
|
|
5
9
|
"uint",
|
|
@@ -23,17 +27,68 @@ export const expressionGenMethods = {
|
|
|
23
27
|
if (expr.litKind === "STRING") return JSON.stringify(expr.value);
|
|
24
28
|
return expr.value; // int, float, bool, nil(null)
|
|
25
29
|
|
|
30
|
+
case "ImagLit":
|
|
31
|
+
return `{ re: 0, im: ${expr.value} }`;
|
|
32
|
+
|
|
26
33
|
case "Ident":
|
|
34
|
+
if (this._boxedVars.has(expr.name) && !expr._isAddressOf)
|
|
35
|
+
return `${expr.name}.value`;
|
|
27
36
|
return expr.name;
|
|
28
37
|
|
|
29
38
|
case "UnaryExpr": {
|
|
30
39
|
const op = expr.op === "^" ? "~" : expr.op; // bitwise NOT
|
|
31
|
-
//
|
|
32
|
-
if (op === "
|
|
40
|
+
// Address-of: &x
|
|
41
|
+
if (op === "&") {
|
|
42
|
+
if (expr.operand.kind === "Ident") {
|
|
43
|
+
// Mark so Ident codegen does NOT append .value
|
|
44
|
+
expr.operand._isAddressOf = true;
|
|
45
|
+
// For boxed vars, &x returns the box itself
|
|
46
|
+
if (this._boxedVars.has(expr.operand.name)) {
|
|
47
|
+
return this.genExpr(expr.operand);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// For non-boxed vars (structs, etc.), wrap in { value: x }
|
|
51
|
+
return `{ value: ${this.genExpr(expr.operand)} }`;
|
|
52
|
+
}
|
|
53
|
+
// Dereference: *p → p.value
|
|
54
|
+
if (op === "*") {
|
|
55
|
+
return `${this.genExpr(expr.operand)}.value`;
|
|
56
|
+
}
|
|
57
|
+
// Unary minus/plus on complex
|
|
58
|
+
if ((op === "-" || op === "+") && isComplex(expr.operand._type)) {
|
|
59
|
+
const inner = this.genExpr(expr.operand);
|
|
60
|
+
if (op === "-") return `{ re: -${inner}.re, im: -${inner}.im }`;
|
|
61
|
+
return inner;
|
|
62
|
+
}
|
|
33
63
|
return `${op}${this.genExpr(expr.operand)}`;
|
|
34
64
|
}
|
|
35
65
|
|
|
36
66
|
case "BinaryExpr": {
|
|
67
|
+
// Complex binary operations
|
|
68
|
+
if (
|
|
69
|
+
isComplex(expr._type) ||
|
|
70
|
+
isComplex(expr.left._type) ||
|
|
71
|
+
isComplex(expr.right._type)
|
|
72
|
+
) {
|
|
73
|
+
const l = this._genComplexOperand(expr.left);
|
|
74
|
+
const r = this._genComplexOperand(expr.right);
|
|
75
|
+
switch (expr.op) {
|
|
76
|
+
case "+":
|
|
77
|
+
return `{ re: ${l}.re + ${r}.re, im: ${l}.im + ${r}.im }`;
|
|
78
|
+
case "-":
|
|
79
|
+
return `{ re: ${l}.re - ${r}.re, im: ${l}.im - ${r}.im }`;
|
|
80
|
+
case "*":
|
|
81
|
+
this._usesCmul = true;
|
|
82
|
+
return `__cmul(${l}, ${r})`;
|
|
83
|
+
case "/":
|
|
84
|
+
this._usesCdiv = true;
|
|
85
|
+
return `__cdiv(${l}, ${r})`;
|
|
86
|
+
case "==":
|
|
87
|
+
return `(${l}.re === ${r}.re && ${l}.im === ${r}.im)`;
|
|
88
|
+
case "!=":
|
|
89
|
+
return `(${l}.re !== ${r}.re || ${l}.im !== ${r}.im)`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
37
92
|
const l = this.genExpr(expr.left);
|
|
38
93
|
const r = this.genExpr(expr.right);
|
|
39
94
|
// Integer division: only when both sides are int
|
|
@@ -66,6 +121,9 @@ export const expressionGenMethods = {
|
|
|
66
121
|
case "CallExpr":
|
|
67
122
|
return this.genCall(expr);
|
|
68
123
|
|
|
124
|
+
case "InstantiationExpr":
|
|
125
|
+
return this.genExpr(expr.expr); // type erasure
|
|
126
|
+
|
|
69
127
|
case "SelectorExpr": {
|
|
70
128
|
// Method expression: TypeName.MethodName → (recv, ...args) => recv.method(...args)
|
|
71
129
|
if (expr._isMethodExpr) {
|
|
@@ -112,7 +170,7 @@ export const expressionGenMethods = {
|
|
|
112
170
|
const base = this.genExpr(expr.expr);
|
|
113
171
|
// Bundled GoFront packages are inlined — drop the qualifier.
|
|
114
172
|
if (this.bundledPackages.has(base)) return expr.field;
|
|
115
|
-
// Pointer types
|
|
173
|
+
// Pointer types: route through .value
|
|
116
174
|
if (expr.expr._type?.kind === "pointer" && expr.field !== "value") {
|
|
117
175
|
const sel = `${base}.value.${expr.field}`;
|
|
118
176
|
if (expr._isMethodValue && !expr._callee)
|
|
@@ -164,10 +222,14 @@ export const expressionGenMethods = {
|
|
|
164
222
|
const params = expr.params.map((p) => p.name).join(", ");
|
|
165
223
|
const asyncPrefix = expr.async ? "async " : "";
|
|
166
224
|
const saved = this.out;
|
|
225
|
+
const prevBoxed = this._boxedVars;
|
|
226
|
+
this._boxedVars = new Set(prevBoxed); // inherit parent's boxed vars (closures)
|
|
227
|
+
this._scanAddressTaken(expr.body);
|
|
167
228
|
this.out = [];
|
|
168
229
|
this.indented(() => this._genBody(expr.body));
|
|
169
230
|
const body = this.out.join("\n");
|
|
170
231
|
this.out = saved;
|
|
232
|
+
this._boxedVars = prevBoxed;
|
|
171
233
|
return `${asyncPrefix}function(${params}) {\n${body}\n${" ".repeat(this.indent)}}`;
|
|
172
234
|
}
|
|
173
235
|
|
|
@@ -175,6 +237,26 @@ export const expressionGenMethods = {
|
|
|
175
237
|
const inner = this.genExpr(expr.expr);
|
|
176
238
|
const t = expr.targetType;
|
|
177
239
|
|
|
240
|
+
// Complex type conversions
|
|
241
|
+
if (t?.name === "complex128" || t?.name === "complex64") {
|
|
242
|
+
const srcType = expr.expr._type;
|
|
243
|
+
if (isComplex(srcType)) return inner; // complex→complex identity
|
|
244
|
+
return `{ re: ${inner}, im: 0 }`; // numeric→complex
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Array type conversion: [N]T(slice) → slice(0, N)
|
|
248
|
+
if (t?.kind === "ArrayType") {
|
|
249
|
+
const srcType = expr.expr._type;
|
|
250
|
+
const srcResolved =
|
|
251
|
+
srcType?.kind === "named" ? srcType.underlying : srcType;
|
|
252
|
+
if (srcResolved?.kind === "slice") {
|
|
253
|
+
const size =
|
|
254
|
+
t.size?.value !== undefined ? Number(t.size.value) : t.size;
|
|
255
|
+
return `${inner}.slice(0, ${size})`;
|
|
256
|
+
}
|
|
257
|
+
return inner;
|
|
258
|
+
}
|
|
259
|
+
|
|
178
260
|
// Slice type conversions
|
|
179
261
|
if (t?.kind === "SliceType") {
|
|
180
262
|
const elem = t.elem?.name;
|
|
@@ -197,6 +279,11 @@ export const expressionGenMethods = {
|
|
|
197
279
|
}
|
|
198
280
|
|
|
199
281
|
const target = t?.name;
|
|
282
|
+
// error("msg") → __error("msg")
|
|
283
|
+
if (target === "error") {
|
|
284
|
+
this._usesError = true;
|
|
285
|
+
return `__error(${inner})`;
|
|
286
|
+
}
|
|
200
287
|
switch (target) {
|
|
201
288
|
case "string": {
|
|
202
289
|
// Go string(65) → "A" (Unicode code point), not "65"
|
|
@@ -204,6 +291,14 @@ export const expressionGenMethods = {
|
|
|
204
291
|
if (srcType && this.isIntType(srcType)) {
|
|
205
292
|
return `String.fromCodePoint(${inner})`;
|
|
206
293
|
}
|
|
294
|
+
// string([]byte) → decode byte array to string
|
|
295
|
+
if (
|
|
296
|
+
srcType &&
|
|
297
|
+
srcType.kind === "slice" &&
|
|
298
|
+
srcType.elem?.name === "int"
|
|
299
|
+
) {
|
|
300
|
+
return `${inner}.map(c => String.fromCharCode(c)).join("")`;
|
|
301
|
+
}
|
|
207
302
|
return `String(${inner})`;
|
|
208
303
|
}
|
|
209
304
|
case "int":
|
|
@@ -244,12 +339,16 @@ export const expressionGenMethods = {
|
|
|
244
339
|
},
|
|
245
340
|
|
|
246
341
|
genCall(expr) {
|
|
342
|
+
// Unwrap InstantiationExpr for function calls: Foo[int](42) → Foo(42)
|
|
343
|
+
const funcExpr =
|
|
344
|
+
expr.func.kind === "InstantiationExpr" ? expr.func.expr : expr.func;
|
|
247
345
|
// Handle built-ins that need special JS translation
|
|
248
|
-
if (
|
|
249
|
-
switch (
|
|
346
|
+
if (funcExpr.kind === "Ident") {
|
|
347
|
+
switch (funcExpr.name) {
|
|
250
348
|
case "append":
|
|
251
349
|
return this.genAppend(expr);
|
|
252
350
|
case "len": {
|
|
351
|
+
if (expr._constLen != null) return String(expr._constLen);
|
|
253
352
|
const arg = expr.args[0];
|
|
254
353
|
const t = arg?._type;
|
|
255
354
|
const js = this.genExpr(arg);
|
|
@@ -285,9 +384,9 @@ export const expressionGenMethods = {
|
|
|
285
384
|
case "recover":
|
|
286
385
|
return `(typeof __panic !== "undefined" && __panic !== null ? (() => { const __r = __panic.message ?? String(__panic); __panic = null; return __r; })() : null)`;
|
|
287
386
|
case "error": {
|
|
288
|
-
|
|
387
|
+
this._usesError = true;
|
|
289
388
|
const arg = this.genExpr(expr.args[0]);
|
|
290
|
-
return arg
|
|
389
|
+
return `__error(${arg})`;
|
|
291
390
|
}
|
|
292
391
|
case "min": {
|
|
293
392
|
const args = expr.args.map((a) => this.genExpr(a)).join(", ");
|
|
@@ -309,264 +408,39 @@ export const expressionGenMethods = {
|
|
|
309
408
|
}
|
|
310
409
|
return `(${js}).length = 0`;
|
|
311
410
|
}
|
|
411
|
+
case "complex": {
|
|
412
|
+
const re = this.genExpr(expr.args[0]);
|
|
413
|
+
const im = this.genExpr(expr.args[1]);
|
|
414
|
+
return `{ re: ${re}, im: ${im} }`;
|
|
415
|
+
}
|
|
416
|
+
case "real":
|
|
417
|
+
return `(${this.genExpr(expr.args[0])}).re`;
|
|
418
|
+
case "imag":
|
|
419
|
+
return `(${this.genExpr(expr.args[0])}).im`;
|
|
312
420
|
}
|
|
313
421
|
}
|
|
314
422
|
|
|
315
|
-
// error.Error() →
|
|
423
|
+
// error.Error() → real method call
|
|
316
424
|
if (
|
|
317
425
|
expr.func.kind === "SelectorExpr" &&
|
|
318
426
|
expr.func.field === "Error" &&
|
|
319
|
-
expr.func.expr._type
|
|
427
|
+
expr.func.expr._type &&
|
|
428
|
+
(expr.func.expr._type === globalError ||
|
|
429
|
+
expr.func.expr._type?.name === "error" ||
|
|
430
|
+
(expr.func.expr._type?.kind === "named" &&
|
|
431
|
+
expr.func.expr._type?.underlying?.kind === "interface"))
|
|
320
432
|
) {
|
|
321
|
-
return this.genExpr(expr.func.expr)
|
|
433
|
+
return `${this.genExpr(expr.func.expr)}.Error()`;
|
|
322
434
|
}
|
|
323
435
|
|
|
324
436
|
// fmt.Sprintf / fmt.Printf / fmt.Println / fmt.Print / fmt.Errorf
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
expr.func.expr.name
|
|
329
|
-
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
case "Sprintf":
|
|
333
|
-
case "Errorf":
|
|
334
|
-
this._usesSprintf = true;
|
|
335
|
-
return `__sprintf(${fmtArgs})`;
|
|
336
|
-
case "Printf":
|
|
337
|
-
case "Print":
|
|
338
|
-
this._usesSprintf = true;
|
|
339
|
-
return `process?.stdout?.write(__sprintf(${fmtArgs}))`;
|
|
340
|
-
case "Println":
|
|
341
|
-
this._usesSprintf = true;
|
|
342
|
-
return `console.log(__sprintf(${fmtArgs}))`;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// strings.* — direct JS string method mappings
|
|
347
|
-
if (
|
|
348
|
-
expr.func.kind === "SelectorExpr" &&
|
|
349
|
-
expr.func.expr.kind === "Ident" &&
|
|
350
|
-
expr.func.expr.name === "strings"
|
|
351
|
-
) {
|
|
352
|
-
const a = expr.args.map((e) => this.genExpr(e));
|
|
353
|
-
switch (expr.func.field) {
|
|
354
|
-
case "Contains":
|
|
355
|
-
return `${a[0]}.includes(${a[1]})`;
|
|
356
|
-
case "HasPrefix":
|
|
357
|
-
return `${a[0]}.startsWith(${a[1]})`;
|
|
358
|
-
case "HasSuffix":
|
|
359
|
-
return `${a[0]}.endsWith(${a[1]})`;
|
|
360
|
-
case "Index":
|
|
361
|
-
return `${a[0]}.indexOf(${a[1]})`;
|
|
362
|
-
case "LastIndex":
|
|
363
|
-
return `${a[0]}.lastIndexOf(${a[1]})`;
|
|
364
|
-
case "Count":
|
|
365
|
-
return `${a[0]}.split(${a[1]}).length - 1`;
|
|
366
|
-
case "Repeat":
|
|
367
|
-
return `${a[0]}.repeat(${a[1]})`;
|
|
368
|
-
case "Replace":
|
|
369
|
-
return `${a[0]}.replace(${a[1]}, ${a[2]})`;
|
|
370
|
-
case "ReplaceAll":
|
|
371
|
-
return `${a[0]}.replaceAll(${a[1]}, ${a[2]})`;
|
|
372
|
-
case "ToUpper":
|
|
373
|
-
return `${a[0]}.toUpperCase()`;
|
|
374
|
-
case "ToLower":
|
|
375
|
-
return `${a[0]}.toLowerCase()`;
|
|
376
|
-
case "TrimSpace":
|
|
377
|
-
return `${a[0]}.trim()`;
|
|
378
|
-
case "Trim":
|
|
379
|
-
return `${a[0]}.replace(new RegExp(\`^[\${${a[1]}}]+|[\${${a[1]}}]+$\`, "g"), "")`;
|
|
380
|
-
case "TrimPrefix":
|
|
381
|
-
return `(${a[0]}.startsWith(${a[1]}) ? ${a[0]}.slice(${a[1]}.length) : ${a[0]})`;
|
|
382
|
-
case "TrimSuffix":
|
|
383
|
-
return `(${a[0]}.endsWith(${a[1]}) ? ${a[0]}.slice(0, -${a[1]}.length) : ${a[0]})`;
|
|
384
|
-
case "TrimLeft":
|
|
385
|
-
return `${a[0]}.replace(new RegExp(\`^[\${${a[1]}}]+\`), "")`;
|
|
386
|
-
case "TrimRight":
|
|
387
|
-
return `${a[0]}.replace(new RegExp(\`[\${${a[1]}}]+$\`), "")`;
|
|
388
|
-
case "Split":
|
|
389
|
-
return `${a[0]}.split(${a[1]})`;
|
|
390
|
-
case "Join":
|
|
391
|
-
return `${a[0]}.join(${a[1]})`;
|
|
392
|
-
case "EqualFold":
|
|
393
|
-
return `${a[0]}.toLowerCase() === ${a[1]}.toLowerCase()`;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// strconv.* — number/string conversion
|
|
398
|
-
if (
|
|
399
|
-
expr.func.kind === "SelectorExpr" &&
|
|
400
|
-
expr.func.expr.kind === "Ident" &&
|
|
401
|
-
expr.func.expr.name === "strconv"
|
|
402
|
-
) {
|
|
403
|
-
const a = expr.args.map((e) => this.genExpr(e));
|
|
404
|
-
switch (expr.func.field) {
|
|
405
|
-
case "Itoa":
|
|
406
|
-
return `String(${a[0]})`;
|
|
407
|
-
case "Atoi":
|
|
408
|
-
return `(Number.isNaN(Number(${a[0]})) ? [0, "invalid syntax"] : [Number(${a[0]}) | 0, null])`;
|
|
409
|
-
case "FormatBool":
|
|
410
|
-
return `String(${a[0]})`;
|
|
411
|
-
case "FormatInt":
|
|
412
|
-
return `(${a[0]}).toString(${a[1]})`;
|
|
413
|
-
case "FormatFloat":
|
|
414
|
-
return `String(${a[0]})`;
|
|
415
|
-
case "ParseFloat":
|
|
416
|
-
return `(Number.isNaN(Number(${a[0]})) ? [0, "invalid syntax"] : [Number(${a[0]}), null])`;
|
|
417
|
-
case "ParseInt":
|
|
418
|
-
return `(Number.isNaN(parseInt(${a[0]}, ${a[1]} || 10)) ? [0, "invalid syntax"] : [parseInt(${a[0]}, ${a[1]} || 10), null])`;
|
|
419
|
-
case "ParseBool":
|
|
420
|
-
return `(${a[0]} === "true" || ${a[0]} === "1" ? [true, null] : ${a[0]} === "false" || ${a[0]} === "0" ? [false, null] : [false, "invalid syntax"])`;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
// sort.* — in-place sorting
|
|
425
|
-
if (
|
|
426
|
-
expr.func.kind === "SelectorExpr" &&
|
|
427
|
-
expr.func.expr.kind === "Ident" &&
|
|
428
|
-
expr.func.expr.name === "sort"
|
|
429
|
-
) {
|
|
430
|
-
const a = expr.args.map((e) => this.genExpr(e));
|
|
431
|
-
switch (expr.func.field) {
|
|
432
|
-
case "Ints":
|
|
433
|
-
case "Float64s":
|
|
434
|
-
return `${a[0]}.sort((a, b) => a - b)`;
|
|
435
|
-
case "Strings":
|
|
436
|
-
return `${a[0]}.sort()`;
|
|
437
|
-
case "Slice":
|
|
438
|
-
return `${a[0]}.sort((a, b) => ${a[1]}(a, b) ? -1 : ${a[1]}(b, a) ? 1 : 0)`;
|
|
439
|
-
case "SliceStable":
|
|
440
|
-
return `${a[0]}.sort((a, b) => ${a[1]}(a, b) ? -1 : ${a[1]}(b, a) ? 1 : 0)`;
|
|
441
|
-
case "SliceIsSorted":
|
|
442
|
-
return `${a[0]}.every((v, i, a) => i === 0 || ${a[1]}(a[i - 1], v))`;
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// math.* — math functions
|
|
447
|
-
if (
|
|
448
|
-
expr.func.kind === "SelectorExpr" &&
|
|
449
|
-
expr.func.expr.kind === "Ident" &&
|
|
450
|
-
expr.func.expr.name === "math"
|
|
451
|
-
) {
|
|
452
|
-
const a = expr.args.map((e) => this.genExpr(e));
|
|
453
|
-
switch (expr.func.field) {
|
|
454
|
-
case "Abs":
|
|
455
|
-
return `Math.abs(${a[0]})`;
|
|
456
|
-
case "Floor":
|
|
457
|
-
return `Math.floor(${a[0]})`;
|
|
458
|
-
case "Ceil":
|
|
459
|
-
return `Math.ceil(${a[0]})`;
|
|
460
|
-
case "Round":
|
|
461
|
-
return `Math.round(${a[0]})`;
|
|
462
|
-
case "Sqrt":
|
|
463
|
-
return `Math.sqrt(${a[0]})`;
|
|
464
|
-
case "Cbrt":
|
|
465
|
-
return `Math.cbrt(${a[0]})`;
|
|
466
|
-
case "Pow":
|
|
467
|
-
return `Math.pow(${a[0]}, ${a[1]})`;
|
|
468
|
-
case "Log":
|
|
469
|
-
return `Math.log(${a[0]})`;
|
|
470
|
-
case "Log2":
|
|
471
|
-
return `Math.log2(${a[0]})`;
|
|
472
|
-
case "Log10":
|
|
473
|
-
return `Math.log10(${a[0]})`;
|
|
474
|
-
case "Sin":
|
|
475
|
-
return `Math.sin(${a[0]})`;
|
|
476
|
-
case "Cos":
|
|
477
|
-
return `Math.cos(${a[0]})`;
|
|
478
|
-
case "Tan":
|
|
479
|
-
return `Math.tan(${a[0]})`;
|
|
480
|
-
case "Min":
|
|
481
|
-
return `Math.min(${a[0]}, ${a[1]})`;
|
|
482
|
-
case "Max":
|
|
483
|
-
return `Math.max(${a[0]}, ${a[1]})`;
|
|
484
|
-
case "Mod":
|
|
485
|
-
return `${a[0]} % ${a[1]}`;
|
|
486
|
-
case "Inf":
|
|
487
|
-
return `(${a[0]} >= 0 ? Infinity : -Infinity)`;
|
|
488
|
-
case "IsNaN":
|
|
489
|
-
return `Number.isNaN(${a[0]})`;
|
|
490
|
-
case "IsInf":
|
|
491
|
-
return `(${a[1]} > 0 ? ${a[0]} === Infinity : ${a[1]} < 0 ? ${a[0]} === -Infinity : !Number.isFinite(${a[0]}))`;
|
|
492
|
-
case "NaN":
|
|
493
|
-
return "NaN";
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// unicode.* — rune/character classification
|
|
498
|
-
if (
|
|
499
|
-
expr.func.kind === "SelectorExpr" &&
|
|
500
|
-
expr.func.expr.kind === "Ident" &&
|
|
501
|
-
expr.func.expr.name === "unicode"
|
|
502
|
-
) {
|
|
503
|
-
const a = expr.args.map((e) => this.genExpr(e));
|
|
504
|
-
switch (expr.func.field) {
|
|
505
|
-
case "IsLetter":
|
|
506
|
-
return `/\\p{L}/u.test(String.fromCodePoint(${a[0]}))`;
|
|
507
|
-
case "IsDigit":
|
|
508
|
-
return `/\\p{Nd}/u.test(String.fromCodePoint(${a[0]}))`;
|
|
509
|
-
case "IsSpace":
|
|
510
|
-
return `/\\s/.test(String.fromCodePoint(${a[0]}))`;
|
|
511
|
-
case "IsUpper":
|
|
512
|
-
return `((__c) => __c === __c.toUpperCase() && /\\p{L}/u.test(__c))(String.fromCodePoint(${a[0]}))`;
|
|
513
|
-
case "IsLower":
|
|
514
|
-
return `((__c) => __c === __c.toLowerCase() && /\\p{L}/u.test(__c))(String.fromCodePoint(${a[0]}))`;
|
|
515
|
-
case "IsPunct":
|
|
516
|
-
return `/\\p{P}/u.test(String.fromCodePoint(${a[0]}))`;
|
|
517
|
-
case "IsControl":
|
|
518
|
-
return `/\\p{Cc}/u.test(String.fromCodePoint(${a[0]}))`;
|
|
519
|
-
case "IsPrint":
|
|
520
|
-
return `!/\\p{Cc}/u.test(String.fromCodePoint(${a[0]}))`;
|
|
521
|
-
case "IsGraphic":
|
|
522
|
-
return `!/\\p{Cc}/u.test(String.fromCodePoint(${a[0]}))`;
|
|
523
|
-
case "ToUpper":
|
|
524
|
-
return `String.fromCodePoint(${a[0]}).toUpperCase().codePointAt(0)`;
|
|
525
|
-
case "ToLower":
|
|
526
|
-
return `String.fromCodePoint(${a[0]}).toLowerCase().codePointAt(0)`;
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// os.* — process/environment access
|
|
531
|
-
if (
|
|
532
|
-
expr.func.kind === "SelectorExpr" &&
|
|
533
|
-
expr.func.expr.kind === "Ident" &&
|
|
534
|
-
expr.func.expr.name === "os"
|
|
535
|
-
) {
|
|
536
|
-
const a = expr.args.map((e) => this.genExpr(e));
|
|
537
|
-
switch (expr.func.field) {
|
|
538
|
-
case "Exit":
|
|
539
|
-
return `process.exit(${a[0]})`;
|
|
540
|
-
case "Getenv":
|
|
541
|
-
return `(process.env[${a[0]}] ?? "")`;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
// errors.New — identity (errors are plain strings)
|
|
546
|
-
if (
|
|
547
|
-
expr.func.kind === "SelectorExpr" &&
|
|
548
|
-
expr.func.expr.kind === "Ident" &&
|
|
549
|
-
expr.func.expr.name === "errors"
|
|
550
|
-
) {
|
|
551
|
-
const a = expr.args.map((e) => this.genExpr(e));
|
|
552
|
-
if (expr.func.field === "New") return a[0];
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
// time.* — partial JS-friendly time support
|
|
556
|
-
if (
|
|
557
|
-
expr.func.kind === "SelectorExpr" &&
|
|
558
|
-
expr.func.expr.kind === "Ident" &&
|
|
559
|
-
expr.func.expr.name === "time"
|
|
560
|
-
) {
|
|
561
|
-
const a = expr.args.map((e) => this.genExpr(e));
|
|
562
|
-
switch (expr.func.field) {
|
|
563
|
-
case "Now":
|
|
564
|
-
return "Date.now()";
|
|
565
|
-
case "Since":
|
|
566
|
-
return `(Date.now() - ${a[0]})`;
|
|
567
|
-
case "Sleep":
|
|
568
|
-
return `await new Promise(r => setTimeout(r, ${a[0]} / 1000000))`;
|
|
569
|
-
}
|
|
437
|
+
// Standard library namespace dispatch — all follow the pattern:
|
|
438
|
+
// pkg.Func(args) → inline JS
|
|
439
|
+
if (expr.func.kind === "SelectorExpr" && expr.func.expr.kind === "Ident") {
|
|
440
|
+
const ns = expr.func.expr.name;
|
|
441
|
+
const fn = expr.func.field;
|
|
442
|
+
const result = this._genStdlibCall(ns, fn, expr);
|
|
443
|
+
if (result !== undefined) return result;
|
|
570
444
|
}
|
|
571
445
|
|
|
572
446
|
// Mark the callee so SelectorExpr knows it's being called, not used as a value
|
|
@@ -718,10 +592,18 @@ export const expressionGenMethods = {
|
|
|
718
592
|
|
|
719
593
|
// ── Helpers ───────────────────────────────────────────────────
|
|
720
594
|
|
|
595
|
+
_genComplexOperand(expr) {
|
|
596
|
+
if (isComplex(expr._type)) return this.genExpr(expr);
|
|
597
|
+
return `{ re: ${this.genExpr(expr)}, im: 0 }`;
|
|
598
|
+
},
|
|
599
|
+
|
|
721
600
|
getTypeName(typeNode) {
|
|
722
601
|
if (!typeNode) return null;
|
|
723
602
|
if (typeNode.kind === "TypeName") return typeNode.name;
|
|
603
|
+
if (typeNode.kind === "GenericTypeName") return typeNode.name;
|
|
724
604
|
if (typeNode.kind === "Ident") return typeNode.name;
|
|
605
|
+
if (typeNode.kind === "InstantiationExpr")
|
|
606
|
+
return this.getTypeName(typeNode.expr);
|
|
725
607
|
if (typeNode.kind === "SelectorExpr") return typeNode.field;
|
|
726
608
|
return null;
|
|
727
609
|
},
|
|
@@ -762,6 +644,9 @@ export const expressionGenMethods = {
|
|
|
762
644
|
case "byte":
|
|
763
645
|
case "rune":
|
|
764
646
|
return "0";
|
|
647
|
+
case "complex64":
|
|
648
|
+
case "complex128":
|
|
649
|
+
return "{ re: 0, im: 0 }";
|
|
765
650
|
case "string":
|
|
766
651
|
return '""';
|
|
767
652
|
case "bool":
|
|
@@ -856,7 +741,7 @@ export const expressionGenMethods = {
|
|
|
856
741
|
case "nil":
|
|
857
742
|
return `${val} === null`;
|
|
858
743
|
case "error":
|
|
859
|
-
return `typeof ${val} === "
|
|
744
|
+
return `(typeof ${val} === "object" && ${val} !== null && typeof ${val}.Error === "function")`;
|
|
860
745
|
default:
|
|
861
746
|
if (this.structNames.has(typeNode.name))
|
|
862
747
|
return `${val} instanceof ${typeNode.name}`;
|
|
@@ -904,4 +789,311 @@ export const expressionGenMethods = {
|
|
|
904
789
|
return typeNode.kind;
|
|
905
790
|
}
|
|
906
791
|
},
|
|
792
|
+
|
|
793
|
+
// Dispatch table for stdlib namespace calls (pkg.Func → inline JS).
|
|
794
|
+
// Returns the generated JS string, or undefined if not handled.
|
|
795
|
+
_genStdlibCall(ns, fn, expr) {
|
|
796
|
+
const a = () => expr.args.map((e) => this.genExpr(e));
|
|
797
|
+
switch (ns) {
|
|
798
|
+
case "fmt":
|
|
799
|
+
return this._genFmt(fn, a, expr);
|
|
800
|
+
case "strings":
|
|
801
|
+
return this._genStrings(fn, a);
|
|
802
|
+
case "bytes":
|
|
803
|
+
return this._genBytes(fn, a);
|
|
804
|
+
case "strconv":
|
|
805
|
+
return this._genStrconv(fn, a);
|
|
806
|
+
case "sort":
|
|
807
|
+
return this._genSort(fn, a);
|
|
808
|
+
case "math":
|
|
809
|
+
return this._genMath(fn, a);
|
|
810
|
+
case "unicode":
|
|
811
|
+
return this._genUnicode(fn, a);
|
|
812
|
+
case "os":
|
|
813
|
+
return this._genOs(fn, a);
|
|
814
|
+
case "errors":
|
|
815
|
+
return this._genErrors(fn, a);
|
|
816
|
+
case "time":
|
|
817
|
+
return this._genTime(fn, a);
|
|
818
|
+
default:
|
|
819
|
+
return undefined;
|
|
820
|
+
}
|
|
821
|
+
},
|
|
822
|
+
|
|
823
|
+
_genFmt(fn, _a, expr) {
|
|
824
|
+
const fmtArgs = expr.args.map((e) => this.genExpr(e)).join(", ");
|
|
825
|
+
switch (fn) {
|
|
826
|
+
case "Sprintf":
|
|
827
|
+
this._usesSprintf = true;
|
|
828
|
+
return `__sprintf(${fmtArgs})`;
|
|
829
|
+
case "Errorf": {
|
|
830
|
+
this._usesSprintf = true;
|
|
831
|
+
this._usesError = true;
|
|
832
|
+
const fmtStr = expr.args[0];
|
|
833
|
+
if (fmtStr?.kind === "BasicLit" && fmtStr.value?.includes("%w")) {
|
|
834
|
+
const lastArg = this.genExpr(expr.args[expr.args.length - 1]);
|
|
835
|
+
return `__error(__sprintf(${fmtArgs}), ${lastArg})`;
|
|
836
|
+
}
|
|
837
|
+
return `__error(__sprintf(${fmtArgs}))`;
|
|
838
|
+
}
|
|
839
|
+
case "Printf":
|
|
840
|
+
case "Print":
|
|
841
|
+
this._usesSprintf = true;
|
|
842
|
+
return `process?.stdout?.write(__sprintf(${fmtArgs}))`;
|
|
843
|
+
case "Println":
|
|
844
|
+
this._usesSprintf = true;
|
|
845
|
+
return `console.log(__sprintf(${fmtArgs}))`;
|
|
846
|
+
default:
|
|
847
|
+
return undefined;
|
|
848
|
+
}
|
|
849
|
+
},
|
|
850
|
+
|
|
851
|
+
_genStrings(fn, a) {
|
|
852
|
+
const args = a();
|
|
853
|
+
switch (fn) {
|
|
854
|
+
case "Contains":
|
|
855
|
+
return `${args[0]}.includes(${args[1]})`;
|
|
856
|
+
case "HasPrefix":
|
|
857
|
+
return `${args[0]}.startsWith(${args[1]})`;
|
|
858
|
+
case "HasSuffix":
|
|
859
|
+
return `${args[0]}.endsWith(${args[1]})`;
|
|
860
|
+
case "Index":
|
|
861
|
+
return `${args[0]}.indexOf(${args[1]})`;
|
|
862
|
+
case "LastIndex":
|
|
863
|
+
return `${args[0]}.lastIndexOf(${args[1]})`;
|
|
864
|
+
case "Count":
|
|
865
|
+
return `${args[0]}.split(${args[1]}).length - 1`;
|
|
866
|
+
case "Repeat":
|
|
867
|
+
return `${args[0]}.repeat(${args[1]})`;
|
|
868
|
+
case "Replace":
|
|
869
|
+
return `${args[0]}.replace(${args[1]}, ${args[2]})`;
|
|
870
|
+
case "ReplaceAll":
|
|
871
|
+
return `${args[0]}.replaceAll(${args[1]}, ${args[2]})`;
|
|
872
|
+
case "ToUpper":
|
|
873
|
+
return `${args[0]}.toUpperCase()`;
|
|
874
|
+
case "ToLower":
|
|
875
|
+
return `${args[0]}.toLowerCase()`;
|
|
876
|
+
case "TrimSpace":
|
|
877
|
+
return `${args[0]}.trim()`;
|
|
878
|
+
case "Trim":
|
|
879
|
+
return `${args[0]}.replace(new RegExp(\`^[\${${args[1]}}]+|[\${${args[1]}}]+$\`, "g"), "")`;
|
|
880
|
+
case "TrimPrefix":
|
|
881
|
+
return `(${args[0]}.startsWith(${args[1]}) ? ${args[0]}.slice(${args[1]}.length) : ${args[0]})`;
|
|
882
|
+
case "TrimSuffix":
|
|
883
|
+
return `(${args[0]}.endsWith(${args[1]}) ? ${args[0]}.slice(0, -${args[1]}.length) : ${args[0]})`;
|
|
884
|
+
case "TrimLeft":
|
|
885
|
+
return `${args[0]}.replace(new RegExp(\`^[\${${args[1]}}]+\`), "")`;
|
|
886
|
+
case "TrimRight":
|
|
887
|
+
return `${args[0]}.replace(new RegExp(\`[\${${args[1]}}]+$\`), "")`;
|
|
888
|
+
case "Split":
|
|
889
|
+
return `${args[0]}.split(${args[1]})`;
|
|
890
|
+
case "Join":
|
|
891
|
+
return `${args[0]}.join(${args[1]})`;
|
|
892
|
+
case "EqualFold":
|
|
893
|
+
return `${args[0]}.toLowerCase() === ${args[1]}.toLowerCase()`;
|
|
894
|
+
default:
|
|
895
|
+
return undefined;
|
|
896
|
+
}
|
|
897
|
+
},
|
|
898
|
+
|
|
899
|
+
_genBytes(fn, a) {
|
|
900
|
+
const __bs = `(b => String.fromCharCode(...b))`;
|
|
901
|
+
const __sb = `(s => [...s].map(c => c.charCodeAt(0)))`;
|
|
902
|
+
const args = a();
|
|
903
|
+
switch (fn) {
|
|
904
|
+
case "Contains":
|
|
905
|
+
return `${__bs}(${args[0]}).includes(${__bs}(${args[1]}))`;
|
|
906
|
+
case "HasPrefix":
|
|
907
|
+
return `((b, p) => { for (let i = 0; i < p.length; i++) if (b[i] !== p[i]) return false; return b.length >= p.length; })(${args[0]}, ${args[1]})`;
|
|
908
|
+
case "HasSuffix":
|
|
909
|
+
return `((b, s) => { const off = b.length - s.length; if (off < 0) return false; for (let i = 0; i < s.length; i++) if (b[off + i] !== s[i]) return false; return true; })(${args[0]}, ${args[1]})`;
|
|
910
|
+
case "Index":
|
|
911
|
+
return `${__bs}(${args[0]}).indexOf(${__bs}(${args[1]}))`;
|
|
912
|
+
case "Count":
|
|
913
|
+
return `${__bs}(${args[0]}).split(${__bs}(${args[1]})).length - 1`;
|
|
914
|
+
case "Repeat":
|
|
915
|
+
return `${__sb}(${__bs}(${args[0]}).repeat(${args[1]}))`;
|
|
916
|
+
case "Replace":
|
|
917
|
+
return `((b, o, n, cnt) => { let s = ${__bs}(b), os = ${__bs}(o), ns = ${__bs}(n); if (cnt < 0) return ${__sb}(s.replaceAll(os, ns)); for (let i = 0; i < cnt; i++) s = s.replace(os, ns); return ${__sb}(s); })(${args[0]}, ${args[1]}, ${args[2]}, ${args[3]})`;
|
|
918
|
+
case "ToUpper":
|
|
919
|
+
return `${__sb}(${__bs}(${args[0]}).toUpperCase())`;
|
|
920
|
+
case "ToLower":
|
|
921
|
+
return `${__sb}(${__bs}(${args[0]}).toLowerCase())`;
|
|
922
|
+
case "TrimSpace":
|
|
923
|
+
return `${__sb}(${__bs}(${args[0]}).trim())`;
|
|
924
|
+
case "Trim":
|
|
925
|
+
return `${__sb}(${__bs}(${args[0]}).replace(new RegExp(\`^[\${${args[1]}}]+|[\${${args[1]}}]+$\`, "g"), ""))`;
|
|
926
|
+
case "Equal":
|
|
927
|
+
return `((a, b) => { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false; return true; })(${args[0]}, ${args[1]})`;
|
|
928
|
+
case "Split":
|
|
929
|
+
return `${__bs}(${args[0]}).split(${__bs}(${args[1]})).map(p => ${__sb}(p))`;
|
|
930
|
+
case "Join":
|
|
931
|
+
return `${__sb}(${args[0]}.map(p => ${__bs}(p)).join(${__bs}(${args[1]})))`;
|
|
932
|
+
default:
|
|
933
|
+
return undefined;
|
|
934
|
+
}
|
|
935
|
+
},
|
|
936
|
+
|
|
937
|
+
_genStrconv(fn, a) {
|
|
938
|
+
const args = a();
|
|
939
|
+
switch (fn) {
|
|
940
|
+
case "Itoa":
|
|
941
|
+
return `String(${args[0]})`;
|
|
942
|
+
case "Atoi":
|
|
943
|
+
return `(Number.isNaN(Number(${args[0]})) ? [0, "invalid syntax"] : [Number(${args[0]}) | 0, null])`;
|
|
944
|
+
case "FormatBool":
|
|
945
|
+
return `String(${args[0]})`;
|
|
946
|
+
case "FormatInt":
|
|
947
|
+
return `(${args[0]}).toString(${args[1]})`;
|
|
948
|
+
case "FormatFloat":
|
|
949
|
+
return `String(${args[0]})`;
|
|
950
|
+
case "ParseFloat":
|
|
951
|
+
return `(Number.isNaN(Number(${args[0]})) ? [0, "invalid syntax"] : [Number(${args[0]}), null])`;
|
|
952
|
+
case "ParseInt":
|
|
953
|
+
return `(Number.isNaN(parseInt(${args[0]}, ${args[1]} || 10)) ? [0, "invalid syntax"] : [parseInt(${args[0]}, ${args[1]} || 10), null])`;
|
|
954
|
+
case "ParseBool":
|
|
955
|
+
return `(${args[0]} === "true" || ${args[0]} === "1" ? [true, null] : ${args[0]} === "false" || ${args[0]} === "0" ? [false, null] : [false, "invalid syntax"])`;
|
|
956
|
+
default:
|
|
957
|
+
return undefined;
|
|
958
|
+
}
|
|
959
|
+
},
|
|
960
|
+
|
|
961
|
+
_genSort(fn, a) {
|
|
962
|
+
const args = a();
|
|
963
|
+
switch (fn) {
|
|
964
|
+
case "Ints":
|
|
965
|
+
case "Float64s":
|
|
966
|
+
return `${args[0]}.sort((a, b) => a - b)`;
|
|
967
|
+
case "Strings":
|
|
968
|
+
return `${args[0]}.sort()`;
|
|
969
|
+
case "Slice":
|
|
970
|
+
case "SliceStable":
|
|
971
|
+
return `${args[0]}.sort((a, b) => ${args[1]}(a, b) ? -1 : ${args[1]}(b, a) ? 1 : 0)`;
|
|
972
|
+
case "SliceIsSorted":
|
|
973
|
+
return `${args[0]}.every((v, i, a) => i === 0 || ${args[1]}(a[i - 1], v))`;
|
|
974
|
+
default:
|
|
975
|
+
return undefined;
|
|
976
|
+
}
|
|
977
|
+
},
|
|
978
|
+
|
|
979
|
+
_genMath(fn, a) {
|
|
980
|
+
const args = a();
|
|
981
|
+
switch (fn) {
|
|
982
|
+
case "Abs":
|
|
983
|
+
return `Math.abs(${args[0]})`;
|
|
984
|
+
case "Floor":
|
|
985
|
+
return `Math.floor(${args[0]})`;
|
|
986
|
+
case "Ceil":
|
|
987
|
+
return `Math.ceil(${args[0]})`;
|
|
988
|
+
case "Round":
|
|
989
|
+
return `Math.round(${args[0]})`;
|
|
990
|
+
case "Sqrt":
|
|
991
|
+
return `Math.sqrt(${args[0]})`;
|
|
992
|
+
case "Cbrt":
|
|
993
|
+
return `Math.cbrt(${args[0]})`;
|
|
994
|
+
case "Pow":
|
|
995
|
+
return `Math.pow(${args[0]}, ${args[1]})`;
|
|
996
|
+
case "Log":
|
|
997
|
+
return `Math.log(${args[0]})`;
|
|
998
|
+
case "Log2":
|
|
999
|
+
return `Math.log2(${args[0]})`;
|
|
1000
|
+
case "Log10":
|
|
1001
|
+
return `Math.log10(${args[0]})`;
|
|
1002
|
+
case "Sin":
|
|
1003
|
+
return `Math.sin(${args[0]})`;
|
|
1004
|
+
case "Cos":
|
|
1005
|
+
return `Math.cos(${args[0]})`;
|
|
1006
|
+
case "Tan":
|
|
1007
|
+
return `Math.tan(${args[0]})`;
|
|
1008
|
+
case "Min":
|
|
1009
|
+
return `Math.min(${args[0]}, ${args[1]})`;
|
|
1010
|
+
case "Max":
|
|
1011
|
+
return `Math.max(${args[0]}, ${args[1]})`;
|
|
1012
|
+
case "Mod":
|
|
1013
|
+
return `${args[0]} % ${args[1]}`;
|
|
1014
|
+
case "Inf":
|
|
1015
|
+
return `(${args[0]} >= 0 ? Infinity : -Infinity)`;
|
|
1016
|
+
case "IsNaN":
|
|
1017
|
+
return `Number.isNaN(${args[0]})`;
|
|
1018
|
+
case "IsInf":
|
|
1019
|
+
return `(${args[1]} > 0 ? ${args[0]} === Infinity : ${args[1]} < 0 ? ${args[0]} === -Infinity : !Number.isFinite(${args[0]}))`;
|
|
1020
|
+
case "NaN":
|
|
1021
|
+
return "NaN";
|
|
1022
|
+
default:
|
|
1023
|
+
return undefined;
|
|
1024
|
+
}
|
|
1025
|
+
},
|
|
1026
|
+
|
|
1027
|
+
_genUnicode(fn, a) {
|
|
1028
|
+
const args = a();
|
|
1029
|
+
const cp = `String.fromCodePoint(${args[0]})`;
|
|
1030
|
+
switch (fn) {
|
|
1031
|
+
case "IsLetter":
|
|
1032
|
+
return `/\\p{L}/u.test(${cp})`;
|
|
1033
|
+
case "IsDigit":
|
|
1034
|
+
return `/\\p{Nd}/u.test(${cp})`;
|
|
1035
|
+
case "IsSpace":
|
|
1036
|
+
return `/\\s/.test(${cp})`;
|
|
1037
|
+
case "IsUpper":
|
|
1038
|
+
return `((__c) => __c === __c.toUpperCase() && /\\p{L}/u.test(__c))(${cp})`;
|
|
1039
|
+
case "IsLower":
|
|
1040
|
+
return `((__c) => __c === __c.toLowerCase() && /\\p{L}/u.test(__c))(${cp})`;
|
|
1041
|
+
case "IsPunct":
|
|
1042
|
+
return `/\\p{P}/u.test(${cp})`;
|
|
1043
|
+
case "IsControl":
|
|
1044
|
+
return `/\\p{Cc}/u.test(${cp})`;
|
|
1045
|
+
case "IsPrint":
|
|
1046
|
+
return `!/\\p{Cc}/u.test(${cp})`;
|
|
1047
|
+
case "IsGraphic":
|
|
1048
|
+
return `!/\\p{Cc}/u.test(${cp})`;
|
|
1049
|
+
case "ToUpper":
|
|
1050
|
+
return `${cp}.toUpperCase().codePointAt(0)`;
|
|
1051
|
+
case "ToLower":
|
|
1052
|
+
return `${cp}.toLowerCase().codePointAt(0)`;
|
|
1053
|
+
default:
|
|
1054
|
+
return undefined;
|
|
1055
|
+
}
|
|
1056
|
+
},
|
|
1057
|
+
|
|
1058
|
+
_genOs(fn, a) {
|
|
1059
|
+
const args = a();
|
|
1060
|
+
switch (fn) {
|
|
1061
|
+
case "Exit":
|
|
1062
|
+
return `process.exit(${args[0]})`;
|
|
1063
|
+
case "Getenv":
|
|
1064
|
+
return `(process.env[${args[0]}] ?? "")`;
|
|
1065
|
+
default:
|
|
1066
|
+
return undefined;
|
|
1067
|
+
}
|
|
1068
|
+
},
|
|
1069
|
+
|
|
1070
|
+
_genErrors(fn, a) {
|
|
1071
|
+
const args = a();
|
|
1072
|
+
switch (fn) {
|
|
1073
|
+
case "New":
|
|
1074
|
+
this._usesError = true;
|
|
1075
|
+
return `__error(${args[0]})`;
|
|
1076
|
+
case "Is":
|
|
1077
|
+
this._usesErrorIs = true;
|
|
1078
|
+
return `__errorIs(${args[0]}, ${args[1]})`;
|
|
1079
|
+
case "Unwrap":
|
|
1080
|
+
return `(${args[0]}?._cause ?? null)`;
|
|
1081
|
+
default:
|
|
1082
|
+
return undefined;
|
|
1083
|
+
}
|
|
1084
|
+
},
|
|
1085
|
+
|
|
1086
|
+
_genTime(fn, a) {
|
|
1087
|
+
const args = a();
|
|
1088
|
+
switch (fn) {
|
|
1089
|
+
case "Now":
|
|
1090
|
+
return "Date.now()";
|
|
1091
|
+
case "Since":
|
|
1092
|
+
return `(Date.now() - ${args[0]})`;
|
|
1093
|
+
case "Sleep":
|
|
1094
|
+
return `await new Promise(r => setTimeout(r, ${args[0]} / 1000000))`;
|
|
1095
|
+
default:
|
|
1096
|
+
return undefined;
|
|
1097
|
+
}
|
|
1098
|
+
},
|
|
907
1099
|
};
|