gofront 1.7.0 → 1.9.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.
Files changed (194) hide show
  1. package/README.md +14 -14
  2. package/package.json +10 -38
  3. package/src/backend/js/expressions.js +2060 -389
  4. package/src/backend/js/index.js +586 -174
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +936 -1644
  7. package/src/backend/js/statements.js +1349 -132
  8. package/src/backend/js/stdlib/index.js +51 -94
  9. package/src/backend/js/templ.js +67 -118
  10. package/src/backend/js/type-info.js +436 -0
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +80 -0
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +753 -872
  15. package/src/backend/wasm/emit-builtins.js +914 -237
  16. package/src/backend/wasm/emit-exprs.js +1456 -195
  17. package/src/backend/wasm/emit-maps.js +78 -380
  18. package/src/backend/wasm/emit-stmts.js +1659 -214
  19. package/src/backend/wasm/emit.js +614 -88
  20. package/src/backend/wasm/encode.js +43 -13
  21. package/src/backend/wasm/globals.js +491 -0
  22. package/src/backend/wasm/glue.js +2 -4
  23. package/src/backend/wasm/index.js +406 -3195
  24. package/src/backend/wasm/method-expr.js +392 -0
  25. package/src/backend/wasm/module-emitter.js +1615 -0
  26. package/src/backend/wasm/monomorph.js +164 -9
  27. package/src/backend/wasm/natives.js +596 -0
  28. package/src/backend/wasm/prescan.js +249 -0
  29. package/src/backend/wasm/prune-funcs.js +89 -0
  30. package/src/backend/wasm/stdlib/index.js +2 -37
  31. package/src/backend/wasm/stdlib/simd.js +293 -28
  32. package/src/backend/wasm/types.js +260 -27
  33. package/src/backend/wasm/variadic.js +93 -0
  34. package/src/backend/wasm/wat.js +47 -20
  35. package/src/{cli-core.js → cli/cli-core.js} +241 -11
  36. package/src/{test-runner.js → cli/test-runner.js} +188 -122
  37. package/src/{vendor.js → cli/vendor.js} +3 -4
  38. package/src/compiler.js +202 -386
  39. package/src/index.js +15 -169
  40. package/src/{lexer.js → lexer/lexer.js} +203 -62
  41. package/src/{templ-lexer.js → lexer/templ-lexer.js} +61 -18
  42. package/src/{tokens.js → lexer/tokens.js} +2 -0
  43. package/src/link/sourcemap.js +97 -0
  44. package/src/link/stdlib.js +737 -0
  45. package/src/link/type-names.js +148 -0
  46. package/src/link/wasm.js +318 -0
  47. package/src/lower/bounds.js +547 -0
  48. package/src/lower/boxing.js +1 -1
  49. package/src/lower/captures.js +267 -64
  50. package/src/lower/embedding.js +32 -3
  51. package/src/lower/errors-as.js +196 -0
  52. package/src/lower/fmt-formatters.js +905 -0
  53. package/src/lower/functions.js +2 -0
  54. package/src/lower/gen-types.js +274 -0
  55. package/src/lower/index.js +33 -19
  56. package/src/lower/json-codecs.js +1379 -0
  57. package/src/lower/ownership.js +47 -8
  58. package/src/lower/range.js +86 -1
  59. package/src/lower/reachability.js +150 -0
  60. package/src/lower/walk.js +12 -0
  61. package/src/parser/declarations.js +83 -15
  62. package/src/parser/expressions.js +110 -18
  63. package/src/parser/index.js +2 -1
  64. package/src/parser/statements.js +38 -22
  65. package/src/{templ-parser.js → parser/templ.js} +179 -17
  66. package/src/parser/types.js +70 -9
  67. package/src/resolver.js +21 -1
  68. package/src/typechecker/assignability.js +291 -19
  69. package/src/typechecker/const-fold.js +399 -0
  70. package/src/typechecker/constants.js +282 -0
  71. package/src/typechecker/expressions.js +1220 -183
  72. package/src/typechecker/index.js +659 -92
  73. package/src/typechecker/init-order.js +426 -0
  74. package/src/typechecker/operand-text.js +40 -0
  75. package/src/typechecker/resolve.js +613 -62
  76. package/src/typechecker/statements.js +212 -20
  77. package/src/typechecker/stdlib/excluded.js +902 -0
  78. package/src/typechecker/stdlib/index.js +38 -0
  79. package/src/typechecker/stdlib/simd.js +65 -15
  80. package/src/typechecker/termination.js +11 -2
  81. package/src/typechecker/types.js +268 -514
  82. package/stdlib/bytes/buffer.go +479 -0
  83. package/stdlib/bytes/bytes.go +1010 -0
  84. package/stdlib/bytes/reader.go +161 -0
  85. package/stdlib/cmp/cmp.go +65 -0
  86. package/stdlib/context/context.go +115 -0
  87. package/stdlib/crypto/rand/rand.go +34 -0
  88. package/stdlib/crypto/sha256/sha256.go +249 -0
  89. package/stdlib/encoding/base64/base64.go +331 -0
  90. package/stdlib/encoding/binary/binary.go +332 -0
  91. package/stdlib/encoding/hex/hex.go +140 -0
  92. package/stdlib/encoding/json/errors.go +31 -0
  93. package/stdlib/encoding/json/indent.go +71 -0
  94. package/stdlib/encoding/json/json.go +62 -0
  95. package/stdlib/encoding/json/number.go +12 -0
  96. package/stdlib/encoding/json/stream.go +173 -0
  97. package/stdlib/errors/errors.go +174 -0
  98. package/stdlib/fmt/errors.go +110 -0
  99. package/stdlib/fmt/format.go +732 -0
  100. package/stdlib/fmt/print.go +1232 -0
  101. package/stdlib/gom/gom.go +293 -0
  102. package/stdlib/hash/hash.go +53 -0
  103. package/stdlib/html/html.go +251 -0
  104. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  105. package/stdlib/internal/jsonrt/dec.go +871 -0
  106. package/stdlib/internal/jsonrt/enc.go +516 -0
  107. package/stdlib/internal/jsonrt/indent.go +135 -0
  108. package/stdlib/internal/jsonrt/number.go +27 -0
  109. package/stdlib/internal/jsonrt/reader.go +73 -0
  110. package/stdlib/internal/jsonrt/scanner.go +658 -0
  111. package/stdlib/io/io.go +502 -0
  112. package/stdlib/iter/iter.go +18 -0
  113. package/stdlib/maps/maps.go +131 -0
  114. package/stdlib/math/bits/bits.go +507 -0
  115. package/stdlib/math/extra.go +272 -0
  116. package/stdlib/math/math.go +439 -0
  117. package/stdlib/math/rand/rand.go +297 -0
  118. package/stdlib/os/os.go +93 -0
  119. package/stdlib/path/filepath/filepath.go +47 -0
  120. package/stdlib/path/path.go +394 -0
  121. package/stdlib/regexp/regexp.go +231 -0
  122. package/stdlib/slices/slices.go +526 -0
  123. package/stdlib/slices/sort.go +209 -0
  124. package/stdlib/slices/zsort_cmp.go +480 -0
  125. package/stdlib/slices/zsort_ordered.go +482 -0
  126. package/stdlib/sort/sort.go +500 -0
  127. package/stdlib/sort/zsort_func.go +480 -0
  128. package/stdlib/sort/zsort_iface.go +480 -0
  129. package/stdlib/strconv/float.go +1699 -0
  130. package/stdlib/strconv/isprint.go +752 -0
  131. package/stdlib/strconv/quote.go +526 -0
  132. package/stdlib/strconv/strconv.go +616 -0
  133. package/stdlib/strings/builder.go +95 -0
  134. package/stdlib/strings/reader.go +163 -0
  135. package/stdlib/strings/replacer.go +102 -0
  136. package/stdlib/strings/strings.go +807 -0
  137. package/stdlib/sync/sync.go +268 -0
  138. package/stdlib/testing/async_js.go +61 -0
  139. package/stdlib/testing/benchmark.go +297 -0
  140. package/stdlib/testing/testing.go +523 -0
  141. package/stdlib/time/duration.go +233 -0
  142. package/stdlib/time/format.go +745 -0
  143. package/stdlib/time/parse.go +790 -0
  144. package/stdlib/time/sleep_js.go +63 -0
  145. package/stdlib/time/time.go +834 -0
  146. package/stdlib/unicode/unicode.go +250 -0
  147. package/stdlib/unicode/utf8/utf8.go +464 -0
  148. package/src/backend/js/stdlib/base64.js +0 -12
  149. package/src/backend/js/stdlib/binary.js +0 -102
  150. package/src/backend/js/stdlib/bits.js +0 -46
  151. package/src/backend/js/stdlib/builder.js +0 -63
  152. package/src/backend/js/stdlib/bytes.js +0 -122
  153. package/src/backend/js/stdlib/errors.js +0 -44
  154. package/src/backend/js/stdlib/fmt.js +0 -178
  155. package/src/backend/js/stdlib/gom.js +0 -155
  156. package/src/backend/js/stdlib/hex.js +0 -17
  157. package/src/backend/js/stdlib/html.js +0 -20
  158. package/src/backend/js/stdlib/io.js +0 -137
  159. package/src/backend/js/stdlib/json.js +0 -972
  160. package/src/backend/js/stdlib/maps.js +0 -45
  161. package/src/backend/js/stdlib/math.js +0 -69
  162. package/src/backend/js/stdlib/os.js +0 -13
  163. package/src/backend/js/stdlib/path.js +0 -48
  164. package/src/backend/js/stdlib/rand.js +0 -32
  165. package/src/backend/js/stdlib/regexp.js +0 -54
  166. package/src/backend/js/stdlib/sha256.js +0 -12
  167. package/src/backend/js/stdlib/shared.js +0 -17
  168. package/src/backend/js/stdlib/simd.js +0 -24
  169. package/src/backend/js/stdlib/slices.js +0 -77
  170. package/src/backend/js/stdlib/sort.js +0 -30
  171. package/src/backend/js/stdlib/strconv.js +0 -74
  172. package/src/backend/js/stdlib/strings.js +0 -222
  173. package/src/backend/js/stdlib/sync.js +0 -13
  174. package/src/backend/js/stdlib/testing.js +0 -34
  175. package/src/backend/js/stdlib/time.js +0 -128
  176. package/src/backend/js/stdlib/unicode.js +0 -25
  177. package/src/backend/js/stdlib/utf8.js +0 -26
  178. package/src/backend/wasm/const-fold.js +0 -205
  179. package/src/backend/wasm/emit-stdlib.js +0 -13
  180. package/src/backend/wasm/stdlib/bytes.js +0 -5039
  181. package/src/backend/wasm/stdlib/core.js +0 -8903
  182. package/src/backend/wasm/stdlib/io.js +0 -2161
  183. package/src/backend/wasm/stdlib/packages.js +0 -2400
  184. package/src/backend/wasm/stdlib/pure.js +0 -720
  185. package/src/backend/wasm/stdlib/time.js +0 -1200
  186. package/src/typechecker/stdlib/core.js +0 -801
  187. package/src/typechecker/stdlib/extended.js +0 -914
  188. package/src/typechecker/stdlib.js +0 -22
  189. /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
  190. /package/src/{colors.js → cli/colors.js} +0 -0
  191. /package/src/{dev-server.js → cli/dev-server.js} +0 -0
  192. /package/src/{minifier.js → cli/minifier.js} +0 -0
  193. /package/src/{project-config.js → cli/project-config.js} +0 -0
  194. /package/src/{pwa.js → cli/pwa.js} +0 -0
