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.
Files changed (80) hide show
  1. package/README.md +35 -39
  2. package/package.json +37 -4
  3. package/src/backend/js/expressions.js +559 -144
  4. package/src/backend/js/index.js +174 -49
  5. package/src/backend/js/runtime.js +1518 -54
  6. package/src/backend/js/statements.js +91 -73
  7. package/src/backend/js/stdlib/base64.js +12 -0
  8. package/src/backend/js/stdlib/binary.js +102 -0
  9. package/src/backend/js/stdlib/bits.js +15 -1
  10. package/src/backend/js/stdlib/builder.js +28 -9
  11. package/src/backend/js/stdlib/bytes.js +75 -18
  12. package/src/backend/js/stdlib/errors.js +25 -1
  13. package/src/backend/js/stdlib/fmt.js +70 -13
  14. package/src/backend/js/stdlib/hex.js +17 -0
  15. package/src/backend/js/stdlib/html.js +1 -1
  16. package/src/backend/js/stdlib/index.js +28 -0
  17. package/src/backend/js/stdlib/io.js +105 -3
  18. package/src/backend/js/stdlib/json.js +972 -0
  19. package/src/backend/js/stdlib/math.js +13 -1
  20. package/src/backend/js/stdlib/path.js +18 -4
  21. package/src/backend/js/stdlib/rand.js +10 -5
  22. package/src/backend/js/stdlib/sha256.js +12 -0
  23. package/src/backend/js/stdlib/simd.js +24 -0
  24. package/src/backend/js/stdlib/slices.js +52 -26
  25. package/src/backend/js/stdlib/strconv.js +21 -5
  26. package/src/backend/js/stdlib/strings.js +148 -15
  27. package/src/backend/js/stdlib/sync.js +13 -0
  28. package/src/backend/js/stdlib/time.js +90 -19
  29. package/src/backend/js/stdlib/unicode.js +2 -2
  30. package/src/backend/wasm/boundary.js +1225 -41
  31. package/src/backend/wasm/const-fold.js +205 -0
  32. package/src/backend/wasm/emit-builtins.js +220 -76
  33. package/src/backend/wasm/emit-exprs.js +475 -276
  34. package/src/backend/wasm/emit-maps.js +144 -8
  35. package/src/backend/wasm/emit-stdlib.js +12 -3005
  36. package/src/backend/wasm/emit-stmts.js +264 -270
  37. package/src/backend/wasm/emit.js +124 -87
  38. package/src/backend/wasm/encode.js +140 -29
  39. package/src/backend/wasm/index.js +1001 -32
  40. package/src/backend/wasm/optimize.js +17 -6
  41. package/src/backend/wasm/stdlib/bytes.js +5039 -0
  42. package/src/backend/wasm/stdlib/core.js +8903 -0
  43. package/src/backend/wasm/stdlib/index.js +43 -0
  44. package/src/backend/wasm/stdlib/io.js +2161 -0
  45. package/src/backend/wasm/stdlib/packages.js +2400 -0
  46. package/src/backend/wasm/stdlib/pure.js +720 -0
  47. package/src/backend/wasm/stdlib/simd.js +234 -0
  48. package/src/backend/wasm/stdlib/time.js +1200 -0
  49. package/src/backend/wasm/types.js +174 -1
  50. package/src/backend/wasm/wat.js +37 -0
  51. package/src/cli-core.js +1 -1
  52. package/src/compiler.js +18 -4
  53. package/src/dts-parser.js +150 -140
  54. package/src/index.js +2 -6
  55. package/src/lexer.js +80 -29
  56. package/src/lower/boxing.js +1 -7
  57. package/src/lower/captures.js +2 -6
  58. package/src/lower/embedding.js +2 -1
  59. package/src/lower/ownership.js +30 -9
  60. package/src/minifier.js +20 -68
  61. package/src/parser/declarations.js +3 -6
  62. package/src/parser/expressions.js +3 -8
  63. package/src/parser/index.js +18 -3
  64. package/src/parser/statements.js +25 -38
  65. package/src/parser/struct-tag.js +144 -0
  66. package/src/parser/types.js +64 -8
  67. package/src/resolver.js +2 -27
  68. package/src/templ-lexer.js +29 -63
  69. package/src/templ-parser.js +22 -45
  70. package/src/typechecker/assignability.js +126 -13
  71. package/src/typechecker/expressions.js +168 -16
  72. package/src/typechecker/index.js +35 -8
  73. package/src/typechecker/resolve.js +187 -8
  74. package/src/typechecker/statements.js +68 -9
  75. package/src/typechecker/stdlib/core.js +280 -89
  76. package/src/typechecker/stdlib/extended.js +490 -1
  77. package/src/typechecker/stdlib/simd.js +73 -0
  78. package/src/typechecker/stdlib.js +2 -0
  79. package/src/typechecker/types.js +362 -9
  80. package/src/vendor.js +86 -11
