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
|
@@ -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
|
+
}
|