@@ -1,13 +1,54 @@
1
1
  // src/backend/wasm/stdlib/simd.js
2
2
  // FunctionEmitter mixin: gofront/simd (F32x4 vector math, load/store, composite literals).
3
3
 
4
- const SIMD_BINARY_OPS = {
4
+ // Methods lowered to one instruction over the receiver and its vector arguments.
5
+ const SIMD_LANEWISE_OPS = {
5
6
  Add: "f32x4.add",
6
7
  Sub: "f32x4.sub",
7
8
  Mul: "f32x4.mul",
8
9
  Div: "f32x4.div",
9
10
  Min: "f32x4.min",
10
11
  Max: "f32x4.max",
12
+ Neg: "f32x4.neg",
13
+ Abs: "f32x4.abs",
14
+ Sqrt: "f32x4.sqrt",
15
+ Floor: "f32x4.floor",
16
+ Ceil: "f32x4.ceil",
17
+ Trunc: "f32x4.trunc",
18
+ RoundToEven: "f32x4.nearest",
19
+ Equal: "f32x4.eq",
20
+ NotEqual: "f32x4.ne",
21
+ Less: "f32x4.lt",
22
+ LessEqual: "f32x4.le",
23
+ Greater: "f32x4.gt",
24
+ GreaterEqual: "f32x4.ge",
25
+ };
26
+
27
+ const SIMD_MASK_OPS = {
28
+ And: "v128.and",
29
+ Or: "v128.or",
30
+ Xor: "v128.xor",
31
+ AndNot: "v128.andnot",
32
+ Not: "v128.not",
33
+ Any: "v128.any_true",
34
+ All: "i32x4.all_true",
35
+ };
36
+
37
+ // Methods with their own emitter: name -> FunctionEmitter method.
38
+ const SIMD_SPECIAL_METHODS = {
39
+ MulAdd: "_emitSimdMulAdd",
40
+ Sum: "_emitSimdSum",
41
+ Swizzle: "_emitSimdSwizzle",
42
+ Dot3: "_emitSimdDot3",
43
+ Dot4: "_emitSimdDot4",
44
+ Lane: "_emitSimdLane",
45
+ WithLane: "_emitSimdWithLane",
46
+ Splat: "_emitSimdSplat",
47
+ };
48
+
49
+ const SIMD_MASK_SPECIAL_METHODS = {
50
+ Bits: "_emitSimdMaskBits",
51
+ Lane: "_emitSimdMaskLane",
11
52
  };
12
53
 
13
54
  export class SimdEmitter {
@@ -59,41 +100,162 @@ export class SimdEmitter {
59
100
  this.releaseTemp(tmp, "v128");
60
101
  }
61
102
 
62
- emitSimdMethodCall(method, recvExpr, args, _targetWasmType) {
63
- const op = SIMD_BINARY_OPS[method];
64
- if (op) {
65
- this.emitExpr(recvExpr, "v128");
66
- this.emitExpr(args[0], "v128");
67
- this.pushInstruction(op);
68
- return true;
69
- }
70
- if (method === "Dot3" || method === "Dot4") {
71
- this._emitSimdDot(recvExpr, args[0], method === "Dot3" ? 3 : 4);
72
- return true;
73
- }
74
- if (method === "Lane") {
75
- const laneIdx = this._constIntValue(args[0]) ?? 0;
76
- this.emitExpr(recvExpr, "v128");
77
- this.pushInstruction({ op: "f32x4.extract_lane", lane: laneIdx });
78
- return true;
103
+ _isSimdMaskType(goType) {
104
+ return (
105
+ goType?.name === "simd.Mask32x4" ||
106
+ goType?.name === "Mask32x4" ||
107
+ goType?.simd === "Mask32x4" ||
108
+ goType?.underlying?.simd === "Mask32x4"
109
+ );
110
+ }
111
+
112
+ // Lane-wise equality of two vectors on the stack -> i32 (Go array `==`:
113
+ // NaN != NaN, -0 == +0).
114
+ _emitSimdEq(goType) {
115
+ this.pushInstruction(
116
+ this._isSimdMaskType(goType) ? "i32x4.eq" : "f32x4.eq",
117
+ );
118
+ this.pushInstruction("i32x4.all_true");
119
+ }
120
+
121
+ _emitSimdSum(recvExpr) {
122
+ this.emitExpr(recvExpr, "v128");
123
+ const tmp = this.acquireTemp("v128");
124
+ this.pushInstruction({ op: "local.set", index: tmp });
125
+ this.pushInstruction({ op: "local.get", index: tmp });
126
+ this.pushInstruction({ op: "f32x4.extract_lane", lane: 0 });
127
+ for (let i = 1; i < 4; i++) {
128
+ this.pushInstruction({ op: "local.get", index: tmp });
129
+ this.pushInstruction({ op: "f32x4.extract_lane", lane: i });
130
+ this.pushInstruction("f32.add");
79
131
  }
80
- if (method === "WithLane") {
81
- const laneIdx = this._constIntValue(args[0]) ?? 0;
82
- this.emitExpr(recvExpr, "v128");
83
- this.emitExpr(args[1], "f32");
84
- this.pushInstruction({ op: "f32x4.replace_lane", lane: laneIdx });
85
- return true;
132
+ this.releaseTemp(tmp, "v128");
133
+ }
134
+
135
+ // Lane i (0-3 from a, 4-7 from b) as the four byte indices of an i8x16.shuffle.
136
+ _simdShuffleBytes(lanes) {
137
+ const out = [];
138
+ for (const lane of lanes) {
139
+ for (let k = 0; k < 4; k++) out.push(lane * 4 + k);
86
140
  }
87
- if (method === "Splat") {
88
- this.emitExpr(args[0], "f32");
89
- this.pushInstruction("f32x4.splat");
141
+ return out;
142
+ }
143
+
144
+ _simdLaneConsts(nodes, max) {
145
+ return nodes.map((n) => {
146
+ const v = this._constIntValue(n);
147
+ if (v === null || v < 0 || v > max)
148
+ throw new Error(`simd: lane index must be a constant in [0, ${max}]`);
149
+ return v;
150
+ });
151
+ }
152
+
153
+ _emitSimdSwizzle(recvExpr, args) {
154
+ const lanes = this._simdLaneConsts(args, 3);
155
+ const tmp = this.acquireTemp("v128");
156
+ this.emitExpr(recvExpr, "v128");
157
+ this.pushInstruction({ op: "local.tee", index: tmp });
158
+ this.pushInstruction({ op: "local.get", index: tmp });
159
+ this.pushInstruction({
160
+ op: "i8x16.shuffle",
161
+ lanes: this._simdShuffleBytes(lanes),
162
+ });
163
+ this.releaseTemp(tmp, "v128");
164
+ }
165
+
166
+ _emitSimdSelect(args) {
167
+ const maskTmp = this.acquireTemp("v128");
168
+ this.emitExpr(args[0], "v128");
169
+ this.pushInstruction({ op: "local.set", index: maskTmp });
170
+ this.emitExpr(args[1], "v128");
171
+ this.emitExpr(args[2], "v128");
172
+ this.pushInstruction({ op: "local.get", index: maskTmp });
173
+ this.pushInstruction("v128.bitselect");
174
+ this.releaseTemp(maskTmp, "v128");
175
+ }
176
+
177
+ _emitSimdShuffle(args) {
178
+ const lanes = this._simdLaneConsts(args.slice(2, 6), 7);
179
+ this.emitExpr(args[0], "v128");
180
+ this.emitExpr(args[1], "v128");
181
+ this.pushInstruction({
182
+ op: "i8x16.shuffle",
183
+ lanes: this._simdShuffleBytes(lanes),
184
+ });
185
+ }
186
+
187
+ _emitSimdOp(op, recvExpr, args) {
188
+ this.emitExpr(recvExpr, "v128");
189
+ for (const arg of args) this.emitExpr(arg, "v128");
190
+ this.pushInstruction(op);
191
+ }
192
+
193
+ _emitSimdMaskBits(recvExpr) {
194
+ this._emitSimdOp("i32x4.bitmask", recvExpr, []);
195
+ this.pushInstruction("i64.extend_i32_u");
196
+ }
197
+
198
+ _emitSimdMaskLane(recvExpr, args) {
199
+ const [lane] = this._simdLaneConsts([args[0]], 3);
200
+ this.emitExpr(recvExpr, "v128");
201
+ this.pushInstruction({ op: "i32x4.extract_lane", lane });
202
+ this.pushInstruction({ op: "i32.const", value: 0 });
203
+ this.pushInstruction("i32.ne");
204
+ }
205
+
206
+ _emitSimdMulAdd(recvExpr, args) {
207
+ // Two roundings (mul, then add), not fused.
208
+ this._emitSimdOp("f32x4.mul", recvExpr, [args[0]]);
209
+ this.emitExpr(args[1], "v128");
210
+ this.pushInstruction("f32x4.add");
211
+ }
212
+
213
+ _emitSimdDot3(recvExpr, args) {
214
+ this._emitSimdDot(recvExpr, args[0], 3);
215
+ }
216
+
217
+ _emitSimdDot4(recvExpr, args) {
218
+ this._emitSimdDot(recvExpr, args[0], 4);
219
+ }
220
+
221
+ _emitSimdLane(recvExpr, args) {
222
+ const lane = this._constIntValue(args[0]) ?? 0;
223
+ this.emitExpr(recvExpr, "v128");
224
+ this.pushInstruction({ op: "f32x4.extract_lane", lane });
225
+ }
226
+
227
+ _emitSimdWithLane(recvExpr, args) {
228
+ const lane = this._constIntValue(args[0]) ?? 0;
229
+ this.emitExpr(recvExpr, "v128");
230
+ this.emitExpr(args[1], "f32");
231
+ this.pushInstruction({ op: "f32x4.replace_lane", lane });
232
+ }
233
+
234
+ _emitSimdSplat(_recvExpr, args) {
235
+ this.emitExpr(args[0], "f32");
236
+ this.pushInstruction("f32x4.splat");
237
+ }
238
+
239
+ emitSimdMethodCall(method, recvExpr, args, _targetWasmType, isMask = false) {
240
+ const ops = isMask ? SIMD_MASK_OPS : SIMD_LANEWISE_OPS;
241
+ const specials = isMask ? SIMD_MASK_SPECIAL_METHODS : SIMD_SPECIAL_METHODS;
242
+ if (ops[method]) {
243
+ this._emitSimdOp(ops[method], recvExpr, args);
90
244
  return true;
91
245
  }
92
- return false;
246
+ if (!specials[method]) return false;
247
+ this[specials[method]](recvExpr, args);
248
+ return true;
93
249
  }
94
250
 
95
251
  emitSimdPackageCall(fn, args, _targetWasmType) {
96
252
  switch (fn) {
253
+ case "Select":
254
+ this._emitSimdSelect(args);
255
+ return true;
256
+ case "Shuffle":
257
+ this._emitSimdShuffle(args);
258
+ return true;
97
259
  case "Splat":
98
260
  this.emitExpr(args[0], "f32");
99
261
  this.pushInstruction("f32x4.splat");
@@ -114,6 +276,15 @@ export class SimdEmitter {
114
276
  case "StoreF32x4":
115
277
  this.emitSimdStore(args[0], args[1], args[2]);
116
278
  return true;
279
+ case "LoadF32x4Slice":
280
+ this.emitSimdSliceAccess(args[0], args[1], null);
281
+ return true;
282
+ case "StoreF32x4Slice":
283
+ this.emitSimdSliceAccess(args[0], args[1], args[2]);
284
+ return true;
285
+ case "Pad4":
286
+ this._emitSimdPad4(args[0]);
287
+ return true;
117
288
  default:
118
289
  return false;
119
290
  }
@@ -190,8 +361,102 @@ export class SimdEmitter {
190
361
  this.pushInstruction({ op: "v128.store", align: 2, offset: 0 });
191
362
  }
192
363
 
364
+ // Pad4(n) = (n + 3) &^ 3; a Go int, so always computed as i64.
365
+ _emitSimdPad4(nNode) {
366
+ this.emitExpr(nNode, "i64");
367
+ this.pushInstruction({ op: "i64.const", value: 3n });
368
+ this.pushInstruction("i64.add");
369
+ this.pushInstruction({ op: "i64.const", value: -4n });
370
+ this.pushInstruction("i64.and");
371
+ }
372
+
373
+ // LoadF32x4Slice (valNode null) and StoreF32x4Slice on a []float32: a
374
+ // GC array cannot be read as v128, so each lane is moved on its own.
375
+ emitSimdSliceAccess(sliceNode, indexNode, valNode) {
376
+ const sliceType = sliceNode._type ?? this._resolveExprGoType(sliceNode);
377
+ const elemGoType = this._getArrayElemType(sliceType);
378
+ const arrInfo = this.mod.getArrayType(elemGoType);
379
+ const sliceInfo = this.mod.getSliceType(elemGoType);
380
+ const sTI = sliceInfo.typeIndex;
381
+ const sliceWType = { kind: "ref", nullable: true, typeIndex: sTI };
382
+ const sliceTmp = this.acquireTemp(sliceWType);
383
+ const idx64 = this.acquireTemp("i64");
384
+ const baseTmp = this.acquireTemp("i32");
385
+ const vecTmp = valNode ? this.acquireTemp("v128") : null;
386
+ const lenOf = () => {
387
+ this.pushInstruction({ op: "local.get", index: sliceTmp });
388
+ this.pushInstruction({ op: "struct.get", typeIndex: sTI, fieldIndex: 2 });
389
+ };
390
+
391
+ this.emitExpr(sliceNode, sliceWType);
392
+ this.pushInstruction({ op: "local.set", index: sliceTmp });
393
+ if (this._isI32IndexExpr(indexNode)) {
394
+ this.emitExpr(indexNode, "i32");
395
+ this.pushInstruction("i64.extend_i32_s");
396
+ } else {
397
+ this.emitExpr(indexNode, "i64");
398
+ }
399
+ this.pushInstruction({ op: "local.set", index: idx64 });
400
+ if (valNode) {
401
+ this.emitExpr(valNode, "v128");
402
+ this.pushInstruction({ op: "local.set", index: vecTmp });
403
+ }
404
+
405
+ // Out of range when len < 4 or unsigned(i) > len - 4 (negative i wraps).
406
+ lenOf();
407
+ this.pushInstruction({ op: "i32.const", value: 4 });
408
+ this.pushInstruction("i32.lt_u");
409
+ this._emitBoundsBranch();
410
+ this.pushInstruction({ op: "local.get", index: idx64 });
411
+ lenOf();
412
+ this.pushInstruction({ op: "i32.const", value: 4 });
413
+ this.pushInstruction("i32.sub");
414
+ this.pushInstruction("i64.extend_i32_u");
415
+ this.pushInstruction("i64.gt_u");
416
+ this._emitBoundsBranch();
417
+
418
+ this.pushInstruction({ op: "local.get", index: sliceTmp });
419
+ this.pushInstruction({ op: "struct.get", typeIndex: sTI, fieldIndex: 1 });
420
+ this.pushInstruction({ op: "local.get", index: idx64 });
421
+ this.pushInstruction("i32.wrap_i64");
422
+ this.pushInstruction("i32.add");
423
+ this.pushInstruction({ op: "local.set", index: baseTmp });
424
+
425
+ const elemAt = (lane) => {
426
+ this.pushInstruction({ op: "local.get", index: sliceTmp });
427
+ this.pushInstruction({ op: "struct.get", typeIndex: sTI, fieldIndex: 0 });
428
+ this.pushInstruction({ op: "local.get", index: baseTmp });
429
+ if (lane) {
430
+ this.pushInstruction({ op: "i32.const", value: lane });
431
+ this.pushInstruction("i32.add");
432
+ }
433
+ };
434
+ if (valNode) {
435
+ for (let lane = 0; lane < 4; lane++) {
436
+ elemAt(lane);
437
+ this.pushInstruction({ op: "local.get", index: vecTmp });
438
+ this.pushInstruction({ op: "f32x4.extract_lane", lane });
439
+ this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
440
+ }
441
+ } else {
442
+ elemAt(0);
443
+ this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
444
+ this.pushInstruction("f32x4.splat");
445
+ for (let lane = 1; lane < 4; lane++) {
446
+ elemAt(lane);
447
+ this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
448
+ this.pushInstruction({ op: "f32x4.replace_lane", lane });
449
+ }
450
+ }
451
+ if (vecTmp !== null) this.releaseTemp(vecTmp, "v128");
452
+ this.releaseTemp(baseTmp, "i32");
453
+ this.releaseTemp(idx64, "i64");
454
+ this.releaseTemp(sliceTmp, sliceWType);
455
+ }
456
+
193
457
  _constIntValue(node) {
194
458
  if (!node) return null;
459
+ if (typeof node._constInt === "number") return node._constInt;
195
460
  if (node.kind === "BasicLit" && node.litKind === "INT") {
196
461
  return Number(node.value);
197
462
  }