gofront 1.6.0 → 1.6.1
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/package.json +1 -1
- package/src/backend/js/expressions.js +238 -109
- package/src/backend/js/index.js +38 -1
- package/src/backend/js/runtime.js +953 -53
- package/src/backend/js/statements.js +55 -67
- package/src/backend/js/stdlib/base64.js +12 -0
- package/src/backend/js/stdlib/binary.js +102 -0
- package/src/backend/js/stdlib/bits.js +15 -1
- package/src/backend/js/stdlib/builder.js +28 -9
- package/src/backend/js/stdlib/bytes.js +75 -18
- package/src/backend/js/stdlib/errors.js +20 -1
- package/src/backend/js/stdlib/fmt.js +70 -13
- package/src/backend/js/stdlib/hex.js +17 -0
- package/src/backend/js/stdlib/html.js +1 -1
- package/src/backend/js/stdlib/index.js +16 -0
- package/src/backend/js/stdlib/io.js +105 -3
- package/src/backend/js/stdlib/math.js +13 -1
- package/src/backend/js/stdlib/path.js +18 -4
- package/src/backend/js/stdlib/rand.js +10 -5
- package/src/backend/js/stdlib/sha256.js +12 -0
- package/src/backend/js/stdlib/slices.js +52 -26
- package/src/backend/js/stdlib/strconv.js +21 -5
- package/src/backend/js/stdlib/strings.js +148 -15
- package/src/backend/js/stdlib/sync.js +13 -0
- package/src/backend/js/stdlib/time.js +90 -19
- package/src/backend/js/stdlib/unicode.js +2 -2
- package/src/backend/wasm/boundary.js +1207 -41
- package/src/backend/wasm/const-fold.js +205 -0
- package/src/backend/wasm/emit-builtins.js +203 -76
- package/src/backend/wasm/emit-exprs.js +464 -276
- package/src/backend/wasm/emit-maps.js +144 -8
- package/src/backend/wasm/emit-stdlib.js +12 -3005
- package/src/backend/wasm/emit-stmts.js +264 -270
- package/src/backend/wasm/emit.js +115 -87
- package/src/backend/wasm/encode.js +55 -29
- package/src/backend/wasm/index.js +1001 -32
- package/src/backend/wasm/optimize.js +13 -4
- package/src/backend/wasm/stdlib/bytes.js +5039 -0
- package/src/backend/wasm/stdlib/core.js +8903 -0
- package/src/backend/wasm/stdlib/index.js +40 -0
- package/src/backend/wasm/stdlib/io.js +2161 -0
- package/src/backend/wasm/stdlib/packages.js +2400 -0
- package/src/backend/wasm/stdlib/pure.js +720 -0
- package/src/backend/wasm/stdlib/time.js +1200 -0
- package/src/backend/wasm/types.js +153 -1
- package/src/cli-core.js +1 -1
- package/src/compiler.js +18 -4
- package/src/dts-parser.js +79 -126
- package/src/index.js +2 -6
- package/src/lexer.js +80 -29
- package/src/lower/boxing.js +1 -2
- package/src/lower/captures.js +2 -6
- package/src/lower/ownership.js +30 -9
- package/src/minifier.js +20 -68
- package/src/parser/declarations.js +3 -6
- package/src/parser/expressions.js +3 -8
- package/src/parser/index.js +18 -3
- package/src/parser/statements.js +25 -38
- package/src/parser/types.js +1 -2
- package/src/resolver.js +2 -27
- package/src/templ-lexer.js +29 -63
- package/src/templ-parser.js +22 -45
- package/src/typechecker/assignability.js +81 -13
- package/src/typechecker/expressions.js +102 -2
- package/src/typechecker/resolve.js +36 -6
- package/src/typechecker/stdlib/core.js +280 -89
- package/src/typechecker/stdlib/extended.js +453 -1
- package/src/typechecker/types.js +344 -6
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// Parsers return [value, msg|null] from the shared __strconv_* helpers
|
|
6
6
|
// (runtime.js); the message becomes a Go error value.
|
|
7
7
|
const parsed = (call, toValue = "r[0]") =>
|
|
8
|
-
`((r) => [${toValue}, r[1] === null ? null : __error(r[1])])(${call})`;
|
|
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})`;
|
|
9
9
|
|
|
10
10
|
const STRCONV_DISPATCH = {
|
|
11
11
|
Itoa: (a) => `String(${a[0]})`,
|
|
@@ -25,17 +25,28 @@ const STRCONV_DISPATCH = {
|
|
|
25
25
|
ParseBool: (a) => parsed(`__strconv_parse_bool(${a[0]})`),
|
|
26
26
|
Quote: (a) => `JSON.stringify(${a[0]})`,
|
|
27
27
|
Unquote: (a) =>
|
|
28
|
-
`((s) => { try { const v = JSON.parse(s); return [v, null]; } catch(e) { return ["",
|
|
28
|
+
`((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]})`,
|
|
29
29
|
AppendInt: (a) =>
|
|
30
|
-
`
|
|
30
|
+
`((d, s) => { const e = new TextEncoder().encode(s); const dl = d ? d.length : 0; const r = new Uint8Array(dl + e.length); if (dl > 0) r.set(d, 0); r.set(e, dl); return r; })(${a[0]}, (${a[1]}).toString(${a[2]}))`,
|
|
31
|
+
AppendUint: (a) =>
|
|
32
|
+
`((d, s) => { const e = new TextEncoder().encode(s); const dl = d ? d.length : 0; const r = new Uint8Array(dl + e.length); if (dl > 0) r.set(d, 0); r.set(e, dl); return r; })(${a[0]}, (BigInt.asUintN(64, BigInt(${a[1]}))).toString(${a[2]}))`,
|
|
33
|
+
AppendBool: (a) =>
|
|
34
|
+
`((d, s) => { const e = new TextEncoder().encode(s); const dl = d ? d.length : 0; const r = new Uint8Array(dl + e.length); if (dl > 0) r.set(d, 0); r.set(e, dl); return r; })(${a[0]}, String(${a[1]}))`,
|
|
31
35
|
AppendFloat: (a) =>
|
|
32
|
-
`
|
|
36
|
+
`((d, s) => { const e = new TextEncoder().encode(s); const dl = d ? d.length : 0; const r = new Uint8Array(dl + e.length); if (dl > 0) r.set(d, 0); r.set(e, dl); return r; })(${a[0]}, __strconv_format_float(${a[1]}, typeof (${a[2]}) === "string" ? (${a[2]}).charCodeAt(0) : (${a[2]}), ${a[3]}))`,
|
|
37
|
+
FormatUint: (a) => `(BigInt.asUintN(64, BigInt(${a[0]}))).toString(${a[1]})`,
|
|
38
|
+
ParseUint: (a) =>
|
|
39
|
+
parsed(
|
|
40
|
+
`__strconv_parse_uint(${a[0]}, ${a[1]}, ${a[2] ?? 64})`,
|
|
41
|
+
"Number(r[0])",
|
|
42
|
+
),
|
|
33
43
|
};
|
|
34
44
|
|
|
35
45
|
const USES_ERROR = new Set([
|
|
36
46
|
"Atoi",
|
|
37
47
|
"ParseFloat",
|
|
38
48
|
"ParseInt",
|
|
49
|
+
"ParseUint",
|
|
39
50
|
"ParseBool",
|
|
40
51
|
"Unquote",
|
|
41
52
|
]);
|
|
@@ -43,15 +54,20 @@ const USES_STRCONV = new Set([
|
|
|
43
54
|
"Atoi",
|
|
44
55
|
"ParseFloat",
|
|
45
56
|
"ParseInt",
|
|
57
|
+
"ParseUint",
|
|
46
58
|
"ParseBool",
|
|
47
59
|
"FormatFloat",
|
|
60
|
+
"AppendFloat",
|
|
48
61
|
]);
|
|
49
62
|
|
|
50
63
|
/** @type {ThisType<CodeGen>} */
|
|
51
64
|
export const strconvMethods = {
|
|
52
65
|
_genStrconv(fn, a) {
|
|
53
66
|
const gen = STRCONV_DISPATCH[fn];
|
|
54
|
-
if (gen && USES_ERROR.has(fn))
|
|
67
|
+
if (gen && USES_ERROR.has(fn)) {
|
|
68
|
+
this.useHelper("error");
|
|
69
|
+
this.useHelper("strconvError");
|
|
70
|
+
}
|
|
55
71
|
if (gen && USES_STRCONV.has(fn)) this.useHelper("strconv");
|
|
56
72
|
return gen ? gen(a()) : undefined;
|
|
57
73
|
},
|
|
@@ -27,27 +27,81 @@ const STRINGS_DISPATCH = {
|
|
|
27
27
|
: `((str, o, nw, cnt) => { if (cnt < 0) return str.replaceAll(o, nw); let r = ""; let i = 0; for (; cnt > 0; cnt--) { const j = str.indexOf(o, i); if (j < 0) break; r += str.slice(i, j) + nw; i = j + o.length; if (o.length === 0) { if (i >= str.length) break; r += str[i]; i++; } } return r + str.slice(i); })(${s}, ${s2}, ${s3}, ${n})`,
|
|
28
28
|
ReplaceAll: ([s, s2, s3]) => `${s}.replaceAll(${s2}, ${s3})`,
|
|
29
29
|
Trim: ([s, s2]) =>
|
|
30
|
-
|
|
30
|
+
`((str, cut) => { const cs = new Set(cut); let i = 0, j = str.length; while (i < j && cs.has(str[i])) i++; while (j > i && cs.has(str[j - 1])) j--; return str.slice(i, j); })(${s}, ${s2})`,
|
|
31
31
|
TrimPrefix: ([s, s2]) =>
|
|
32
32
|
`((s, pre) => s.startsWith(pre) ? s.slice(pre.length) : s)(${s}, ${s2})`,
|
|
33
33
|
TrimSuffix: ([s, s2]) =>
|
|
34
34
|
`((s, suf) => !suf.length || !s.endsWith(suf) ? s : s.slice(0, -suf.length))(${s}, ${s2})`,
|
|
35
|
-
TrimLeft: ([s, s2]) =>
|
|
36
|
-
|
|
35
|
+
TrimLeft: ([s, s2]) =>
|
|
36
|
+
`((str, cut) => { const cs = new Set(cut); let i = 0; while (i < str.length && cs.has(str[i])) i++; return str.slice(i); })(${s}, ${s2})`,
|
|
37
|
+
TrimRight: ([s, s2]) =>
|
|
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})`,
|
|
37
39
|
EqualFold: ([s, s2]) => `${s}.toLowerCase() === ${s2}.toLowerCase()`,
|
|
38
40
|
Fields: ([s]) => `(${s}).trim() === '' ? [] : (${s}).trim().split(/\\s+/)`,
|
|
41
|
+
FieldsFunc: ([s, f]) =>
|
|
42
|
+
`((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})`,
|
|
39
43
|
Cut: ([s, s2]) =>
|
|
40
44
|
`((s, sep) => { const i = s.indexOf(sep); return i < 0 ? [s, "", false] : [s.slice(0, i), s.slice(i + sep.length), true]; })(${s}, ${s2})`,
|
|
41
45
|
CutPrefix: ([s, s2]) =>
|
|
42
|
-
`(
|
|
46
|
+
`((str, pre) => str.startsWith(pre) ? [str.slice(pre.length), true] : [str, false])(${s}, ${s2})`,
|
|
43
47
|
CutSuffix: ([s, s2]) =>
|
|
44
|
-
`(
|
|
48
|
+
`((str, suf) => { if (suf === "") return [str, true]; return str.endsWith(suf) ? [str.slice(0, -suf.length), true] : [str, false]; })(${s}, ${s2})`,
|
|
45
49
|
SplitN: ([s, s2, s3]) =>
|
|
46
|
-
`((s, sep, n) => {
|
|
50
|
+
`((s, sep, n) => {
|
|
51
|
+
if (n === 0) return null;
|
|
52
|
+
if (n < 0) return sep === "" ? [...s] : s.split(sep);
|
|
53
|
+
if (sep === "") {
|
|
54
|
+
const chars = [...s];
|
|
55
|
+
if (chars.length <= n) return chars;
|
|
56
|
+
const r = chars.slice(0, n - 1);
|
|
57
|
+
r.push(chars.slice(n - 1).join(""));
|
|
58
|
+
return r;
|
|
59
|
+
}
|
|
60
|
+
const r = [];
|
|
61
|
+
let cur = s;
|
|
62
|
+
for (let i = 1; i < n && cur.length; i++) {
|
|
63
|
+
const j = cur.indexOf(sep);
|
|
64
|
+
if (j < 0) break;
|
|
65
|
+
r.push(cur.slice(0, j));
|
|
66
|
+
cur = cur.slice(j + sep.length);
|
|
67
|
+
}
|
|
68
|
+
r.push(cur);
|
|
69
|
+
return r;
|
|
70
|
+
})(${s}, ${s2}, ${s3})`,
|
|
47
71
|
SplitAfter: ([s, s2]) =>
|
|
48
|
-
`((s, sep) => {
|
|
72
|
+
`((s, sep) => {
|
|
73
|
+
if (sep === "") return [...s];
|
|
74
|
+
const r = [];
|
|
75
|
+
let cur = s;
|
|
76
|
+
while (true) {
|
|
77
|
+
const j = cur.indexOf(sep);
|
|
78
|
+
if (j < 0) { r.push(cur); break; }
|
|
79
|
+
r.push(cur.slice(0, j + sep.length));
|
|
80
|
+
cur = cur.slice(j + sep.length);
|
|
81
|
+
}
|
|
82
|
+
return r;
|
|
83
|
+
})(${s}, ${s2})`,
|
|
49
84
|
SplitAfterN: ([s, s2, s3]) =>
|
|
50
|
-
`((s, sep, n) => {
|
|
85
|
+
`((s, sep, n) => {
|
|
86
|
+
if (n === 0) return null;
|
|
87
|
+
if (sep === "") {
|
|
88
|
+
const chars = [...s];
|
|
89
|
+
if (n < 0 || chars.length <= n) return chars;
|
|
90
|
+
const r = chars.slice(0, n - 1);
|
|
91
|
+
r.push(chars.slice(n - 1).join(""));
|
|
92
|
+
return r;
|
|
93
|
+
}
|
|
94
|
+
const r = [];
|
|
95
|
+
let cur = s;
|
|
96
|
+
for (let i = 1; (n < 0 || i < n) && cur.length; i++) {
|
|
97
|
+
const j = cur.indexOf(sep);
|
|
98
|
+
if (j < 0) break;
|
|
99
|
+
r.push(cur.slice(0, j + sep.length));
|
|
100
|
+
cur = cur.slice(j + sep.length);
|
|
101
|
+
}
|
|
102
|
+
r.push(cur);
|
|
103
|
+
return r;
|
|
104
|
+
})(${s}, ${s2}, ${s3})`,
|
|
51
105
|
IndexAny: ([s, s2]) =>
|
|
52
106
|
`((s, chars) => { let m = -1; for (const c of chars) { const i = s.indexOf(c); if (i >= 0 && (m < 0 || i < m)) m = i; } return m; })(${s}, ${s2})`,
|
|
53
107
|
LastIndexAny: ([s, s2]) =>
|
|
@@ -58,27 +112,106 @@ const STRINGS_DISPATCH = {
|
|
|
58
112
|
IndexByte: ([s, s2]) => `(${s}).indexOf(String.fromCharCode(${s2}))`,
|
|
59
113
|
LastIndexByte: ([s, s2]) => `(${s}).lastIndexOf(String.fromCharCode(${s2}))`,
|
|
60
114
|
Map: ([s, s2]) =>
|
|
61
|
-
`
|
|
115
|
+
`((f, s) => { let out = ""; for (const c of s) { const r = f(c.codePointAt(0)); if (r >= 0) out += String.fromCodePoint(r); } return out; })(${s}, ${s2})`,
|
|
62
116
|
Title: ([s]) => `(${s}).replace(/\\b\\w/g, c => c.toUpperCase())`,
|
|
63
117
|
TrimFunc: ([s, s2]) =>
|
|
64
|
-
`((s, f) => {
|
|
118
|
+
`((s, f) => {
|
|
119
|
+
let l = 0, r = s.length;
|
|
120
|
+
while (l < r) {
|
|
121
|
+
const cp = s.codePointAt(l);
|
|
122
|
+
if (!f(cp)) break;
|
|
123
|
+
l += cp > 0xFFFF ? 2 : 1;
|
|
124
|
+
}
|
|
125
|
+
while (r > l) {
|
|
126
|
+
let cp, step;
|
|
127
|
+
if (r > 1 && s.charCodeAt(r - 1) >= 0xDC00 && s.charCodeAt(r - 1) <= 0xDFFF &&
|
|
128
|
+
s.charCodeAt(r - 2) >= 0xD800 && s.charCodeAt(r - 2) <= 0xDBFF) {
|
|
129
|
+
cp = s.codePointAt(r - 2);
|
|
130
|
+
step = 2;
|
|
131
|
+
} else {
|
|
132
|
+
cp = s.codePointAt(r - 1);
|
|
133
|
+
step = 1;
|
|
134
|
+
}
|
|
135
|
+
if (!f(cp)) break;
|
|
136
|
+
r -= step;
|
|
137
|
+
}
|
|
138
|
+
return s.slice(l, r);
|
|
139
|
+
})(${s}, ${s2})`,
|
|
65
140
|
TrimLeftFunc: ([s, s2]) =>
|
|
66
|
-
`((s, f) => {
|
|
141
|
+
`((s, f) => {
|
|
142
|
+
let l = 0;
|
|
143
|
+
while (l < s.length) {
|
|
144
|
+
const cp = s.codePointAt(l);
|
|
145
|
+
if (!f(cp)) break;
|
|
146
|
+
l += cp > 0xFFFF ? 2 : 1;
|
|
147
|
+
}
|
|
148
|
+
return s.slice(l);
|
|
149
|
+
})(${s}, ${s2})`,
|
|
67
150
|
TrimRightFunc: ([s, s2]) =>
|
|
68
|
-
`((s, f) => {
|
|
151
|
+
`((s, f) => {
|
|
152
|
+
let r = s.length;
|
|
153
|
+
while (r > 0) {
|
|
154
|
+
let cp, step;
|
|
155
|
+
if (r > 1 && s.charCodeAt(r - 1) >= 0xDC00 && s.charCodeAt(r - 1) <= 0xDFFF &&
|
|
156
|
+
s.charCodeAt(r - 2) >= 0xD800 && s.charCodeAt(r - 2) <= 0xDBFF) {
|
|
157
|
+
cp = s.codePointAt(r - 2);
|
|
158
|
+
step = 2;
|
|
159
|
+
} else {
|
|
160
|
+
cp = s.codePointAt(r - 1);
|
|
161
|
+
step = 1;
|
|
162
|
+
}
|
|
163
|
+
if (!f(cp)) break;
|
|
164
|
+
r -= step;
|
|
165
|
+
}
|
|
166
|
+
return s.slice(0, r);
|
|
167
|
+
})(${s}, ${s2})`,
|
|
69
168
|
IndexFunc: ([s, s2]) =>
|
|
70
169
|
`((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})`,
|
|
71
170
|
LastIndexFunc: ([s, s2]) =>
|
|
72
|
-
`((s, f) => { for (let i = s.length - 1; i >= 0; i--) {
|
|
171
|
+
`((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})`,
|
|
73
172
|
NewReader: ([s]) =>
|
|
74
|
-
`{
|
|
173
|
+
`((s) => ({ _bytes: new TextEncoder().encode(s), _pos: 0, Read(p) { if (this._pos >= this._bytes.length) return [0, __io_eof]; const n = Math.min(p.length, this._bytes.length - this._pos); for (let i = 0; i < n; i++) p[i] = this._bytes[this._pos + i]; this._pos += n; return [n, null]; }, Len() { return Math.max(0, this._bytes.length - this._pos); }, Reset(s2) { this._bytes = new TextEncoder().encode(s2); this._pos = 0; } }))(${s})`,
|
|
75
174
|
NewReplacer: (args) =>
|
|
76
|
-
`((...pairs) => {
|
|
175
|
+
`((...pairs) => {
|
|
176
|
+
const p = [];
|
|
177
|
+
for (let i = 0; i < pairs.length; i += 2) {
|
|
178
|
+
if (pairs[i] !== undefined && pairs[i+1] !== undefined) {
|
|
179
|
+
p.push([pairs[i], pairs[i+1]]);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
_p: p,
|
|
184
|
+
Replace(s) {
|
|
185
|
+
s = s ?? "";
|
|
186
|
+
if (!this._p || this._p.length === 0 || s === "") return s;
|
|
187
|
+
let out = "";
|
|
188
|
+
let i = 0;
|
|
189
|
+
while (i < s.length) {
|
|
190
|
+
let matched = false;
|
|
191
|
+
for (let k = 0; k < this._p.length; k++) {
|
|
192
|
+
const [oldStr, newStr] = this._p[k];
|
|
193
|
+
if (oldStr.length > 0 && s.startsWith(oldStr, i)) {
|
|
194
|
+
out += newStr;
|
|
195
|
+
i += oldStr.length;
|
|
196
|
+
matched = true;
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (!matched) {
|
|
201
|
+
out += s[i];
|
|
202
|
+
i++;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return out;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
})(${args.join(", ")})`,
|
|
77
209
|
};
|
|
78
210
|
|
|
79
211
|
/** @type {ThisType<CodeGen>} */
|
|
80
212
|
export const stringsMethods = {
|
|
81
213
|
_genStrings(fn, a) {
|
|
214
|
+
if (fn === "NewReader") this.useHelper("ioEOF");
|
|
82
215
|
const args = a();
|
|
83
216
|
const [s, s2] = args;
|
|
84
217
|
if (STRINGS_M1[fn]) return `${s}.${STRINGS_M1[fn]}()`;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/backend/js/stdlib/sync.js
|
|
2
|
+
// CodeGen for Go sync package.
|
|
3
|
+
|
|
4
|
+
export const syncMethods = {
|
|
5
|
+
_genSync(fn) {
|
|
6
|
+
this.useHelper("sync");
|
|
7
|
+
if (fn === "Once") return "__sync_once()";
|
|
8
|
+
if (fn === "Mutex") return "__sync_mutex()";
|
|
9
|
+
if (fn === "RWMutex") return "__sync_rwmutex()";
|
|
10
|
+
if (fn === "WaitGroup") return "__sync_waitgroup()";
|
|
11
|
+
return undefined;
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -3,29 +3,77 @@
|
|
|
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
|
-
|
|
6
|
+
Year: (r) =>
|
|
7
|
+
`(${r}._offset === 0 ? ${r}._d.getUTCFullYear() : ${r}._d.getFullYear())`,
|
|
8
|
+
Month: (r) =>
|
|
9
|
+
`(${r}._offset === 0 ? ${r}._d.getUTCMonth() + 1 : ${r}._d.getMonth() + 1)`,
|
|
10
|
+
Day: (r) => `(${r}._offset === 0 ? ${r}._d.getUTCDate() : ${r}._d.getDate())`,
|
|
11
|
+
Hour: (r) =>
|
|
12
|
+
`(${r}._offset === 0 ? ${r}._d.getUTCHours() : ${r}._d.getHours())`,
|
|
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())`,
|
|
13
19
|
Unix: (r) => `Math.floor(${r}._d.getTime() / 1000)`,
|
|
14
20
|
UnixMilli: (r) => `${r}._d.getTime()`,
|
|
15
|
-
Add: (r, a) =>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
Add: (r, a) =>
|
|
22
|
+
`{_d: new Date(${r}._d.getTime() + Math.round(Number(${a[0]}) / 1000000))}`,
|
|
23
|
+
Sub: (r, a) =>
|
|
24
|
+
`Math.round((${r}._d.getTime() - (${a[0]})._d.getTime()) * 1000000)`,
|
|
25
|
+
Before: (r, a) => `(${r}._d < (${a[0]})._d)`,
|
|
26
|
+
After: (r, a) => `(${r}._d > (${a[0]})._d)`,
|
|
27
|
+
Equal: (r, a) => `(${r}._d.getTime() === (${a[0]})._d.getTime())`,
|
|
28
|
+
IsZero: (r) =>
|
|
29
|
+
`(!${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) => `(${r}?._d ? Math.round(${r}._d.getTime() * 1000000) : 0)`,
|
|
31
|
+
Nanosecond: (r) =>
|
|
32
|
+
`(${r}?._d ? (${r}._offset === 0 ? ${r}._d.getUTCMilliseconds() : ${r}._d.getMilliseconds()) * 1000000 : 0)`,
|
|
33
|
+
UTC: (r) => `({_d: ${r}?._d ?? new Date(0), _offset: 0})`,
|
|
34
|
+
Local: (r) => `({_d: ${r}?._d ?? new Date(0)})`,
|
|
35
|
+
AddDate: (r, a) =>
|
|
36
|
+
`({_d: new Date(${r}._d.getFullYear() + Number(${a[0]}), ${r}._d.getMonth() + Number(${a[1]}), ${r}._d.getDate() + Number(${a[2]}))})`,
|
|
37
|
+
Truncate: (r, a) =>
|
|
38
|
+
`({_d: new Date(Math.floor(${r}._d.getTime() / (Number(${a[0]}) / 1000000)) * (Number(${a[0]}) / 1000000))})`,
|
|
39
|
+
Round: (r, a) =>
|
|
40
|
+
`({_d: new Date(Math.round(${r}._d.getTime() / (Number(${a[0]}) / 1000000)) * (Number(${a[0]}) / 1000000))})`,
|
|
41
|
+
Date: (r) =>
|
|
42
|
+
`[${r}._offset === 0 ? ${r}._d.getUTCFullYear() : ${r}._d.getFullYear(), ${r}._offset === 0 ? ${r}._d.getUTCMonth() + 1 : ${r}._d.getMonth() + 1, ${r}._offset === 0 ? ${r}._d.getUTCDate() : ${r}._d.getDate()]`,
|
|
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)`,
|
|
47
|
+
Compare: (r, a) =>
|
|
48
|
+
`(${r}._d.getTime() < (${a[0]})._d.getTime() ? -1 : (${r}._d.getTime() > (${a[0]})._d.getTime() ? 1 : 0))`,
|
|
49
|
+
In: (r) => `${r}`,
|
|
50
|
+
Location: () => `null`,
|
|
51
|
+
Zone: (r) =>
|
|
52
|
+
`[${r}._offset === 0 ? "UTC" : "LOCAL", ${r}._offset === 0 ? 0 : -${r}._d.getTimezoneOffset() * 60]`,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const DURATION_METHOD_DISPATCH = {
|
|
56
|
+
Nanoseconds: (r) => `${r}`,
|
|
57
|
+
Microseconds: (r) => `Math.trunc(Number(${r}) / 1000)`,
|
|
58
|
+
Milliseconds: (r) => `Math.trunc(Number(${r}) / 1000000)`,
|
|
59
|
+
Seconds: (r) => `(Number(${r}) / 1000000000)`,
|
|
60
|
+
Minutes: (r) => `(Number(${r}) / 60000000000)`,
|
|
61
|
+
Hours: (r) => `(Number(${r}) / 3600000000000)`,
|
|
62
|
+
String: (r) => `__durationString(${r})`,
|
|
20
63
|
};
|
|
21
64
|
|
|
22
65
|
const TIME_DISPATCH = {
|
|
23
|
-
Now: () =>
|
|
24
|
-
|
|
66
|
+
Now: () =>
|
|
67
|
+
'(typeof globalThis.__GOFRONT_CLOCK === "function" ? {_d: new Date(globalThis.__GOFRONT_CLOCK())} : {_d: new Date()})',
|
|
68
|
+
Since: (a) =>
|
|
69
|
+
`(Math.round(((typeof globalThis.__GOFRONT_CLOCK === "function" ? globalThis.__GOFRONT_CLOCK() : Date.now()) - (${a[0]})._d.getTime()) * 1000000))`,
|
|
25
70
|
Sleep: (a) => `await new Promise(r => setTimeout(r, ${a[0]} / 1000000))`,
|
|
26
|
-
Unix: (a) =>
|
|
71
|
+
Unix: (a) =>
|
|
72
|
+
`{_d: new Date(Number(${a[0]}) * 1000 + Math.round(Number(${a[1] || 0}) / 1000000))}`,
|
|
73
|
+
UnixMicro: (a) => `{_d: new Date(Math.round(Number(${a[0]}) / 1000))}`,
|
|
74
|
+
UnixMilli: (a) => `{_d: new Date(Number(${a[0]}))}`,
|
|
27
75
|
Date: (a) =>
|
|
28
|
-
`{_d: new Date(${a[0]}, ${a[1]} - 1, ${a[2]}, ${a[3]}, ${a[4]}, ${a[5]})}`,
|
|
76
|
+
`{_d: new Date(${a[0]}, ${a[1]} - 1, ${a[2]}, ${a[3]}, ${a[4]}, ${a[5]}, Math.round(Number(${a[6] || 0}) / 1000000))}`,
|
|
29
77
|
};
|
|
30
78
|
|
|
31
79
|
/** @type {ThisType<CodeGen>} */
|
|
@@ -36,21 +84,44 @@ export const timeMethods = {
|
|
|
36
84
|
const args = expr.args.map((a) => this.genExpr(a));
|
|
37
85
|
if (method === "Format") {
|
|
38
86
|
this.useHelper("timeFmt");
|
|
39
|
-
return `__timeFmt(${recvJs}
|
|
87
|
+
return `__timeFmt(${recvJs}, ${args[0]})`;
|
|
40
88
|
}
|
|
41
89
|
if (method === "String") {
|
|
42
90
|
this.useHelper("timeFmt");
|
|
43
|
-
return `__timeFmt(${recvJs}
|
|
91
|
+
return `__timeFmt(${recvJs}, "2006-01-02 15:04:05.999999999 -0700 MST")`;
|
|
44
92
|
}
|
|
45
93
|
const gen = TIME_METHOD_DISPATCH[method];
|
|
46
94
|
return gen ? gen(recvJs, args) : undefined;
|
|
47
95
|
},
|
|
48
96
|
|
|
49
|
-
|
|
97
|
+
_genDurationMethodCall(method, expr) {
|
|
98
|
+
const recv = expr.func.expr;
|
|
99
|
+
const recvJs = this.genExpr(recv);
|
|
100
|
+
if (method === "String") {
|
|
101
|
+
this.useHelper("duration");
|
|
102
|
+
}
|
|
103
|
+
const gen = DURATION_METHOD_DISPATCH[method];
|
|
104
|
+
return gen ? gen(recvJs) : undefined;
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
_genTime(fn, a, expr) {
|
|
50
108
|
if (fn === "Parse") {
|
|
51
109
|
this.useHelper("timeParse");
|
|
52
110
|
return `__timeParse(${a()[0]}, ${a()[1]})`;
|
|
53
111
|
}
|
|
112
|
+
if (fn === "Date") {
|
|
113
|
+
const args = a();
|
|
114
|
+
const locArg = expr?.args?.[7];
|
|
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))}`;
|
|
124
|
+
}
|
|
54
125
|
const gen = TIME_DISPATCH[fn];
|
|
55
126
|
return gen ? gen(a()) : undefined;
|
|
56
127
|
},
|
|
@@ -11,8 +11,8 @@ export const unicodeMethods = {
|
|
|
11
11
|
IsLetter: `/\\p{L}/u.test(${cp})`,
|
|
12
12
|
IsDigit: `/\\p{Nd}/u.test(${cp})`,
|
|
13
13
|
IsSpace: `/\\s/.test(${cp})`,
|
|
14
|
-
IsUpper:
|
|
15
|
-
IsLower:
|
|
14
|
+
IsUpper: `/\\p{Lu}/u.test(${cp})`,
|
|
15
|
+
IsLower: `/\\p{Ll}/u.test(${cp})`,
|
|
16
16
|
IsPunct: `/\\p{P}/u.test(${cp})`,
|
|
17
17
|
IsControl: `/\\p{Cc}/u.test(${cp})`,
|
|
18
18
|
IsPrint: `!/\\p{Cc}/u.test(${cp})`,
|