gofront 1.4.0 → 1.5.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/README.md +72 -9
- package/package.json +2 -1
- package/src/{codegen → backend/js}/expressions.js +217 -60
- package/src/{codegen → backend/js}/index.js +21 -35
- package/src/{codegen → backend/js}/statements.js +43 -48
- package/src/backend/js/stdlib/bits.js +32 -0
- package/src/{codegen → backend/js}/stdlib/index.js +3 -0
- package/src/{codegen → backend/js}/templ.js +2 -2
- package/src/backend/wasm/boundary.js +1345 -0
- package/src/backend/wasm/emit.js +5779 -0
- package/src/backend/wasm/encode.js +789 -0
- package/src/backend/wasm/glue.js +130 -0
- package/src/backend/wasm/index.js +1413 -0
- package/src/backend/wasm/types.js +420 -0
- package/src/backend/wasm/wat.js +255 -0
- package/src/cli-core.js +52 -7
- package/src/compiler.js +322 -12
- package/src/dev-server.js +56 -15
- package/src/index.js +17 -9
- package/src/lexer.js +18 -0
- package/src/lower/boxing.js +36 -0
- package/src/lower/captures.js +179 -0
- package/src/lower/embedding.js +30 -0
- package/src/lower/escape.js +169 -0
- package/src/lower/functions.js +30 -0
- package/src/lower/globals.js +324 -0
- package/src/lower/index.js +115 -0
- package/src/lower/ownership.js +142 -0
- package/src/lower/range.js +70 -0
- package/src/minifier.js +2 -0
- package/src/parser/index.js +8 -3
- package/src/resolver.js +1 -0
- package/src/test-runner.js +74 -20
- package/src/typechecker/expressions.js +40 -1
- package/src/typechecker/index.js +234 -4
- package/src/typechecker/statements.js +7 -0
- package/src/typechecker/stdlib/core.js +17 -0
- package/src/typechecker/types.js +56 -2
- /package/src/{codegen → backend/js}/runtime.js +0 -0
- /package/src/{codegen → backend/js}/source-map.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/builder.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/bytes.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/errors.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/fmt.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/gom.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/html.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/io.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/maps.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/math.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/os.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/path.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/rand.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/regexp.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/slices.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/sort.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/strconv.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/strings.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/testing.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/time.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/unicode.js +0 -0
- /package/src/{codegen → backend/js}/stdlib/utf8.js +0 -0
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
bodyRedeclares,
|
|
3
|
+
isIntRangeType,
|
|
4
|
+
isMapRangeType,
|
|
5
|
+
isRangeFor,
|
|
6
|
+
isSimpleIntRange,
|
|
7
|
+
isStringRangeType,
|
|
8
|
+
nodeAssigns,
|
|
9
|
+
} from "../../lower/index.js";
|
|
10
|
+
import { isComplex } from "../../typechecker/types.js";
|
|
4
11
|
|
|
5
12
|
/** @typedef {import('./index.js').CodeGen} CodeGen */
|
|
6
13
|
|
|
@@ -55,9 +62,20 @@ export const statementGenMethods = {
|
|
|
55
62
|
case "TypeDecl":
|
|
56
63
|
this.genTypeDeclWithMethods(stmt, []);
|
|
57
64
|
break;
|
|
58
|
-
case "IncDecStmt":
|
|
59
|
-
|
|
65
|
+
case "IncDecStmt": {
|
|
66
|
+
if (
|
|
67
|
+
this.strict &&
|
|
68
|
+
this._genStrictCompound(
|
|
69
|
+
stmt.expr,
|
|
70
|
+
stmt.op === "++" ? "+" : "-",
|
|
71
|
+
"1",
|
|
72
|
+
srcLine,
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
break;
|
|
76
|
+
this.line(`${this.genExpr(stmt.expr)}${stmt.op};`, srcLine);
|
|
60
77
|
break;
|
|
78
|
+
}
|
|
61
79
|
case "ExprStmt":
|
|
62
80
|
this.line(`${this.genExpr(stmt.expr)};`);
|
|
63
81
|
break;
|
|
@@ -248,6 +266,19 @@ export const statementGenMethods = {
|
|
|
248
266
|
if (active.length === 0) {
|
|
249
267
|
if (rhs.length > 0) this.line(`${rhs[0]};`);
|
|
250
268
|
} else if (lhs.length === 1) {
|
|
269
|
+
if (
|
|
270
|
+
this.strict &&
|
|
271
|
+
stmt.op !== "=" &&
|
|
272
|
+
this._genStrictCompound(
|
|
273
|
+
stmt.lhs[0],
|
|
274
|
+
stmt.op.slice(0, -1),
|
|
275
|
+
active[0].r,
|
|
276
|
+
null,
|
|
277
|
+
active[0].l,
|
|
278
|
+
)
|
|
279
|
+
) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
251
282
|
this.line(`${active[0].l} ${stmt.op} ${active[0].r};`);
|
|
252
283
|
} else {
|
|
253
284
|
this._genAssignMulti(stmt, lhs, rhs, active, pairs);
|
|
@@ -449,28 +480,19 @@ export const statementGenMethods = {
|
|
|
449
480
|
},
|
|
450
481
|
|
|
451
482
|
isRangeFor(stmt) {
|
|
452
|
-
|
|
453
|
-
const init = stmt.init;
|
|
454
|
-
if (init.kind !== "DefineStmt" && init.kind !== "AssignStmt") return false;
|
|
455
|
-
return init.rhs?.[0]?.kind === "RangeExpr";
|
|
483
|
+
return isRangeFor(stmt);
|
|
456
484
|
},
|
|
457
485
|
|
|
458
486
|
_isIntRangeType(iterType) {
|
|
459
|
-
return
|
|
487
|
+
return isIntRangeType(iterType);
|
|
460
488
|
},
|
|
461
489
|
|
|
462
490
|
_isMapRangeType(iterType) {
|
|
463
|
-
return (
|
|
464
|
-
iterType?.kind === "map" ||
|
|
465
|
-
(iterType?.kind === "named" && iterType.underlying?.kind === "map")
|
|
466
|
-
);
|
|
491
|
+
return isMapRangeType(iterType);
|
|
467
492
|
},
|
|
468
493
|
|
|
469
494
|
_isStringRangeType(iterType) {
|
|
470
|
-
return (
|
|
471
|
-
(iterType?.kind === "basic" && iterType.name === "string") ||
|
|
472
|
-
(iterType?.kind === "untyped" && iterType.base === "string")
|
|
473
|
-
);
|
|
495
|
+
return isStringRangeType(iterType);
|
|
474
496
|
},
|
|
475
497
|
|
|
476
498
|
_rangeVarTarget(e, isAssign) {
|
|
@@ -498,17 +520,7 @@ export const statementGenMethods = {
|
|
|
498
520
|
|
|
499
521
|
// True when the body re-declares one of `names` at its top level (legal Go shadowing).
|
|
500
522
|
_bodyRedeclares(body, names) {
|
|
501
|
-
|
|
502
|
-
for (const s of body.stmts ?? []) {
|
|
503
|
-
if (s.kind === "DefineStmt" && s.lhs.some((e) => names.includes(e.name)))
|
|
504
|
-
return true;
|
|
505
|
-
if (
|
|
506
|
-
(s.kind === "VarDecl" || s.kind === "ConstDecl") &&
|
|
507
|
-
s.decls?.some((d) => d.names?.some((n) => names.includes(n)))
|
|
508
|
-
)
|
|
509
|
-
return true;
|
|
510
|
-
}
|
|
511
|
-
return false;
|
|
523
|
+
return bodyRedeclares(body, names);
|
|
512
524
|
},
|
|
513
525
|
|
|
514
526
|
// Range value variable: aliases the element unless the body writes the variable or the collection.
|
|
@@ -565,9 +577,7 @@ export const statementGenMethods = {
|
|
|
565
577
|
|
|
566
578
|
// Whether `for i := range n` can be emitted as a plain `for (let i = 0; …)` without hidden registers.
|
|
567
579
|
_isSimpleIntRange(stmt, name, isAssign) {
|
|
568
|
-
|
|
569
|
-
if (!name || name === "_") return true;
|
|
570
|
-
return !this._boxedVars.has(name) && !this._nodeAssigns(stmt.body, name);
|
|
580
|
+
return isSimpleIntRange(stmt, name, isAssign, this._boxedVars);
|
|
571
581
|
},
|
|
572
582
|
|
|
573
583
|
_genIntRangeBody(stmt, name, isAssign) {
|
|
@@ -603,22 +613,7 @@ export const statementGenMethods = {
|
|
|
603
613
|
|
|
604
614
|
// True when `node` contains an assignment or ++/-- targeting identifier `name`.
|
|
605
615
|
_nodeAssigns(node, name) {
|
|
606
|
-
|
|
607
|
-
if (Array.isArray(node))
|
|
608
|
-
return node.some((n) => this._nodeAssigns(n, name));
|
|
609
|
-
if (
|
|
610
|
-
(node.kind === "AssignStmt" &&
|
|
611
|
-
node.lhs.some((e) => e.kind === "Ident" && e.name === name)) ||
|
|
612
|
-
(node.kind === "IncDecStmt" &&
|
|
613
|
-
node.expr.kind === "Ident" &&
|
|
614
|
-
node.expr.name === name)
|
|
615
|
-
)
|
|
616
|
-
return true;
|
|
617
|
-
for (const key of Object.keys(node)) {
|
|
618
|
-
if (key.startsWith("_")) continue;
|
|
619
|
-
if (this._nodeAssigns(node[key], name)) return true;
|
|
620
|
-
}
|
|
621
|
-
return false;
|
|
616
|
+
return nodeAssigns(node, name);
|
|
622
617
|
},
|
|
623
618
|
|
|
624
619
|
_genIterFor(init, iterType, iteree, lhs, body) {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// src/backend/js/stdlib/bits.js
|
|
2
|
+
// CodeGen for Go `math/bits` package.
|
|
3
|
+
|
|
4
|
+
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
5
|
+
|
|
6
|
+
const BITS_MAP = {
|
|
7
|
+
LeadingZeros32: ([x]) => `Math.clz32((${x}) >>> 0)`,
|
|
8
|
+
TrailingZeros32: ([x]) =>
|
|
9
|
+
`((() => { const v = (${x}) >>> 0; return v === 0 ? 32 : 31 - Math.clz32(v & -v); })())`,
|
|
10
|
+
OnesCount32: ([x]) =>
|
|
11
|
+
`((() => { let v = (${x}) >>> 0; v = v - ((v >>> 1) & 0x55555555); v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); return (Math.imul((v + (v >>> 4)) & 0x0f0f0f0f, 0x01010101)) >>> 24; })())`,
|
|
12
|
+
RotateLeft32: ([x, k]) =>
|
|
13
|
+
`((() => { const s = (${k}) & 31; const v = (${x}) >>> 0; return ((v << s) | (v >>> ((32 - s) & 31))) >>> 0; })())`,
|
|
14
|
+
|
|
15
|
+
LeadingZeros64: ([x]) =>
|
|
16
|
+
`((() => { const v = BigInt.asUintN(64, BigInt(${x})); if (v === 0n) return 64; const hi = Number(v >> 32n); return hi !== 0 ? Math.clz32(hi) : 32 + Math.clz32(Number(v & 0xffffffffn)); })())`,
|
|
17
|
+
TrailingZeros64: ([x]) =>
|
|
18
|
+
`((() => { const v = BigInt.asUintN(64, BigInt(${x})); if (v === 0n) return 64; const lo = Number(v & 0xffffffffn); if (lo !== 0) return 31 - Math.clz32(lo & -lo); const hi = Number((v >> 32n) & 0xffffffffn); return 32 + (31 - Math.clz32(hi & -hi)); })())`,
|
|
19
|
+
OnesCount64: ([x]) =>
|
|
20
|
+
`((() => { let v = BigInt.asUintN(64, BigInt(${x})); let c = 0; while (v > 0n) { if (v & 1n) c++; v >>= 1n; } return c; })())`,
|
|
21
|
+
RotateLeft64: ([x, k]) =>
|
|
22
|
+
`((() => { const s = BigInt(${k}) & 63n; const v = BigInt.asUintN(64, BigInt(${x})); return BigInt.asUintN(64, (v << s) | (v >> ((64n - s) & 63n))); })())`,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** @type {ThisType<CodeGen>} */
|
|
26
|
+
export const bitsMethods = {
|
|
27
|
+
_genBits(fn, a) {
|
|
28
|
+
const args = a();
|
|
29
|
+
const gen = BITS_MAP[fn];
|
|
30
|
+
return gen ? gen(args) : undefined;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// CodeGen stdlib call generation — installed as a mixin on CodeGen.prototype.
|
|
2
2
|
// One file per Go package under ./stdlib/. This index merges them.
|
|
3
3
|
|
|
4
|
+
import { bitsMethods } from "./bits.js";
|
|
4
5
|
import { builderMethods } from "./builder.js";
|
|
5
6
|
import { bytesMethods } from "./bytes.js";
|
|
6
7
|
import { errorsMethods } from "./errors.js";
|
|
@@ -34,6 +35,7 @@ const STDLIB_METHOD_MAP = {
|
|
|
34
35
|
strconv: "_genStrconv",
|
|
35
36
|
sort: "_genSort",
|
|
36
37
|
math: "_genMath",
|
|
38
|
+
bits: "_genBits",
|
|
37
39
|
unicode: "_genUnicode",
|
|
38
40
|
os: "_genOs",
|
|
39
41
|
errors: "_genErrors",
|
|
@@ -76,6 +78,7 @@ const dispatchMethods = {
|
|
|
76
78
|
|
|
77
79
|
/** @type {ThisType<CodeGen>} */
|
|
78
80
|
export const stdlibGenMethods = {
|
|
81
|
+
...bitsMethods,
|
|
79
82
|
...builderMethods,
|
|
80
83
|
...bytesMethods,
|
|
81
84
|
...errorsMethods,
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Mounts an HTML/expression tree onto a parent DOM node by emitting plain
|
|
3
3
|
// document.createElement / appendChild / setAttribute calls.
|
|
4
4
|
|
|
5
|
-
import { Parser } from "
|
|
6
|
-
import { T, Token } from "
|
|
5
|
+
import { Parser } from "../../parser/index.js";
|
|
6
|
+
import { T, Token } from "../../tokens.js";
|
|
7
7
|
|
|
8
8
|
/** @typedef {import('./index.js').CodeGen} CodeGen */
|
|
9
9
|
|