gofront 1.5.1 → 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/README.md +174 -466
- package/package.json +16 -20
- package/src/backend/js/expressions.js +288 -128
- package/src/backend/js/index.js +138 -56
- package/src/backend/js/runtime.js +1055 -53
- package/src/backend/js/source-map.js +32 -0
- package/src/backend/js/statements.js +151 -83
- 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 +22 -3
- package/src/backend/js/stdlib/fmt.js +95 -20
- 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 +19 -0
- package/src/backend/js/stdlib/io.js +105 -3
- package/src/backend/js/stdlib/maps.js +1 -1
- package/src/backend/js/stdlib/math.js +13 -1
- package/src/backend/js/stdlib/path.js +20 -6
- package/src/backend/js/stdlib/rand.js +10 -5
- package/src/backend/js/stdlib/sha256.js +12 -0
- package/src/backend/js/stdlib/shared.js +17 -0
- package/src/backend/js/stdlib/slices.js +53 -27
- package/src/backend/js/stdlib/sort.js +1 -1
- package/src/backend/js/stdlib/strconv.js +52 -11
- package/src/backend/js/stdlib/strings.js +152 -16
- package/src/backend/js/stdlib/sync.js +13 -0
- package/src/backend/js/stdlib/testing.js +2 -2
- package/src/backend/js/stdlib/time.js +93 -22
- package/src/backend/js/stdlib/unicode.js +2 -2
- package/src/backend/js/templ.js +1 -1
- package/src/backend/wasm/boundary.js +1677 -58
- package/src/backend/wasm/const-fold.js +205 -0
- package/src/backend/wasm/emit-builtins.js +1230 -0
- package/src/backend/wasm/emit-exprs.js +2096 -0
- package/src/backend/wasm/emit-maps.js +1999 -0
- package/src/backend/wasm/emit-shared.js +519 -0
- package/src/backend/wasm/emit-stdlib.js +13 -0
- package/src/backend/wasm/emit-stmts.js +2466 -0
- package/src/backend/wasm/emit.js +656 -5031
- package/src/backend/wasm/encode.js +259 -85
- package/src/backend/wasm/glue.js +19 -5
- package/src/backend/wasm/index.js +2432 -86
- package/src/backend/wasm/monomorph.js +711 -0
- package/src/backend/wasm/optimize.js +236 -0
- 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 +312 -36
- package/src/backend/wasm/wat.js +49 -2
- package/src/cli-core.js +276 -73
- package/src/compiler.js +162 -25
- package/src/dts-parser.js +79 -126
- package/src/index.js +88 -121
- package/src/lexer.js +80 -29
- package/src/lower/boxing.js +4 -6
- package/src/lower/captures.js +12 -23
- package/src/lower/escape.js +4 -9
- package/src/lower/functions.js +277 -5
- package/src/lower/globals.js +7 -15
- package/src/lower/index.js +5 -2
- package/src/lower/ownership.js +35 -19
- package/src/lower/range.js +2 -5
- package/src/lower/walk.js +25 -0
- 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 +3 -27
- package/src/templ-lexer.js +29 -63
- package/src/templ-parser.js +22 -45
- package/src/test-runner.js +20 -0
- package/src/typechecker/assignability.js +123 -14
- package/src/typechecker/expressions.js +244 -4
- package/src/typechecker/index.js +27 -1
- package/src/typechecker/resolve.js +71 -12
- package/src/typechecker/statements.js +0 -7
- package/src/typechecker/stdlib/core.js +292 -103
- package/src/typechecker/stdlib/extended.js +471 -4
- package/src/typechecker/stdlib/shared.js +53 -0
- package/src/typechecker/stdlib.js +2 -0
- package/src/typechecker/types.js +545 -8
- package/src/vendor.js +2 -2
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
|
|
15
15
|
/** @typedef {import('./index.js').CodeGen} CodeGen */
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const STRICT_NUMERIC_TYPES = new Set([
|
|
18
18
|
"float32",
|
|
19
19
|
"int8",
|
|
20
20
|
"int16",
|
|
@@ -26,7 +26,7 @@ export const STRICT_NUMERIC_TYPES = new Set([
|
|
|
26
26
|
"uint32",
|
|
27
27
|
]);
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
const STRICT_OPS = new Set([
|
|
30
30
|
"+",
|
|
31
31
|
"-",
|
|
32
32
|
"*",
|
|
@@ -40,6 +40,23 @@ export const STRICT_OPS = new Set([
|
|
|
40
40
|
">>",
|
|
41
41
|
]);
|
|
42
42
|
|
|
43
|
+
const NAMED_ZERO_TABLE = {
|
|
44
|
+
"time.Time": [null, "{ _d: new Date(0), _isZero: true }"],
|
|
45
|
+
"strings.Builder": [null, '{ _buf: "" }'],
|
|
46
|
+
"bytes.Buffer": [null, "{ _buf: [] }"],
|
|
47
|
+
"strings.Replacer": [null, "{ _p: [], Replace(s) { return s; } }"],
|
|
48
|
+
"sync.Mutex": ["sync", "__sync_mutex()"],
|
|
49
|
+
"sync.RWMutex": ["sync", "__sync_rwmutex()"],
|
|
50
|
+
"sync.Once": ["sync", "__sync_once()"],
|
|
51
|
+
"sync.WaitGroup": ["sync", "__sync_waitgroup()"],
|
|
52
|
+
"binary.LittleEndian": ["binary", "__binary_le"],
|
|
53
|
+
"encoding/binary.LittleEndian": ["binary", "__binary_le"],
|
|
54
|
+
"binary.BigEndian": ["binary", "__binary_be"],
|
|
55
|
+
"encoding/binary.BigEndian": ["binary", "__binary_be"],
|
|
56
|
+
"base64.Encoding": ["base64", "__base64_std"],
|
|
57
|
+
"encoding/base64.Encoding": ["base64", "__base64_std"],
|
|
58
|
+
};
|
|
59
|
+
|
|
43
60
|
// Splits a generated JS lvalue at its outermost trailing access:
|
|
44
61
|
// `a.b[i]` → { obj: "a.b", key: "i" }, `a.b.c` → { obj: "a.b", prop: "c" }.
|
|
45
62
|
function splitLastAccess(js) {
|
|
@@ -78,18 +95,76 @@ const NS_CONSTANTS = {
|
|
|
78
95
|
math: {
|
|
79
96
|
Pi: "Math.PI",
|
|
80
97
|
E: "Math.E",
|
|
98
|
+
Phi: "1.618033988749895",
|
|
99
|
+
Sqrt2: "Math.SQRT2",
|
|
100
|
+
SqrtE: "1.6487212707001282",
|
|
101
|
+
SqrtPi: "1.7724538509055159",
|
|
102
|
+
SqrtPhi: "1.272019649514069",
|
|
103
|
+
Ln2: "Math.LN2",
|
|
104
|
+
Log2E: "Math.LOG2E",
|
|
105
|
+
Ln10: "Math.LN10",
|
|
106
|
+
Log10E: "Math.LOG10E",
|
|
107
|
+
MaxFloat32: "3.4028234663852886e38",
|
|
108
|
+
SmallestNonzeroFloat32: "1.401298464324817e-45",
|
|
81
109
|
MaxFloat64: "Number.MAX_VALUE",
|
|
82
110
|
SmallestNonzeroFloat64: "Number.MIN_VALUE",
|
|
83
111
|
MaxInt: "Number.MAX_SAFE_INTEGER",
|
|
84
112
|
MinInt: "Number.MIN_SAFE_INTEGER",
|
|
113
|
+
MaxInt8: "127",
|
|
114
|
+
MinInt8: "-128",
|
|
115
|
+
MaxInt16: "32767",
|
|
116
|
+
MinInt16: "-32768",
|
|
117
|
+
MaxInt32: "2147483647",
|
|
118
|
+
MinInt32: "-2147483648",
|
|
119
|
+
MaxInt64: "9223372036854775807",
|
|
120
|
+
MinInt64: "-9223372036854775808",
|
|
121
|
+
MaxUint8: "255",
|
|
122
|
+
MaxUint16: "65535",
|
|
123
|
+
MaxUint32: "4294967295",
|
|
124
|
+
MaxUint: "18446744073709551615",
|
|
125
|
+
MaxUint64: "18446744073709551615",
|
|
126
|
+
},
|
|
127
|
+
strconv: {
|
|
128
|
+
ErrSyntax: "__strconv_err_syntax",
|
|
129
|
+
ErrRange: "__strconv_err_range",
|
|
130
|
+
},
|
|
131
|
+
path: {
|
|
132
|
+
ErrBadPattern: "__path_err_bad_pattern",
|
|
133
|
+
},
|
|
134
|
+
filepath: {
|
|
135
|
+
ErrBadPattern: "__path_err_bad_pattern",
|
|
85
136
|
},
|
|
86
137
|
io: {
|
|
87
|
-
EOF:
|
|
138
|
+
EOF: "__io_eof",
|
|
88
139
|
Discard:
|
|
89
|
-
"{ WriteString(s) { return s.length; }, Write(b) { return b.length; } }",
|
|
140
|
+
"{ WriteString(s) { return [s.length, null]; }, Write(b) { return [b.length, null]; } }",
|
|
141
|
+
},
|
|
142
|
+
sha256: {
|
|
143
|
+
Size: "32",
|
|
144
|
+
BlockSize: "64",
|
|
145
|
+
},
|
|
146
|
+
hex: {
|
|
147
|
+
ErrLength: '__error("encoding/hex: odd length hex string")',
|
|
148
|
+
},
|
|
149
|
+
base64: {
|
|
150
|
+
StdPadding: "61",
|
|
151
|
+
NoPadding: "-1",
|
|
152
|
+
StdEncoding: "__base64_std",
|
|
153
|
+
URLEncoding: "__base64_url",
|
|
154
|
+
RawStdEncoding: "__base64_raw_std",
|
|
155
|
+
RawURLEncoding: "__base64_raw_url",
|
|
156
|
+
},
|
|
157
|
+
binary: {
|
|
158
|
+
LittleEndian: "__binary_le",
|
|
159
|
+
BigEndian: "__binary_be",
|
|
160
|
+
},
|
|
161
|
+
rand: {
|
|
162
|
+
Reader: "__crypto_rand_reader",
|
|
90
163
|
},
|
|
91
164
|
os: { Args: "process.argv" },
|
|
92
165
|
time: {
|
|
166
|
+
Nanosecond: "1",
|
|
167
|
+
Microsecond: "1000",
|
|
93
168
|
Millisecond: "1000000",
|
|
94
169
|
Second: "1000000000",
|
|
95
170
|
Minute: "60000000000",
|
|
@@ -233,14 +308,19 @@ const BUILTIN_GEN = {
|
|
|
233
308
|
}
|
|
234
309
|
return `{ value: ${s.zeroValueForExpr(arg)} }`;
|
|
235
310
|
},
|
|
236
|
-
print
|
|
311
|
+
// `print` writes without a trailing newline (Go semantics); the wasm glue
|
|
312
|
+
// buffers the same way, so output parity holds across backends.
|
|
313
|
+
print: (s, e) =>
|
|
314
|
+
`((__s) => (typeof process !== "undefined" && process?.stdout?.write ? process.stdout.write(__s) : console.log(__s)))([${e.args.map((a) => s.genExpr(a)).join(", ")}].map(String).join(" "))`,
|
|
237
315
|
println: (s, e) =>
|
|
238
316
|
`console.log(${e.args.map((a) => s.genExpr(a)).join(", ")})`,
|
|
239
317
|
panic: (s, e) => `(() => { throw new Error(${s.genExpr(e.args[0])}); })()`,
|
|
240
|
-
recover: () =>
|
|
241
|
-
|
|
318
|
+
recover: (s) => {
|
|
319
|
+
s.useHelper("panicRt");
|
|
320
|
+
return `__recover(${s._recoverOkInScope ? "__recoverOk" : "false"})`;
|
|
321
|
+
},
|
|
242
322
|
error: (s, e) => {
|
|
243
|
-
s.
|
|
323
|
+
s.useHelper("error");
|
|
244
324
|
return `__error(${s.genExpr(e.args[0])})`;
|
|
245
325
|
},
|
|
246
326
|
min: (s, e) => `Math.min(${e.args.map((a) => s.genExpr(a)).join(", ")})`,
|
|
@@ -272,9 +352,23 @@ export const expressionGenMethods = {
|
|
|
272
352
|
if (expr._ifaceBox && !expr._ifaceBoxing) {
|
|
273
353
|
expr._ifaceBoxing = true;
|
|
274
354
|
try {
|
|
275
|
-
this.
|
|
276
|
-
const fn =
|
|
277
|
-
|
|
355
|
+
this.useHelper("ifaceBox");
|
|
356
|
+
const fn =
|
|
357
|
+
expr._ifaceBox === "ptr"
|
|
358
|
+
? "__ifp"
|
|
359
|
+
: expr._ifaceBox === "ptr_slice"
|
|
360
|
+
? "__ifps"
|
|
361
|
+
: expr._ifaceBox === "ptr_map"
|
|
362
|
+
? "__ifpm"
|
|
363
|
+
: expr._ifaceBox === "map"
|
|
364
|
+
? "__ifm"
|
|
365
|
+
: expr._ifaceBox === "slice"
|
|
366
|
+
? "__ifs"
|
|
367
|
+
: "__ifv";
|
|
368
|
+
const extra = expr._ifacePtrFields?.length
|
|
369
|
+
? `, ${JSON.stringify(expr._ifacePtrFields)}`
|
|
370
|
+
: "";
|
|
371
|
+
return `${fn}(${this.genExpr(expr)}${extra})`;
|
|
278
372
|
} finally {
|
|
279
373
|
expr._ifaceBoxing = false;
|
|
280
374
|
}
|
|
@@ -365,7 +459,7 @@ export const expressionGenMethods = {
|
|
|
365
459
|
if (base.kind === "struct") {
|
|
366
460
|
if (this._structClassName(t) || this._structClassName(base))
|
|
367
461
|
return `${js}.__clone()`;
|
|
368
|
-
this.
|
|
462
|
+
this.useHelper("sclone");
|
|
369
463
|
return `__sclone(${js})`;
|
|
370
464
|
}
|
|
371
465
|
const elemClone = this._cloneJs(base.elem, "__e");
|
|
@@ -495,6 +589,13 @@ export const expressionGenMethods = {
|
|
|
495
589
|
) {
|
|
496
590
|
return this.genExpr(expr.operand);
|
|
497
591
|
}
|
|
592
|
+
if (
|
|
593
|
+
expr.operand.kind === "SelectorExpr" ||
|
|
594
|
+
expr.operand.kind === "IndexExpr"
|
|
595
|
+
) {
|
|
596
|
+
const inner = this.genExpr(expr.operand);
|
|
597
|
+
return `{ get value() { return ${inner}; }, set value(v) { ${inner} = v; } }`;
|
|
598
|
+
}
|
|
498
599
|
// For non-boxed vars (primitives, etc.), wrap in { value: x }
|
|
499
600
|
return `{ value: ${this.genExpr(expr.operand)} }`;
|
|
500
601
|
}
|
|
@@ -524,7 +625,27 @@ export const expressionGenMethods = {
|
|
|
524
625
|
}
|
|
525
626
|
if (expr.expr.kind === "Ident") {
|
|
526
627
|
const nsConst = NS_CONSTANTS[expr.expr.name]?.[expr.field];
|
|
527
|
-
if (nsConst !== undefined)
|
|
628
|
+
if (nsConst !== undefined) {
|
|
629
|
+
if (expr.expr.name === "strconv") {
|
|
630
|
+
this.useHelper("strconvError");
|
|
631
|
+
} else if (expr.expr.name === "path" || expr.expr.name === "filepath") {
|
|
632
|
+
if (expr.field === "ErrBadPattern") this.useHelper("pathError");
|
|
633
|
+
} else if (expr.expr.name === "io" && expr.field === "EOF") {
|
|
634
|
+
this.useHelper("ioEOF");
|
|
635
|
+
} else if (expr.expr.name === "binary") {
|
|
636
|
+
this.useHelper("binary");
|
|
637
|
+
} else if (expr.expr.name === "hex") {
|
|
638
|
+
this.useHelper("hex");
|
|
639
|
+
this.useHelper("error");
|
|
640
|
+
} else if (expr.expr.name === "base64") {
|
|
641
|
+
this.useHelper("base64");
|
|
642
|
+
} else if (expr.expr.name === "rand" && expr.field === "Reader") {
|
|
643
|
+
this.useHelper("cryptoRand");
|
|
644
|
+
} else if (expr.expr.name === "sha256") {
|
|
645
|
+
this.useHelper("sha256");
|
|
646
|
+
}
|
|
647
|
+
return nsConst;
|
|
648
|
+
}
|
|
528
649
|
}
|
|
529
650
|
const base = this.genExpr(expr.expr);
|
|
530
651
|
if (this.bundledPackages.has(base)) return expr.field;
|
|
@@ -613,7 +734,7 @@ export const expressionGenMethods = {
|
|
|
613
734
|
this._withFnCtx(expr.body, () =>
|
|
614
735
|
this.indented(() => {
|
|
615
736
|
this._emitParamCopies(expr.params);
|
|
616
|
-
this._genBody(expr.body);
|
|
737
|
+
this._genBody(expr.body, expr);
|
|
617
738
|
}),
|
|
618
739
|
);
|
|
619
740
|
const body = this.out.join("\n");
|
|
@@ -700,14 +821,71 @@ export const expressionGenMethods = {
|
|
|
700
821
|
return this._genRegexpMethodCall(expr.func.field, expr);
|
|
701
822
|
if (recvName === "time.Time")
|
|
702
823
|
return this._genTimeMethodCall(expr.func.field, expr);
|
|
824
|
+
if (recvName === "time.Duration")
|
|
825
|
+
return this._genDurationMethodCall(expr.func.field, expr);
|
|
703
826
|
if (recvName === "testing.T")
|
|
704
827
|
return this._genTestingMethodCall(expr.func.field, expr);
|
|
828
|
+
if (recvName === "strings.Replacer") {
|
|
829
|
+
const recv = this.genExpr(expr.func.expr);
|
|
830
|
+
const arg = this.genExpr(expr.args[0]);
|
|
831
|
+
return `(${recv} ? ${recv}.Replace(${arg}) : ${arg})`;
|
|
832
|
+
}
|
|
833
|
+
if (recvName?.startsWith("shared.") && expr.func.field === "Subarray") {
|
|
834
|
+
const args = expr.args.map((a) => this.genExpr(a)).join(", ");
|
|
835
|
+
return `${this.genExpr(expr.func.expr)}.subarray(${args})`;
|
|
836
|
+
}
|
|
837
|
+
if (recvName === "sync.Mutex" || recvName === "sync.RWMutex") {
|
|
838
|
+
if (expr.func.field === "TryLock" || expr.func.field === "TryRLock")
|
|
839
|
+
return "true";
|
|
840
|
+
return "(void 0)";
|
|
841
|
+
}
|
|
842
|
+
if (recvName === "sync.Once" && expr.func.field === "Do") {
|
|
843
|
+
const recv = this.genExpr(expr.func.expr);
|
|
844
|
+
const f = this.genExpr(expr.args[0]);
|
|
845
|
+
return `((o, fn) => { if (!o.done) { o.done = 1; fn(); } })(${recv}, ${f})`;
|
|
846
|
+
}
|
|
847
|
+
if (recvName === "sync.WaitGroup") {
|
|
848
|
+
const recv = this.genExpr(expr.func.expr);
|
|
849
|
+
if (expr.func.field === "Add") {
|
|
850
|
+
return `((wg, d) => { wg.counter = (wg.counter || 0) + d; })(${recv}, ${this.genExpr(expr.args[0])})`;
|
|
851
|
+
}
|
|
852
|
+
if (expr.func.field === "Done") {
|
|
853
|
+
return `((wg) => { wg.counter = (wg.counter || 0) - 1; })(${recv})`;
|
|
854
|
+
}
|
|
855
|
+
if (expr.func.field === "Wait") return "(void 0)";
|
|
856
|
+
}
|
|
857
|
+
if (
|
|
858
|
+
recvName === "binary.LittleEndian" ||
|
|
859
|
+
recvName === "binary.BigEndian" ||
|
|
860
|
+
recvName === "encoding/binary.LittleEndian" ||
|
|
861
|
+
recvName === "encoding/binary.BigEndian" ||
|
|
862
|
+
recvName === "binary.ByteOrder" ||
|
|
863
|
+
recvName === "encoding/binary.ByteOrder"
|
|
864
|
+
) {
|
|
865
|
+
this.useHelper("binary");
|
|
866
|
+
const recv = this.genExpr(expr.func.expr);
|
|
867
|
+
const args = expr.args.map((a) => this.genExpr(a)).join(", ");
|
|
868
|
+
return `${recv}.${expr.func.field}(${args})`;
|
|
869
|
+
}
|
|
870
|
+
if (
|
|
871
|
+
recvName === "base64.Encoding" ||
|
|
872
|
+
recvName === "encoding/base64.Encoding"
|
|
873
|
+
) {
|
|
874
|
+
this.useHelper("base64");
|
|
875
|
+
const recv = this.genExpr(expr.func.expr);
|
|
876
|
+
const args = expr.args.map((a) => this.genExpr(a)).join(", ");
|
|
877
|
+
return `${recv}.${expr.func.field}(${args})`;
|
|
878
|
+
}
|
|
705
879
|
return undefined;
|
|
706
880
|
},
|
|
707
881
|
|
|
708
882
|
_genSelectorCall(expr) {
|
|
709
|
-
if (this._isErrorMethodCall(expr))
|
|
710
|
-
|
|
883
|
+
if (this._isErrorMethodCall(expr)) {
|
|
884
|
+
const recv = this.genExpr(expr.func.expr);
|
|
885
|
+
if (!this.strict) return `${recv}.Error()`;
|
|
886
|
+
this.useHelper("nilCall");
|
|
887
|
+
return `__nilcall(${recv}).Error()`;
|
|
888
|
+
}
|
|
711
889
|
if (expr.func.expr.kind === "Ident") {
|
|
712
890
|
const ns = expr.func.expr.name;
|
|
713
891
|
const fn = expr.func.field;
|
|
@@ -716,7 +894,25 @@ export const expressionGenMethods = {
|
|
|
716
894
|
}
|
|
717
895
|
const recvType = expr.func.expr._type;
|
|
718
896
|
const recvName = this._resolveRecvName(recvType);
|
|
719
|
-
|
|
897
|
+
const typed = this._genReceiverTypeCall(recvName, expr);
|
|
898
|
+
if (typed !== undefined) return typed;
|
|
899
|
+
if (this.strict && this._isInterfaceType(recvType)) {
|
|
900
|
+
// Go panics with a nil-dereference runtime error; JS would throw a
|
|
901
|
+
// TypeError with a different message.
|
|
902
|
+
this.useHelper("nilCall");
|
|
903
|
+
const recv = this.genExpr(expr.func.expr);
|
|
904
|
+
const args = expr.args
|
|
905
|
+
.map((a) => (a._spread ? `...${this.genExpr(a)}` : this.genExpr(a)))
|
|
906
|
+
.join(", ");
|
|
907
|
+
return `__nilcall(${recv}).${expr.func.field}(${args})`;
|
|
908
|
+
}
|
|
909
|
+
return undefined;
|
|
910
|
+
},
|
|
911
|
+
|
|
912
|
+
_isInterfaceType(t) {
|
|
913
|
+
if (!t) return false;
|
|
914
|
+
if (t.kind === "interface") return true;
|
|
915
|
+
return t.kind === "named" && t.underlying?.kind === "interface";
|
|
720
916
|
},
|
|
721
917
|
|
|
722
918
|
_genBuiltinLen(expr) {
|
|
@@ -727,7 +923,7 @@ export const expressionGenMethods = {
|
|
|
727
923
|
if (wrapField) return `${this.genExpr(arg)}.${wrapField}.length`;
|
|
728
924
|
const js = this.genExpr(arg);
|
|
729
925
|
if (t?.kind === "map") return `Object.keys(${js}).length`;
|
|
730
|
-
this.
|
|
926
|
+
this.useHelper("len");
|
|
731
927
|
return `__len(${js})`;
|
|
732
928
|
},
|
|
733
929
|
|
|
@@ -760,7 +956,7 @@ export const expressionGenMethods = {
|
|
|
760
956
|
a._spread ? `...${this.genExpr(a)}` : this.genValueExpr(a),
|
|
761
957
|
);
|
|
762
958
|
if (elems.length === 0) return this.genExpr(expr.args[0]);
|
|
763
|
-
this.
|
|
959
|
+
this.useHelper("append");
|
|
764
960
|
return `new ${retType.name}(__append(${sliceJS}, ${elems.join(", ")}))`;
|
|
765
961
|
}
|
|
766
962
|
const slice = this.genExpr(expr.args[0]);
|
|
@@ -768,7 +964,7 @@ export const expressionGenMethods = {
|
|
|
768
964
|
.slice(1)
|
|
769
965
|
.map((a) => (a._spread ? `...${this.genExpr(a)}` : this.genValueExpr(a)));
|
|
770
966
|
if (elems.length === 0) return slice;
|
|
771
|
-
this.
|
|
967
|
+
this.useHelper("append");
|
|
772
968
|
const sliceType = expr._type ?? expr.args[0]._type;
|
|
773
969
|
const typedCtor = isTypedArraySlice(sliceType)
|
|
774
970
|
? typedArrayConstructorForElem(
|
|
@@ -950,10 +1146,38 @@ export const expressionGenMethods = {
|
|
|
950
1146
|
return `new ${typeName}(${args.join(", ")})`;
|
|
951
1147
|
},
|
|
952
1148
|
|
|
1149
|
+
_genSliceOrArrayLit(t, expr) {
|
|
1150
|
+
const elems = expr.elems
|
|
1151
|
+
.map((e) => this.genValueExpr(e.kind === "KeyValueExpr" ? e.value : e))
|
|
1152
|
+
.join(", ");
|
|
1153
|
+
const elemNode =
|
|
1154
|
+
t.kind === "SliceType" || t.kind === "ArrayType" ? t.elem : null;
|
|
1155
|
+
const elemResolved =
|
|
1156
|
+
expr._type?.kind === "slice" || expr._type?.kind === "array"
|
|
1157
|
+
? expr._type.elem
|
|
1158
|
+
: null;
|
|
1159
|
+
const typedCtor =
|
|
1160
|
+
typedArrayConstructorForElem(elemResolved) ??
|
|
1161
|
+
(elemNode?.name
|
|
1162
|
+
? typedArrayConstructorForElem({
|
|
1163
|
+
kind: "basic",
|
|
1164
|
+
name: elemNode.name,
|
|
1165
|
+
})
|
|
1166
|
+
: null);
|
|
1167
|
+
if (typedCtor) {
|
|
1168
|
+
return `new ${typedCtor}([${elems}])`;
|
|
1169
|
+
}
|
|
1170
|
+
return `[${elems}]`;
|
|
1171
|
+
},
|
|
1172
|
+
|
|
953
1173
|
genCompositeLit(expr) {
|
|
954
1174
|
const t = expr.typeExpr;
|
|
955
1175
|
if (t === null) return this._genImplicitCompositeLit(expr);
|
|
956
1176
|
const typeName = this.getTypeName(t);
|
|
1177
|
+
if (typeName === "bytes.Buffer" || typeName === "Buffer")
|
|
1178
|
+
return "{ _buf: [] }";
|
|
1179
|
+
if (typeName === "strings.Builder" || typeName === "Builder")
|
|
1180
|
+
return '{ _buf: "" }';
|
|
957
1181
|
if (typeName && this.structNames.has(typeName))
|
|
958
1182
|
return this._genPositionalStructLit(typeName, expr);
|
|
959
1183
|
if (typeName && this.namedWrapperNames.has(typeName))
|
|
@@ -961,29 +1185,7 @@ export const expressionGenMethods = {
|
|
|
961
1185
|
if (expr.elems.some((e) => e._positionalField)) {
|
|
962
1186
|
if (typeName) return this._genPositionalStructLit(typeName, expr);
|
|
963
1187
|
}
|
|
964
|
-
if (this._isSliceOrArrayType(t))
|
|
965
|
-
const elems = expr.elems
|
|
966
|
-
.map((e) => this.genValueExpr(e.kind === "KeyValueExpr" ? e.value : e))
|
|
967
|
-
.join(", ");
|
|
968
|
-
const elemNode =
|
|
969
|
-
t.kind === "SliceType" || t.kind === "ArrayType" ? t.elem : null;
|
|
970
|
-
const elemResolved =
|
|
971
|
-
expr._type?.kind === "slice" || expr._type?.kind === "array"
|
|
972
|
-
? expr._type.elem
|
|
973
|
-
: null;
|
|
974
|
-
const typedCtor =
|
|
975
|
-
typedArrayConstructorForElem(elemResolved) ??
|
|
976
|
-
(elemNode?.name
|
|
977
|
-
? typedArrayConstructorForElem({
|
|
978
|
-
kind: "basic",
|
|
979
|
-
name: elemNode.name,
|
|
980
|
-
})
|
|
981
|
-
: null);
|
|
982
|
-
if (typedCtor) {
|
|
983
|
-
return `new ${typedCtor}([${elems}])`;
|
|
984
|
-
}
|
|
985
|
-
return `[${elems}]`;
|
|
986
|
-
}
|
|
1188
|
+
if (this._isSliceOrArrayType(t)) return this._genSliceOrArrayLit(t, expr);
|
|
987
1189
|
if (this._isMapTypeNode(t))
|
|
988
1190
|
return `{ ${this._genMapLitEntries(expr.elems)} }`;
|
|
989
1191
|
return this._genFallbackCompositeLit(expr);
|
|
@@ -1018,19 +1220,7 @@ export const expressionGenMethods = {
|
|
|
1018
1220
|
const namedType = this.checker?.types.get(typeName);
|
|
1019
1221
|
const u = namedType?.underlying;
|
|
1020
1222
|
if (u?.kind === "map") {
|
|
1021
|
-
|
|
1022
|
-
.map((e) => {
|
|
1023
|
-
if (e.kind === "KeyValueExpr") {
|
|
1024
|
-
const k =
|
|
1025
|
-
e.key.litKind === "STRING"
|
|
1026
|
-
? JSON.stringify(e.key.value)
|
|
1027
|
-
: `[${this.genExpr(e.key)}]`;
|
|
1028
|
-
return `${k}: ${this.genValueExpr(e.value)}`;
|
|
1029
|
-
}
|
|
1030
|
-
return this.genValueExpr(e);
|
|
1031
|
-
})
|
|
1032
|
-
.join(", ");
|
|
1033
|
-
return `new ${typeName}({ ${entries} })`;
|
|
1223
|
+
return `new ${typeName}({ ${this._genMapLitEntries(expr.elems)} })`;
|
|
1034
1224
|
}
|
|
1035
1225
|
// Default: slice
|
|
1036
1226
|
const elems = expr.elems
|
|
@@ -1093,8 +1283,11 @@ export const expressionGenMethods = {
|
|
|
1093
1283
|
},
|
|
1094
1284
|
|
|
1095
1285
|
_zeroForNamedType(name) {
|
|
1096
|
-
|
|
1097
|
-
if (
|
|
1286
|
+
const entry = NAMED_ZERO_TABLE[name];
|
|
1287
|
+
if (entry) {
|
|
1288
|
+
if (entry[0]) this.useHelper(entry[0]);
|
|
1289
|
+
return entry[1];
|
|
1290
|
+
}
|
|
1098
1291
|
name = this._dequalify(name);
|
|
1099
1292
|
if (this.structNames.has(name)) return `new ${name}()`;
|
|
1100
1293
|
return "null";
|
|
@@ -1240,10 +1433,10 @@ export const expressionGenMethods = {
|
|
|
1240
1433
|
case "-":
|
|
1241
1434
|
return `{ re: ${l}.re - ${r}.re, im: ${l}.im - ${r}.im }`;
|
|
1242
1435
|
case "*":
|
|
1243
|
-
this.
|
|
1436
|
+
this.useHelper("cmul");
|
|
1244
1437
|
return `__cmul(${l}, ${r})`;
|
|
1245
1438
|
case "/":
|
|
1246
|
-
this.
|
|
1439
|
+
this.useHelper("cdiv");
|
|
1247
1440
|
return `__cdiv(${l}, ${r})`;
|
|
1248
1441
|
case "==":
|
|
1249
1442
|
return `(${l}.re === ${r}.re && ${l}.im === ${r}.im)`;
|
|
@@ -1261,7 +1454,7 @@ export const expressionGenMethods = {
|
|
|
1261
1454
|
return this._genComplexBinary(expr);
|
|
1262
1455
|
|
|
1263
1456
|
if (this._isStructEquality(expr)) {
|
|
1264
|
-
this.
|
|
1457
|
+
this.useHelper("equal");
|
|
1265
1458
|
const cmp = `__equal(${this.genExpr(expr.left)}, ${this.genExpr(expr.right)})`;
|
|
1266
1459
|
return expr.op === "==" ? cmp : `!${cmp}`;
|
|
1267
1460
|
}
|
|
@@ -1346,7 +1539,7 @@ export const expressionGenMethods = {
|
|
|
1346
1539
|
return this._genSliceTypeConversion(expr, inner, t);
|
|
1347
1540
|
const target = t?.name;
|
|
1348
1541
|
if (target === "error") {
|
|
1349
|
-
this.
|
|
1542
|
+
this.useHelper("error");
|
|
1350
1543
|
return `__error(${inner})`;
|
|
1351
1544
|
}
|
|
1352
1545
|
if (target && this.namedWrapperNames.has(target))
|
|
@@ -1366,24 +1559,17 @@ export const expressionGenMethods = {
|
|
|
1366
1559
|
return inner;
|
|
1367
1560
|
},
|
|
1368
1561
|
|
|
1369
|
-
_isStringSource(srcType) {
|
|
1370
|
-
return (
|
|
1371
|
-
(srcType?.kind === "basic" && srcType?.name === "string") ||
|
|
1372
|
-
(srcType?.kind === "untyped" && srcType?.base === "string")
|
|
1373
|
-
);
|
|
1374
|
-
},
|
|
1375
|
-
|
|
1376
1562
|
_genSliceTypeConversion(expr, inner, t) {
|
|
1377
1563
|
const elem = t.elem?.name;
|
|
1378
1564
|
if (elem === "byte" || elem === "uint8") {
|
|
1379
|
-
if (this.
|
|
1565
|
+
if (this._isStringExprType(expr.expr._type))
|
|
1380
1566
|
return `new TextEncoder().encode(${inner})`;
|
|
1381
1567
|
return `new Uint8Array(${inner})`;
|
|
1382
1568
|
}
|
|
1383
1569
|
const typedCtor = typedArrayConstructorForElem(
|
|
1384
1570
|
t.elem ? { kind: "basic", name: t.elem.name } : null,
|
|
1385
1571
|
);
|
|
1386
|
-
const fromString = this.
|
|
1572
|
+
const fromString = this._isStringExprType(expr.expr._type);
|
|
1387
1573
|
if (typedCtor) {
|
|
1388
1574
|
return fromString
|
|
1389
1575
|
? `${typedCtor}.from(${inner}, __c => __c.codePointAt(0))`
|
|
@@ -1501,81 +1687,55 @@ export const expressionGenMethods = {
|
|
|
1501
1687
|
if (tName === "float32") {
|
|
1502
1688
|
return `Math.fround(${l} ${op} ${r})`;
|
|
1503
1689
|
}
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
if (op === "<<" || op === ">>") {
|
|
1511
|
-
return `((${r}) >= 32 ? (${op === ">>" ? `((${l}) < 0 ? -1 : 0)` : "0"}) : ((${l}) ${op} (${r}))) | 0`;
|
|
1512
|
-
}
|
|
1513
|
-
if (op === "&^") return `((${l}) & ~(${r})) | 0`;
|
|
1514
|
-
return `((${l} ${op} ${r}) | 0)`;
|
|
1515
|
-
}
|
|
1516
|
-
if (tName === "uint32") {
|
|
1690
|
+
const divZero =
|
|
1691
|
+
'(() => { throw new Error("runtime error: integer divide by zero"); })()';
|
|
1692
|
+
if (tName === "int32" || tName === "rune" || tName === "uint32") {
|
|
1693
|
+
const signed = tName !== "uint32";
|
|
1694
|
+
const cast = signed ? "| 0" : ">>> 0";
|
|
1695
|
+
if (signed && op === "*") return `Math.imul(${l}, ${r})`;
|
|
1517
1696
|
if (op === "/")
|
|
1518
|
-
return `((${r}) === 0 ?
|
|
1697
|
+
return `((${r}) === 0 ? ${divZero} : (Math.trunc((${l}) / (${r})) ${cast}))`;
|
|
1519
1698
|
if (op === "%")
|
|
1520
|
-
return `((${r}) === 0 ?
|
|
1699
|
+
return `((${r}) === 0 ? ${divZero} : (((${l}) % (${r})) ${cast}))`;
|
|
1521
1700
|
if (op === "<<" || op === ">>") {
|
|
1522
|
-
const
|
|
1523
|
-
|
|
1701
|
+
const ovf = signed && op === ">>" ? `((${l}) < 0 ? -1 : 0)` : "0";
|
|
1702
|
+
const jsOp = !signed && op === ">>" ? ">>>" : op;
|
|
1703
|
+
return `((${r}) >= 32 ? ${ovf} : ((${l}) ${jsOp} (${r}))) ${cast}`;
|
|
1524
1704
|
}
|
|
1525
|
-
if (op === "&^") return `((${l}) & ~(${r}))
|
|
1526
|
-
return `((${l} ${op} ${r})
|
|
1705
|
+
if (op === "&^") return `((${l}) & ~(${r})) ${cast}`;
|
|
1706
|
+
return `((${l} ${op} ${r}) ${cast})`;
|
|
1527
1707
|
}
|
|
1528
|
-
if (tName === "int8") {
|
|
1708
|
+
if (tName === "int8" || tName === "int16") {
|
|
1709
|
+
const bits = tName === "int8" ? 8 : 16;
|
|
1710
|
+
const sh = 32 - bits;
|
|
1529
1711
|
if (op === "/")
|
|
1530
|
-
return `((${r}) === 0 ?
|
|
1712
|
+
return `((${r}) === 0 ? ${divZero} : ((Math.trunc((${l}) / (${r})) << ${sh}) >> ${sh}))`;
|
|
1531
1713
|
if (op === "%")
|
|
1532
|
-
return `((${r}) === 0 ?
|
|
1714
|
+
return `((${r}) === 0 ? ${divZero} : (((((${l}) % (${r})) << ${sh}) >> ${sh})))`;
|
|
1533
1715
|
if (op === "<<" || op === ">>") {
|
|
1534
|
-
return `((${r}) >=
|
|
1716
|
+
return `((${r}) >= ${bits} ? (${op === ">>" ? `((${l}) < 0 ? -1 : 0)` : "0"}) : (((${l}) ${op} (${r})) << ${sh} >> ${sh}))`;
|
|
1535
1717
|
}
|
|
1536
|
-
if (op === "&^") return `((((${l}) & ~(${r})) <<
|
|
1537
|
-
return `((((${l} ${op} ${r})) <<
|
|
1718
|
+
if (op === "&^") return `((((${l}) & ~(${r})) << ${sh}) >> ${sh})`;
|
|
1719
|
+
return `((((${l} ${op} ${r})) << ${sh}) >> ${sh})`;
|
|
1538
1720
|
}
|
|
1539
|
-
if (tName === "
|
|
1721
|
+
if (tName === "uint8" || tName === "byte" || tName === "uint16") {
|
|
1722
|
+
const bits = tName === "uint16" ? 16 : 8;
|
|
1723
|
+
const mask = bits === 16 ? "0xFFFF" : "0xFF";
|
|
1540
1724
|
if (op === "/")
|
|
1541
|
-
return `((${r}) === 0 ?
|
|
1725
|
+
return `((${r}) === 0 ? ${divZero} : (Math.trunc((${l}) / (${r})) & ${mask}))`;
|
|
1542
1726
|
if (op === "%")
|
|
1543
|
-
return `((${r}) === 0 ?
|
|
1544
|
-
if (op === "<<" || op === ">>") {
|
|
1545
|
-
return `((${r}) >= 16 ? (${op === ">>" ? `((${l}) < 0 ? -1 : 0)` : "0"}) : (((${l}) ${op} (${r})) << 16 >> 16))`;
|
|
1546
|
-
}
|
|
1547
|
-
if (op === "&^") return `((((${l}) & ~(${r})) << 16) >> 16)`;
|
|
1548
|
-
return `((((${l} ${op} ${r})) << 16) >> 16)`;
|
|
1549
|
-
}
|
|
1550
|
-
if (tName === "uint8" || tName === "byte") {
|
|
1551
|
-
if (op === "/")
|
|
1552
|
-
return `((${r}) === 0 ? (() => { throw new Error("runtime error: integer divide by zero"); })() : (Math.trunc((${l}) / (${r})) & 0xFF))`;
|
|
1553
|
-
if (op === "%")
|
|
1554
|
-
return `((${r}) === 0 ? (() => { throw new Error("runtime error: integer divide by zero"); })() : (((${l}) % (${r})) & 0xFF))`;
|
|
1727
|
+
return `((${r}) === 0 ? ${divZero} : (((${l}) % (${r})) & ${mask}))`;
|
|
1555
1728
|
if (op === "<<" || op === ">>") {
|
|
1556
1729
|
const jsOp = op === ">>" ? ">>>" : "<<";
|
|
1557
|
-
return `((${r}) >=
|
|
1730
|
+
return `((${r}) >= ${bits} ? 0 : (((${l}) ${jsOp} (${r})) & ${mask}))`;
|
|
1558
1731
|
}
|
|
1559
|
-
if (op === "&^") return `(((${l}) & ~(${r})) &
|
|
1560
|
-
return `((${l} ${op} ${r}) &
|
|
1561
|
-
}
|
|
1562
|
-
if (tName === "uint16") {
|
|
1563
|
-
if (op === "/")
|
|
1564
|
-
return `((${r}) === 0 ? (() => { throw new Error("runtime error: integer divide by zero"); })() : (Math.trunc((${l}) / (${r})) & 0xFFFF))`;
|
|
1565
|
-
if (op === "%")
|
|
1566
|
-
return `((${r}) === 0 ? (() => { throw new Error("runtime error: integer divide by zero"); })() : (((${l}) % (${r})) & 0xFFFF))`;
|
|
1567
|
-
if (op === "<<" || op === ">>") {
|
|
1568
|
-
const jsOp = op === ">>" ? ">>>" : "<<";
|
|
1569
|
-
return `((${r}) >= 16 ? 0 : (((${l}) ${jsOp} (${r})) & 0xFFFF))`;
|
|
1570
|
-
}
|
|
1571
|
-
if (op === "&^") return `(((${l}) & ~(${r})) & 0xFFFF)`;
|
|
1572
|
-
return `((${l} ${op} ${r}) & 0xFFFF)`;
|
|
1732
|
+
if (op === "&^") return `(((${l}) & ~(${r})) & ${mask})`;
|
|
1733
|
+
return `((${l} ${op} ${r}) & ${mask})`;
|
|
1573
1734
|
}
|
|
1574
1735
|
if (this.isIntType(type)) {
|
|
1575
1736
|
if (op === "/")
|
|
1576
|
-
return `((${r}) === 0 ?
|
|
1577
|
-
if (op === "%")
|
|
1578
|
-
return `((${r}) === 0 ? (() => { throw new Error("runtime error: integer divide by zero"); })() : ((${l}) % (${r})))`;
|
|
1737
|
+
return `((${r}) === 0 ? ${divZero} : Math.trunc((${l}) / (${r})))`;
|
|
1738
|
+
if (op === "%") return `((${r}) === 0 ? ${divZero} : ((${l}) % (${r})))`;
|
|
1579
1739
|
}
|
|
1580
1740
|
return `${l} ${op} ${r}`;
|
|
1581
1741
|
},
|