gofront 1.6.1 → 1.8.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/README.md +45 -49
- package/package.json +12 -8
- package/src/backend/js/expressions.js +1627 -148
- package/src/backend/js/fmt-runtime.js +573 -0
- package/src/backend/js/index.js +508 -102
- package/src/backend/js/runtime.js +1997 -106
- package/src/backend/js/statements.js +931 -87
- package/src/backend/js/stdlib/bits.js +87 -14
- package/src/backend/js/stdlib/builder.js +41 -6
- package/src/backend/js/stdlib/bytes.js +253 -7
- package/src/backend/js/stdlib/errors.js +7 -1
- package/src/backend/js/stdlib/fmt.js +349 -10
- package/src/backend/js/stdlib/index.js +19 -2
- package/src/backend/js/stdlib/json.js +1167 -0
- package/src/backend/js/stdlib/maps.js +0 -8
- package/src/backend/js/stdlib/math.js +17 -1
- package/src/backend/js/stdlib/simd.js +34 -0
- package/src/backend/js/stdlib/slices.js +36 -6
- package/src/backend/js/stdlib/strconv.js +10 -5
- package/src/backend/js/stdlib/strings.js +83 -4
- package/src/backend/js/stdlib/testing.js +7 -0
- package/src/backend/js/stdlib/time.js +79 -55
- package/src/backend/js/stdlib/unicode.js +1 -1
- package/src/backend/js/stdlib/utf8.js +1 -1
- package/src/backend/js/templ.js +38 -76
- package/src/backend/js/type-info.js +272 -0
- package/src/backend/shared/fmt-types.js +188 -0
- package/src/backend/wasm/boundary.js +446 -72
- package/src/backend/wasm/emit-builtins.js +320 -13
- package/src/backend/wasm/emit-exprs.js +1404 -199
- package/src/backend/wasm/emit-maps.js +61 -13
- package/src/backend/wasm/emit-stmts.js +1359 -164
- package/src/backend/wasm/emit.js +518 -74
- package/src/backend/wasm/encode.js +128 -13
- package/src/backend/wasm/globals.js +452 -0
- package/src/backend/wasm/index.js +194 -2489
- package/src/backend/wasm/method-expr.js +381 -0
- package/src/backend/wasm/module-emitter.js +2240 -0
- package/src/backend/wasm/monomorph.js +62 -4
- package/src/backend/wasm/optimize.js +4 -2
- package/src/backend/wasm/prescan.js +397 -0
- package/src/backend/wasm/stdlib/bytes.js +1804 -127
- package/src/backend/wasm/stdlib/core.js +1574 -199
- package/src/backend/wasm/stdlib/index.js +3 -5
- package/src/backend/wasm/stdlib/io.js +1567 -150
- package/src/backend/wasm/stdlib/packages.js +2 -0
- package/src/backend/wasm/stdlib/simd.js +499 -0
- package/src/backend/wasm/stdlib/time.js +1041 -12
- package/src/backend/wasm/types.js +221 -15
- package/src/backend/wasm/variadic.js +93 -0
- package/src/backend/wasm/wat.js +84 -20
- package/src/{cli-core.js → cli/cli-core.js} +236 -10
- package/src/{test-runner.js → cli/test-runner.js} +332 -39
- package/src/{vendor.js → cli/vendor.js} +89 -15
- package/src/compiler.js +107 -269
- package/src/dts-parser.js +71 -14
- package/src/index.js +15 -169
- package/src/{lexer.js → lexer/lexer.js} +102 -55
- package/src/{tokens.js → lexer/tokens.js} +1 -0
- package/src/link/sourcemap.js +97 -0
- package/src/link/stdlib.js +515 -0
- package/src/link/wasm.js +294 -0
- package/src/lower/bounds.js +394 -0
- package/src/lower/boxing.js +1 -6
- package/src/lower/captures.js +176 -32
- package/src/lower/embedding.js +2 -1
- package/src/lower/index.js +26 -18
- package/src/lower/json-codecs.js +1398 -0
- package/src/lower/ownership.js +22 -1
- package/src/lower/range.js +86 -1
- package/src/lower/reachability.js +132 -0
- package/src/parser/declarations.js +58 -13
- package/src/parser/expressions.js +29 -7
- package/src/parser/index.js +2 -1
- package/src/parser/statements.js +37 -22
- package/src/parser/struct-tag.js +144 -0
- package/src/{templ-parser.js → parser/templ.js} +138 -15
- package/src/parser/types.js +130 -13
- package/src/resolver.js +22 -1
- package/src/typechecker/assignability.js +215 -11
- package/src/typechecker/const-fold.js +356 -0
- package/src/typechecker/constants.js +256 -0
- package/src/typechecker/expressions.js +960 -99
- package/src/typechecker/index.js +491 -72
- package/src/typechecker/init-order.js +330 -0
- package/src/typechecker/resolve.js +596 -52
- package/src/typechecker/statements.js +157 -17
- package/src/typechecker/stdlib/core.js +333 -55
- package/src/typechecker/stdlib/excluded.js +898 -0
- package/src/typechecker/stdlib/extended.js +359 -26
- package/src/typechecker/{stdlib.js → stdlib/index.js} +6 -4
- package/src/typechecker/stdlib/simd.js +123 -0
- package/src/typechecker/termination.js +1 -1
- package/src/typechecker/types.js +165 -26
- package/stdlib/bytes/iter.go +192 -0
- package/stdlib/bytes/search.go +240 -0
- package/stdlib/bytes/split.go +218 -0
- package/stdlib/cmp/cmp.go +65 -0
- package/stdlib/encoding/json/errors.go +31 -0
- package/stdlib/encoding/json/indent.go +71 -0
- package/stdlib/encoding/json/number.go +12 -0
- package/stdlib/encoding/json/stream.go +173 -0
- package/stdlib/errors/overlay.go +12 -0
- package/stdlib/hash/hash.go +53 -0
- package/stdlib/internal/jsonrt/dec.go +738 -0
- package/stdlib/internal/jsonrt/enc.go +366 -0
- package/stdlib/internal/jsonrt/indent.go +135 -0
- package/stdlib/internal/jsonrt/number.go +27 -0
- package/stdlib/internal/jsonrt/reader.go +73 -0
- package/stdlib/internal/jsonrt/scanner.go +649 -0
- package/stdlib/io/io.go +346 -0
- package/stdlib/iter/iter.go +18 -0
- package/stdlib/maps/iter.go +65 -0
- package/stdlib/math/extra.go +270 -0
- package/stdlib/slices/extra.go +73 -0
- package/stdlib/slices/iter.go +113 -0
- package/stdlib/sort/sort.go +561 -0
- package/stdlib/strconv/quote.go +341 -0
- package/stdlib/strings/extra.go +35 -0
- package/stdlib/strings/iter.go +122 -0
- package/stdlib/sync/extra.go +105 -0
- package/stdlib/unicode/unicode.go +112 -0
- package/stdlib/unicode/utf8/bytes.go +239 -0
- package/src/backend/wasm/const-fold.js +0 -205
- package/src/backend/wasm/emit-stdlib.js +0 -13
- /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
- /package/src/{colors.js → cli/colors.js} +0 -0
- /package/src/{dev-server.js → cli/dev-server.js} +0 -0
- /package/src/{minifier.js → cli/minifier.js} +0 -0
- /package/src/{project-config.js → cli/project-config.js} +0 -0
- /package/src/{pwa.js → cli/pwa.js} +0 -0
- /package/src/{templ-lexer.js → lexer/templ-lexer.js} +0 -0
|
@@ -11,14 +11,6 @@ export const mapsMethods = {
|
|
|
11
11
|
return `__equal(${a1}, ${b1})`;
|
|
12
12
|
}
|
|
13
13
|
switch (fn) {
|
|
14
|
-
case "Keys": {
|
|
15
|
-
const [m] = a();
|
|
16
|
-
return `Object.keys(${m})`;
|
|
17
|
-
}
|
|
18
|
-
case "Values": {
|
|
19
|
-
const [m] = a();
|
|
20
|
-
return `Object.values(${m})`;
|
|
21
|
-
}
|
|
22
14
|
case "Clone": {
|
|
23
15
|
const [m] = a();
|
|
24
16
|
return `({...${m}})`;
|
|
@@ -9,8 +9,10 @@ const MATH1 = {
|
|
|
9
9
|
Sqrt: "sqrt",
|
|
10
10
|
Cbrt: "cbrt",
|
|
11
11
|
Log: "log",
|
|
12
|
+
Log1p: "log1p",
|
|
12
13
|
Log2: "log2",
|
|
13
14
|
Log10: "log10",
|
|
15
|
+
Expm1: "expm1",
|
|
14
16
|
Sin: "sin",
|
|
15
17
|
Cos: "cos",
|
|
16
18
|
Tan: "tan",
|
|
@@ -37,7 +39,7 @@ const MATH_EXTRA = {
|
|
|
37
39
|
Inf: ([x]) => `(${x} >= 0 ? Infinity : -Infinity)`,
|
|
38
40
|
IsNaN: ([x]) => `Number.isNaN(${x})`,
|
|
39
41
|
IsInf: ([x, y]) =>
|
|
40
|
-
`(${y} > 0 ? ${x} === Infinity : ${y} < 0 ? ${x} === -Infinity :
|
|
42
|
+
`(${y} > 0 ? ${x} === Infinity : ${y} < 0 ? ${x} === -Infinity : Math.abs(${x}) === Infinity)`,
|
|
41
43
|
NaN: () => "NaN",
|
|
42
44
|
Exp2: ([x]) => `Math.pow(2, ${x})`,
|
|
43
45
|
Signbit: ([x]) => `(${x} < 0 || Object.is(${x}, -0))`,
|
|
@@ -46,6 +48,20 @@ const MATH_EXTRA = {
|
|
|
46
48
|
Dim: ([x, y]) => `Math.max(${x} - ${y}, 0)`,
|
|
47
49
|
Remainder: ([x, y]) =>
|
|
48
50
|
`((x, y) => { if (isNaN(x) || isNaN(y) || y === 0 || !isFinite(x)) return NaN; if (!isFinite(y)) return x; const q = x / y; const r = Math.round(q); const diff = Math.abs(q - r); const n = (diff === 0.5 && (r % 2 !== 0)) ? (r < q ? r + 1 : r - 1) : r; return x - n * y; })(${x}, ${y})`,
|
|
51
|
+
Frexp: ([x]) =>
|
|
52
|
+
`((f) => { if (f === 0 || !Number.isFinite(f)) return [f, 0]; const buf = new ArrayBuffer(8); const f64 = new Float64Array(buf); const u32 = new Uint32Array(buf); f64[0] = f; let hi = u32[1]; let exp = (hi >>> 20) & 0x7ff; if (exp === 0) { f64[0] = f * Math.pow(2, 54); hi = u32[1]; exp = ((hi >>> 20) & 0x7ff) - 54; } exp -= 1022; u32[1] = (hi & 0x800fffff) | 0x3fe00000; return [f64[0], exp]; })(${x})`,
|
|
53
|
+
Ldexp: ([frac, exp]) =>
|
|
54
|
+
`((frac, exp) => { if (frac === 0 || !Number.isFinite(frac)) return frac; if (exp > 1023) return frac < 0 ? -Infinity : Infinity; if (exp < -1074) return frac < 0 ? -0 : 0; if (exp >= -1022) return frac * Math.pow(2, exp); return frac * Math.pow(2, exp + 54) * Math.pow(2, -54); })(${frac}, ${exp})`,
|
|
55
|
+
Modf: ([f]) =>
|
|
56
|
+
`((x) => { if (Number.isNaN(x)) return [NaN, NaN]; if (!Number.isFinite(x)) return [x, NaN]; const i = Math.trunc(x); const frac = x === i ? (x < 0 || Object.is(x, -0) ? -0 : 0) : x - i; return [i, frac]; })(${f})`,
|
|
57
|
+
FMA: ([x, y, z]) =>
|
|
58
|
+
`((x, y, z) => { if (Number.isNaN(x) || Number.isNaN(y) || Number.isNaN(z)) return NaN; if ((x === 0 && !Number.isFinite(y)) || (y === 0 && !Number.isFinite(x))) return NaN; const p = x * y; if (!Number.isFinite(p) && !Number.isFinite(z) && ((p > 0 && z < 0) || (p < 0 && z > 0))) return NaN; return p + z; })(${x}, ${y}, ${z})`,
|
|
59
|
+
RoundToEven: ([x]) =>
|
|
60
|
+
`((x) => { if (x === 0 || !Number.isFinite(x)) return x; const t = Math.trunc(x); const f = Math.abs(x - t); if (f < 0.5) return Object.is(t, 0) && (x < 0 || Object.is(x, -0)) ? -0 : t; if (f > 0.5) return x > 0 ? t + 1 : t - 1; const res = t % 2 === 0 ? t : (x > 0 ? t + 1 : t - 1); return Object.is(res, 0) && (x < 0 || Object.is(x, -0)) ? -0 : res; })(${x})`,
|
|
61
|
+
Nextafter: ([x, y]) =>
|
|
62
|
+
`((x, y) => { if (Number.isNaN(x) || Number.isNaN(y)) return NaN; if (x === y) return x; if (x === 0) { const s = Number.MIN_VALUE; return y > 0 ? s : -s; } const buf = new ArrayBuffer(8); const f64 = new Float64Array(buf); const i64 = new BigInt64Array(buf); f64[0] = x; let b = i64[0]; if ((x > 0 && y > x) || (x < 0 && y > x)) b = b + (x > 0 ? 1n : -1n); else b = b + (x > 0 ? -1n : 1n); i64[0] = b; return f64[0]; })(${x}, ${y})`,
|
|
63
|
+
Nextafter32: ([x, y]) =>
|
|
64
|
+
`((x, y) => { if (Number.isNaN(x) || Number.isNaN(y)) return NaN; if (x === y) return x; if (x === 0) { const s = 1.401298464324817e-45; return y > 0 ? s : -s; } const buf = new ArrayBuffer(4); const f32 = new Float32Array(buf); const i32 = new Int32Array(buf); f32[0] = x; let b = i32[0]; if ((x > 0 && y > x) || (x < 0 && y > x)) b = b + (x > 0 ? 1 : -1); else b = b + (x > 0 ? -1 : 1); i32[0] = b; return f32[0]; })(${x}, ${y})`,
|
|
49
65
|
Float64bits: ([x]) =>
|
|
50
66
|
`((f) => { const b = new ArrayBuffer(8); new Float64Array(b)[0] = f; return Number(new BigUint64Array(b)[0]); })(${x})`,
|
|
51
67
|
Float64frombits: ([b]) =>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/backend/js/stdlib/simd.js
|
|
2
|
+
// CodeGen for the `gofront/simd` package in JS packages.
|
|
3
|
+
|
|
4
|
+
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
5
|
+
|
|
6
|
+
/** @type {ThisType<CodeGen>} */
|
|
7
|
+
export const simdMethods = {
|
|
8
|
+
_genSimd(fn, a) {
|
|
9
|
+
this.useHelper("simd");
|
|
10
|
+
const args = a();
|
|
11
|
+
switch (fn) {
|
|
12
|
+
case "Splat":
|
|
13
|
+
return `__simd_splat(${args[0]})`;
|
|
14
|
+
case "NewF32x4":
|
|
15
|
+
return `__simd_f32x4(${args[0]}, ${args[1]}, ${args[2]}, ${args[3]})`;
|
|
16
|
+
case "Select":
|
|
17
|
+
return `__simd_select(${args[0]}, ${args[1]}, ${args[2]})`;
|
|
18
|
+
case "Shuffle":
|
|
19
|
+
return `__simd_shuffle(${args.join(", ")})`;
|
|
20
|
+
case "LoadF32x4":
|
|
21
|
+
return `__simd_load(${args[0]}, ${args[1]})`;
|
|
22
|
+
case "StoreF32x4":
|
|
23
|
+
return `__simd_store(${args[0]}, ${args[1]}, ${args[2]})`;
|
|
24
|
+
case "LoadF32x4Slice":
|
|
25
|
+
return `__simd_load_slice(${args[0]}, ${args[1]})`;
|
|
26
|
+
case "StoreF32x4Slice":
|
|
27
|
+
return `__simd_store_slice(${args[0]}, ${args[1]}, ${args[2]})`;
|
|
28
|
+
case "Pad4":
|
|
29
|
+
return `(Math.floor((${args[0]} + 3) / 4) * 4)`;
|
|
30
|
+
default:
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -34,26 +34,26 @@ const SLICES_DISPATCH = {
|
|
|
34
34
|
`((s, f) => { if (!s || s.length === 0) throw new Error("slices.MinFunc: empty list"); return s.reduce((m, x) => f(x, m) < 0 ? x : m); })(${a[0]}, ${a[1]})`,
|
|
35
35
|
Clone: (a) => `((s) => s ? s.slice() : null)(${a[0]})`,
|
|
36
36
|
Compact: (a) =>
|
|
37
|
-
`((s) => { if (!s || s.length === 0) return s; let k = 1; for (let i = 1; i < s.length; i++) { if (s[i] !== s[k - 1]) s[k++] = s[i]; } return ArrayBuffer.isView(s) ? s.subarray(0, k) : (s.length = k, s); })(${a[0]})`,
|
|
37
|
+
`((s) => { if (!s || s.length === 0) return s; let k = 1; for (let i = 1; i < s.length; i++) { if (s[i] !== s[k - 1]) s[k++] = s[i]; } return s[__sv] !== undefined ? __slice(s, 0, k) : ArrayBuffer.isView(s) ? s.subarray(0, k) : (s.length = k, s); })(${a[0]})`,
|
|
38
38
|
CompactFunc: (a) =>
|
|
39
|
-
`((s, f) => { if (!s || s.length === 0) return s; let k = 1; for (let i = 1; i < s.length; i++) { if (!f(s[i], s[k - 1])) s[k++] = s[i]; } return ArrayBuffer.isView(s) ? s.subarray(0, k) : (s.length = k, s); })(${a[0]}, ${a[1]})`,
|
|
39
|
+
`((s, f) => { if (!s || s.length === 0) return s; let k = 1; for (let i = 1; i < s.length; i++) { if (!f(s[i], s[k - 1])) s[k++] = s[i]; } return s[__sv] !== undefined ? __slice(s, 0, k) : ArrayBuffer.isView(s) ? s.subarray(0, k) : (s.length = k, s); })(${a[0]}, ${a[1]})`,
|
|
40
40
|
Concat: (a) =>
|
|
41
41
|
a.length === 0
|
|
42
42
|
? "null"
|
|
43
43
|
: `((...slices) => { const nonNull = slices.filter(Boolean); if (nonNull.length === 0) return slices[0] === null ? null : []; if (ArrayBuffer.isView(nonNull[0])) { const totalLen = nonNull.reduce((sum, s) => sum + s.length, 0); const out = new nonNull[0].constructor(totalLen); let off = 0; for (const s of nonNull) { out.set(s, off); off += s.length; } return out; } return [].concat(...slices.map(s => s ? (ArrayBuffer.isView(s) ? Array.from(s) : s) : [])); })(${a.map((x) => `(${x})`).join(", ")})`,
|
|
44
44
|
Delete: (a) =>
|
|
45
|
-
`((s, i, j) => { if (!s && i === 0 && j === 0) return s; s = s || []; if (i < 0 || j < i || j > s.length) throw new Error("runtime error: slice bounds out of range"); if (ArrayBuffer.isView(s)) { s.copyWithin(i, j); return s.subarray(0, s.length - (j - i)); } s.splice(i, j - i); return s; })(${a[0]}, ${a[1]}, ${a[2]})`,
|
|
45
|
+
`((s, i, j) => { if (!s && i === 0 && j === 0) return s; s = s || []; if (i < 0 || j < i || j > s.length) throw new Error("runtime error: slice bounds out of range"); if (ArrayBuffer.isView(s)) { s.copyWithin(i, j); return s.subarray(0, s.length - (j - i)); } if (s[__sv] !== undefined) { s.copyWithin(i, j); return __slice(s, 0, s.length - (j - i)); } s.splice(i, j - i); return s; })(${a[0]}, ${a[1]}, ${a[2]})`,
|
|
46
46
|
DeleteFunc: (a) =>
|
|
47
|
-
`((s, f) => { if (!s || s.length === 0) return s; let k = 0; for (let i = 0; i < s.length; i++) { if (!f(s[i])) s[k++] = s[i]; } return ArrayBuffer.isView(s) ? s.subarray(0, k) : (s.length = k, s); })(${a[0]}, ${a[1]})`,
|
|
47
|
+
`((s, f) => { if (!s || s.length === 0) return s; let k = 0; for (let i = 0; i < s.length; i++) { if (!f(s[i])) s[k++] = s[i]; } return s[__sv] !== undefined ? __slice(s, 0, k) : ArrayBuffer.isView(s) ? s.subarray(0, k) : (s.length = k, s); })(${a[0]}, ${a[1]})`,
|
|
48
48
|
Insert: (a, isTyped) => {
|
|
49
49
|
const items = a.slice(2);
|
|
50
50
|
const nilInit = isTyped ? "new Uint8Array(0)" : "[]";
|
|
51
|
-
return `((s, i, ...v) => { if (!s && i === 0) s = ${nilInit}; if (!s || i < 0 || i > s.length) throw new Error("runtime error: slice bounds out of range"); if (ArrayBuffer.isView(s)) { const res = new s.constructor(s.length + v.length); res.set(s.subarray(0, i), 0); res.set(v, i); res.set(s.subarray(i), i + v.length); return res; } s.splice(i, 0, ...v); return s; })(${a[0]}, ${a[1]}${items.length ? `, ${items.join(", ")}` : ""})`;
|
|
51
|
+
return `((s, i, ...v) => { if (!s && i === 0) s = ${nilInit}; if (!s || i < 0 || i > s.length) throw new Error("runtime error: slice bounds out of range"); if (ArrayBuffer.isView(s)) { const res = new s.constructor(s.length + v.length); res.set(s.subarray(0, i), 0); res.set(v, i); res.set(s.subarray(i), i + v.length); return res; } if (s[__sv] !== undefined) s = Array.from(s); s.splice(i, 0, ...v); return s; })(${a[0]}, ${a[1]}${items.length ? `, ${items.join(", ")}` : ""})`;
|
|
52
52
|
},
|
|
53
53
|
Replace: (a, isTyped) => {
|
|
54
54
|
const items = a.slice(3);
|
|
55
55
|
const nilInit = isTyped ? "new Uint8Array(0)" : "[]";
|
|
56
|
-
return `((s, i, j, ...v) => { if (!s && i === 0 && j === 0) s = ${nilInit}; if (!s || i < 0 || j < i || j > s.length) throw new Error("runtime error: slice bounds out of range"); if (ArrayBuffer.isView(s)) { const res = new s.constructor(s.length - (j - i) + v.length); res.set(s.subarray(0, i), 0); res.set(v, i); res.set(s.subarray(j), i + v.length); return res; } s.splice(i, j - i, ...v); return s; })(${a[0]}, ${a[1]}, ${a[2]}${items.length ? `, ${items.join(", ")}` : ""})`;
|
|
56
|
+
return `((s, i, j, ...v) => { if (!s && i === 0 && j === 0) s = ${nilInit}; if (!s || i < 0 || j < i || j > s.length) throw new Error("runtime error: slice bounds out of range"); if (ArrayBuffer.isView(s)) { const res = new s.constructor(s.length - (j - i) + v.length); res.set(s.subarray(0, i), 0); res.set(v, i); res.set(s.subarray(j), i + v.length); return res; } if (s[__sv] !== undefined) s = Array.from(s); s.splice(i, j - i, ...v); return s; })(${a[0]}, ${a[1]}, ${a[2]}${items.length ? `, ${items.join(", ")}` : ""})`;
|
|
57
57
|
},
|
|
58
58
|
Grow: (a, isTyped) => {
|
|
59
59
|
const nilInit = isTyped ? "new Uint8Array(0)" : "[]";
|
|
@@ -62,6 +62,15 @@ const SLICES_DISPATCH = {
|
|
|
62
62
|
Clip: (a) => `((s) => s ? s.slice() : null)(${a[0]})`,
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
+
const VIEW_AWARE = new Set([
|
|
66
|
+
"Compact",
|
|
67
|
+
"CompactFunc",
|
|
68
|
+
"Delete",
|
|
69
|
+
"DeleteFunc",
|
|
70
|
+
"Insert",
|
|
71
|
+
"Replace",
|
|
72
|
+
]);
|
|
73
|
+
|
|
65
74
|
/** @type {ThisType<CodeGen>} */
|
|
66
75
|
export const slicesMethods = {
|
|
67
76
|
_genSlices(fn, a, expr) {
|
|
@@ -70,8 +79,29 @@ export const slicesMethods = {
|
|
|
70
79
|
const [a1, b1] = a();
|
|
71
80
|
return `__equal(${a1}, ${b1})`;
|
|
72
81
|
}
|
|
82
|
+
// Struct and array elements are values: compare them field by field
|
|
83
|
+
// (`.includes` and `.indexOf` compare object identity).
|
|
84
|
+
if (
|
|
85
|
+
(fn === "Contains" || fn === "Index") &&
|
|
86
|
+
this._sliceElemIsAggregate(expr)
|
|
87
|
+
) {
|
|
88
|
+
this.useHelper("equal");
|
|
89
|
+
const [s1, v1] = a();
|
|
90
|
+
const found = fn === "Contains" ? "true" : "i";
|
|
91
|
+
const missing = fn === "Contains" ? "false" : "-1";
|
|
92
|
+
return `((s, v) => { s = s || []; for (let i = 0; i < s.length; i++) { if (__equal(s[i], v)) return ${found}; } return ${missing}; })(${s1}, ${v1})`;
|
|
93
|
+
}
|
|
73
94
|
const isTyped = isTypedArraySlice(expr?.args?.[0]?._type);
|
|
74
95
|
const gen = SLICES_DISPATCH[fn];
|
|
96
|
+
// These shrink or grow the slice in place; a slice view (`__sv`) has a
|
|
97
|
+
// fixed length, so they reslice it or copy it to a plain array.
|
|
98
|
+
if (VIEW_AWARE.has(fn)) this.useHelper("slice");
|
|
75
99
|
return gen ? gen(a(), isTyped) : undefined;
|
|
76
100
|
},
|
|
101
|
+
|
|
102
|
+
_sliceElemIsAggregate(expr) {
|
|
103
|
+
let t = expr?.args?.[0]?._type;
|
|
104
|
+
while (t?.kind === "named") t = t.underlying;
|
|
105
|
+
return t?.kind === "slice" && Boolean(this._aggregateBase(t.elem));
|
|
106
|
+
},
|
|
77
107
|
};
|
|
@@ -4,25 +4,28 @@
|
|
|
4
4
|
|
|
5
5
|
// Parsers return [value, msg|null] from the shared __strconv_* helpers
|
|
6
6
|
// (runtime.js); the message becomes a Go error value.
|
|
7
|
-
const parsed = (call, toValue = "r[0]") =>
|
|
8
|
-
`((r) => [${toValue}, r[1] === null ? null : __error(r[1], r[1].includes("invalid syntax") ? __strconv_err_syntax : r[1].includes("value out of range") ? __strconv_err_range : null)])(${call})`;
|
|
7
|
+
const parsed = (fnName, numArg, call, toValue = "r[0]") =>
|
|
8
|
+
`((r, s) => [${toValue}, r[1] === null ? null : (typeof NumError$$strconv !== "undefined" ? ((o) => { o.__p = true; return o; })(new NumError$$strconv("${fnName}", String(s), r[1].includes("value out of range") ? __strconv_err_range : __strconv_err_syntax)) : __error(r[1], r[1].includes("invalid syntax") ? __strconv_err_syntax : r[1].includes("value out of range") ? __strconv_err_range : null))])(${call}, ${numArg})`;
|
|
9
9
|
|
|
10
10
|
const STRCONV_DISPATCH = {
|
|
11
11
|
Itoa: (a) => `String(${a[0]})`,
|
|
12
|
-
Atoi: (a) => parsed(`__strconv_atoi(${a[0]})`, "Number(r[0])"),
|
|
12
|
+
Atoi: (a) => parsed("Atoi", a[0], `__strconv_atoi(${a[0]})`, "Number(r[0])"),
|
|
13
13
|
FormatBool: (a) => `String(${a[0]})`,
|
|
14
14
|
FormatInt: (a) => `(${a[0]}).toString(${a[1]})`,
|
|
15
15
|
FormatFloat: (a) =>
|
|
16
16
|
a.length < 3
|
|
17
17
|
? `String(${a[0]})`
|
|
18
18
|
: `__strconv_format_float(${a[0]}, ${a[1]}, ${a[2]})`,
|
|
19
|
-
ParseFloat: (a) =>
|
|
19
|
+
ParseFloat: (a) =>
|
|
20
|
+
parsed("ParseFloat", a[0], `__strconv_parse_float(${a[0]})`),
|
|
20
21
|
ParseInt: (a) =>
|
|
21
22
|
parsed(
|
|
23
|
+
"ParseInt",
|
|
24
|
+
a[0],
|
|
22
25
|
`__strconv_parse_int(${a[0]}, ${a[1]}, ${a[2] ?? 64})`,
|
|
23
26
|
"Number(r[0])",
|
|
24
27
|
),
|
|
25
|
-
ParseBool: (a) => parsed(`__strconv_parse_bool(${a[0]})`),
|
|
28
|
+
ParseBool: (a) => parsed("ParseBool", a[0], `__strconv_parse_bool(${a[0]})`),
|
|
26
29
|
Quote: (a) => `JSON.stringify(${a[0]})`,
|
|
27
30
|
Unquote: (a) =>
|
|
28
31
|
`((s) => { if (typeof s === "string" && s.startsWith("\`") && s.endsWith("\`") && s.length >= 2) { if (s.slice(1, -1).includes("\`")) return ["", __strconv_err_syntax]; return [s.slice(1, -1), null]; } try { const v = JSON.parse(s); if (typeof v !== "string") throw 0; return [v, null]; } catch(e) { return ["", __strconv_err_syntax]; } })(${a[0]})`,
|
|
@@ -37,6 +40,8 @@ const STRCONV_DISPATCH = {
|
|
|
37
40
|
FormatUint: (a) => `(BigInt.asUintN(64, BigInt(${a[0]}))).toString(${a[1]})`,
|
|
38
41
|
ParseUint: (a) =>
|
|
39
42
|
parsed(
|
|
43
|
+
"ParseUint",
|
|
44
|
+
a[0],
|
|
40
45
|
`__strconv_parse_uint(${a[0]}, ${a[1]}, ${a[2] ?? 64})`,
|
|
41
46
|
"Number(r[0])",
|
|
42
47
|
),
|
|
@@ -16,9 +16,9 @@ const STRINGS_M2 = {
|
|
|
16
16
|
LastIndex: "lastIndexOf",
|
|
17
17
|
Repeat: "repeat",
|
|
18
18
|
Split: "split",
|
|
19
|
-
Join: "join",
|
|
20
19
|
};
|
|
21
20
|
const STRINGS_DISPATCH = {
|
|
21
|
+
Join: ([a, sep]) => `(${a} ?? []).join(${sep})`,
|
|
22
22
|
Count: ([s, s2]) =>
|
|
23
23
|
`((s, sep) => sep === "" ? s.length + 1 : s.split(sep).length - 1)(${s}, ${s2})`,
|
|
24
24
|
Replace: ([s, s2, s3, n]) =>
|
|
@@ -37,7 +37,8 @@ const STRINGS_DISPATCH = {
|
|
|
37
37
|
TrimRight: ([s, s2]) =>
|
|
38
38
|
`((str, cut) => { const cs = new Set(cut); let j = str.length; while (j > 0 && cs.has(str[j - 1])) j--; return str.slice(0, j); })(${s}, ${s2})`,
|
|
39
39
|
EqualFold: ([s, s2]) => `${s}.toLowerCase() === ${s2}.toLowerCase()`,
|
|
40
|
-
Fields: ([s]) =>
|
|
40
|
+
Fields: ([s]) =>
|
|
41
|
+
`(${s}).split(/[ \\t\\n\\v\\f\\r\\u0085\\u00A0\\u1680\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]+/).filter(p => p !== "")`,
|
|
41
42
|
FieldsFunc: ([s, f]) =>
|
|
42
43
|
`((s, fn) => { const res = []; const runes = Array.from(s ?? ""); let cur = ""; for (const ch of runes) { const cp = ch.codePointAt(0); if (fn(cp)) { if (cur.length > 0) { res.push(cur); cur = ""; } } else { cur += ch; } } if (cur.length > 0) res.push(cur); return res; })(${s}, ${f})`,
|
|
43
44
|
Cut: ([s, s2]) =>
|
|
@@ -169,8 +170,83 @@ const STRINGS_DISPATCH = {
|
|
|
169
170
|
`((s, f) => { for (let i = 0; i < s.length; i++) { const cp = s.codePointAt(i); if (f(cp)) return i; if (cp > 0xFFFF) i++; } return -1; })(${s}, ${s2})`,
|
|
170
171
|
LastIndexFunc: ([s, s2]) =>
|
|
171
172
|
`((s, f) => { for (let i = s.length - 1; i >= 0; i--) { let cp = s.codePointAt(i); if (i > 0 && s.charCodeAt(i) >= 0xDC00 && s.charCodeAt(i) <= 0xDFFF && s.charCodeAt(i - 1) >= 0xD800 && s.charCodeAt(i - 1) <= 0xDBFF) { cp = s.codePointAt(i - 1); i--; } if (f(cp)) return i; } return -1; })(${s}, ${s2})`,
|
|
173
|
+
ToValidUTF8: ([s, repl]) =>
|
|
174
|
+
`(${s} ? ${s}.replace(/(?:[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF])+/g, ${repl} ?? "") : (${s} ?? ""))`,
|
|
172
175
|
NewReader: ([s]) =>
|
|
173
|
-
`((s) => ({
|
|
176
|
+
`((s) => ({
|
|
177
|
+
_bytes: new TextEncoder().encode(s ?? ""),
|
|
178
|
+
_pos: 0,
|
|
179
|
+
_prevRune: -1,
|
|
180
|
+
Read(p) {
|
|
181
|
+
if (this._pos >= this._bytes.length) return [0, __io_eof];
|
|
182
|
+
const n = Math.min(p.length, this._bytes.length - this._pos);
|
|
183
|
+
for (let i = 0; i < n; i++) p[i] = this._bytes[this._pos + i];
|
|
184
|
+
this._pos += n;
|
|
185
|
+
this._prevRune = -1;
|
|
186
|
+
return [n, null];
|
|
187
|
+
},
|
|
188
|
+
ReadAt(b, off) {
|
|
189
|
+
const o = Number(off);
|
|
190
|
+
if (o < 0) return [0, __error("strings.Reader.ReadAt: negative offset")];
|
|
191
|
+
if (o >= this._bytes.length) return [0, __io_eof];
|
|
192
|
+
const n = Math.min(b.length, this._bytes.length - o);
|
|
193
|
+
for (let i = 0; i < n; i++) b[i] = this._bytes[o + i];
|
|
194
|
+
return [n, n < b.length ? __io_eof : null];
|
|
195
|
+
},
|
|
196
|
+
ReadByte() {
|
|
197
|
+
if (this._pos >= this._bytes.length) return [0, __io_eof];
|
|
198
|
+
this._prevRune = -1;
|
|
199
|
+
return [this._bytes[this._pos++], null];
|
|
200
|
+
},
|
|
201
|
+
UnreadByte() {
|
|
202
|
+
if (this._pos <= 0) return __error("strings.Reader.UnreadByte: at beginning of string");
|
|
203
|
+
this._prevRune = -1;
|
|
204
|
+
this._pos--;
|
|
205
|
+
return null;
|
|
206
|
+
},
|
|
207
|
+
ReadRune() {
|
|
208
|
+
if (this._pos >= this._bytes.length) return [0, 0, __io_eof];
|
|
209
|
+
const rem = this._bytes.subarray(this._pos);
|
|
210
|
+
const str = new TextDecoder().decode(rem);
|
|
211
|
+
const cp = str.codePointAt(0);
|
|
212
|
+
const runeStr = str.slice(0, cp > 0xffff ? 2 : 1);
|
|
213
|
+
const sz = new TextEncoder().encode(runeStr).length;
|
|
214
|
+
this._prevRune = this._pos;
|
|
215
|
+
this._pos += sz;
|
|
216
|
+
return [cp, sz, null];
|
|
217
|
+
},
|
|
218
|
+
UnreadRune() {
|
|
219
|
+
if (this._prevRune === undefined || this._prevRune < 0 || this._prevRune >= this._pos) {
|
|
220
|
+
return __error("strings.Reader.UnreadRune: previous operation was not ReadRune");
|
|
221
|
+
}
|
|
222
|
+
this._pos = this._prevRune;
|
|
223
|
+
this._prevRune = -1;
|
|
224
|
+
return null;
|
|
225
|
+
},
|
|
226
|
+
Seek(offset, whence) {
|
|
227
|
+
const off = BigInt(offset);
|
|
228
|
+
const w = Number(whence);
|
|
229
|
+
let newPos;
|
|
230
|
+
if (w === 0) newPos = off;
|
|
231
|
+
else if (w === 1) newPos = BigInt(this._pos) + off;
|
|
232
|
+
else if (w === 2) newPos = BigInt(this._bytes.length) + off;
|
|
233
|
+
else return [0n, __error("strings.Reader.Seek: invalid whence")];
|
|
234
|
+
if (newPos < 0n) return [0n, __error("strings.Reader.Seek: negative position")];
|
|
235
|
+
this._pos = Number(newPos);
|
|
236
|
+
this._prevRune = -1;
|
|
237
|
+
return [newPos, null];
|
|
238
|
+
},
|
|
239
|
+
Size() { return BigInt(this._bytes.length); },
|
|
240
|
+
WriteTo(w) {
|
|
241
|
+
if (this._pos >= this._bytes.length) return [0, null];
|
|
242
|
+
const rem = this._bytes.subarray(this._pos);
|
|
243
|
+
const [n, err] = w.Write(rem);
|
|
244
|
+
this._pos += n;
|
|
245
|
+
return [n, err];
|
|
246
|
+
},
|
|
247
|
+
Len() { return Math.max(0, this._bytes.length - this._pos); },
|
|
248
|
+
Reset(s2) { this._bytes = new TextEncoder().encode(s2 ?? ""); this._pos = 0; this._prevRune = -1; }
|
|
249
|
+
}))(${s})`,
|
|
174
250
|
NewReplacer: (args) =>
|
|
175
251
|
`((...pairs) => {
|
|
176
252
|
const p = [];
|
|
@@ -211,7 +287,10 @@ const STRINGS_DISPATCH = {
|
|
|
211
287
|
/** @type {ThisType<CodeGen>} */
|
|
212
288
|
export const stringsMethods = {
|
|
213
289
|
_genStrings(fn, a) {
|
|
214
|
-
if (fn === "NewReader")
|
|
290
|
+
if (fn === "NewReader") {
|
|
291
|
+
this.useHelper("ioEOF");
|
|
292
|
+
this.useHelper("error");
|
|
293
|
+
}
|
|
215
294
|
const args = a();
|
|
216
295
|
const [s, s2] = args;
|
|
217
296
|
if (STRINGS_M1[fn]) return `${s}.${STRINGS_M1[fn]}()`;
|
|
@@ -10,6 +10,13 @@ export const testingMethods = {
|
|
|
10
10
|
return "false";
|
|
11
11
|
case "Verbose":
|
|
12
12
|
return "Boolean(globalThis.__gofront_verbose)";
|
|
13
|
+
case "Testing":
|
|
14
|
+
return "true";
|
|
15
|
+
case "Init":
|
|
16
|
+
return "/* testing.Init */";
|
|
17
|
+
case "Benchmark":
|
|
18
|
+
this.useHelper("testing");
|
|
19
|
+
return `__testing_Benchmark(${_a()[0]})`;
|
|
13
20
|
}
|
|
14
21
|
return undefined;
|
|
15
22
|
},
|
|
@@ -3,53 +3,52 @@
|
|
|
3
3
|
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
4
|
|
|
5
5
|
const TIME_METHOD_DISPATCH = {
|
|
6
|
-
Year: (r) =>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Minute: (r) =>
|
|
14
|
-
`(${r}._offset === 0 ? ${r}._d.getUTCMinutes() : ${r}._d.getMinutes())`,
|
|
15
|
-
Second: (r) =>
|
|
16
|
-
`(${r}._offset === 0 ? ${r}._d.getUTCSeconds() : ${r}._d.getSeconds())`,
|
|
17
|
-
Weekday: (r) =>
|
|
18
|
-
`(${r}._offset === 0 ? ${r}._d.getUTCDay() : ${r}._d.getDay())`,
|
|
6
|
+
Year: (r) => `__timeYear(${r})`,
|
|
7
|
+
Month: (r) => `__timeMonth(${r})`,
|
|
8
|
+
Day: (r) => `__timeDay(${r})`,
|
|
9
|
+
Hour: (r) => `__timeHour(${r})`,
|
|
10
|
+
Minute: (r) => `__timeMinute(${r})`,
|
|
11
|
+
Second: (r) => `__timeSecond(${r})`,
|
|
12
|
+
Weekday: (r) => `__timeWeekday(${r})`,
|
|
19
13
|
Unix: (r) => `Math.floor(${r}._d.getTime() / 1000)`,
|
|
20
14
|
UnixMilli: (r) => `${r}._d.getTime()`,
|
|
21
15
|
Add: (r, a) =>
|
|
22
|
-
`{_d: new Date(${r}._d.getTime() + Math.round(Number(${a[0]}) / 1000000))}`,
|
|
16
|
+
`{_d: new Date(${r}._d.getTime() + Math.round(Number(${a[0]}) / 1000000)), _offset: ${r}._offset, _loc: ${r}._loc, _ns: ${r}._ns}`,
|
|
23
17
|
Sub: (r, a) =>
|
|
24
18
|
`Math.round((${r}._d.getTime() - (${a[0]})._d.getTime()) * 1000000)`,
|
|
25
19
|
Before: (r, a) => `(${r}._d < (${a[0]})._d)`,
|
|
26
20
|
After: (r, a) => `(${r}._d > (${a[0]})._d)`,
|
|
27
|
-
Equal: (r, a) =>
|
|
21
|
+
Equal: (r, a) =>
|
|
22
|
+
`(${r}._d.getTime() === (${a[0]})._d.getTime() && (${r}._ns || 0) === ((${a[0]})._ns || 0))`,
|
|
28
23
|
IsZero: (r) =>
|
|
29
24
|
`(!${r} || !${r}._d || ${r}._isZero === true || ${r}._d.getTime() === -62135596800000 || (${r}._d.getUTCFullYear() <= 1 && ${r}._d.getUTCMonth() === 0 && ${r}._d.getUTCDate() === 1 && ${r}._d.getUTCHours() === 0 && ${r}._d.getUTCMinutes() === 0 && ${r}._d.getUTCSeconds() === 0 && ${r}._d.getUTCMilliseconds() === 0))`,
|
|
30
|
-
UnixNano: (r) =>
|
|
25
|
+
UnixNano: (r) =>
|
|
26
|
+
`(${r}?._d ? Math.round(${r}._d.getTime() * 1000000) + (${r}._ns || 0) : 0)`,
|
|
31
27
|
Nanosecond: (r) =>
|
|
32
|
-
`(${r}?._d ? (${r}._offset ===
|
|
33
|
-
UTC: (r) =>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
`({_d:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Round: (r, a) =>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Clock: (r) =>
|
|
44
|
-
`[${r}._offset === 0 ? ${r}._d.getUTCHours() : ${r}._d.getHours(), ${r}._offset === 0 ? ${r}._d.getUTCMinutes() : ${r}._d.getMinutes(), ${r}._offset === 0 ? ${r}._d.getUTCSeconds() : ${r}._d.getSeconds()]`,
|
|
45
|
-
YearDay: (r) =>
|
|
46
|
-
`Math.floor((${r}._d - new Date(${r}._d.getFullYear(), 0, 0)) / 86400000)`,
|
|
28
|
+
`(${r}?._d ? (typeof ${r}._offset === "number" ? ${r}._d.getUTCMilliseconds() : ${r}._d.getMilliseconds()) * 1000000 + (${r}._ns || 0) : 0)`,
|
|
29
|
+
UTC: (r) =>
|
|
30
|
+
`({_d: ${r}?._d ?? new Date(0), _offset: 0, _loc: null, _ns: ${r}?._ns || 0})`,
|
|
31
|
+
Local: (r) =>
|
|
32
|
+
`({_d: ${r}?._d ?? new Date(0), _offset: undefined, _loc: null, _ns: ${r}?._ns || 0})`,
|
|
33
|
+
AddDate: (r, a) => `__timeAddDate(${r}, ${a[0]}, ${a[1]}, ${a[2]})`,
|
|
34
|
+
Truncate: (r, a) => `__timeTruncate(${r}, ${a[0]})`,
|
|
35
|
+
Round: (r, a) => `__timeRound(${r}, ${a[0]})`,
|
|
36
|
+
Date: (r) => `__timeDate(${r})`,
|
|
37
|
+
Clock: (r) => `__timeClock(${r})`,
|
|
38
|
+
YearDay: (r) => `__timeYearDay(${r})`,
|
|
47
39
|
Compare: (r, a) =>
|
|
48
|
-
`(${r}._d.getTime() < (${a[0]})._d.getTime() ? -1 : (${r}._d.getTime() > (${a[0]})._d.getTime() ? 1 : 0))`,
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
`(${r}._d.getTime() < (${a[0]})._d.getTime() ? -1 : (${r}._d.getTime() > (${a[0]})._d.getTime() ? 1 : ((${r}._ns || 0) < ((${a[0]})._ns || 0) ? -1 : ((${r}._ns || 0) > ((${a[0]})._ns || 0) ? 1 : 0))))`,
|
|
41
|
+
ISOWeek: (r) => `__timeISOWeek(${r})`,
|
|
42
|
+
In: (r, a) =>
|
|
43
|
+
`((() => { const _loc = ${a[0]}; const _off = _loc && typeof _loc._offset === "number" ? _loc._offset : 0; return { _d: ${r}._d, _offset: _off, _loc, _ns: ${r}._ns }; })())`,
|
|
44
|
+
Location: (r) =>
|
|
45
|
+
`(${r}._loc ?? (${r}._offset === 0 ? { _name: "UTC", _offset: 0, String() { return "UTC"; } } : { _name: "Local", _offset: -${r}._d.getTimezoneOffset() * 60, String() { return "Local"; } }))`,
|
|
51
46
|
Zone: (r) =>
|
|
52
|
-
`[${r}._offset === 0 ? "UTC" : "LOCAL", ${r}._offset === 0 ? 0 : -${r}._d.getTimezoneOffset() * 60]`,
|
|
47
|
+
`[${r}._loc ? ${r}._loc._name : (${r}._offset === 0 ? "UTC" : "LOCAL"), ${r}._loc ? ${r}._loc._offset : (${r}._offset === 0 ? 0 : -${r}._d.getTimezoneOffset() * 60)]`,
|
|
48
|
+
MarshalJSON: (r) => `__timeMarshalJSON(${r})`,
|
|
49
|
+
UnmarshalJSON: (r, a) => `__timeUnmarshalJSON(${r}, ${a[0]})`,
|
|
50
|
+
MarshalText: (r) => `__timeMarshalText(${r})`,
|
|
51
|
+
UnmarshalText: (r, a) => `__timeUnmarshalText(${r}, ${a[0]})`,
|
|
53
52
|
};
|
|
54
53
|
|
|
55
54
|
const DURATION_METHOD_DISPATCH = {
|
|
@@ -60,6 +59,9 @@ const DURATION_METHOD_DISPATCH = {
|
|
|
60
59
|
Minutes: (r) => `(Number(${r}) / 60000000000)`,
|
|
61
60
|
Hours: (r) => `(Number(${r}) / 3600000000000)`,
|
|
62
61
|
String: (r) => `__durationString(${r})`,
|
|
62
|
+
Truncate: (r, a) => `(${a[0]} <= 0 ? ${r} : ${r} - (${r} % ${a[0]}))`,
|
|
63
|
+
Round: (r, a) => `__durationRound(${r}, ${a[0]})`,
|
|
64
|
+
Abs: (r) => `(${r} >= 0 ? ${r} : -(${r}))`,
|
|
63
65
|
};
|
|
64
66
|
|
|
65
67
|
const TIME_DISPATCH = {
|
|
@@ -69,11 +71,16 @@ const TIME_DISPATCH = {
|
|
|
69
71
|
`(Math.round(((typeof globalThis.__GOFRONT_CLOCK === "function" ? globalThis.__GOFRONT_CLOCK() : Date.now()) - (${a[0]})._d.getTime()) * 1000000))`,
|
|
70
72
|
Sleep: (a) => `await new Promise(r => setTimeout(r, ${a[0]} / 1000000))`,
|
|
71
73
|
Unix: (a) =>
|
|
72
|
-
`{_d: new Date(Number(${a[0]}) * 1000 + Math.round(Number(${a[1] || 0}) / 1000000))}`,
|
|
73
|
-
UnixMicro: (a) =>
|
|
74
|
+
`{_d: new Date(Number(${a[0]}) * 1000 + Math.round(Number(${a[1] || 0}) / 1000000)), _ns: Math.round(Number(${a[1] || 0}) % 1000000)}`,
|
|
75
|
+
UnixMicro: (a) =>
|
|
76
|
+
`{_d: new Date(Math.round(Number(${a[0]}) / 1000)), _ns: Math.round((Number(${a[0]}) % 1000) * 1000)}`,
|
|
74
77
|
UnixMilli: (a) => `{_d: new Date(Number(${a[0]}))}`,
|
|
75
78
|
Date: (a) =>
|
|
76
|
-
`{_d: new Date(${a[0]}, ${a[1]} - 1, ${a[2]}, ${a[3]}, ${a[4]}, ${a[5]}, Math.round(Number(${a[6] || 0}) / 1000000))}`,
|
|
79
|
+
`{_d: new Date(${a[0]}, ${a[1]} - 1, ${a[2]}, ${a[3]}, ${a[4]}, ${a[5]}, Math.round(Number(${a[6] || 0}) / 1000000)), _ns: Math.round(Number(${a[6] || 0}) % 1000000)}`,
|
|
80
|
+
ParseDuration: (a) => `__timeParseDuration(${a[0]})`,
|
|
81
|
+
FixedZone: (a) =>
|
|
82
|
+
`({ _name: ${a[0]}, _offset: ${a[1]}, String() { return this._name; } })`,
|
|
83
|
+
AfterFunc: (a) => `__timeAfterFunc(${a[0]}, ${a[1]})`,
|
|
77
84
|
};
|
|
78
85
|
|
|
79
86
|
/** @type {ThisType<CodeGen>} */
|
|
@@ -82,12 +89,13 @@ export const timeMethods = {
|
|
|
82
89
|
const recv = expr.func.expr;
|
|
83
90
|
const recvJs = this.genExpr(recv);
|
|
84
91
|
const args = expr.args.map((a) => this.genExpr(a));
|
|
92
|
+
this.useHelper("timeFmt");
|
|
93
|
+
this.useHelper("duration");
|
|
94
|
+
this.useHelper("timeParse");
|
|
85
95
|
if (method === "Format") {
|
|
86
|
-
this.useHelper("timeFmt");
|
|
87
96
|
return `__timeFmt(${recvJs}, ${args[0]})`;
|
|
88
97
|
}
|
|
89
98
|
if (method === "String") {
|
|
90
|
-
this.useHelper("timeFmt");
|
|
91
99
|
return `__timeFmt(${recvJs}, "2006-01-02 15:04:05.999999999 -0700 MST")`;
|
|
92
100
|
}
|
|
93
101
|
const gen = TIME_METHOD_DISPATCH[method];
|
|
@@ -97,30 +105,46 @@ export const timeMethods = {
|
|
|
97
105
|
_genDurationMethodCall(method, expr) {
|
|
98
106
|
const recv = expr.func.expr;
|
|
99
107
|
const recvJs = this.genExpr(recv);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
108
|
+
const args = expr.args.map((a) => this.genExpr(a));
|
|
109
|
+
this.useHelper("duration");
|
|
103
110
|
const gen = DURATION_METHOD_DISPATCH[method];
|
|
104
|
-
return gen ? gen(recvJs) : undefined;
|
|
111
|
+
return gen ? gen(recvJs, args) : undefined;
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
_genTimeDate(args, expr) {
|
|
115
|
+
this.useHelper("timeFmt");
|
|
116
|
+
const locArg = expr?.args?.[7];
|
|
117
|
+
const isUtc =
|
|
118
|
+
(locArg?.kind === "SelectorExpr" &&
|
|
119
|
+
(locArg.sel?.name === "UTC" || locArg.field === "UTC")) ||
|
|
120
|
+
(locArg?.kind === "Ident" && locArg.name === "UTC") ||
|
|
121
|
+
args[7] === '"UTC"';
|
|
122
|
+
if (isUtc) {
|
|
123
|
+
return `{_d: new Date(Date.UTC(${args[0]}, ${args[1]} - 1, ${args[2]}, ${args[3]}, ${args[4]}, ${args[5]}, Math.floor(Number(${args[6] || 0}) / 1000000))), _offset: 0, _loc: null, _ns: Math.floor(Number(${args[6] || 0}) % 1000000)}`;
|
|
124
|
+
}
|
|
125
|
+
return `((() => { const _loc = ${args[7]}; const _off = _loc && typeof _loc._offset === "number" ? _loc._offset : undefined; const _ms = Math.floor(Number(${args[6] || 0}) / 1000000); const _remNs = Math.floor(Number(${args[6] || 0}) % 1000000); if (_off !== undefined) { const _d = new Date(Date.UTC(${args[0]}, ${args[1]} - 1, ${args[2]}, ${args[3]}, ${args[4]}, ${args[5]}, _ms) - _off * 1000); return { _d, _offset: _off, _loc, _ns: _remNs }; } return { _d: new Date(${args[0]}, ${args[1]} - 1, ${args[2]}, ${args[3]}, ${args[4]}, ${args[5]}, _ms), _offset: undefined, _loc: null, _ns: _remNs }; })())`;
|
|
105
126
|
},
|
|
106
127
|
|
|
107
128
|
_genTime(fn, a, expr) {
|
|
129
|
+
if (fn === "Date") return this._genTimeDate(a(), expr);
|
|
108
130
|
if (fn === "Parse") {
|
|
109
131
|
this.useHelper("timeParse");
|
|
132
|
+
this.useHelper("timeFmt");
|
|
110
133
|
return `__timeParse(${a()[0]}, ${a()[1]})`;
|
|
111
134
|
}
|
|
112
|
-
if (fn === "
|
|
135
|
+
if (fn === "ParseDuration") {
|
|
136
|
+
this.useHelper("duration");
|
|
137
|
+
return `__timeParseDuration(${a()[0]})`;
|
|
138
|
+
}
|
|
139
|
+
if (fn === "FixedZone") {
|
|
140
|
+
this.useHelper("timeFmt");
|
|
141
|
+
const args = a();
|
|
142
|
+
return `({ _name: ${args[0]}, _offset: ${args[1]}, String() { return this._name; } })`;
|
|
143
|
+
}
|
|
144
|
+
if (fn === "AfterFunc") {
|
|
145
|
+
this.useHelper("timeFmt");
|
|
113
146
|
const args = a();
|
|
114
|
-
|
|
115
|
-
const isUtc =
|
|
116
|
-
(locArg?.kind === "SelectorExpr" &&
|
|
117
|
-
(locArg.sel?.name === "UTC" || locArg.field === "UTC")) ||
|
|
118
|
-
(locArg?.kind === "Ident" && locArg.name === "UTC") ||
|
|
119
|
-
args[7] === '"UTC"';
|
|
120
|
-
if (isUtc) {
|
|
121
|
-
return `{_d: new Date(Date.UTC(${args[0]}, ${args[1]} - 1, ${args[2]}, ${args[3]}, ${args[4]}, ${args[5]}, Math.round(Number(${args[6] || 0}) / 1000000))), _offset: 0}`;
|
|
122
|
-
}
|
|
123
|
-
return `{_d: new Date(${args[0]}, ${args[1]} - 1, ${args[2]}, ${args[3]}, ${args[4]}, ${args[5]}, Math.round(Number(${args[6] || 0}) / 1000000))}`;
|
|
147
|
+
return `__timeAfterFunc(${args[0]}, ${args[1]})`;
|
|
124
148
|
}
|
|
125
149
|
const gen = TIME_DISPATCH[fn];
|
|
126
150
|
return gen ? gen(a()) : undefined;
|
|
@@ -10,7 +10,7 @@ export const unicodeMethods = {
|
|
|
10
10
|
const UNICODE_TEST = {
|
|
11
11
|
IsLetter: `/\\p{L}/u.test(${cp})`,
|
|
12
12
|
IsDigit: `/\\p{Nd}/u.test(${cp})`,
|
|
13
|
-
IsSpace:
|
|
13
|
+
IsSpace: `/[ \\t\\n\\v\\f\\r\\u0085\\u00A0\\u1680\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]/.test(${cp})`,
|
|
14
14
|
IsUpper: `/\\p{Lu}/u.test(${cp})`,
|
|
15
15
|
IsLower: `/\\p{Ll}/u.test(${cp})`,
|
|
16
16
|
IsPunct: `/\\p{P}/u.test(${cp})`,
|
|
@@ -9,7 +9,7 @@ const UTF8_DISPATCH = {
|
|
|
9
9
|
ValidString: (a) =>
|
|
10
10
|
`/[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/.test(${a[0]}) === false`,
|
|
11
11
|
ValidRune: (a) =>
|
|
12
|
-
`(${a[0]}) >= 0 && (${a[0]}) <= 0x10FFFF && !((${a[0]}) >= 0xD800 && (${a[0]}) <= 0xDFFF)`,
|
|
12
|
+
`((${a[0]}) >= 0 && (${a[0]}) <= 0x10FFFF && !((${a[0]}) >= 0xD800 && (${a[0]}) <= 0xDFFF))`,
|
|
13
13
|
DecodeRuneInString: (a) =>
|
|
14
14
|
`((s) => { if (!s) return [0xFFFD, 0]; const cp = s.codePointAt(0); return [cp, cp > 0xFFFF ? 2 : 1]; })(${a[0]})`,
|
|
15
15
|
DecodeLastRuneInString: (a) =>
|