gofront 1.6.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/backend/js/expressions.js +238 -109
- package/src/backend/js/index.js +38 -1
- package/src/backend/js/runtime.js +953 -53
- package/src/backend/js/statements.js +55 -67
- 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 +20 -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 +16 -0
- package/src/backend/js/stdlib/io.js +105 -3
- 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/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 +1207 -41
- package/src/backend/wasm/const-fold.js +205 -0
- package/src/backend/wasm/emit-builtins.js +203 -76
- package/src/backend/wasm/emit-exprs.js +464 -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 +115 -87
- package/src/backend/wasm/encode.js +55 -29
- package/src/backend/wasm/index.js +1001 -32
- package/src/backend/wasm/optimize.js +13 -4
- package/src/backend/wasm/stdlib/bytes.js +5039 -0
- package/src/backend/wasm/stdlib/core.js +8903 -0
- package/src/backend/wasm/stdlib/index.js +40 -0
- package/src/backend/wasm/stdlib/io.js +2161 -0
- package/src/backend/wasm/stdlib/packages.js +2400 -0
- package/src/backend/wasm/stdlib/pure.js +720 -0
- package/src/backend/wasm/stdlib/time.js +1200 -0
- package/src/backend/wasm/types.js +153 -1
- package/src/cli-core.js +1 -1
- package/src/compiler.js +18 -4
- package/src/dts-parser.js +79 -126
- package/src/index.js +2 -6
- package/src/lexer.js +80 -29
- package/src/lower/boxing.js +1 -2
- package/src/lower/captures.js +2 -6
- 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/types.js +1 -2
- 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 +81 -13
- package/src/typechecker/expressions.js +102 -2
- package/src/typechecker/resolve.js +36 -6
- package/src/typechecker/stdlib/core.js +280 -89
- package/src/typechecker/stdlib/extended.js +453 -1
- package/src/typechecker/types.js +344 -6
package/src/backend/wasm/emit.js
CHANGED
|
@@ -8,8 +8,15 @@ import { BuiltinsEmitter } from "./emit-builtins.js";
|
|
|
8
8
|
import { ExprsEmitter } from "./emit-exprs.js";
|
|
9
9
|
import { MapsEmitter } from "./emit-maps.js";
|
|
10
10
|
import { SharedEmitter } from "./emit-shared.js";
|
|
11
|
-
import { StdlibEmitter } from "./emit-stdlib.js";
|
|
12
11
|
import { StmtsEmitter } from "./emit-stmts.js";
|
|
12
|
+
import {
|
|
13
|
+
BytesEmitter,
|
|
14
|
+
ExtendedPackagesEmitter,
|
|
15
|
+
IoEmitter,
|
|
16
|
+
PurePackagesEmitter,
|
|
17
|
+
StdlibCoreEmitter,
|
|
18
|
+
TimeEmitter,
|
|
19
|
+
} from "./stdlib/index.js";
|
|
13
20
|
import {
|
|
14
21
|
isArrayType,
|
|
15
22
|
isPointerToStruct,
|
|
@@ -34,7 +41,14 @@ export class FunctionEmitter {
|
|
|
34
41
|
this.mod.lowerResult?.captures?.get(
|
|
35
42
|
this.rootFuncDecl._sourceDecl ?? this.rootFuncDecl,
|
|
36
43
|
) ?? null;
|
|
37
|
-
this.mutatedCaptures = this.captureAnalysis?.mutatedCaptures ??
|
|
44
|
+
this.mutatedCaptures = new Set(this.captureAnalysis?.mutatedCaptures ?? []);
|
|
45
|
+
const lowerBoxed =
|
|
46
|
+
this.mod.lowerResult?.boxedVars?.get(
|
|
47
|
+
this.rootFuncDecl._sourceDecl ?? this.rootFuncDecl,
|
|
48
|
+
) ?? [];
|
|
49
|
+
for (const name of lowerBoxed) {
|
|
50
|
+
this.mutatedCaptures.add(name);
|
|
51
|
+
}
|
|
38
52
|
|
|
39
53
|
this.capturedNames = this.funcDecl._funcLit
|
|
40
54
|
? Array.from(
|
|
@@ -126,33 +140,7 @@ export class FunctionEmitter {
|
|
|
126
140
|
return;
|
|
127
141
|
}
|
|
128
142
|
|
|
129
|
-
|
|
130
|
-
if (namedReturns && namedReturns.length > 0) {
|
|
131
|
-
this.namedReturnVars = [];
|
|
132
|
-
for (let i = 0; i < namedReturns.length; i++) {
|
|
133
|
-
const r = namedReturns[i];
|
|
134
|
-
const isBlank = !r.name || r.name === "_";
|
|
135
|
-
const varName = isBlank ? `__ret_blank$${i}` : r.name;
|
|
136
|
-
const wType = this.toWasmType(r.type);
|
|
137
|
-
const localIdx = this.allocLocal(varName, wType, r.type, isBlank);
|
|
138
|
-
this.namedReturnVars.push({
|
|
139
|
-
name: varName,
|
|
140
|
-
localIdx,
|
|
141
|
-
type: wType,
|
|
142
|
-
goType: r.type,
|
|
143
|
-
isBlank,
|
|
144
|
-
});
|
|
145
|
-
this.emitZeroValue(r.type, wType);
|
|
146
|
-
const localInfo = this.locals.get(varName);
|
|
147
|
-
if (localInfo?.isBoxed) {
|
|
148
|
-
this.pushInstruction({
|
|
149
|
-
op: "struct.new",
|
|
150
|
-
typeIndex: localInfo.boxInfo.typeIndex,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
this.pushInstruction({ op: "local.set", index: localIdx });
|
|
154
|
-
}
|
|
155
|
-
}
|
|
143
|
+
this._initNamedReturns();
|
|
156
144
|
|
|
157
145
|
const needsOobBlock = this._needsOobBlock(body);
|
|
158
146
|
if (needsOobBlock) {
|
|
@@ -181,34 +169,38 @@ export class FunctionEmitter {
|
|
|
181
169
|
}
|
|
182
170
|
}
|
|
183
171
|
|
|
184
|
-
|
|
172
|
+
_initNamedReturns() {
|
|
185
173
|
const namedReturns = this.funcDecl.returnType?._namedReturns;
|
|
186
|
-
if (namedReturns
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
174
|
+
if (!namedReturns?.length) return false;
|
|
175
|
+
this.namedReturnVars = [];
|
|
176
|
+
for (let i = 0; i < namedReturns.length; i++) {
|
|
177
|
+
const r = namedReturns[i];
|
|
178
|
+
const isBlank = !r.name || r.name === "_";
|
|
179
|
+
const varName = isBlank ? `__ret_blank$${i}` : r.name;
|
|
180
|
+
const wType = this.toWasmType(r.type);
|
|
181
|
+
const localIdx = this.allocLocal(varName, wType, r.type, isBlank);
|
|
182
|
+
this.namedReturnVars.push({
|
|
183
|
+
name: varName,
|
|
184
|
+
localIdx,
|
|
185
|
+
type: wType,
|
|
186
|
+
goType: r.type,
|
|
187
|
+
isBlank,
|
|
188
|
+
});
|
|
189
|
+
this.emitZeroValue(r.type, wType);
|
|
190
|
+
const localInfo = this.locals.get(varName);
|
|
191
|
+
if (localInfo?.isBoxed) {
|
|
192
|
+
this.pushInstruction({
|
|
193
|
+
op: "struct.new",
|
|
194
|
+
typeIndex: localInfo.boxInfo.typeIndex,
|
|
200
195
|
});
|
|
201
|
-
this.emitZeroValue(r.type, wType);
|
|
202
|
-
const localInfo = this.locals.get(varName);
|
|
203
|
-
if (localInfo?.isBoxed) {
|
|
204
|
-
this.pushInstruction({
|
|
205
|
-
op: "struct.new",
|
|
206
|
-
typeIndex: localInfo.boxInfo.typeIndex,
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
this.pushInstruction({ op: "local.set", index: localIdx });
|
|
210
196
|
}
|
|
211
|
-
|
|
197
|
+
this.pushInstruction({ op: "local.set", index: localIdx });
|
|
198
|
+
}
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
_emitFunctionBodyWithDefer(body) {
|
|
203
|
+
if (!this._initNamedReturns() && this.returnTypes.length > 0) {
|
|
212
204
|
this.returnTempLocals = [];
|
|
213
205
|
for (let i = 0; i < this.returnTypes.length; i++) {
|
|
214
206
|
const wType = this.returnTypes[i];
|
|
@@ -662,36 +654,27 @@ export class FunctionEmitter {
|
|
|
662
654
|
return null;
|
|
663
655
|
}
|
|
664
656
|
|
|
665
|
-
|
|
657
|
+
_buildEnvFields(capturedNames) {
|
|
666
658
|
const envFields = [];
|
|
667
|
-
for (const name of
|
|
659
|
+
for (const name of capturedNames) {
|
|
668
660
|
const isBoxed = this.mutatedCaptures.has(name);
|
|
669
661
|
const goType = this._findCapturedVarGoType(name);
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
typeIndex: boxInfo.typeIndex,
|
|
681
|
-
},
|
|
682
|
-
});
|
|
683
|
-
} else {
|
|
684
|
-
const wType = this.toWasmType(goType);
|
|
685
|
-
envFields.push({
|
|
686
|
-
name,
|
|
687
|
-
goType,
|
|
688
|
-
isBoxed: false,
|
|
689
|
-
boxInfo: null,
|
|
690
|
-
wType,
|
|
691
|
-
});
|
|
692
|
-
}
|
|
662
|
+
const boxInfo = isBoxed ? this.mod.getBoxType(goType) : null;
|
|
663
|
+
envFields.push({
|
|
664
|
+
name,
|
|
665
|
+
goType,
|
|
666
|
+
isBoxed,
|
|
667
|
+
boxInfo,
|
|
668
|
+
wType: isBoxed
|
|
669
|
+
? { kind: "ref", nullable: true, typeIndex: boxInfo.typeIndex }
|
|
670
|
+
: this.toWasmType(goType),
|
|
671
|
+
});
|
|
693
672
|
}
|
|
673
|
+
return envFields;
|
|
674
|
+
}
|
|
694
675
|
|
|
676
|
+
_unpackClosureEnv() {
|
|
677
|
+
const envFields = this._buildEnvFields(this.capturedNames);
|
|
695
678
|
const envInfo = this.mod.getEnvType(envFields);
|
|
696
679
|
this.envInfo = envInfo;
|
|
697
680
|
this.envFields = envFields;
|
|
@@ -873,6 +856,21 @@ export class FunctionEmitter {
|
|
|
873
856
|
if (this.mod.structTypes.has(t.name))
|
|
874
857
|
return this.mod.structTypes.get(t.name);
|
|
875
858
|
}
|
|
859
|
+
if (t.kind === "struct" || t.kind === "StructType") {
|
|
860
|
+
const rawFields = [];
|
|
861
|
+
if (t.fields instanceof Map) {
|
|
862
|
+
for (const [k, v] of t.fields.entries())
|
|
863
|
+
rawFields.push({ name: k, goType: v });
|
|
864
|
+
} else if (Array.isArray(t.fields)) {
|
|
865
|
+
for (const f of t.fields) {
|
|
866
|
+
const names = f.names ?? (f.name ? [f.name] : []);
|
|
867
|
+
for (const n of names) rawFields.push({ name: n, goType: f.type });
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
if (rawFields.length > 0 && this.mod.getAnonStructType) {
|
|
871
|
+
return this.mod.getAnonStructType(rawFields);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
876
874
|
return null;
|
|
877
875
|
}
|
|
878
876
|
|
|
@@ -930,6 +928,7 @@ export class FunctionEmitter {
|
|
|
930
928
|
return;
|
|
931
929
|
if (
|
|
932
930
|
node.kind === "CompositeLit" ||
|
|
931
|
+
node.kind === "CallExpr" ||
|
|
933
932
|
(node.kind === "UnaryExpr" && node.op === "*")
|
|
934
933
|
)
|
|
935
934
|
return;
|
|
@@ -969,6 +968,10 @@ export class FunctionEmitter {
|
|
|
969
968
|
return this._getReceiverTypeName(loc.goType);
|
|
970
969
|
}
|
|
971
970
|
}
|
|
971
|
+
if (node && node.kind === "SelectorExpr") {
|
|
972
|
+
const pkg = node.expr?.name;
|
|
973
|
+
if (pkg) return `${pkg}.${node.field}`;
|
|
974
|
+
}
|
|
972
975
|
return null;
|
|
973
976
|
}
|
|
974
977
|
|
|
@@ -1082,6 +1085,18 @@ export class FunctionEmitter {
|
|
|
1082
1085
|
return defaultSize;
|
|
1083
1086
|
}
|
|
1084
1087
|
|
|
1088
|
+
_getArrayElemType(t) {
|
|
1089
|
+
if (!t) return null;
|
|
1090
|
+
if (t.elem) return t.elem;
|
|
1091
|
+
if (t.underlying?.elem) return t.underlying.elem;
|
|
1092
|
+
if (t.kind === "ArrayType") return t.elem;
|
|
1093
|
+
if (t.name && this.mod.checker?.types?.has(t.name)) {
|
|
1094
|
+
const resolved = this.mod.checker.types.get(t.name);
|
|
1095
|
+
return this._getArrayElemType(resolved);
|
|
1096
|
+
}
|
|
1097
|
+
return null;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1085
1100
|
emitZeroValue(goType, wType) {
|
|
1086
1101
|
if (wType === "i32") {
|
|
1087
1102
|
this.pushInstruction({ op: "i32.const", value: 0 });
|
|
@@ -1264,13 +1279,7 @@ export class FunctionEmitter {
|
|
|
1264
1279
|
}
|
|
1265
1280
|
|
|
1266
1281
|
resolveBranchDepthToOob() {
|
|
1267
|
-
|
|
1268
|
-
const ctrl = this.controlStack[i];
|
|
1269
|
-
if (ctrl.role === "oob") {
|
|
1270
|
-
return this.controlStack.length - 1 - i;
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
return null;
|
|
1282
|
+
return this.resolveBranchDepthToRole("oob");
|
|
1274
1283
|
}
|
|
1275
1284
|
|
|
1276
1285
|
resolveBranchDepthToRole(targetRole) {
|
|
@@ -1360,11 +1369,25 @@ export class FunctionEmitter {
|
|
|
1360
1369
|
break;
|
|
1361
1370
|
}
|
|
1362
1371
|
}
|
|
1372
|
+
|
|
1373
|
+
_isPkgExpr(expr, pkgName) {
|
|
1374
|
+
if (expr.expr?.kind !== "Ident") return false;
|
|
1375
|
+
const name = expr.expr.name;
|
|
1376
|
+
if (pkgName !== undefined && name !== pkgName) return false;
|
|
1377
|
+
return !this.resolveLocal(name) && !this.mod.resolveGlobal(name);
|
|
1378
|
+
}
|
|
1363
1379
|
}
|
|
1364
1380
|
|
|
1365
1381
|
function copyMethods(target, source) {
|
|
1366
1382
|
const descriptors = Object.getOwnPropertyDescriptors(source.prototype);
|
|
1367
1383
|
delete descriptors.constructor;
|
|
1384
|
+
for (const key of Object.keys(descriptors)) {
|
|
1385
|
+
if (key in target.prototype) {
|
|
1386
|
+
throw new Error(
|
|
1387
|
+
`Duplicate method "${key}" found while mixing ${source.name} into ${target.name}`,
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1368
1391
|
Object.defineProperties(target.prototype, descriptors);
|
|
1369
1392
|
}
|
|
1370
1393
|
|
|
@@ -1372,5 +1395,10 @@ copyMethods(FunctionEmitter, MapsEmitter);
|
|
|
1372
1395
|
copyMethods(FunctionEmitter, StmtsEmitter);
|
|
1373
1396
|
copyMethods(FunctionEmitter, ExprsEmitter);
|
|
1374
1397
|
copyMethods(FunctionEmitter, BuiltinsEmitter);
|
|
1375
|
-
copyMethods(FunctionEmitter,
|
|
1398
|
+
copyMethods(FunctionEmitter, StdlibCoreEmitter);
|
|
1399
|
+
copyMethods(FunctionEmitter, BytesEmitter);
|
|
1400
|
+
copyMethods(FunctionEmitter, PurePackagesEmitter);
|
|
1401
|
+
copyMethods(FunctionEmitter, IoEmitter);
|
|
1402
|
+
copyMethods(FunctionEmitter, TimeEmitter);
|
|
1403
|
+
copyMethods(FunctionEmitter, ExtendedPackagesEmitter);
|
|
1376
1404
|
copyMethods(FunctionEmitter, SharedEmitter);
|
|
@@ -52,20 +52,32 @@ export function encodeI64LEB(val) {
|
|
|
52
52
|
return bytes;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
const _f32Arr = new Float32Array(1);
|
|
56
|
+
const _f32Bytes = new Uint8Array(_f32Arr.buffer);
|
|
55
57
|
export function encodeF32(val) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return Array.from(new Uint8Array(buf));
|
|
58
|
+
_f32Arr[0] = Number(val);
|
|
59
|
+
return [_f32Bytes[0], _f32Bytes[1], _f32Bytes[2], _f32Bytes[3]];
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
const _f64Arr = new Float64Array(1);
|
|
63
|
+
const _f64Bytes = new Uint8Array(_f64Arr.buffer);
|
|
61
64
|
export function encodeF64(val) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
_f64Arr[0] = Number(val);
|
|
66
|
+
return [
|
|
67
|
+
_f64Bytes[0],
|
|
68
|
+
_f64Bytes[1],
|
|
69
|
+
_f64Bytes[2],
|
|
70
|
+
_f64Bytes[3],
|
|
71
|
+
_f64Bytes[4],
|
|
72
|
+
_f64Bytes[5],
|
|
73
|
+
_f64Bytes[6],
|
|
74
|
+
_f64Bytes[7],
|
|
75
|
+
];
|
|
65
76
|
}
|
|
66
77
|
|
|
78
|
+
const _textEncoder = new TextEncoder();
|
|
67
79
|
function encodeString(str) {
|
|
68
|
-
const utf8 =
|
|
80
|
+
const utf8 = _textEncoder.encode(str);
|
|
69
81
|
return [...encodeU32LEB(utf8.length), ...utf8];
|
|
70
82
|
}
|
|
71
83
|
|
|
@@ -907,31 +919,45 @@ export function encodeModule(mod) {
|
|
|
907
919
|
const sectionOffsets = [];
|
|
908
920
|
const codeSec = encodeCodeSection(mod.funcs, sectionOffsets);
|
|
909
921
|
|
|
910
|
-
const
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
922
|
+
const sections = [
|
|
923
|
+
magic,
|
|
924
|
+
version,
|
|
925
|
+
GOFRONT_SECTION_BYTES,
|
|
926
|
+
typeSec,
|
|
927
|
+
importSec,
|
|
928
|
+
funcSec,
|
|
929
|
+
memorySec,
|
|
930
|
+
tagSec,
|
|
931
|
+
globalSec,
|
|
932
|
+
exportSec,
|
|
933
|
+
startSec,
|
|
934
|
+
elemSec,
|
|
923
935
|
];
|
|
924
|
-
|
|
936
|
+
let totalLen = 0;
|
|
937
|
+
for (const s of sections) totalLen += s.length;
|
|
938
|
+
const codeStart = totalLen;
|
|
925
939
|
mod.codeOffsets = sectionOffsets.map((o) => codeStart + o);
|
|
926
|
-
|
|
940
|
+
totalLen += codeSec.length;
|
|
941
|
+
let smSec = null;
|
|
927
942
|
if (mod.sourceMappingURL) {
|
|
928
|
-
|
|
929
|
-
...
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
943
|
+
smSec = encodeSection(0, [
|
|
944
|
+
...encodeString("sourceMappingURL"),
|
|
945
|
+
...encodeString(mod.sourceMappingURL),
|
|
946
|
+
]);
|
|
947
|
+
totalLen += smSec.length;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
const out = new Uint8Array(totalLen);
|
|
951
|
+
let offset = 0;
|
|
952
|
+
for (const s of sections) {
|
|
953
|
+
out.set(s, offset);
|
|
954
|
+
offset += s.length;
|
|
955
|
+
}
|
|
956
|
+
out.set(codeSec, offset);
|
|
957
|
+
offset += codeSec.length;
|
|
958
|
+
if (smSec) {
|
|
959
|
+
out.set(smSec, offset);
|
|
934
960
|
}
|
|
935
961
|
|
|
936
|
-
return
|
|
962
|
+
return out;
|
|
937
963
|
}
|