@@ -0,0 +1,234 @@
1
+ // src/backend/wasm/stdlib/simd.js
2
+ // FunctionEmitter mixin: gofront/simd (F32x4 vector math, load/store, composite literals).
3
+
4
+ const SIMD_BINARY_OPS = {
5
+ Add: "f32x4.add",
6
+ Sub: "f32x4.sub",
7
+ Mul: "f32x4.mul",
8
+ Div: "f32x4.div",
9
+ Min: "f32x4.min",
10
+ Max: "f32x4.max",
11
+ };
12
+
13
+ export class SimdEmitter {
14
+ emitSimdCompositeLit(lit) {
15
+ const elems = lit.elems ?? [];
16
+ if (elems.length === 0) {
17
+ this.pushInstruction({ op: "v128.const", bytes: new Array(16).fill(0) });
18
+ return;
19
+ }
20
+
21
+ const constVals = elems.map((e) => this._getConstFloatValue(e));
22
+ const allConst = constVals.every((v) => v !== null);
23
+
24
+ if (allConst) {
25
+ const vals = [0, 0, 0, 0];
26
+ for (let i = 0; i < Math.min(elems.length, 4); i++) {
27
+ vals[i] = constVals[i];
28
+ }
29
+ this.pushInstruction({ op: "v128.const", values: vals });
30
+ return;
31
+ }
32
+
33
+ // Runtime elements: splat lane 0, replace lanes 1, 2, 3
34
+ this.emitExpr(elems[0], "f32");
35
+ this.pushInstruction("f32x4.splat");
36
+ for (let i = 1; i < 4; i++) {
37
+ if (elems[i]) {
38
+ this.emitExpr(elems[i], "f32");
39
+ } else {
40
+ this.pushInstruction({ op: "f32.const", value: 0.0 });
41
+ }
42
+ this.pushInstruction({ op: "f32x4.replace_lane", lane: i });
43
+ }
44
+ }
45
+
46
+ _emitSimdDot(recvExpr, otherExpr, count) {
47
+ this.emitExpr(recvExpr, "v128");
48
+ this.emitExpr(otherExpr, "v128");
49
+ this.pushInstruction("f32x4.mul");
50
+ const tmp = this.acquireTemp("v128");
51
+ this.pushInstruction({ op: "local.set", index: tmp });
52
+ this.pushInstruction({ op: "local.get", index: tmp });
53
+ this.pushInstruction({ op: "f32x4.extract_lane", lane: 0 });
54
+ for (let i = 1; i < count; i++) {
55
+ this.pushInstruction({ op: "local.get", index: tmp });
56
+ this.pushInstruction({ op: "f32x4.extract_lane", lane: i });
57
+ this.pushInstruction("f32.add");
58
+ }
59
+ this.releaseTemp(tmp, "v128");
60
+ }
61
+
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;
79
+ }
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;
86
+ }
87
+ if (method === "Splat") {
88
+ this.emitExpr(args[0], "f32");
89
+ this.pushInstruction("f32x4.splat");
90
+ return true;
91
+ }
92
+ return false;
93
+ }
94
+
95
+ emitSimdPackageCall(fn, args, _targetWasmType) {
96
+ switch (fn) {
97
+ case "Splat":
98
+ this.emitExpr(args[0], "f32");
99
+ this.pushInstruction("f32x4.splat");
100
+ return true;
101
+ case "NewF32x4":
102
+ this.emitExpr(args[0], "f32");
103
+ this.pushInstruction("f32x4.splat");
104
+ this.emitExpr(args[1], "f32");
105
+ this.pushInstruction({ op: "f32x4.replace_lane", lane: 1 });
106
+ this.emitExpr(args[2], "f32");
107
+ this.pushInstruction({ op: "f32x4.replace_lane", lane: 2 });
108
+ this.emitExpr(args[3], "f32");
109
+ this.pushInstruction({ op: "f32x4.replace_lane", lane: 3 });
110
+ return true;
111
+ case "LoadF32x4":
112
+ this.emitSimdLoad(args[0], args[1]);
113
+ return true;
114
+ case "StoreF32x4":
115
+ this.emitSimdStore(args[0], args[1], args[2]);
116
+ return true;
117
+ default:
118
+ return false;
119
+ }
120
+ }
121
+
122
+ _emitSharedFloat32Address(bufNode, indexNode) {
123
+ const { wType, typeIndex } = this.mod.getSharedType();
124
+ const bufTmp = this.acquireTemp(wType);
125
+ const iTmp = this.acquireTemp("i32");
126
+
127
+ this.emitExpr(bufNode, wType);
128
+ this.pushInstruction({ op: "local.set", index: bufTmp });
129
+
130
+ // Bounds check 1: if unsigned(len) < 4 branch to OOB
131
+ this.pushInstruction({ op: "local.get", index: bufTmp });
132
+ this.pushInstruction({ op: "struct.get", typeIndex, fieldIndex: 1 });
133
+ this.pushInstruction({ op: "i32.const", value: 4 });
134
+ this.pushInstruction("i32.lt_u");
135
+ this._emitBoundsBranch();
136
+
137
+ if (this._isI32IndexExpr(indexNode)) {
138
+ this.emitExpr(indexNode, "i32");
139
+ this.pushInstruction({ op: "local.set", index: iTmp });
140
+
141
+ // Bounds check: if unsigned(i) > len - 4 branch to OOB
142
+ this.pushInstruction({ op: "local.get", index: iTmp });
143
+ this.pushInstruction({ op: "local.get", index: bufTmp });
144
+ this.pushInstruction({ op: "struct.get", typeIndex, fieldIndex: 1 });
145
+ this.pushInstruction({ op: "i32.const", value: 4 });
146
+ this.pushInstruction("i32.sub");
147
+ this.pushInstruction("i32.gt_u");
148
+ this._emitBoundsBranch();
149
+ } else {
150
+ const idx64 = this.acquireTemp("i64");
151
+ this.emitExpr(indexNode, "i64");
152
+ this.pushInstruction({ op: "local.set", index: idx64 });
153
+
154
+ // Bounds check in 64-bit: if unsigned(idx64) > unsigned(len - 4) branch to OOB
155
+ this.pushInstruction({ op: "local.get", index: idx64 });
156
+ this.pushInstruction({ op: "local.get", index: bufTmp });
157
+ this.pushInstruction({ op: "struct.get", typeIndex, fieldIndex: 1 });
158
+ this.pushInstruction({ op: "i32.const", value: 4 });
159
+ this.pushInstruction("i32.sub");
160
+ this.pushInstruction("i64.extend_i32_u");
161
+ this.pushInstruction("i64.gt_u");
162
+ this._emitBoundsBranch();
163
+
164
+ this.pushInstruction({ op: "local.get", index: idx64 });
165
+ this.pushInstruction("i32.wrap_i64");
166
+ this.pushInstruction({ op: "local.set", index: iTmp });
167
+ this.releaseTemp(idx64, "i64");
168
+ }
169
+
170
+ // Address: buf.base + (i << 2)
171
+ this.pushInstruction({ op: "local.get", index: bufTmp });
172
+ this.pushInstruction({ op: "struct.get", typeIndex, fieldIndex: 0 });
173
+ this.pushInstruction({ op: "local.get", index: iTmp });
174
+ this.pushInstruction({ op: "i32.const", value: 2 });
175
+ this.pushInstruction("i32.shl");
176
+ this.pushInstruction("i32.add");
177
+
178
+ this.releaseTemp(bufTmp, wType);
179
+ this.releaseTemp(iTmp, "i32");
180
+ }
181
+
182
+ emitSimdLoad(bufNode, indexNode) {
183
+ this._emitSharedFloat32Address(bufNode, indexNode);
184
+ this.pushInstruction({ op: "v128.load", align: 2, offset: 0 });
185
+ }
186
+
187
+ emitSimdStore(bufNode, indexNode, valNode) {
188
+ this._emitSharedFloat32Address(bufNode, indexNode);
189
+ this.emitExpr(valNode, "v128");
190
+ this.pushInstruction({ op: "v128.store", align: 2, offset: 0 });
191
+ }
192
+
193
+ _constIntValue(node) {
194
+ if (!node) return null;
195
+ if (node.kind === "BasicLit" && node.litKind === "INT") {
196
+ return Number(node.value);
197
+ }
198
+ if (node.kind === "Ident") {
199
+ const c = this.mod?.resolveConst?.(node.name);
200
+ if (c && c.kind === "BasicLit") {
201
+ return Number(c.value);
202
+ }
203
+ }
204
+ if (node.kind === "ParenExpr") {
205
+ return this._constIntValue(node.expr);
206
+ }
207
+ if (node.kind === "UnaryExpr" && node.op === "+") {
208
+ return this._constIntValue(node.operand);
209
+ }
210
+ return null;
211
+ }
212
+
213
+ _getConstFloatValue(e) {
214
+ if (!e) return null;
215
+ if (
216
+ e.kind === "BasicLit" &&
217
+ (e.litKind === "FLOAT" || e.litKind === "INT")
218
+ ) {
219
+ return Number(e.value);
220
+ }
221
+ if (e.kind === "UnaryExpr" && (e.op === "-" || e.op === "+")) {
222
+ const v = this._getConstFloatValue(e.operand);
223
+ return v !== null ? (e.op === "-" ? -v : v) : null;
224
+ }
225
+ if (e.kind === "Ident") {
226
+ const c = this.mod?.resolveConst?.(e.name);
227
+ if (c) return this._getConstFloatValue(c);
228
+ }
229
+ if (e.kind === "ParenExpr") {
230
+ return this._getConstFloatValue(e.expr);
231
+ }
232
+ return null;
233
+ }
234
+ }