gofront 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -39
- package/package.json +37 -4
- package/src/backend/js/expressions.js +559 -144
- package/src/backend/js/index.js +174 -49
- package/src/backend/js/runtime.js +1518 -54
- package/src/backend/js/statements.js +91 -73
- 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 +25 -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 +28 -0
- package/src/backend/js/stdlib/io.js +105 -3
- package/src/backend/js/stdlib/json.js +972 -0
- 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/simd.js +24 -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 +1225 -41
- package/src/backend/wasm/const-fold.js +205 -0
- package/src/backend/wasm/emit-builtins.js +220 -76
- package/src/backend/wasm/emit-exprs.js +475 -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 +124 -87
- package/src/backend/wasm/encode.js +140 -29
- package/src/backend/wasm/index.js +1001 -32
- package/src/backend/wasm/optimize.js +17 -6
- 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 +43 -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/simd.js +234 -0
- package/src/backend/wasm/stdlib/time.js +1200 -0
- package/src/backend/wasm/types.js +174 -1
- package/src/backend/wasm/wat.js +37 -0
- package/src/cli-core.js +1 -1
- package/src/compiler.js +18 -4
- package/src/dts-parser.js +150 -140
- package/src/index.js +2 -6
- package/src/lexer.js +80 -29
- package/src/lower/boxing.js +1 -7
- package/src/lower/captures.js +2 -6
- package/src/lower/embedding.js +2 -1
- 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/struct-tag.js +144 -0
- package/src/parser/types.js +64 -8
- 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 +126 -13
- package/src/typechecker/expressions.js +168 -16
- package/src/typechecker/index.js +35 -8
- package/src/typechecker/resolve.js +187 -8
- package/src/typechecker/statements.js +68 -9
- package/src/typechecker/stdlib/core.js +280 -89
- package/src/typechecker/stdlib/extended.js +490 -1
- package/src/typechecker/stdlib/simd.js +73 -0
- package/src/typechecker/stdlib.js +2 -0
- package/src/typechecker/types.js +362 -9
- package/src/vendor.js +86 -11
|
@@ -12,16 +12,21 @@ import {
|
|
|
12
12
|
scanBoundaryImports,
|
|
13
13
|
wTypeKey,
|
|
14
14
|
} from "./boundary.js";
|
|
15
|
+
import { foldConstExpr } from "./const-fold.js";
|
|
15
16
|
import { FunctionEmitter } from "./emit.js";
|
|
16
|
-
import { BINARY_MATH_IMPORTS } from "./emit-stdlib.js";
|
|
17
17
|
import { encodeModule, isGoFrontWasm } from "./encode.js";
|
|
18
18
|
import { hasGenerics, monomorphise } from "./monomorph.js";
|
|
19
19
|
import { hasNativeWasmOpt, optimizeWasm } from "./optimize.js";
|
|
20
|
+
import { BINARY_MATH_IMPORTS } from "./stdlib/index.js";
|
|
20
21
|
import {
|
|
22
|
+
anonIfaceName,
|
|
21
23
|
ERROR_STRUCT,
|
|
22
24
|
getFuncSignature,
|
|
25
|
+
getInterfaceMethodList,
|
|
23
26
|
getMapKeyValTypes,
|
|
24
27
|
getReceiverTypeName,
|
|
28
|
+
goTypeKey,
|
|
29
|
+
isInterfaceType,
|
|
25
30
|
isMapType,
|
|
26
31
|
isNonEmptyInterface,
|
|
27
32
|
isTestingT,
|
|
@@ -31,7 +36,28 @@ import { emitWat } from "./wat.js";
|
|
|
31
36
|
|
|
32
37
|
export { hasNativeWasmOpt, isGoFrontWasm, optimizeWasm };
|
|
33
38
|
|
|
34
|
-
const ERROR_PRODUCING_PKGS = new Set([
|
|
39
|
+
const ERROR_PRODUCING_PKGS = new Set([
|
|
40
|
+
"errors",
|
|
41
|
+
"fmt",
|
|
42
|
+
"strconv",
|
|
43
|
+
"path",
|
|
44
|
+
"path/filepath",
|
|
45
|
+
"io",
|
|
46
|
+
"strings",
|
|
47
|
+
"bytes",
|
|
48
|
+
"time",
|
|
49
|
+
"sync",
|
|
50
|
+
"crypto/rand",
|
|
51
|
+
"rand",
|
|
52
|
+
"crypto/sha256",
|
|
53
|
+
"sha256",
|
|
54
|
+
"encoding/binary",
|
|
55
|
+
"binary",
|
|
56
|
+
"encoding/hex",
|
|
57
|
+
"hex",
|
|
58
|
+
"encoding/base64",
|
|
59
|
+
"base64",
|
|
60
|
+
]);
|
|
35
61
|
// Packages whose calls lower to the `env.*` imports in STDLIB_IMPORTS (the
|
|
36
62
|
// matching JS lives in WASM_STDLIB_JS). Only modules importing one of them
|
|
37
63
|
// declare the imports and ship that JS block.
|
|
@@ -41,16 +67,64 @@ const STDLIB_ENV_PKGS = new Set([
|
|
|
41
67
|
"unicode/utf8",
|
|
42
68
|
"fmt",
|
|
43
69
|
"testing",
|
|
70
|
+
"unicode",
|
|
71
|
+
"math/rand",
|
|
72
|
+
"path",
|
|
73
|
+
"path/filepath",
|
|
74
|
+
"html",
|
|
75
|
+
"bytes",
|
|
76
|
+
"io",
|
|
77
|
+
"time",
|
|
78
|
+
"sync",
|
|
79
|
+
"crypto/rand",
|
|
80
|
+
"rand",
|
|
81
|
+
"crypto/sha256",
|
|
82
|
+
"sha256",
|
|
83
|
+
"encoding/binary",
|
|
84
|
+
"binary",
|
|
85
|
+
"encoding/hex",
|
|
86
|
+
"hex",
|
|
87
|
+
"encoding/base64",
|
|
88
|
+
"base64",
|
|
44
89
|
]);
|
|
45
90
|
|
|
46
91
|
function importsAnyOf(programs, pkgs) {
|
|
92
|
+
const has = (p) => (pkgs instanceof Set ? pkgs.has(p) : pkgs.includes(p));
|
|
47
93
|
return (programs ?? []).some((p) =>
|
|
48
94
|
(p.imports ?? []).some((decl) =>
|
|
49
|
-
(decl.imports ?? [decl]).some((imp) =>
|
|
95
|
+
(decl.imports ?? [decl]).some((imp) => has(imp.path)),
|
|
50
96
|
),
|
|
51
97
|
);
|
|
52
98
|
}
|
|
53
99
|
|
|
100
|
+
function hasErrorUsage(programs) {
|
|
101
|
+
return (programs ?? []).some((p) => {
|
|
102
|
+
let found = false;
|
|
103
|
+
const scan = (n) => {
|
|
104
|
+
if (!n || found || typeof n !== "object") return;
|
|
105
|
+
if (Array.isArray(n)) {
|
|
106
|
+
for (const x of n) scan(x);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (
|
|
110
|
+
(n.kind === "Ident" ||
|
|
111
|
+
n.kind === "TypeName" ||
|
|
112
|
+
n.kind === "basic" ||
|
|
113
|
+
n.kind === "interface") &&
|
|
114
|
+
n.name === "error"
|
|
115
|
+
) {
|
|
116
|
+
found = true;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
for (const k of Object.keys(n)) {
|
|
120
|
+
if (!k.startsWith("_")) scan(n[k]);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
scan(p);
|
|
124
|
+
return found;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
54
128
|
// [name, params, results] for `env.*` imports backing stdlib calls; the JS
|
|
55
129
|
// side lives in WASM_STDLIB_JS (boundary.js). All are registered eagerly
|
|
56
130
|
// (when any STDLIB_ENV_PKGS package is imported) because the import table is
|
|
@@ -63,6 +137,11 @@ const STDLIB_IMPORTS = [
|
|
|
63
137
|
["str_trim_right", [S, S], [S]],
|
|
64
138
|
["str_trim_prefix", [S, S], [S]],
|
|
65
139
|
["str_trim_suffix", [S, S], [S]],
|
|
140
|
+
["str_cut", [S, S], ["i32"]],
|
|
141
|
+
["str_cut_before", [], [S]],
|
|
142
|
+
["str_cut_after", [], [S]],
|
|
143
|
+
["str_cut_prefix", [S, S], ["i32"]],
|
|
144
|
+
["str_cut_suffix", [S, S], ["i32"]],
|
|
66
145
|
["str_replace", [S, S, S, "i32"], [S]],
|
|
67
146
|
["str_contains_rune", [S, "i32"], ["i32"]],
|
|
68
147
|
["str_contains_any", [S, S], ["i32"]],
|
|
@@ -70,19 +149,30 @@ const STDLIB_IMPORTS = [
|
|
|
70
149
|
["str_index_rune", [S, "i32"], ["i32"]],
|
|
71
150
|
["str_index_any", [S, S], ["i32"]],
|
|
72
151
|
["str_last_index_byte", [S, "i32"], ["i32"]],
|
|
152
|
+
["str_last_index_any", [S, S], ["i32"]],
|
|
73
153
|
["str_title", [S], [S]],
|
|
74
154
|
["str_split", [S, S], ["i32"]],
|
|
155
|
+
["str_split_n", [S, S, "i32"], ["i32"]],
|
|
156
|
+
["str_split_after", [S, S], ["i32"]],
|
|
157
|
+
["str_split_after_n", [S, S, "i32"], ["i32"]],
|
|
75
158
|
["str_fields", [S], ["i32"]],
|
|
76
159
|
["str_part", ["i32"], [S]],
|
|
160
|
+
["str_replacer_init", [S], []],
|
|
161
|
+
["str_replacer_add", [S, S], []],
|
|
162
|
+
["str_replacer_run", [], [S]],
|
|
77
163
|
// strconv
|
|
78
164
|
["strconv_atoi", [S], ["i64"]],
|
|
79
165
|
["strconv_parse_int", [S, "i32", "i32"], ["i64"]],
|
|
80
166
|
["strconv_parse_float", [S], ["f64"]],
|
|
81
167
|
["strconv_parse_bool", [S], ["i32"]],
|
|
82
168
|
["strconv_err", [], [S]],
|
|
169
|
+
["strconv_err_kind", [], ["i32"]],
|
|
83
170
|
["strconv_format_float", ["f64", "i32", "i32", "i32"], [S]],
|
|
84
171
|
["strconv_format_int", ["i64", "i32"], [S]],
|
|
172
|
+
["strconv_format_uint", ["i64", "i32"], [S]],
|
|
173
|
+
["strconv_parse_uint", [S, "i32", "i32"], ["i64"]],
|
|
85
174
|
["strconv_quote", [S], [S]],
|
|
175
|
+
["strconv_unquote", [S], [S]],
|
|
86
176
|
// unicode/utf8
|
|
87
177
|
["utf8_rune_count", [S], ["i32"]],
|
|
88
178
|
["utf8_rune_len", ["i32"], ["i32"]],
|
|
@@ -93,8 +183,78 @@ const STDLIB_IMPORTS = [
|
|
|
93
183
|
// fmt (arguments travel through the testing_arg_* buffer)
|
|
94
184
|
["fmt_sprintf", [S], [S]],
|
|
95
185
|
["fmt_printf", [S], []],
|
|
186
|
+
["fmt_format_v", [S], [S]],
|
|
187
|
+
["fmt_sscan_init", [S, "i32"], ["i32"]],
|
|
188
|
+
["fmt_sscanf_init", [S, S], ["i32"]],
|
|
189
|
+
["fmt_sscan_has_err", [], ["i32"]],
|
|
190
|
+
["fmt_sscan_err_msg", [], [S]],
|
|
191
|
+
["fmt_sscan_token_str", ["i32"], [S]],
|
|
192
|
+
["fmt_sscan_token_i64", ["i32"], ["i64"]],
|
|
193
|
+
["fmt_sscan_token_f64", ["i32"], ["f64"]],
|
|
194
|
+
["fmt_sscan_token_bool", ["i32"], ["i32"]],
|
|
96
195
|
// testing.T.Run: the harness calls back into the exported __testing_run_cb
|
|
97
196
|
["testing_run", [S, S, "anyref"], ["i32"]],
|
|
197
|
+
// unicode
|
|
198
|
+
["unicode_is_letter", ["i32"], ["i32"]],
|
|
199
|
+
["unicode_is_digit", ["i32"], ["i32"]],
|
|
200
|
+
["unicode_is_space", ["i32"], ["i32"]],
|
|
201
|
+
["unicode_is_upper", ["i32"], ["i32"]],
|
|
202
|
+
["unicode_is_lower", ["i32"], ["i32"]],
|
|
203
|
+
["unicode_is_punct", ["i32"], ["i32"]],
|
|
204
|
+
["unicode_is_control", ["i32"], ["i32"]],
|
|
205
|
+
["unicode_is_print", ["i32"], ["i32"]],
|
|
206
|
+
["unicode_is_graphic", ["i32"], ["i32"]],
|
|
207
|
+
["unicode_to_upper", ["i32"], ["i32"]],
|
|
208
|
+
["unicode_to_lower", ["i32"], ["i32"]],
|
|
209
|
+
// html
|
|
210
|
+
["html_escape", [S], [S]],
|
|
211
|
+
["html_unescape", [S], [S]],
|
|
212
|
+
// path
|
|
213
|
+
["path_base", [S], [S]],
|
|
214
|
+
["path_dir", [S], [S]],
|
|
215
|
+
["path_ext", [S], [S]],
|
|
216
|
+
["path_is_abs", [S], ["i32"]],
|
|
217
|
+
["path_clean", [S], [S]],
|
|
218
|
+
["path_split", [S], []],
|
|
219
|
+
["path_split_dir", [], [S]],
|
|
220
|
+
["path_split_file", [], [S]],
|
|
221
|
+
["path_join_init", [], []],
|
|
222
|
+
["path_join_push", [S], []],
|
|
223
|
+
["path_join_run", [], [S]],
|
|
224
|
+
["path_match", [S, S], ["i32"]],
|
|
225
|
+
["path_match_has_err", [], ["i32"]],
|
|
226
|
+
["bytes_trim", [S, S, "i32", "i32"], []],
|
|
227
|
+
["bytes_trim_start", [], ["i32"]],
|
|
228
|
+
["bytes_trim_end", [], ["i32"]],
|
|
229
|
+
// time
|
|
230
|
+
["time_now_ms", [], ["f64"]],
|
|
231
|
+
["time_timezone_offset", ["f64"], ["i32"]],
|
|
232
|
+
["time_parse", [S, S], ["f64"]],
|
|
233
|
+
["time_parse_err", [], [S]],
|
|
234
|
+
["time_parse_offset", [], ["i32"]],
|
|
235
|
+
[
|
|
236
|
+
"time_format",
|
|
237
|
+
["i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32", "i32", S],
|
|
238
|
+
[S],
|
|
239
|
+
],
|
|
240
|
+
["time_duration_string", ["i64"], [S]],
|
|
241
|
+
// raw binary buffer for crypto/rand, crypto/sha256, hex, base64
|
|
242
|
+
["raw_bytes_init", ["i32"], []],
|
|
243
|
+
["raw_bytes_push", ["i32"], []],
|
|
244
|
+
["raw_bytes_len", [], ["i32"]],
|
|
245
|
+
["raw_bytes_get", ["i32"], ["i32"]],
|
|
246
|
+
// crypto/rand
|
|
247
|
+
["crypto_rand_fill", ["i32"], ["i32"]],
|
|
248
|
+
// crypto/sha256
|
|
249
|
+
["crypto_sha256_sum", [], ["i32"]],
|
|
250
|
+
// encoding/hex
|
|
251
|
+
["hex_encode_to_string", [], [S]],
|
|
252
|
+
["hex_decode_string", [S], ["i32"]],
|
|
253
|
+
["hex_get_err", [], [S]],
|
|
254
|
+
// encoding/base64
|
|
255
|
+
["base64_encode_to_string", ["i32"], [S]],
|
|
256
|
+
["base64_decode_string", ["i32", S], ["i32"]],
|
|
257
|
+
["base64_get_err", [], [S]],
|
|
98
258
|
];
|
|
99
259
|
|
|
100
260
|
class ModuleEmitter {
|
|
@@ -113,6 +273,7 @@ class ModuleEmitter {
|
|
|
113
273
|
|
|
114
274
|
this.structTypes = new Map(); // name -> struct info
|
|
115
275
|
this.boxTypes = new Map(); // wType key -> box info
|
|
276
|
+
this.ifaceBoxTypes = new Map(); // key -> iface box info
|
|
116
277
|
this.arrayTypes = new Map(); // wType key -> array info
|
|
117
278
|
this.sliceTypes = new Map(); // wType key -> slice info
|
|
118
279
|
this.sliceTypesByIndex = new Map(); // typeIndex -> slice info
|
|
@@ -145,7 +306,8 @@ class ModuleEmitter {
|
|
|
145
306
|
// `errors.New` / `fmt.Errorf` / strconv parse failures allocate the
|
|
146
307
|
// runtime's own error struct; it joins the struct rec group so the
|
|
147
308
|
// `error.Error` dispatcher can `ref.test` it like any user type.
|
|
148
|
-
this.hasErrorType =
|
|
309
|
+
this.hasErrorType =
|
|
310
|
+
importsAnyOf(programs, ERROR_PRODUCING_PKGS) || hasErrorUsage(programs);
|
|
149
311
|
this.usesStdlibEnv = importsAnyOf(programs, STDLIB_ENV_PKGS);
|
|
150
312
|
|
|
151
313
|
if (programs && programs.length > 0) {
|
|
@@ -315,23 +477,95 @@ class ModuleEmitter {
|
|
|
315
477
|
return this.structTypes.get(name) ?? null;
|
|
316
478
|
}
|
|
317
479
|
|
|
480
|
+
getAnonStructType(fields) {
|
|
481
|
+
const key = fields.map((f) => `${f.name}:${goTypeKey(f.goType)}`).join(";");
|
|
482
|
+
const name = `__anon_${key.replace(/[^a-zA-Z0-9_]/g, "_")}`;
|
|
483
|
+
if (this.structTypes.has(name)) {
|
|
484
|
+
return this.structTypes.get(name);
|
|
485
|
+
}
|
|
486
|
+
const fieldWTypes = fields.map((f) =>
|
|
487
|
+
toWasmType(f.goType, this.checker, this),
|
|
488
|
+
);
|
|
489
|
+
const typeIndex = this._getTotalTypeCount();
|
|
490
|
+
const typeEntry = {
|
|
491
|
+
form: "struct",
|
|
492
|
+
fields: fieldWTypes.map((t) => ({ type: t, mutable: true })),
|
|
493
|
+
};
|
|
494
|
+
this._pushType(typeEntry);
|
|
495
|
+
const info = {
|
|
496
|
+
name,
|
|
497
|
+
typeIndex,
|
|
498
|
+
typeEntry,
|
|
499
|
+
fields: fields.map((f, i) => ({
|
|
500
|
+
name: f.name,
|
|
501
|
+
wType: fieldWTypes[i],
|
|
502
|
+
goType: f.goType,
|
|
503
|
+
fieldIndex: i,
|
|
504
|
+
})),
|
|
505
|
+
fieldIndexMap: new Map(fields.map((f, i) => [f.name, i])),
|
|
506
|
+
embeds: [],
|
|
507
|
+
pkgName: null,
|
|
508
|
+
pkgTarget: "wasm",
|
|
509
|
+
isAnon: true,
|
|
510
|
+
};
|
|
511
|
+
this.structTypes.set(name, info);
|
|
512
|
+
return info;
|
|
513
|
+
}
|
|
514
|
+
|
|
318
515
|
getBoxType(goType) {
|
|
319
|
-
const
|
|
320
|
-
const key = typeof wType === "string" ? wType : JSON.stringify(wType);
|
|
516
|
+
const key = goTypeKey(goType);
|
|
321
517
|
if (this.boxTypes.has(key)) {
|
|
322
518
|
return this.boxTypes.get(key);
|
|
323
519
|
}
|
|
520
|
+
const wType = toWasmType(goType, this.checker, this);
|
|
324
521
|
const typeIndex = this._getTotalTypeCount();
|
|
325
522
|
const typeEntry = {
|
|
326
523
|
form: "struct",
|
|
327
524
|
fields: [{ type: wType, mutable: true }],
|
|
328
525
|
};
|
|
329
526
|
this._pushType(typeEntry);
|
|
330
|
-
const boxInfo = { typeIndex, typeEntry, wType };
|
|
527
|
+
const boxInfo = { key, typeIndex, typeEntry, wType, goType };
|
|
331
528
|
this.boxTypes.set(key, boxInfo);
|
|
332
529
|
return boxInfo;
|
|
333
530
|
}
|
|
334
531
|
|
|
532
|
+
getIfaceBoxType(goType) {
|
|
533
|
+
const key = goTypeKey(goType);
|
|
534
|
+
if (this.ifaceBoxTypes.has(key)) {
|
|
535
|
+
return this.ifaceBoxTypes.get(key);
|
|
536
|
+
}
|
|
537
|
+
const wType = toWasmType(goType, this.checker, this);
|
|
538
|
+
const tagIndex = this.ifaceBoxTypes.size;
|
|
539
|
+
const tagTypeIndex = this._getTotalTypeCount();
|
|
540
|
+
const tagFields = [];
|
|
541
|
+
for (let i = 0; i < tagIndex; i++) {
|
|
542
|
+
tagFields.push({ type: "i32", mutable: false });
|
|
543
|
+
}
|
|
544
|
+
this._pushType({
|
|
545
|
+
form: "struct",
|
|
546
|
+
fields: tagFields,
|
|
547
|
+
});
|
|
548
|
+
const typeIndex = this._getTotalTypeCount();
|
|
549
|
+
const typeEntry = {
|
|
550
|
+
form: "struct",
|
|
551
|
+
fields: [
|
|
552
|
+
{ type: wType, mutable: true },
|
|
553
|
+
{
|
|
554
|
+
type: {
|
|
555
|
+
kind: "ref",
|
|
556
|
+
nullable: true,
|
|
557
|
+
typeIndex: tagTypeIndex,
|
|
558
|
+
},
|
|
559
|
+
mutable: false,
|
|
560
|
+
},
|
|
561
|
+
],
|
|
562
|
+
};
|
|
563
|
+
this._pushType(typeEntry);
|
|
564
|
+
const boxInfo = { key, typeIndex, typeEntry, wType, goType, tagTypeIndex };
|
|
565
|
+
this.ifaceBoxTypes.set(key, boxInfo);
|
|
566
|
+
return boxInfo;
|
|
567
|
+
}
|
|
568
|
+
|
|
335
569
|
getArrayType(elemGoType) {
|
|
336
570
|
const elemWType = toWasmType(elemGoType, this.checker, this);
|
|
337
571
|
const key =
|
|
@@ -641,6 +875,11 @@ class ModuleEmitter {
|
|
|
641
875
|
this.getStrFromI32ImportIndex();
|
|
642
876
|
this.getStrFromF64ImportIndex();
|
|
643
877
|
this.getIsStringImportIndex(); // env.is_string
|
|
878
|
+
this.getStrToBytesImportIndex();
|
|
879
|
+
this.getStrByteAtImportIndex();
|
|
880
|
+
this.getBytesToStrInitImportIndex();
|
|
881
|
+
this.getBytesToStrPushImportIndex();
|
|
882
|
+
this.getBytesToStrFinishImportIndex();
|
|
644
883
|
this.getTestingCallImportIndex();
|
|
645
884
|
this.getTestingNameImportIndex();
|
|
646
885
|
this.getTestingFlagImportIndex();
|
|
@@ -648,6 +887,17 @@ class ModuleEmitter {
|
|
|
648
887
|
this.getTestingArgImportIndex(t, false);
|
|
649
888
|
}
|
|
650
889
|
this.getTestingArgImportIndex("i32", true);
|
|
890
|
+
this.getFmtNewArrayIndex();
|
|
891
|
+
this.getFmtArrayPushIndex();
|
|
892
|
+
this.getFmtNewMapIndex();
|
|
893
|
+
this.getFmtMapSetIndex();
|
|
894
|
+
this.getFmtNewStructIndex();
|
|
895
|
+
this.getFmtStructSetIndex();
|
|
896
|
+
this.getFmtBoxI32Index();
|
|
897
|
+
this.getFmtBoxI64Index();
|
|
898
|
+
this.getFmtBoxF64Index();
|
|
899
|
+
this.getFmtBoxBoolIndex();
|
|
900
|
+
this.getFmtNewBoxIndex();
|
|
651
901
|
if (this.usesStdlibEnv) {
|
|
652
902
|
for (const [name, params, results] of STDLIB_IMPORTS) {
|
|
653
903
|
this.getOrAddFuncImport("env", name, params, results);
|
|
@@ -766,6 +1016,80 @@ class ModuleEmitter {
|
|
|
766
1016
|
return gIdx;
|
|
767
1017
|
}
|
|
768
1018
|
|
|
1019
|
+
getRandStateGlobalIndex() {
|
|
1020
|
+
if (this.randStateGlobalIndex !== undefined) {
|
|
1021
|
+
return this.randStateGlobalIndex;
|
|
1022
|
+
}
|
|
1023
|
+
const gIdx = this.globals.length;
|
|
1024
|
+
this.globals.push({
|
|
1025
|
+
type: "i64",
|
|
1026
|
+
mutable: true,
|
|
1027
|
+
init: [{ op: "i64.const", value: 1n }],
|
|
1028
|
+
});
|
|
1029
|
+
this.randStateGlobalIndex = gIdx;
|
|
1030
|
+
return gIdx;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
getStrconvErrGlobalIndex(field) {
|
|
1034
|
+
if (!this.strconvErrGlobals) this.strconvErrGlobals = new Map();
|
|
1035
|
+
if (this.strconvErrGlobals.has(field)) {
|
|
1036
|
+
return this.strconvErrGlobals.get(field);
|
|
1037
|
+
}
|
|
1038
|
+
const gIdx = this.globals.length;
|
|
1039
|
+
this.globals.push({
|
|
1040
|
+
type: "anyref",
|
|
1041
|
+
mutable: true,
|
|
1042
|
+
init: [{ op: "ref.null", heapType: "any" }],
|
|
1043
|
+
});
|
|
1044
|
+
this.strconvErrGlobals.set(field, gIdx);
|
|
1045
|
+
return gIdx;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
getPathErrGlobalIndex(field) {
|
|
1049
|
+
if (!this.pathErrGlobals) this.pathErrGlobals = new Map();
|
|
1050
|
+
if (this.pathErrGlobals.has(field)) {
|
|
1051
|
+
return this.pathErrGlobals.get(field);
|
|
1052
|
+
}
|
|
1053
|
+
const gIdx = this.globals.length;
|
|
1054
|
+
this.globals.push({
|
|
1055
|
+
type: "anyref",
|
|
1056
|
+
mutable: true,
|
|
1057
|
+
init: [{ op: "ref.null", heapType: "any" }],
|
|
1058
|
+
});
|
|
1059
|
+
this.pathErrGlobals.set(field, gIdx);
|
|
1060
|
+
return gIdx;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
getIoErrGlobalIndex(field) {
|
|
1064
|
+
if (!this.ioErrGlobals) this.ioErrGlobals = new Map();
|
|
1065
|
+
if (this.ioErrGlobals.has(field)) {
|
|
1066
|
+
return this.ioErrGlobals.get(field);
|
|
1067
|
+
}
|
|
1068
|
+
const gIdx = this.globals.length;
|
|
1069
|
+
this.globals.push({
|
|
1070
|
+
type: "anyref",
|
|
1071
|
+
mutable: true,
|
|
1072
|
+
init: [{ op: "ref.null", heapType: "any" }],
|
|
1073
|
+
});
|
|
1074
|
+
this.ioErrGlobals.set(field, gIdx);
|
|
1075
|
+
return gIdx;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
getIoDiscardGlobalIndex() {
|
|
1079
|
+
if (this.ioDiscardGlobalIndex !== undefined) {
|
|
1080
|
+
return this.ioDiscardGlobalIndex;
|
|
1081
|
+
}
|
|
1082
|
+
this.getStructType("io.discard");
|
|
1083
|
+
const gIdx = this.globals.length;
|
|
1084
|
+
this.globals.push({
|
|
1085
|
+
type: "anyref",
|
|
1086
|
+
mutable: true,
|
|
1087
|
+
init: [{ op: "ref.null", heapType: "any" }],
|
|
1088
|
+
});
|
|
1089
|
+
this.ioDiscardGlobalIndex = gIdx;
|
|
1090
|
+
return gIdx;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
769
1093
|
getDeferNodeTypeIndex() {
|
|
770
1094
|
if (this.deferNodeTypeIndex !== undefined) {
|
|
771
1095
|
return this.deferNodeTypeIndex;
|
|
@@ -895,6 +1219,90 @@ class ModuleEmitter {
|
|
|
895
1219
|
return this.getOrAddFuncImport("env", "println_empty", [], []);
|
|
896
1220
|
}
|
|
897
1221
|
|
|
1222
|
+
getFmtNewArrayIndex() {
|
|
1223
|
+
return this.getOrAddFuncImport("env", "fmt_new_array", [], ["externref"]);
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
getFmtArrayPushIndex() {
|
|
1227
|
+
return this.getOrAddFuncImport(
|
|
1228
|
+
"env",
|
|
1229
|
+
"fmt_array_push",
|
|
1230
|
+
["externref", "externref"],
|
|
1231
|
+
[],
|
|
1232
|
+
);
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
getFmtNewMapIndex() {
|
|
1236
|
+
return this.getOrAddFuncImport("env", "fmt_new_map", [], ["externref"]);
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
getFmtMapSetIndex() {
|
|
1240
|
+
return this.getOrAddFuncImport(
|
|
1241
|
+
"env",
|
|
1242
|
+
"fmt_map_set",
|
|
1243
|
+
["externref", "externref", "externref"],
|
|
1244
|
+
[],
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
getFmtNewStructIndex() {
|
|
1249
|
+
return this.getOrAddFuncImport(
|
|
1250
|
+
"env",
|
|
1251
|
+
"fmt_new_struct",
|
|
1252
|
+
["anyref", "i32"],
|
|
1253
|
+
["externref"],
|
|
1254
|
+
);
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
getFmtStructSetIndex() {
|
|
1258
|
+
return this.getOrAddFuncImport(
|
|
1259
|
+
"env",
|
|
1260
|
+
"fmt_struct_set",
|
|
1261
|
+
["externref", "i32", "externref"],
|
|
1262
|
+
[],
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
getFmtBoxI32Index() {
|
|
1267
|
+
return this.getOrAddFuncImport(
|
|
1268
|
+
"env",
|
|
1269
|
+
"fmt_box_i32",
|
|
1270
|
+
["i32"],
|
|
1271
|
+
["externref"],
|
|
1272
|
+
);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
getFmtBoxI64Index() {
|
|
1276
|
+
return this.getOrAddFuncImport(
|
|
1277
|
+
"env",
|
|
1278
|
+
"fmt_box_i64",
|
|
1279
|
+
["i64"],
|
|
1280
|
+
["externref"],
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
getFmtBoxF64Index() {
|
|
1285
|
+
return this.getOrAddFuncImport(
|
|
1286
|
+
"env",
|
|
1287
|
+
"fmt_box_f64",
|
|
1288
|
+
["f64"],
|
|
1289
|
+
["externref"],
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
getFmtBoxBoolIndex() {
|
|
1294
|
+
return this.getOrAddFuncImport(
|
|
1295
|
+
"env",
|
|
1296
|
+
"fmt_box_bool",
|
|
1297
|
+
["i32"],
|
|
1298
|
+
["externref"],
|
|
1299
|
+
);
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
getFmtNewBoxIndex() {
|
|
1303
|
+
return this.getOrAddFuncImport("env", "fmt_new_box", [], ["externref"]);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
898
1306
|
// `*testing.T` method calls: args are pushed one by one to a JS-side
|
|
899
1307
|
// buffer, then `testing_call(t, methodNameStrIdx)` invokes the method.
|
|
900
1308
|
getTestingArgImportIndex(wType, isBool = false) {
|
|
@@ -1186,11 +1594,45 @@ class ModuleEmitter {
|
|
|
1186
1594
|
);
|
|
1187
1595
|
}
|
|
1188
1596
|
|
|
1597
|
+
getStrToBytesImportIndex() {
|
|
1598
|
+
return this.getOrAddFuncImport(
|
|
1599
|
+
"env",
|
|
1600
|
+
"str_to_bytes",
|
|
1601
|
+
["externref"],
|
|
1602
|
+
["i32"],
|
|
1603
|
+
);
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
getStrByteAtImportIndex() {
|
|
1607
|
+
return this.getOrAddFuncImport("env", "str_byte_at", ["i32"], ["i32"]);
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
getBytesToStrInitImportIndex() {
|
|
1611
|
+
return this.getOrAddFuncImport("env", "bytes_to_str_init", ["i32"], []);
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
getBytesToStrPushImportIndex() {
|
|
1615
|
+
return this.getOrAddFuncImport("env", "bytes_to_str_push", ["i32"], []);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
getBytesToStrFinishImportIndex() {
|
|
1619
|
+
return this.getOrAddFuncImport(
|
|
1620
|
+
"env",
|
|
1621
|
+
"bytes_to_str_finish",
|
|
1622
|
+
[],
|
|
1623
|
+
["externref"],
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1189
1627
|
getMathImportIndex(jsName, isBinary = false) {
|
|
1190
1628
|
const params = isBinary ? ["f64", "f64"] : ["f64"];
|
|
1191
1629
|
return this.getOrAddFuncImport("Math", jsName, params, ["f64"]);
|
|
1192
1630
|
}
|
|
1193
1631
|
|
|
1632
|
+
getMathRandomImportIndex() {
|
|
1633
|
+
return this.getOrAddFuncImport("Math", "random", [], ["f64"]);
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1194
1636
|
// Imports from the STDLIB_IMPORTS table (strings/strconv/utf8/fmt/testing.Run).
|
|
1195
1637
|
getStdlibImportIndex(name) {
|
|
1196
1638
|
const idx = this.importCache.get(`env.${name}`);
|
|
@@ -1198,6 +1640,10 @@ class ModuleEmitter {
|
|
|
1198
1640
|
return idx;
|
|
1199
1641
|
}
|
|
1200
1642
|
|
|
1643
|
+
getTimezoneOffsetImportIndex() {
|
|
1644
|
+
return this.getStdlibImportIndex("time_timezone_offset");
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1201
1647
|
// Closure type of `func(*testing.T)` (the t.Run body).
|
|
1202
1648
|
getTestingRunClosureType() {
|
|
1203
1649
|
return this.getClosureType({
|
|
@@ -1280,7 +1726,7 @@ class ModuleEmitter {
|
|
|
1280
1726
|
structInfo: sInfo,
|
|
1281
1727
|
});
|
|
1282
1728
|
}
|
|
1283
|
-
const box = this.
|
|
1729
|
+
const box = this.getIfaceBoxType({ kind: "named", name: sName });
|
|
1284
1730
|
const valKey = `val:${sName}`;
|
|
1285
1731
|
if (box && !seenKeys.has(valKey)) {
|
|
1286
1732
|
seenKeys.add(valKey);
|
|
@@ -1332,7 +1778,7 @@ class ModuleEmitter {
|
|
|
1332
1778
|
}
|
|
1333
1779
|
|
|
1334
1780
|
if (!isPtrRecv) {
|
|
1335
|
-
const box = this.
|
|
1781
|
+
const box = this.getIfaceBoxType({ kind: "named", name: sName });
|
|
1336
1782
|
const valKey = `val:${sName}`;
|
|
1337
1783
|
if (box && !seenKeys.has(valKey)) {
|
|
1338
1784
|
seenKeys.add(valKey);
|
|
@@ -1364,7 +1810,7 @@ class ModuleEmitter {
|
|
|
1364
1810
|
if (fnName.endsWith(`.${methodName}`)) {
|
|
1365
1811
|
const rName = fnName.slice(0, fnName.length - methodName.length - 1);
|
|
1366
1812
|
if (!this.structTypes.has(rName)) {
|
|
1367
|
-
const box = this.
|
|
1813
|
+
const box = this.getIfaceBoxType({ kind: "named", name: rName });
|
|
1368
1814
|
const key = `named:${rName}`;
|
|
1369
1815
|
if (box && !seenKeys.has(key)) {
|
|
1370
1816
|
seenKeys.add(key);
|
|
@@ -1412,7 +1858,7 @@ class ModuleEmitter {
|
|
|
1412
1858
|
|
|
1413
1859
|
// Check struct value (boxed)
|
|
1414
1860
|
if (this.checker?.implements?.(namedType, ifaceResolved)) {
|
|
1415
|
-
const box = this.
|
|
1861
|
+
const box = this.getIfaceBoxType(namedType);
|
|
1416
1862
|
if (box && !seen.has(box.typeIndex)) {
|
|
1417
1863
|
seen.add(box.typeIndex);
|
|
1418
1864
|
candidates.push({ name: sName, typeIndex: box.typeIndex });
|
|
@@ -1429,7 +1875,7 @@ class ModuleEmitter {
|
|
|
1429
1875
|
tVal.underlying?.kind !== "interface"
|
|
1430
1876
|
) {
|
|
1431
1877
|
if (this.checker.implements(tVal, ifaceResolved)) {
|
|
1432
|
-
const box = this.
|
|
1878
|
+
const box = this.getIfaceBoxType(tVal);
|
|
1433
1879
|
if (box && !seen.has(box.typeIndex)) {
|
|
1434
1880
|
seen.add(box.typeIndex);
|
|
1435
1881
|
candidates.push({ name: tName, typeIndex: box.typeIndex });
|
|
@@ -1685,8 +2131,19 @@ export function compileWasmModule(
|
|
|
1685
2131
|
}
|
|
1686
2132
|
funcDecls.push(...trampolines);
|
|
1687
2133
|
|
|
2134
|
+
_collectPackageConsts(progs, mod, checker);
|
|
2135
|
+
if (checker?.errors?.length > 0) {
|
|
2136
|
+
if (options.boundary) {
|
|
2137
|
+
throw new Error(checker.errors.map((e) => e.message).join("\n"));
|
|
2138
|
+
}
|
|
2139
|
+
return {
|
|
2140
|
+
wasm: null,
|
|
2141
|
+
facade: null,
|
|
2142
|
+
stringTable: null,
|
|
2143
|
+
errors: checker.errors,
|
|
2144
|
+
};
|
|
2145
|
+
}
|
|
1688
2146
|
const pendingInits = _collectPackageGlobals(progs, mod, checker);
|
|
1689
|
-
_collectPackageConsts(progs, mod);
|
|
1690
2147
|
const globalInitFn =
|
|
1691
2148
|
pendingInits.length > 0 || initNames.length > 0
|
|
1692
2149
|
? _makeGlobalInitFunc(pendingInits, initNames)
|
|
@@ -1975,6 +2432,23 @@ export function compileWasmModule(
|
|
|
1975
2432
|
),
|
|
1976
2433
|
);
|
|
1977
2434
|
}
|
|
2435
|
+
mod.usesAnyHash = false;
|
|
2436
|
+
for (const info of mod.mapTypes.values()) {
|
|
2437
|
+
if (isInterfaceType(info.keyGoType, checker)) {
|
|
2438
|
+
mod.usesAnyHash = true;
|
|
2439
|
+
break;
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
if (mod.usesAnyHash) {
|
|
2443
|
+
funcDecls.push(
|
|
2444
|
+
helper(
|
|
2445
|
+
"__any_hash",
|
|
2446
|
+
[{ name: "a", type: ANY_T }],
|
|
2447
|
+
{ kind: "basic", name: "int32" },
|
|
2448
|
+
"any_hash",
|
|
2449
|
+
),
|
|
2450
|
+
);
|
|
2451
|
+
}
|
|
1978
2452
|
if (mod.hasErrorType) {
|
|
1979
2453
|
const errPtr = {
|
|
1980
2454
|
kind: "pointer",
|
|
@@ -2057,6 +2531,7 @@ export function compileWasmModule(
|
|
|
2057
2531
|
),
|
|
2058
2532
|
);
|
|
2059
2533
|
}
|
|
2534
|
+
_registerIoSyntheticMethods(funcDecls, mod, STR_T, progs);
|
|
2060
2535
|
|
|
2061
2536
|
// 1f. Boundary metadata (exported surface of wasm packages)
|
|
2062
2537
|
const boundaryMeta = options.boundary
|
|
@@ -2118,6 +2593,8 @@ export function compileWasmModule(
|
|
|
2118
2593
|
fn._forceExport ||
|
|
2119
2594
|
(!fn._isGlobalInit &&
|
|
2120
2595
|
!fn._isRuntimeHelper &&
|
|
2596
|
+
!fn._isIoHelper &&
|
|
2597
|
+
!fn._isPhase7Helper &&
|
|
2121
2598
|
(options.exportAll ||
|
|
2122
2599
|
fn.name === "main" ||
|
|
2123
2600
|
(fn.name[0] >= "A" && fn.name[0] <= "Z") ||
|
|
@@ -2177,6 +2654,8 @@ export function compileWasmModule(
|
|
|
2177
2654
|
emitter.emitSharedHelper(fn);
|
|
2178
2655
|
} else if (fn._isRuntimeHelper) {
|
|
2179
2656
|
emitter.emitRuntimeHelper(fn);
|
|
2657
|
+
} else if (fn._isIoHelper || fn._isPhase7Helper) {
|
|
2658
|
+
emitter.emitIoHelper(fn);
|
|
2180
2659
|
} else if (fn.body) {
|
|
2181
2660
|
emitter.emitFunctionBody(fn.body);
|
|
2182
2661
|
}
|
|
@@ -2264,29 +2743,65 @@ export function compileWasmModule(
|
|
|
2264
2743
|
};
|
|
2265
2744
|
}
|
|
2266
2745
|
|
|
2267
|
-
// Package-level `const` declarations
|
|
2268
|
-
//
|
|
2269
|
-
//
|
|
2270
|
-
|
|
2746
|
+
// Package-level `const` declarations (iota is already substituted by the
|
|
2747
|
+
// parser). Literals and expressions the folder can reduce become BasicLits in
|
|
2748
|
+
// `constCache`; whatever is left is recorded in `nonLiteralConsts` and later
|
|
2749
|
+
// becomes a global initialised by the start function.
|
|
2750
|
+
function _collectPackageConsts(progs, mod, checker = null) {
|
|
2751
|
+
const entries = [];
|
|
2271
2752
|
for (const p of progs) {
|
|
2272
2753
|
for (const d of p.decls ?? []) {
|
|
2273
2754
|
if (d.kind !== "ConstDecl") continue;
|
|
2274
2755
|
for (const spec of d.decls ?? []) {
|
|
2275
2756
|
for (let i = 0; i < spec.names.length; i++) {
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
}
|
|
2284
|
-
if (lit?.kind === "BasicLit") mod.constCache.set(spec.names[i], lit);
|
|
2285
|
-
else if (lit) mod.nonLiteralConsts.add(spec.names[i]);
|
|
2757
|
+
if (spec.value?.[i])
|
|
2758
|
+
entries.push({
|
|
2759
|
+
name: spec.names[i],
|
|
2760
|
+
expr: spec.value[i],
|
|
2761
|
+
filename: p._filename,
|
|
2762
|
+
source: p._source,
|
|
2763
|
+
});
|
|
2286
2764
|
}
|
|
2287
2765
|
}
|
|
2288
2766
|
}
|
|
2289
2767
|
}
|
|
2768
|
+
const resolve = (name) => mod.constCache.get(name) ?? null;
|
|
2769
|
+
// Iterate to a fixpoint so a constant may refer to one declared later.
|
|
2770
|
+
let pending = entries;
|
|
2771
|
+
let progress = true;
|
|
2772
|
+
while (progress && pending.length > 0) {
|
|
2773
|
+
progress = false;
|
|
2774
|
+
const rest = [];
|
|
2775
|
+
for (const entry of pending) {
|
|
2776
|
+
let lit = null;
|
|
2777
|
+
try {
|
|
2778
|
+
lit = foldConstExpr(entry.expr, resolve);
|
|
2779
|
+
} catch (err) {
|
|
2780
|
+
if (checker?.err) {
|
|
2781
|
+
const savedFile = checker._currentFile;
|
|
2782
|
+
const savedSource = checker._currentSource;
|
|
2783
|
+
if (entry.filename) checker._currentFile = entry.filename;
|
|
2784
|
+
if (entry.source) checker._currentSource = entry.source;
|
|
2785
|
+
checker.err(err.message, entry.expr);
|
|
2786
|
+
checker._currentFile = savedFile;
|
|
2787
|
+
checker._currentSource = savedSource;
|
|
2788
|
+
} else {
|
|
2789
|
+
throw new Error(
|
|
2790
|
+
`Constant expression error for '${entry.name}': ${err.message}`,
|
|
2791
|
+
);
|
|
2792
|
+
}
|
|
2793
|
+
continue;
|
|
2794
|
+
}
|
|
2795
|
+
if (lit) {
|
|
2796
|
+
mod.constCache.set(entry.name, lit);
|
|
2797
|
+
progress = true;
|
|
2798
|
+
} else {
|
|
2799
|
+
rest.push(entry);
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
pending = rest;
|
|
2803
|
+
}
|
|
2804
|
+
for (const entry of pending) mod.nonLiteralConsts.add(entry.name);
|
|
2290
2805
|
}
|
|
2291
2806
|
|
|
2292
2807
|
// Depth-first search over AST nodes (skipping `_`-prefixed annotations).
|
|
@@ -2318,6 +2833,9 @@ function _usesTestingRun(node) {
|
|
|
2318
2833
|
// site, so a gap surfaces as a compile error rather than a bad module.
|
|
2319
2834
|
function _usesAnyEq(funcDecls, mod) {
|
|
2320
2835
|
if (mod.hasErrorType) return true;
|
|
2836
|
+
for (const info of mod.mapTypes.values()) {
|
|
2837
|
+
if (isInterfaceType(info.keyGoType, mod.checker)) return true;
|
|
2838
|
+
}
|
|
2321
2839
|
for (const info of mod.structTypes.values()) {
|
|
2322
2840
|
if (info.fields?.some((f) => f.wType === "anyref")) return true;
|
|
2323
2841
|
}
|
|
@@ -2377,6 +2895,9 @@ function _scanImportsInBody(node, mod) {
|
|
|
2377
2895
|
Log2: "log2",
|
|
2378
2896
|
Log10: "log10",
|
|
2379
2897
|
Round: "round",
|
|
2898
|
+
Sinh: "sinh",
|
|
2899
|
+
Cosh: "cosh",
|
|
2900
|
+
Tanh: "tanh",
|
|
2380
2901
|
};
|
|
2381
2902
|
if (jsMathMap[func.field]) {
|
|
2382
2903
|
const isBinary = BINARY_MATH_IMPORTS.has(jsMathMap[func.field]);
|
|
@@ -2445,6 +2966,10 @@ export function compileWasm(source, options = {}) {
|
|
|
2445
2966
|
exportAll: options.exportAll ?? true,
|
|
2446
2967
|
});
|
|
2447
2968
|
|
|
2969
|
+
if (checker.errors?.length > 0) {
|
|
2970
|
+
return { wasm: null, errors: checker.errors };
|
|
2971
|
+
}
|
|
2972
|
+
|
|
2448
2973
|
return { ...res, errors: [] };
|
|
2449
2974
|
}
|
|
2450
2975
|
|
|
@@ -2490,14 +3015,18 @@ function _zeroFieldConst(f, mod) {
|
|
|
2490
3015
|
|
|
2491
3016
|
function _collectPackageGlobals(progs, mod, checker) {
|
|
2492
3017
|
const pending = []; // non-constant initializers, run by the start function
|
|
3018
|
+
const pendingConsts = []; // unfoldable consts; they run before any var
|
|
2493
3019
|
for (const p of progs) {
|
|
2494
3020
|
for (const d of p.decls ?? []) {
|
|
2495
|
-
|
|
3021
|
+
const isConst = d.kind === "ConstDecl";
|
|
3022
|
+
if (d.kind !== "VarDecl" && !isConst) continue;
|
|
2496
3023
|
for (const spec of d.decls ?? d.specs ?? [d]) {
|
|
2497
3024
|
const names = spec.names ?? (spec.name ? [spec.name] : []);
|
|
2498
3025
|
const values = spec.value ?? (spec.init ? [spec.init] : []);
|
|
2499
3026
|
for (let i = 0; i < names.length; i++) {
|
|
2500
3027
|
const name = names[i];
|
|
3028
|
+
// Foldable consts live in `constCache`, not in a global.
|
|
3029
|
+
if (isConst && !mod.isNonLiteralConst(name)) continue;
|
|
2501
3030
|
const rawType = spec.type ?? values[i]?._type;
|
|
2502
3031
|
const wType = toWasmType(rawType, checker, mod);
|
|
2503
3032
|
const gIdx = mod.globals.length;
|
|
@@ -2562,15 +3091,17 @@ function _collectPackageGlobals(progs, mod, checker) {
|
|
|
2562
3091
|
if (litNode && litNode.kind === "BasicLit") {
|
|
2563
3092
|
if (litNode.litKind === "INT") {
|
|
2564
3093
|
isConstInit = true;
|
|
3094
|
+
const s = String(litNode.value);
|
|
3095
|
+
const clean = /^0[0-7]+$/.test(s) ? `0o${s.slice(1)}` : s;
|
|
2565
3096
|
initInsts = [
|
|
2566
3097
|
wType === "i64"
|
|
2567
3098
|
? {
|
|
2568
3099
|
op: "i64.const",
|
|
2569
|
-
value: BigInt(sign) * BigInt(
|
|
3100
|
+
value: BigInt(sign) * BigInt(clean),
|
|
2570
3101
|
}
|
|
2571
3102
|
: {
|
|
2572
3103
|
op: "i32.const",
|
|
2573
|
-
value: (sign * Number(
|
|
3104
|
+
value: (sign * Number(clean)) | 0,
|
|
2574
3105
|
},
|
|
2575
3106
|
];
|
|
2576
3107
|
} else if (litNode.litKind === "FLOAT") {
|
|
@@ -2592,7 +3123,10 @@ function _collectPackageGlobals(progs, mod, checker) {
|
|
|
2592
3123
|
}
|
|
2593
3124
|
}
|
|
2594
3125
|
if (values[i] && !isConstInit && names.length === values.length) {
|
|
2595
|
-
|
|
3126
|
+
(isConst ? pendingConsts : pending).push({
|
|
3127
|
+
name,
|
|
3128
|
+
expr: values[i],
|
|
3129
|
+
});
|
|
2596
3130
|
}
|
|
2597
3131
|
mod.globals.push({
|
|
2598
3132
|
type: wType,
|
|
@@ -2608,7 +3142,26 @@ function _collectPackageGlobals(progs, mod, checker) {
|
|
|
2608
3142
|
}
|
|
2609
3143
|
}
|
|
2610
3144
|
}
|
|
2611
|
-
return pending;
|
|
3145
|
+
return [..._orderConstInits(pendingConsts), ...pending];
|
|
3146
|
+
}
|
|
3147
|
+
|
|
3148
|
+
// Orders runtime-initialised consts so each runs after the consts it
|
|
3149
|
+
// references (Go allows a constant to use one declared later).
|
|
3150
|
+
function _orderConstInits(entries) {
|
|
3151
|
+
const byName = new Map(entries.map((e) => [e.name, e]));
|
|
3152
|
+
const ordered = [];
|
|
3153
|
+
const state = new Map();
|
|
3154
|
+
const visit = (entry) => {
|
|
3155
|
+
if (state.has(entry.name)) return;
|
|
3156
|
+
state.set(entry.name, true);
|
|
3157
|
+
_someNode(entry.expr, (n) => {
|
|
3158
|
+
if (n.kind === "Ident" && byName.has(n.name)) visit(byName.get(n.name));
|
|
3159
|
+
return false;
|
|
3160
|
+
});
|
|
3161
|
+
ordered.push(entry);
|
|
3162
|
+
};
|
|
3163
|
+
for (const e of entries) visit(e);
|
|
3164
|
+
return ordered;
|
|
2612
3165
|
}
|
|
2613
3166
|
|
|
2614
3167
|
// Synthesises `__init_globals()` assigning every non-constant package-level
|
|
@@ -2759,12 +3312,57 @@ function _makeInterfaceDispatcher(info, checker) {
|
|
|
2759
3312
|
};
|
|
2760
3313
|
}
|
|
2761
3314
|
|
|
3315
|
+
function _scanFuncSigInterfaces(
|
|
3316
|
+
progs,
|
|
3317
|
+
funcDecls,
|
|
3318
|
+
interfaceCalls,
|
|
3319
|
+
checker,
|
|
3320
|
+
mod,
|
|
3321
|
+
) {
|
|
3322
|
+
const scanType = (t) => {
|
|
3323
|
+
if (!t) return;
|
|
3324
|
+
if (t.kind === "InterfaceType" || (t.kind === "interface" && !t.name)) {
|
|
3325
|
+
const mList = getInterfaceMethodList(t);
|
|
3326
|
+
if (mList.length === 0) return;
|
|
3327
|
+
const ifaceName = anonIfaceName(t, checker, mod);
|
|
3328
|
+
for (const m of mList) {
|
|
3329
|
+
const key = `${ifaceName}.${m.name}`;
|
|
3330
|
+
if (!interfaceCalls.has(key)) {
|
|
3331
|
+
interfaceCalls.set(key, {
|
|
3332
|
+
ifaceName,
|
|
3333
|
+
ifaceType: t,
|
|
3334
|
+
methodName: m.name,
|
|
3335
|
+
methodSig: {
|
|
3336
|
+
kind: "func",
|
|
3337
|
+
params: m.params,
|
|
3338
|
+
returns: m.returns,
|
|
3339
|
+
},
|
|
3340
|
+
});
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
}
|
|
3344
|
+
};
|
|
3345
|
+
for (const fn of funcDecls) {
|
|
3346
|
+
for (const p of fn.params ?? []) scanType(p.type);
|
|
3347
|
+
scanType(fn.returnType);
|
|
3348
|
+
}
|
|
3349
|
+
for (const p of progs) {
|
|
3350
|
+
for (const d of p.decls ?? []) {
|
|
3351
|
+
if (d.kind === "FuncDecl") {
|
|
3352
|
+
for (const param of d.params ?? []) scanType(param.type);
|
|
3353
|
+
scanType(d.returnType);
|
|
3354
|
+
}
|
|
3355
|
+
}
|
|
3356
|
+
}
|
|
3357
|
+
}
|
|
3358
|
+
|
|
2762
3359
|
function _collectInterfaceDispatchers(progs, funcDecls, mod, checker) {
|
|
2763
3360
|
const interfaceCalls = new Map();
|
|
2764
3361
|
for (const fn of funcDecls) {
|
|
2765
3362
|
if (fn.body) _scanInterfaceCallNodes(fn.body, interfaceCalls, checker);
|
|
2766
3363
|
}
|
|
2767
3364
|
_scanInterfaceTypeDecls(progs, interfaceCalls, checker);
|
|
3365
|
+
_scanFuncSigInterfaces(progs, funcDecls, interfaceCalls, checker, mod);
|
|
2768
3366
|
|
|
2769
3367
|
// `error.Error()` is reached implicitly by fmt verbs and errors.Is, so
|
|
2770
3368
|
// the dispatcher must exist even when user code never calls it.
|
|
@@ -2784,7 +3382,378 @@ function _collectInterfaceDispatchers(progs, funcDecls, mod, checker) {
|
|
|
2784
3382
|
});
|
|
2785
3383
|
}
|
|
2786
3384
|
|
|
3385
|
+
const hasIo = importsAnyOf(progs, [
|
|
3386
|
+
"io",
|
|
3387
|
+
"fmt",
|
|
3388
|
+
"strings",
|
|
3389
|
+
"bytes",
|
|
3390
|
+
"crypto/sha256",
|
|
3391
|
+
"sha256",
|
|
3392
|
+
"encoding/binary",
|
|
3393
|
+
"binary",
|
|
3394
|
+
"encoding/hex",
|
|
3395
|
+
"hex",
|
|
3396
|
+
"encoding/base64",
|
|
3397
|
+
"base64",
|
|
3398
|
+
]);
|
|
3399
|
+
if (hasIo) {
|
|
3400
|
+
const byteSliceType = {
|
|
3401
|
+
kind: "slice",
|
|
3402
|
+
elem: { kind: "basic", name: "byte" },
|
|
3403
|
+
};
|
|
3404
|
+
const intErrReturns = [
|
|
3405
|
+
{ kind: "basic", name: "int" },
|
|
3406
|
+
{ kind: "interface", name: "error" },
|
|
3407
|
+
];
|
|
3408
|
+
if (!interfaceCalls.has("io.Reader.Read")) {
|
|
3409
|
+
interfaceCalls.set("io.Reader.Read", {
|
|
3410
|
+
ifaceName: "io.Reader",
|
|
3411
|
+
ifaceType: checker?.types?.get("io.Reader"),
|
|
3412
|
+
methodName: "Read",
|
|
3413
|
+
methodSig: {
|
|
3414
|
+
kind: "func",
|
|
3415
|
+
params: [byteSliceType],
|
|
3416
|
+
returns: intErrReturns,
|
|
3417
|
+
},
|
|
3418
|
+
});
|
|
3419
|
+
}
|
|
3420
|
+
if (!interfaceCalls.has("io.Writer.Write")) {
|
|
3421
|
+
interfaceCalls.set("io.Writer.Write", {
|
|
3422
|
+
ifaceName: "io.Writer",
|
|
3423
|
+
ifaceType: checker?.types?.get("io.Writer"),
|
|
3424
|
+
methodName: "Write",
|
|
3425
|
+
methodSig: {
|
|
3426
|
+
kind: "func",
|
|
3427
|
+
params: [byteSliceType],
|
|
3428
|
+
returns: intErrReturns,
|
|
3429
|
+
},
|
|
3430
|
+
});
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
|
|
2787
3434
|
for (const info of interfaceCalls.values()) {
|
|
2788
3435
|
funcDecls.push(_makeInterfaceDispatcher(info, checker));
|
|
2789
3436
|
}
|
|
2790
3437
|
}
|
|
3438
|
+
|
|
3439
|
+
function _registerIoSyntheticMethods(funcDecls, mod, strType, programs) {
|
|
3440
|
+
const progs = Array.isArray(programs) ? programs : [programs];
|
|
3441
|
+
const hasStrings = importsAnyOf(progs, ["strings"]);
|
|
3442
|
+
const hasBytes = importsAnyOf(progs, ["bytes"]);
|
|
3443
|
+
const hasIo = importsAnyOf(progs, ["io"]);
|
|
3444
|
+
|
|
3445
|
+
const BYTE_SLICE_T = {
|
|
3446
|
+
kind: "slice",
|
|
3447
|
+
elem: { kind: "basic", name: "byte" },
|
|
3448
|
+
};
|
|
3449
|
+
const INT_T = { kind: "basic", name: "int" };
|
|
3450
|
+
const ERR_T = { kind: "interface", name: "error" };
|
|
3451
|
+
const INT_ERR_RET = { kind: "tuple", types: [INT_T, ERR_T] };
|
|
3452
|
+
const ioHelper = (name, params, returnType, kind, extra = {}) => ({
|
|
3453
|
+
kind: "FuncDecl",
|
|
3454
|
+
name,
|
|
3455
|
+
params,
|
|
3456
|
+
returnType,
|
|
3457
|
+
body: { kind: "Block", stmts: [], list: [] },
|
|
3458
|
+
_isIoHelper: kind,
|
|
3459
|
+
_rootFuncDecl: null,
|
|
3460
|
+
...extra,
|
|
3461
|
+
});
|
|
3462
|
+
|
|
3463
|
+
if (hasStrings && mod.structTypes.has("strings.Builder")) {
|
|
3464
|
+
const bPtr = {
|
|
3465
|
+
kind: "pointer",
|
|
3466
|
+
base: { kind: "named", name: "strings.Builder" },
|
|
3467
|
+
};
|
|
3468
|
+
funcDecls.push(
|
|
3469
|
+
ioHelper(
|
|
3470
|
+
"strings.Builder.Write",
|
|
3471
|
+
[
|
|
3472
|
+
{ name: "b", type: bPtr },
|
|
3473
|
+
{ name: "p", type: BYTE_SLICE_T },
|
|
3474
|
+
],
|
|
3475
|
+
INT_ERR_RET,
|
|
3476
|
+
"builder_write",
|
|
3477
|
+
{
|
|
3478
|
+
_isMethod: true,
|
|
3479
|
+
_recvTypeName: "strings.Builder",
|
|
3480
|
+
_methodName: "Write",
|
|
3481
|
+
},
|
|
3482
|
+
),
|
|
3483
|
+
ioHelper(
|
|
3484
|
+
"strings.Builder.WriteString",
|
|
3485
|
+
[
|
|
3486
|
+
{ name: "b", type: bPtr },
|
|
3487
|
+
{ name: "s", type: strType },
|
|
3488
|
+
],
|
|
3489
|
+
INT_ERR_RET,
|
|
3490
|
+
"builder_write_string",
|
|
3491
|
+
{
|
|
3492
|
+
_isMethod: true,
|
|
3493
|
+
_recvTypeName: "strings.Builder",
|
|
3494
|
+
_methodName: "WriteString",
|
|
3495
|
+
},
|
|
3496
|
+
),
|
|
3497
|
+
);
|
|
3498
|
+
}
|
|
3499
|
+
if (hasBytes && mod.structTypes.has("bytes.Buffer")) {
|
|
3500
|
+
const bPtr = {
|
|
3501
|
+
kind: "pointer",
|
|
3502
|
+
base: { kind: "named", name: "bytes.Buffer" },
|
|
3503
|
+
};
|
|
3504
|
+
funcDecls.push(
|
|
3505
|
+
ioHelper(
|
|
3506
|
+
"bytes.Buffer.Write",
|
|
3507
|
+
[
|
|
3508
|
+
{ name: "b", type: bPtr },
|
|
3509
|
+
{ name: "p", type: BYTE_SLICE_T },
|
|
3510
|
+
],
|
|
3511
|
+
INT_ERR_RET,
|
|
3512
|
+
"buffer_write",
|
|
3513
|
+
{
|
|
3514
|
+
_isMethod: true,
|
|
3515
|
+
_recvTypeName: "bytes.Buffer",
|
|
3516
|
+
_methodName: "Write",
|
|
3517
|
+
},
|
|
3518
|
+
),
|
|
3519
|
+
ioHelper(
|
|
3520
|
+
"bytes.Buffer.WriteString",
|
|
3521
|
+
[
|
|
3522
|
+
{ name: "b", type: bPtr },
|
|
3523
|
+
{ name: "s", type: strType },
|
|
3524
|
+
],
|
|
3525
|
+
INT_ERR_RET,
|
|
3526
|
+
"buffer_write_string",
|
|
3527
|
+
{
|
|
3528
|
+
_isMethod: true,
|
|
3529
|
+
_recvTypeName: "bytes.Buffer",
|
|
3530
|
+
_methodName: "WriteString",
|
|
3531
|
+
},
|
|
3532
|
+
),
|
|
3533
|
+
ioHelper(
|
|
3534
|
+
"bytes.Buffer.Read",
|
|
3535
|
+
[
|
|
3536
|
+
{ name: "b", type: bPtr },
|
|
3537
|
+
{ name: "p", type: BYTE_SLICE_T },
|
|
3538
|
+
],
|
|
3539
|
+
INT_ERR_RET,
|
|
3540
|
+
"buffer_read",
|
|
3541
|
+
{
|
|
3542
|
+
_isMethod: true,
|
|
3543
|
+
_recvTypeName: "bytes.Buffer",
|
|
3544
|
+
_methodName: "Read",
|
|
3545
|
+
},
|
|
3546
|
+
),
|
|
3547
|
+
);
|
|
3548
|
+
}
|
|
3549
|
+
if (hasStrings && mod.structTypes.has("strings.Reader")) {
|
|
3550
|
+
const rPtr = {
|
|
3551
|
+
kind: "pointer",
|
|
3552
|
+
base: { kind: "named", name: "strings.Reader" },
|
|
3553
|
+
};
|
|
3554
|
+
funcDecls.push(
|
|
3555
|
+
ioHelper(
|
|
3556
|
+
"strings.Reader.Read",
|
|
3557
|
+
[
|
|
3558
|
+
{ name: "r", type: rPtr },
|
|
3559
|
+
{ name: "p", type: BYTE_SLICE_T },
|
|
3560
|
+
],
|
|
3561
|
+
INT_ERR_RET,
|
|
3562
|
+
"strings_reader_read",
|
|
3563
|
+
{
|
|
3564
|
+
_isMethod: true,
|
|
3565
|
+
_recvTypeName: "strings.Reader",
|
|
3566
|
+
_methodName: "Read",
|
|
3567
|
+
},
|
|
3568
|
+
),
|
|
3569
|
+
ioHelper(
|
|
3570
|
+
"strings.Reader.Len",
|
|
3571
|
+
[{ name: "r", type: rPtr }],
|
|
3572
|
+
INT_T,
|
|
3573
|
+
"strings_reader_len",
|
|
3574
|
+
{
|
|
3575
|
+
_isMethod: true,
|
|
3576
|
+
_recvTypeName: "strings.Reader",
|
|
3577
|
+
_methodName: "Len",
|
|
3578
|
+
},
|
|
3579
|
+
),
|
|
3580
|
+
ioHelper(
|
|
3581
|
+
"strings.Reader.Reset",
|
|
3582
|
+
[
|
|
3583
|
+
{ name: "r", type: rPtr },
|
|
3584
|
+
{ name: "s", type: strType },
|
|
3585
|
+
],
|
|
3586
|
+
null,
|
|
3587
|
+
"strings_reader_reset",
|
|
3588
|
+
{
|
|
3589
|
+
_isMethod: true,
|
|
3590
|
+
_recvTypeName: "strings.Reader",
|
|
3591
|
+
_methodName: "Reset",
|
|
3592
|
+
},
|
|
3593
|
+
),
|
|
3594
|
+
);
|
|
3595
|
+
}
|
|
3596
|
+
if (hasBytes && mod.structTypes.has("bytes.Reader")) {
|
|
3597
|
+
const rPtr = {
|
|
3598
|
+
kind: "pointer",
|
|
3599
|
+
base: { kind: "named", name: "bytes.Reader" },
|
|
3600
|
+
};
|
|
3601
|
+
funcDecls.push(
|
|
3602
|
+
ioHelper(
|
|
3603
|
+
"bytes.Reader.Read",
|
|
3604
|
+
[
|
|
3605
|
+
{ name: "r", type: rPtr },
|
|
3606
|
+
{ name: "p", type: BYTE_SLICE_T },
|
|
3607
|
+
],
|
|
3608
|
+
INT_ERR_RET,
|
|
3609
|
+
"bytes_reader_read",
|
|
3610
|
+
{ _isMethod: true, _recvTypeName: "bytes.Reader", _methodName: "Read" },
|
|
3611
|
+
),
|
|
3612
|
+
ioHelper(
|
|
3613
|
+
"bytes.Reader.Len",
|
|
3614
|
+
[{ name: "r", type: rPtr }],
|
|
3615
|
+
INT_T,
|
|
3616
|
+
"bytes_reader_len",
|
|
3617
|
+
{ _isMethod: true, _recvTypeName: "bytes.Reader", _methodName: "Len" },
|
|
3618
|
+
),
|
|
3619
|
+
ioHelper(
|
|
3620
|
+
"bytes.Reader.Reset",
|
|
3621
|
+
[
|
|
3622
|
+
{ name: "r", type: rPtr },
|
|
3623
|
+
{ name: "b", type: BYTE_SLICE_T },
|
|
3624
|
+
],
|
|
3625
|
+
null,
|
|
3626
|
+
"bytes_reader_reset",
|
|
3627
|
+
{
|
|
3628
|
+
_isMethod: true,
|
|
3629
|
+
_recvTypeName: "bytes.Reader",
|
|
3630
|
+
_methodName: "Reset",
|
|
3631
|
+
},
|
|
3632
|
+
),
|
|
3633
|
+
);
|
|
3634
|
+
}
|
|
3635
|
+
if (hasIo && mod.structTypes.has("io.discard")) {
|
|
3636
|
+
const dPtr = {
|
|
3637
|
+
kind: "pointer",
|
|
3638
|
+
base: { kind: "named", name: "io.discard" },
|
|
3639
|
+
};
|
|
3640
|
+
funcDecls.push(
|
|
3641
|
+
ioHelper(
|
|
3642
|
+
"io.discard.Write",
|
|
3643
|
+
[
|
|
3644
|
+
{ name: "d", type: dPtr },
|
|
3645
|
+
{ name: "p", type: BYTE_SLICE_T },
|
|
3646
|
+
],
|
|
3647
|
+
INT_ERR_RET,
|
|
3648
|
+
"discard_write",
|
|
3649
|
+
{ _isMethod: true, _recvTypeName: "io.discard", _methodName: "Write" },
|
|
3650
|
+
),
|
|
3651
|
+
ioHelper(
|
|
3652
|
+
"io.discard.WriteString",
|
|
3653
|
+
[
|
|
3654
|
+
{ name: "d", type: dPtr },
|
|
3655
|
+
{ name: "s", type: strType },
|
|
3656
|
+
],
|
|
3657
|
+
INT_ERR_RET,
|
|
3658
|
+
"discard_write_string",
|
|
3659
|
+
{
|
|
3660
|
+
_isMethod: true,
|
|
3661
|
+
_recvTypeName: "io.discard",
|
|
3662
|
+
_methodName: "WriteString",
|
|
3663
|
+
},
|
|
3664
|
+
),
|
|
3665
|
+
);
|
|
3666
|
+
}
|
|
3667
|
+
if (hasIo && mod.structTypes.has("io.LimitedReader")) {
|
|
3668
|
+
const lrPtr = {
|
|
3669
|
+
kind: "pointer",
|
|
3670
|
+
base: { kind: "named", name: "io.LimitedReader" },
|
|
3671
|
+
};
|
|
3672
|
+
funcDecls.push(
|
|
3673
|
+
ioHelper(
|
|
3674
|
+
"io.LimitedReader.Read",
|
|
3675
|
+
[
|
|
3676
|
+
{ name: "l", type: lrPtr },
|
|
3677
|
+
{ name: "p", type: BYTE_SLICE_T },
|
|
3678
|
+
],
|
|
3679
|
+
INT_ERR_RET,
|
|
3680
|
+
"limited_reader_read",
|
|
3681
|
+
{
|
|
3682
|
+
_isMethod: true,
|
|
3683
|
+
_recvTypeName: "io.LimitedReader",
|
|
3684
|
+
_methodName: "Read",
|
|
3685
|
+
},
|
|
3686
|
+
),
|
|
3687
|
+
);
|
|
3688
|
+
}
|
|
3689
|
+
const hasSha256 = importsAnyOf(progs, ["crypto/sha256", "sha256"]);
|
|
3690
|
+
if (
|
|
3691
|
+
hasSha256 &&
|
|
3692
|
+
(mod.structTypes.has("sha256.digest") ||
|
|
3693
|
+
mod.structTypes.has("crypto/sha256.digest"))
|
|
3694
|
+
) {
|
|
3695
|
+
const dPtr = {
|
|
3696
|
+
kind: "pointer",
|
|
3697
|
+
base: { kind: "named", name: "sha256.digest" },
|
|
3698
|
+
};
|
|
3699
|
+
funcDecls.push(
|
|
3700
|
+
ioHelper(
|
|
3701
|
+
"sha256.digest.Write",
|
|
3702
|
+
[
|
|
3703
|
+
{ name: "d", type: dPtr },
|
|
3704
|
+
{ name: "p", type: BYTE_SLICE_T },
|
|
3705
|
+
],
|
|
3706
|
+
INT_ERR_RET,
|
|
3707
|
+
"sha256_write",
|
|
3708
|
+
{
|
|
3709
|
+
_isMethod: true,
|
|
3710
|
+
_recvTypeName: "sha256.digest",
|
|
3711
|
+
_methodName: "Write",
|
|
3712
|
+
},
|
|
3713
|
+
),
|
|
3714
|
+
ioHelper(
|
|
3715
|
+
"sha256.digest.Sum",
|
|
3716
|
+
[
|
|
3717
|
+
{ name: "d", type: dPtr },
|
|
3718
|
+
{ name: "b", type: BYTE_SLICE_T },
|
|
3719
|
+
],
|
|
3720
|
+
BYTE_SLICE_T,
|
|
3721
|
+
"sha256_sum",
|
|
3722
|
+
{ _isMethod: true, _recvTypeName: "sha256.digest", _methodName: "Sum" },
|
|
3723
|
+
),
|
|
3724
|
+
ioHelper(
|
|
3725
|
+
"sha256.digest.Reset",
|
|
3726
|
+
[{ name: "d", type: dPtr }],
|
|
3727
|
+
null,
|
|
3728
|
+
"sha256_reset",
|
|
3729
|
+
{
|
|
3730
|
+
_isMethod: true,
|
|
3731
|
+
_recvTypeName: "sha256.digest",
|
|
3732
|
+
_methodName: "Reset",
|
|
3733
|
+
},
|
|
3734
|
+
),
|
|
3735
|
+
ioHelper(
|
|
3736
|
+
"sha256.digest.Size",
|
|
3737
|
+
[{ name: "d", type: dPtr }],
|
|
3738
|
+
INT_T,
|
|
3739
|
+
"sha256_size",
|
|
3740
|
+
{
|
|
3741
|
+
_isMethod: true,
|
|
3742
|
+
_recvTypeName: "sha256.digest",
|
|
3743
|
+
_methodName: "Size",
|
|
3744
|
+
},
|
|
3745
|
+
),
|
|
3746
|
+
ioHelper(
|
|
3747
|
+
"sha256.digest.BlockSize",
|
|
3748
|
+
[{ name: "d", type: dPtr }],
|
|
3749
|
+
INT_T,
|
|
3750
|
+
"sha256_block_size",
|
|
3751
|
+
{
|
|
3752
|
+
_isMethod: true,
|
|
3753
|
+
_recvTypeName: "sha256.digest",
|
|
3754
|
+
_methodName: "BlockSize",
|
|
3755
|
+
},
|
|
3756
|
+
),
|
|
3757
|
+
);
|
|
3758
|
+
}
|
|
3759
|
+
}
|