gofront 0.0.7 → 0.0.9
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 -18
- package/package.json +9 -4
- package/src/codegen/expressions.js +351 -6
- package/src/codegen/source-map.js +8 -5
- package/src/codegen.js +329 -4
- package/src/compiler.js +39 -4
- package/src/dev-server.js +1 -0
- package/src/index.js +10 -6
- package/src/lexer.js +14 -14
- package/src/parser/expressions.js +3 -2
- package/src/parser/statements.js +5 -1
- package/src/parser.js +8 -1
- package/src/resolver.js +29 -0
- package/src/templ-lexer.js +737 -0
- package/src/templ-parser.js +235 -0
- package/src/typechecker/stdlib.js +305 -2
- package/src/typechecker/types.js +6 -18
- package/src/typechecker.js +30 -2
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { ERROR, isComplex } from "../typechecker/types.js";
|
|
4
4
|
|
|
5
|
-
const globalError = ERROR;
|
|
6
|
-
|
|
7
5
|
const INT_TYPE_NAMES = new Set([
|
|
8
6
|
"int",
|
|
9
7
|
"uint",
|
|
@@ -163,7 +161,7 @@ export const expressionGenMethods = {
|
|
|
163
161
|
return "process.argv";
|
|
164
162
|
}
|
|
165
163
|
}
|
|
166
|
-
// time constants (nanosecond durations)
|
|
164
|
+
// time constants (nanosecond durations and layout strings)
|
|
167
165
|
if (expr.expr.kind === "Ident" && expr.expr.name === "time") {
|
|
168
166
|
switch (expr.field) {
|
|
169
167
|
case "Millisecond":
|
|
@@ -174,6 +172,68 @@ export const expressionGenMethods = {
|
|
|
174
172
|
return "60000000000";
|
|
175
173
|
case "Hour":
|
|
176
174
|
return "3600000000000";
|
|
175
|
+
case "RFC3339":
|
|
176
|
+
return '"2006-01-02T15:04:05Z07:00"';
|
|
177
|
+
case "RFC3339Nano":
|
|
178
|
+
return '"2006-01-02T15:04:05.999999999Z07:00"';
|
|
179
|
+
case "DateOnly":
|
|
180
|
+
return '"2006-01-02"';
|
|
181
|
+
case "TimeOnly":
|
|
182
|
+
return '"15:04:05"';
|
|
183
|
+
case "DateTime":
|
|
184
|
+
return '"2006-01-02 15:04:05"';
|
|
185
|
+
case "UTC":
|
|
186
|
+
case "Local":
|
|
187
|
+
return "null";
|
|
188
|
+
case "January":
|
|
189
|
+
return "1";
|
|
190
|
+
case "February":
|
|
191
|
+
return "2";
|
|
192
|
+
case "March":
|
|
193
|
+
return "3";
|
|
194
|
+
case "April":
|
|
195
|
+
return "4";
|
|
196
|
+
case "May":
|
|
197
|
+
return "5";
|
|
198
|
+
case "June":
|
|
199
|
+
return "6";
|
|
200
|
+
case "July":
|
|
201
|
+
return "7";
|
|
202
|
+
case "August":
|
|
203
|
+
return "8";
|
|
204
|
+
case "September":
|
|
205
|
+
return "9";
|
|
206
|
+
case "October":
|
|
207
|
+
return "10";
|
|
208
|
+
case "November":
|
|
209
|
+
return "11";
|
|
210
|
+
case "December":
|
|
211
|
+
return "12";
|
|
212
|
+
case "Sunday":
|
|
213
|
+
return "0";
|
|
214
|
+
case "Monday":
|
|
215
|
+
return "1";
|
|
216
|
+
case "Tuesday":
|
|
217
|
+
return "2";
|
|
218
|
+
case "Wednesday":
|
|
219
|
+
return "3";
|
|
220
|
+
case "Thursday":
|
|
221
|
+
return "4";
|
|
222
|
+
case "Friday":
|
|
223
|
+
return "5";
|
|
224
|
+
case "Saturday":
|
|
225
|
+
return "6";
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// utf8 constants
|
|
229
|
+
if (expr.expr.kind === "Ident" && expr.expr.name === "utf8") {
|
|
230
|
+
switch (expr.field) {
|
|
231
|
+
case "RuneError":
|
|
232
|
+
return "0xFFFD";
|
|
233
|
+
case "MaxRune":
|
|
234
|
+
return "0x10FFFF";
|
|
235
|
+
case "UTFMax":
|
|
236
|
+
return "4";
|
|
177
237
|
}
|
|
178
238
|
}
|
|
179
239
|
const base = this.genExpr(expr.expr);
|
|
@@ -456,7 +516,7 @@ export const expressionGenMethods = {
|
|
|
456
516
|
expr.func.kind === "SelectorExpr" &&
|
|
457
517
|
expr.func.field === "Error" &&
|
|
458
518
|
expr.func.expr._type &&
|
|
459
|
-
(expr.func.expr._type ===
|
|
519
|
+
(expr.func.expr._type === ERROR ||
|
|
460
520
|
expr.func.expr._type?.name === "error" ||
|
|
461
521
|
(expr.func.expr._type?.kind === "named" &&
|
|
462
522
|
expr.func.expr._type?.underlying?.kind === "interface"))
|
|
@@ -485,6 +545,9 @@ export const expressionGenMethods = {
|
|
|
485
545
|
if (recvName === "regexp.Regexp") {
|
|
486
546
|
return this._genRegexpMethodCall(expr.func.field, expr);
|
|
487
547
|
}
|
|
548
|
+
if (recvName === "time.Time") {
|
|
549
|
+
return this._genTimeMethodCall(expr.func.field, expr);
|
|
550
|
+
}
|
|
488
551
|
}
|
|
489
552
|
|
|
490
553
|
// Mark the callee so SelectorExpr knows it's being called, not used as a value
|
|
@@ -1096,6 +1159,10 @@ export const expressionGenMethods = {
|
|
|
1096
1159
|
// strings.Builder has { _buf: string }, bytes.Buffer has { _buf: [] }.
|
|
1097
1160
|
return `((b,s) => { const w = b?.value ?? b; if (typeof w.WriteString === "function") return [w.WriteString(s), null]; if (typeof w._buf === "string") { w._buf += s; return [s.length, null]; } if (Array.isArray(w._buf)) { w._buf.push(...new TextEncoder().encode(s)); return [s.length, null]; } return [0, "io.WriteString: unsupported writer"]; })(${w}, ${s})`;
|
|
1098
1161
|
}
|
|
1162
|
+
case "ReadAll": {
|
|
1163
|
+
const r = this.genExpr(expr.args[0]);
|
|
1164
|
+
return `((r) => { const w = r?.value ?? r; if (typeof w._src === "string") { const s = w._src.slice(w._pos); w._pos = w._src.length; return [[...s].map(c => c.charCodeAt(0)), null]; } if (Array.isArray(w._src)) { const b = w._src.slice(w._pos); w._pos = w._src.length; return [b, null]; } const chunks = []; const buf = new Array(4096); let err = null; while (!err) { const [n, e] = w.Read(buf); if (n > 0) chunks.push(...buf.slice(0, n)); err = e; } return [chunks, err === "EOF" ? null : err]; })(${r})`;
|
|
1165
|
+
}
|
|
1099
1166
|
}
|
|
1100
1167
|
return undefined;
|
|
1101
1168
|
},
|
|
@@ -1202,6 +1269,12 @@ export const expressionGenMethods = {
|
|
|
1202
1269
|
return this._genHtml(fn, a);
|
|
1203
1270
|
case "io":
|
|
1204
1271
|
return this._genIo(fn, a, expr);
|
|
1272
|
+
case "rand":
|
|
1273
|
+
return this._genRand(fn, a);
|
|
1274
|
+
case "utf8":
|
|
1275
|
+
return this._genUtf8(fn, a);
|
|
1276
|
+
case "path":
|
|
1277
|
+
return this._genPath(fn, a, expr);
|
|
1205
1278
|
case "gom":
|
|
1206
1279
|
return this._genGom(fn, expr);
|
|
1207
1280
|
default:
|
|
@@ -1425,6 +1498,31 @@ export const expressionGenMethods = {
|
|
|
1425
1498
|
return `(${buf} += __sprintf("%v\\n", ${restJs}))`;
|
|
1426
1499
|
return `(${buf} += __sprintf("%v", ${restJs}))`;
|
|
1427
1500
|
}
|
|
1501
|
+
case "Sscan": {
|
|
1502
|
+
const strArg = this.genExpr(expr.args[0]);
|
|
1503
|
+
const restArgs = expr.args
|
|
1504
|
+
.slice(1)
|
|
1505
|
+
.map((e) => this.genExpr(e))
|
|
1506
|
+
.join(", ");
|
|
1507
|
+
return `((str, ...ptrs) => { const tokens = str.trim().split(/\\s+/).filter(Boolean); let n = 0; for (let i = 0; i < ptrs.length && i < tokens.length; i++) { const t = tokens[i]; const p = ptrs[i]; if (typeof p.value === "number") p.value = Number(t); else if (typeof p.value === "boolean") p.value = t === "true"; else p.value = t; n++; } return [n, n < ptrs.length ? "unexpected EOF" : null]; })(${strArg}, ${restArgs})`;
|
|
1508
|
+
}
|
|
1509
|
+
case "Sscanln": {
|
|
1510
|
+
const strArg = this.genExpr(expr.args[0]);
|
|
1511
|
+
const restArgs = expr.args
|
|
1512
|
+
.slice(1)
|
|
1513
|
+
.map((e) => this.genExpr(e))
|
|
1514
|
+
.join(", ");
|
|
1515
|
+
return `((str, ...ptrs) => { const line = str.split("\\n")[0]; const tokens = line.trim().split(/\\s+/).filter(Boolean); let n = 0; for (let i = 0; i < ptrs.length && i < tokens.length; i++) { const t = tokens[i]; const p = ptrs[i]; if (typeof p.value === "number") p.value = Number(t); else if (typeof p.value === "boolean") p.value = t === "true"; else p.value = t; n++; } return [n, n < ptrs.length ? "unexpected EOF" : null]; })(${strArg}, ${restArgs})`;
|
|
1516
|
+
}
|
|
1517
|
+
case "Sscanf": {
|
|
1518
|
+
const strArg = this.genExpr(expr.args[0]);
|
|
1519
|
+
const fmtArg = this.genExpr(expr.args[1]);
|
|
1520
|
+
const restArgs = expr.args
|
|
1521
|
+
.slice(2)
|
|
1522
|
+
.map((e) => this.genExpr(e))
|
|
1523
|
+
.join(", ");
|
|
1524
|
+
return `((str, _fmt, ...ptrs) => { const tokens = str.trim().split(/\\s+/).filter(Boolean); let n = 0; for (let i = 0; i < ptrs.length && i < tokens.length; i++) { const t = tokens[i]; const p = ptrs[i]; if (typeof p.value === "number") p.value = Number(t); else if (typeof p.value === "boolean") p.value = t === "true"; else p.value = t; n++; } return [n, n < ptrs.length ? "input does not match format" : null]; })(${strArg}, ${fmtArg}, ${restArgs})`;
|
|
1525
|
+
}
|
|
1428
1526
|
default:
|
|
1429
1527
|
return undefined;
|
|
1430
1528
|
}
|
|
@@ -1473,6 +1571,56 @@ export const expressionGenMethods = {
|
|
|
1473
1571
|
return `${args[0]}.join(${args[1]})`;
|
|
1474
1572
|
case "EqualFold":
|
|
1475
1573
|
return `${args[0]}.toLowerCase() === ${args[1]}.toLowerCase()`;
|
|
1574
|
+
case "Fields":
|
|
1575
|
+
return `(${args[0]}).trim() === '' ? [] : (${args[0]}).trim().split(/\\s+/)`;
|
|
1576
|
+
case "Cut":
|
|
1577
|
+
return `((s, sep) => { const i = s.indexOf(sep); return i < 0 ? [s, "", false] : [s.slice(0, i), s.slice(i + sep.length), true]; })(${args[0]}, ${args[1]})`;
|
|
1578
|
+
case "CutPrefix":
|
|
1579
|
+
return `(${args[0]}).startsWith(${args[1]}) ? [(${args[0]}).slice((${args[1]}).length), true] : [${args[0]}, false]`;
|
|
1580
|
+
case "CutSuffix":
|
|
1581
|
+
return `(${args[0]}).endsWith(${args[1]}) ? [(${args[0]}).slice(0, -(${args[1]}).length), true] : [${args[0]}, false]`;
|
|
1582
|
+
case "SplitN":
|
|
1583
|
+
return `((s, sep, n) => { if (n === 0) return []; if (n < 0) return s.split(sep); const r = []; let cur = s; for (let i = 1; i < n && cur.length; i++) { const j = cur.indexOf(sep); if (j < 0) break; r.push(cur.slice(0, j)); cur = cur.slice(j + sep.length); } r.push(cur); return r; })(${args[0]}, ${args[1]}, ${args[2]})`;
|
|
1584
|
+
case "SplitAfter":
|
|
1585
|
+
return `((s, sep) => { if (sep === "") return [...s]; const r = []; let cur = s; while (cur.length) { const j = cur.indexOf(sep); if (j < 0) { r.push(cur); break; } r.push(cur.slice(0, j + sep.length)); cur = cur.slice(j + sep.length); } return r; })(${args[0]}, ${args[1]})`;
|
|
1586
|
+
case "SplitAfterN":
|
|
1587
|
+
return `((s, sep, n) => { if (n === 0) return []; if (n < 0 || sep === "") return ((s, sep) => { if (sep === "") return [...s]; const r = []; let cur = s; while (cur.length) { const j = cur.indexOf(sep); if (j < 0) { r.push(cur); break; } r.push(cur.slice(0, j + sep.length)); cur = cur.slice(j + sep.length); } return r; })(s, sep); const r = []; let cur = s; for (let i = 1; i < n && cur.length; i++) { const j = cur.indexOf(sep); if (j < 0) break; r.push(cur.slice(0, j + sep.length)); cur = cur.slice(j + sep.length); } r.push(cur); return r; })(${args[0]}, ${args[1]}, ${args[2]})`;
|
|
1588
|
+
case "IndexAny":
|
|
1589
|
+
return `((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; })(${args[0]}, ${args[1]})`;
|
|
1590
|
+
case "LastIndexAny":
|
|
1591
|
+
return `((s, chars) => { let m = -1; for (const c of chars) { const i = s.lastIndexOf(c); if (i > m) m = i; } return m; })(${args[0]}, ${args[1]})`;
|
|
1592
|
+
case "ContainsAny":
|
|
1593
|
+
return `[...(${args[1]})].some(c => (${args[0]}).includes(c))`;
|
|
1594
|
+
case "ContainsRune":
|
|
1595
|
+
return `(${args[0]}).includes(String.fromCodePoint(${args[1]}))`;
|
|
1596
|
+
case "IndexRune":
|
|
1597
|
+
return `(${args[0]}).indexOf(String.fromCodePoint(${args[1]}))`;
|
|
1598
|
+
case "IndexByte":
|
|
1599
|
+
return `(${args[0]}).indexOf(String.fromCharCode(${args[1]}))`;
|
|
1600
|
+
case "LastIndexByte":
|
|
1601
|
+
return `(${args[0]}).lastIndexOf(String.fromCharCode(${args[1]}))`;
|
|
1602
|
+
case "Map":
|
|
1603
|
+
return `[...(${args[1]})].map(c => String.fromCodePoint((${args[0]})(c.codePointAt(0)))).join("")`;
|
|
1604
|
+
case "Title":
|
|
1605
|
+
return `(${args[0]}).replace(/\\b\\w/g, c => c.toUpperCase())`;
|
|
1606
|
+
case "ToTitle":
|
|
1607
|
+
return `(${args[0]}).toUpperCase()`;
|
|
1608
|
+
case "TrimFunc":
|
|
1609
|
+
return `((s, f) => { let l = 0, r = s.length; while (l < r && f(s.codePointAt(l))) l++; while (r > l && f(s.codePointAt(r - 1))) r--; return s.slice(l, r); })(${args[0]}, ${args[1]})`;
|
|
1610
|
+
case "TrimLeftFunc":
|
|
1611
|
+
return `((s, f) => { let l = 0; while (l < s.length && f(s.codePointAt(l))) l++; return s.slice(l); })(${args[0]}, ${args[1]})`;
|
|
1612
|
+
case "TrimRightFunc":
|
|
1613
|
+
return `((s, f) => { let r = s.length; while (r > 0 && f(s.codePointAt(r - 1))) r--; return s.slice(0, r); })(${args[0]}, ${args[1]})`;
|
|
1614
|
+
case "IndexFunc":
|
|
1615
|
+
return `((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; })(${args[0]}, ${args[1]})`;
|
|
1616
|
+
case "LastIndexFunc":
|
|
1617
|
+
return `((s, f) => { for (let i = s.length - 1; i >= 0; i--) { const cp = s.codePointAt(i); if (f(cp)) return i; } return -1; })(${args[0]}, ${args[1]})`;
|
|
1618
|
+
case "NewReader":
|
|
1619
|
+
return `{_src: ${args[0]}, _pos: 0, Read(p) { const n = Math.min(p.length, this._src.length - this._pos); for (let i = 0; i < n; i++) p[i] = this._src.charCodeAt(this._pos + i); this._pos += n; return [n, n === 0 ? "EOF" : null]; }, Len() { return this._src.length - this._pos; }, Reset(s) { this._src = s; this._pos = 0; }}`;
|
|
1620
|
+
case "NewReplacer": {
|
|
1621
|
+
const allArgs = args.join(", ");
|
|
1622
|
+
return `((...pairs) => { const p = []; for (let i = 0; i < pairs.length; i += 2) p.push([pairs[i], pairs[i+1]]); return { _p: p, Replace(s) { let r = s; for (const [o, n] of this._p) r = r.split(o).join(n); return r; } }; })(${allArgs})`;
|
|
1623
|
+
}
|
|
1476
1624
|
default:
|
|
1477
1625
|
return undefined;
|
|
1478
1626
|
}
|
|
@@ -1511,6 +1659,38 @@ export const expressionGenMethods = {
|
|
|
1511
1659
|
return `${__bs}(${args[0]}).split(${__bs}(${args[1]})).map(p => ${__sb}(p))`;
|
|
1512
1660
|
case "Join":
|
|
1513
1661
|
return `${__sb}(${args[0]}.map(p => ${__bs}(p)).join(${__bs}(${args[1]})))`;
|
|
1662
|
+
case "ReplaceAll":
|
|
1663
|
+
return `((b, o, n) => { const r = []; let i = 0; while (i <= b.length - o.length) { if (o.every((v, j) => b[i + j] === v)) { r.push(...n); i += o.length; } else r.push(b[i++]); } return r.concat(b.slice(i)); })(${args[0]}, ${args[1]}, ${args[2]})`;
|
|
1664
|
+
case "TrimPrefix":
|
|
1665
|
+
return `((b, p) => p.every((v, i) => b[i] === v) ? b.slice(p.length) : b.slice())(${args[0]}, ${args[1]})`;
|
|
1666
|
+
case "TrimSuffix":
|
|
1667
|
+
return `((b, s) => s.length && s.every((v, i) => b[b.length - s.length + i] === v) ? b.slice(0, -s.length) : b.slice())(${args[0]}, ${args[1]})`;
|
|
1668
|
+
case "TrimLeft":
|
|
1669
|
+
return `((b, c) => { let i = 0; while (i < b.length && c.includes(String.fromCharCode(b[i]))) i++; return b.slice(i); })(${args[0]}, ${args[1]})`;
|
|
1670
|
+
case "TrimRight":
|
|
1671
|
+
return `((b, c) => { let i = b.length; while (i > 0 && c.includes(String.fromCharCode(b[i - 1]))) i--; return b.slice(0, i); })(${args[0]}, ${args[1]})`;
|
|
1672
|
+
case "TrimFunc":
|
|
1673
|
+
return `((b, f) => { let l = 0, r = b.length; while (l < r && f(b[l])) l++; while (r > l && f(b[r - 1])) r--; return b.slice(l, r); })(${args[0]}, ${args[1]})`;
|
|
1674
|
+
case "IndexByte":
|
|
1675
|
+
return `(${args[0]}).indexOf(${args[1]})`;
|
|
1676
|
+
case "LastIndex":
|
|
1677
|
+
return `((b, s) => { for (let i = b.length - s.length; i >= 0; i--) if (s.every((v, j) => b[i + j] === v)) return i; return -1; })(${args[0]}, ${args[1]})`;
|
|
1678
|
+
case "LastIndexByte":
|
|
1679
|
+
return `(${args[0]}).lastIndexOf(${args[1]})`;
|
|
1680
|
+
case "Fields":
|
|
1681
|
+
return `((b) => { const s = String.fromCharCode(...b).trim(); return s === '' ? [] : s.split(/\\s+/).map(w => [...w].map(c => c.charCodeAt(0))); })(${args[0]})`;
|
|
1682
|
+
case "Cut":
|
|
1683
|
+
return `((b, sep) => { for (let i = 0; i <= b.length - sep.length; i++) if (sep.every((v, j) => b[i + j] === v)) return [b.slice(0, i), b.slice(i + sep.length), true]; return [b.slice(), [], false]; })(${args[0]}, ${args[1]})`;
|
|
1684
|
+
case "ContainsAny":
|
|
1685
|
+
return `[...(${args[1]})].some(c => (${args[0]}).includes(c.charCodeAt(0)))`;
|
|
1686
|
+
case "ContainsRune":
|
|
1687
|
+
return `(${args[0]}).includes(${args[1]})`;
|
|
1688
|
+
case "Map":
|
|
1689
|
+
return `(${args[1]}).map(v => (${args[0]})(v))`;
|
|
1690
|
+
case "SplitN":
|
|
1691
|
+
return `((b, sep, n) => { if (n === 0) return []; if (n < 0) return ((b, sep) => { const r = []; let i = 0; while (i <= b.length) { const j = b.findIndex((_, k) => k >= i && sep.every((v, l) => b[k + l] === sep[l])); if (j < 0 || j >= b.length) break; r.push(b.slice(i, j)); i = j + sep.length; } r.push(b.slice(i)); return r; })(b, sep); const r = []; let i = 0; for (let c = 1; c < n; c++) { const j = b.findIndex((_, k) => k >= i && sep.every((v, l) => b[k + l] === sep[l])); if (j < 0) break; r.push(b.slice(i, j)); i = j + sep.length; } r.push(b.slice(i)); return r; })(${args[0]}, ${args[1]}, ${args[2]})`;
|
|
1692
|
+
case "NewReader":
|
|
1693
|
+
return `{_src: ${args[0]}, _pos: 0, Read(p) { const n = Math.min(p.length, this._src.length - this._pos); for (let i = 0; i < n; i++) p[i] = this._src[this._pos + i]; this._pos += n; return [n, n === 0 ? "EOF" : null]; }, Len() { return this._src.length - this._pos; }, Reset(b) { this._src = b; this._pos = 0; }}`;
|
|
1514
1694
|
default:
|
|
1515
1695
|
return undefined;
|
|
1516
1696
|
}
|
|
@@ -1535,6 +1715,14 @@ export const expressionGenMethods = {
|
|
|
1535
1715
|
return `(Number.isNaN(parseInt(${args[0]}, ${args[1]} || 10)) ? [0, "invalid syntax"] : [parseInt(${args[0]}, ${args[1]} || 10), null])`;
|
|
1536
1716
|
case "ParseBool":
|
|
1537
1717
|
return `(${args[0]} === "true" || ${args[0]} === "1" ? [true, null] : ${args[0]} === "false" || ${args[0]} === "0" ? [false, null] : [false, "invalid syntax"])`;
|
|
1718
|
+
case "Quote":
|
|
1719
|
+
return `JSON.stringify(${args[0]})`;
|
|
1720
|
+
case "Unquote":
|
|
1721
|
+
return `((s) => { try { const v = JSON.parse(s); return [v, null]; } catch(e) { return ["", "invalid syntax"]; } })(${args[0]})`;
|
|
1722
|
+
case "AppendInt":
|
|
1723
|
+
return `[...(${args[0]}), ...new TextEncoder().encode((${args[1]}).toString(${args[2]}))]`;
|
|
1724
|
+
case "AppendFloat":
|
|
1725
|
+
return `[...(${args[0]}), ...new TextEncoder().encode(${args[1]}.toFixed(${args[3]} < 0 ? 6 : ${args[3]}))]`;
|
|
1538
1726
|
default:
|
|
1539
1727
|
return undefined;
|
|
1540
1728
|
}
|
|
@@ -1553,6 +1741,12 @@ export const expressionGenMethods = {
|
|
|
1553
1741
|
return `${args[0]}.sort((a, b) => ${args[1]}(a, b) ? -1 : ${args[1]}(b, a) ? 1 : 0)`;
|
|
1554
1742
|
case "SliceIsSorted":
|
|
1555
1743
|
return `${args[0]}.every((v, i, a) => i === 0 || ${args[1]}(a[i - 1], v))`;
|
|
1744
|
+
case "Search":
|
|
1745
|
+
return `((n, f) => { let lo = 0, hi = n; while (lo < hi) { const mid = (lo + hi) >>> 1; if (f(mid)) hi = mid; else lo = mid + 1; } return lo; })(${args[0]}, ${args[1]})`;
|
|
1746
|
+
case "IntsAreSorted":
|
|
1747
|
+
case "Float64sAreSorted":
|
|
1748
|
+
case "StringsAreSorted":
|
|
1749
|
+
return `(${args[0]}).every((v, i, a) => i === 0 || a[i - 1] <= v)`;
|
|
1556
1750
|
default:
|
|
1557
1751
|
return undefined;
|
|
1558
1752
|
}
|
|
@@ -1601,6 +1795,30 @@ export const expressionGenMethods = {
|
|
|
1601
1795
|
return `(${args[1]} > 0 ? ${args[0]} === Infinity : ${args[1]} < 0 ? ${args[0]} === -Infinity : !Number.isFinite(${args[0]}))`;
|
|
1602
1796
|
case "NaN":
|
|
1603
1797
|
return "NaN";
|
|
1798
|
+
case "Atan":
|
|
1799
|
+
return `Math.atan(${args[0]})`;
|
|
1800
|
+
case "Atan2":
|
|
1801
|
+
return `Math.atan2(${args[0]}, ${args[1]})`;
|
|
1802
|
+
case "Asin":
|
|
1803
|
+
return `Math.asin(${args[0]})`;
|
|
1804
|
+
case "Acos":
|
|
1805
|
+
return `Math.acos(${args[0]})`;
|
|
1806
|
+
case "Exp":
|
|
1807
|
+
return `Math.exp(${args[0]})`;
|
|
1808
|
+
case "Exp2":
|
|
1809
|
+
return `Math.pow(2, ${args[0]})`;
|
|
1810
|
+
case "Trunc":
|
|
1811
|
+
return `Math.trunc(${args[0]})`;
|
|
1812
|
+
case "Hypot":
|
|
1813
|
+
return `Math.hypot(${args[0]}, ${args[1]})`;
|
|
1814
|
+
case "Signbit":
|
|
1815
|
+
return `(${args[0]} < 0 || Object.is(${args[0]}, -0))`;
|
|
1816
|
+
case "Copysign":
|
|
1817
|
+
return `(Math.abs(${args[0]}) * (${args[1]} < 0 || Object.is(${args[1]}, -0) ? -1 : 1))`;
|
|
1818
|
+
case "Dim":
|
|
1819
|
+
return `Math.max(${args[0]} - ${args[1]}, 0)`;
|
|
1820
|
+
case "Remainder":
|
|
1821
|
+
return `(${args[0]} - Math.round(${args[0]} / ${args[1]}) * ${args[1]})`;
|
|
1604
1822
|
default:
|
|
1605
1823
|
return undefined;
|
|
1606
1824
|
}
|
|
@@ -1665,15 +1883,142 @@ export const expressionGenMethods = {
|
|
|
1665
1883
|
}
|
|
1666
1884
|
},
|
|
1667
1885
|
|
|
1886
|
+
_genTimeMethodCall(method, expr) {
|
|
1887
|
+
const recv = expr.func.expr;
|
|
1888
|
+
const recvJs = this.genExpr(recv);
|
|
1889
|
+
const args = expr.args.map((a) => this.genExpr(a));
|
|
1890
|
+
switch (method) {
|
|
1891
|
+
case "Format":
|
|
1892
|
+
this._usesTimeFmt = true;
|
|
1893
|
+
return `__timeFmt(${recvJs}._d, ${args[0]})`;
|
|
1894
|
+
case "String":
|
|
1895
|
+
this._usesTimeFmt = true;
|
|
1896
|
+
return `__timeFmt(${recvJs}._d, "2006-01-02T15:04:05Z07:00")`;
|
|
1897
|
+
case "Year":
|
|
1898
|
+
return `${recvJs}._d.getFullYear()`;
|
|
1899
|
+
case "Month":
|
|
1900
|
+
return `${recvJs}._d.getMonth() + 1`;
|
|
1901
|
+
case "Day":
|
|
1902
|
+
return `${recvJs}._d.getDate()`;
|
|
1903
|
+
case "Hour":
|
|
1904
|
+
return `${recvJs}._d.getHours()`;
|
|
1905
|
+
case "Minute":
|
|
1906
|
+
return `${recvJs}._d.getMinutes()`;
|
|
1907
|
+
case "Second":
|
|
1908
|
+
return `${recvJs}._d.getSeconds()`;
|
|
1909
|
+
case "Weekday":
|
|
1910
|
+
return `${recvJs}._d.getDay()`;
|
|
1911
|
+
case "Unix":
|
|
1912
|
+
return `Math.floor(${recvJs}._d.getTime() / 1000)`;
|
|
1913
|
+
case "UnixMilli":
|
|
1914
|
+
return `${recvJs}._d.getTime()`;
|
|
1915
|
+
case "Add":
|
|
1916
|
+
return `{_d: new Date(${recvJs}._d.getTime() + (${args[0]}))}`;
|
|
1917
|
+
case "Sub":
|
|
1918
|
+
return `${recvJs}._d.getTime() - (${args[0]})._d.getTime()`;
|
|
1919
|
+
case "Before":
|
|
1920
|
+
return `${recvJs}._d < (${args[0]})._d`;
|
|
1921
|
+
case "After":
|
|
1922
|
+
return `${recvJs}._d > (${args[0]})._d`;
|
|
1923
|
+
case "Equal":
|
|
1924
|
+
return `${recvJs}._d.getTime() === (${args[0]})._d.getTime()`;
|
|
1925
|
+
default:
|
|
1926
|
+
return undefined;
|
|
1927
|
+
}
|
|
1928
|
+
},
|
|
1929
|
+
|
|
1668
1930
|
_genTime(fn, a) {
|
|
1669
1931
|
const args = a();
|
|
1670
1932
|
switch (fn) {
|
|
1671
1933
|
case "Now":
|
|
1672
|
-
return "Date
|
|
1934
|
+
return "{_d: new Date()}";
|
|
1673
1935
|
case "Since":
|
|
1674
|
-
return `(Date.now() - ${args[0]})`;
|
|
1936
|
+
return `(Date.now() - (${args[0]})._d.getTime())`;
|
|
1675
1937
|
case "Sleep":
|
|
1676
1938
|
return `await new Promise(r => setTimeout(r, ${args[0]} / 1000000))`;
|
|
1939
|
+
case "Parse":
|
|
1940
|
+
this._usesTimeParse = true;
|
|
1941
|
+
return `__timeParse(${args[0]}, ${args[1]})`;
|
|
1942
|
+
case "Unix":
|
|
1943
|
+
return `{_d: new Date((${args[0]}) * 1000)}`;
|
|
1944
|
+
case "Date":
|
|
1945
|
+
return `{_d: new Date(${args[0]}, ${args[1]} - 1, ${args[2]}, ${args[3]}, ${args[4]}, ${args[5]})}`;
|
|
1946
|
+
default:
|
|
1947
|
+
return undefined;
|
|
1948
|
+
}
|
|
1949
|
+
},
|
|
1950
|
+
|
|
1951
|
+
_genRand(fn, a) {
|
|
1952
|
+
const args = a();
|
|
1953
|
+
switch (fn) {
|
|
1954
|
+
case "Intn":
|
|
1955
|
+
case "Int63n":
|
|
1956
|
+
case "Int31n":
|
|
1957
|
+
return `Math.floor(Math.random() * ${args[0]})`;
|
|
1958
|
+
case "Float64":
|
|
1959
|
+
case "Float32":
|
|
1960
|
+
return "Math.random()";
|
|
1961
|
+
case "Int":
|
|
1962
|
+
case "Int31":
|
|
1963
|
+
return "Math.floor(Math.random() * 2147483647)";
|
|
1964
|
+
case "Int63":
|
|
1965
|
+
return "Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)";
|
|
1966
|
+
case "Seed":
|
|
1967
|
+
return "(void 0)";
|
|
1968
|
+
case "Shuffle":
|
|
1969
|
+
return `((n, f) => { for (let i = n - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); f(i, j); } })(${args[0]}, ${args[1]})`;
|
|
1970
|
+
case "Perm":
|
|
1971
|
+
return `((n) => { const a = Array.from({length: n}, (_, i) => i); for (let i = n - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; })(${args[0]})`;
|
|
1972
|
+
default:
|
|
1973
|
+
return undefined;
|
|
1974
|
+
}
|
|
1975
|
+
},
|
|
1976
|
+
|
|
1977
|
+
_genUtf8(fn, a) {
|
|
1978
|
+
const args = a();
|
|
1979
|
+
switch (fn) {
|
|
1980
|
+
case "RuneCountInString":
|
|
1981
|
+
return `[...(${args[0]})].length`;
|
|
1982
|
+
case "RuneLen":
|
|
1983
|
+
return `((r) => r < 0 ? -1 : r <= 0x7F ? 1 : r <= 0x7FF ? 2 : r <= 0xFFFF ? (r >= 0xD800 && r <= 0xDFFF ? -1 : 3) : r <= 0x10FFFF ? 4 : -1)(${args[0]})`;
|
|
1984
|
+
case "ValidString":
|
|
1985
|
+
return `/[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/.test(${args[0]}) === false`;
|
|
1986
|
+
case "ValidRune":
|
|
1987
|
+
return `(${args[0]}) >= 0 && (${args[0]}) <= 0x10FFFF && !((${args[0]}) >= 0xD800 && (${args[0]}) <= 0xDFFF)`;
|
|
1988
|
+
case "DecodeRuneInString":
|
|
1989
|
+
return `((s) => { if (!s) return [0xFFFD, 0]; const cp = s.codePointAt(0); return [cp, cp > 0xFFFF ? 2 : 1]; })(${args[0]})`;
|
|
1990
|
+
case "DecodeLastRuneInString":
|
|
1991
|
+
return `((s) => { if (!s) return [0xFFFD, 0]; const i = s.length > 1 && s.charCodeAt(s.length - 1) >= 0xDC00 && s.charCodeAt(s.length - 1) <= 0xDFFF ? s.length - 2 : s.length - 1; const cp = s.codePointAt(i); return [cp, cp > 0xFFFF ? 2 : 1]; })(${args[0]})`;
|
|
1992
|
+
case "FullRuneInString":
|
|
1993
|
+
return `(${args[0]}).length > 0`;
|
|
1994
|
+
default:
|
|
1995
|
+
return undefined;
|
|
1996
|
+
}
|
|
1997
|
+
},
|
|
1998
|
+
|
|
1999
|
+
_genPath(fn, a, expr) {
|
|
2000
|
+
const args = a();
|
|
2001
|
+
switch (fn) {
|
|
2002
|
+
case "Base":
|
|
2003
|
+
return `((p) => { if (!p) return "."; const stripped = p.replace(/\\/+$/, ""); if (!stripped) return "/"; const i = stripped.lastIndexOf("/"); return i < 0 ? stripped : stripped.slice(i + 1) || "/"; })(${args[0]})`;
|
|
2004
|
+
case "Dir":
|
|
2005
|
+
return `((p) => { const i = p.lastIndexOf("/"); if (i < 0) return "."; if (i === 0) return "/"; return p.slice(0, i); })(${args[0]})`;
|
|
2006
|
+
case "Ext":
|
|
2007
|
+
return `((p) => { const b = p.slice(p.lastIndexOf("/") + 1); const i = b.lastIndexOf("."); return i <= 0 ? "" : b.slice(i); })(${args[0]})`;
|
|
2008
|
+
case "Join": {
|
|
2009
|
+
this._usesPathClean = true;
|
|
2010
|
+
const allArgs = expr.args.map((e) => this.genExpr(e)).join(", ");
|
|
2011
|
+
return `__pathClean([${allArgs}].filter(x => x !== "").join("/"))`;
|
|
2012
|
+
}
|
|
2013
|
+
case "Clean":
|
|
2014
|
+
this._usesPathClean = true;
|
|
2015
|
+
return `__pathClean(${args[0]})`;
|
|
2016
|
+
case "IsAbs":
|
|
2017
|
+
return `(${args[0]}).startsWith("/")`;
|
|
2018
|
+
case "Split":
|
|
2019
|
+
return `((p) => { const i = p.lastIndexOf("/"); return i < 0 ? ["", p] : [p.slice(0, i + 1), p.slice(i + 1)]; })(${args[0]})`;
|
|
2020
|
+
case "Match":
|
|
2021
|
+
return `((pat, name) => { try { const sp=/[.+^$()|[\\]\\\\]/g; const re = new RegExp("^" + pat.replace(sp, "\\\\$&").replace(/\\*/g, "[^/]*").replace(/\\?/g, "[^/]") + "$"); return [re.test(name), null]; } catch(e) { return [false, "syntax error in pattern"]; } })(${args[0]}, ${args[1]})`;
|
|
1677
2022
|
default:
|
|
1678
2023
|
return undefined;
|
|
1679
2024
|
}
|
|
@@ -16,9 +16,10 @@ function vlqEncode(value) {
|
|
|
16
16
|
return result;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export function buildSourceMap(sources, mappings) {
|
|
20
|
-
// sources:
|
|
21
|
-
// mappings:
|
|
19
|
+
export function buildSourceMap(sources, mappings, sourcesContent) {
|
|
20
|
+
// sources: string[]
|
|
21
|
+
// mappings: Array<{ genLine: number, srcLine: number, srcFileIdx?: number }> (0-based)
|
|
22
|
+
// sourcesContent: string[] | undefined — original file contents, embedded for DevTools
|
|
22
23
|
// Emits one segment per generated line, column 0 → source line (delta-encoded).
|
|
23
24
|
const lines = [];
|
|
24
25
|
let prevSrcLine = 0;
|
|
@@ -44,10 +45,12 @@ export function buildSourceMap(sources, mappings) {
|
|
|
44
45
|
lines.push(""); // no mapping for this generated line
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
+
const map = {
|
|
48
49
|
version: 3,
|
|
49
50
|
sources,
|
|
50
51
|
names: [],
|
|
51
52
|
mappings: lines.join(";"),
|
|
52
|
-
}
|
|
53
|
+
};
|
|
54
|
+
if (sourcesContent) map.sourcesContent = sourcesContent;
|
|
55
|
+
return JSON.stringify(map);
|
|
53
56
|
}
|