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/package.json
CHANGED
|
@@ -40,6 +40,23 @@ const STRICT_OPS = new Set([
|
|
|
40
40
|
">>",
|
|
41
41
|
]);
|
|
42
42
|
|
|
43
|
+
const NAMED_ZERO_TABLE = {
|
|
44
|
+
"time.Time": [null, "{ _d: new Date(0), _isZero: true }"],
|
|
45
|
+
"strings.Builder": [null, '{ _buf: "" }'],
|
|
46
|
+
"bytes.Buffer": [null, "{ _buf: [] }"],
|
|
47
|
+
"strings.Replacer": [null, "{ _p: [], Replace(s) { return s; } }"],
|
|
48
|
+
"sync.Mutex": ["sync", "__sync_mutex()"],
|
|
49
|
+
"sync.RWMutex": ["sync", "__sync_rwmutex()"],
|
|
50
|
+
"sync.Once": ["sync", "__sync_once()"],
|
|
51
|
+
"sync.WaitGroup": ["sync", "__sync_waitgroup()"],
|
|
52
|
+
"binary.LittleEndian": ["binary", "__binary_le"],
|
|
53
|
+
"encoding/binary.LittleEndian": ["binary", "__binary_le"],
|
|
54
|
+
"binary.BigEndian": ["binary", "__binary_be"],
|
|
55
|
+
"encoding/binary.BigEndian": ["binary", "__binary_be"],
|
|
56
|
+
"base64.Encoding": ["base64", "__base64_std"],
|
|
57
|
+
"encoding/base64.Encoding": ["base64", "__base64_std"],
|
|
58
|
+
};
|
|
59
|
+
|
|
43
60
|
// Splits a generated JS lvalue at its outermost trailing access:
|
|
44
61
|
// `a.b[i]` → { obj: "a.b", key: "i" }, `a.b.c` → { obj: "a.b", prop: "c" }.
|
|
45
62
|
function splitLastAccess(js) {
|
|
@@ -78,18 +95,76 @@ const NS_CONSTANTS = {
|
|
|
78
95
|
math: {
|
|
79
96
|
Pi: "Math.PI",
|
|
80
97
|
E: "Math.E",
|
|
98
|
+
Phi: "1.618033988749895",
|
|
99
|
+
Sqrt2: "Math.SQRT2",
|
|
100
|
+
SqrtE: "1.6487212707001282",
|
|
101
|
+
SqrtPi: "1.7724538509055159",
|
|
102
|
+
SqrtPhi: "1.272019649514069",
|
|
103
|
+
Ln2: "Math.LN2",
|
|
104
|
+
Log2E: "Math.LOG2E",
|
|
105
|
+
Ln10: "Math.LN10",
|
|
106
|
+
Log10E: "Math.LOG10E",
|
|
107
|
+
MaxFloat32: "3.4028234663852886e38",
|
|
108
|
+
SmallestNonzeroFloat32: "1.401298464324817e-45",
|
|
81
109
|
MaxFloat64: "Number.MAX_VALUE",
|
|
82
110
|
SmallestNonzeroFloat64: "Number.MIN_VALUE",
|
|
83
111
|
MaxInt: "Number.MAX_SAFE_INTEGER",
|
|
84
112
|
MinInt: "Number.MIN_SAFE_INTEGER",
|
|
113
|
+
MaxInt8: "127",
|
|
114
|
+
MinInt8: "-128",
|
|
115
|
+
MaxInt16: "32767",
|
|
116
|
+
MinInt16: "-32768",
|
|
117
|
+
MaxInt32: "2147483647",
|
|
118
|
+
MinInt32: "-2147483648",
|
|
119
|
+
MaxInt64: "9223372036854775807",
|
|
120
|
+
MinInt64: "-9223372036854775808",
|
|
121
|
+
MaxUint8: "255",
|
|
122
|
+
MaxUint16: "65535",
|
|
123
|
+
MaxUint32: "4294967295",
|
|
124
|
+
MaxUint: "18446744073709551615",
|
|
125
|
+
MaxUint64: "18446744073709551615",
|
|
126
|
+
},
|
|
127
|
+
strconv: {
|
|
128
|
+
ErrSyntax: "__strconv_err_syntax",
|
|
129
|
+
ErrRange: "__strconv_err_range",
|
|
130
|
+
},
|
|
131
|
+
path: {
|
|
132
|
+
ErrBadPattern: "__path_err_bad_pattern",
|
|
133
|
+
},
|
|
134
|
+
filepath: {
|
|
135
|
+
ErrBadPattern: "__path_err_bad_pattern",
|
|
85
136
|
},
|
|
86
137
|
io: {
|
|
87
|
-
EOF:
|
|
138
|
+
EOF: "__io_eof",
|
|
88
139
|
Discard:
|
|
89
|
-
"{ WriteString(s) { return s.length; }, Write(b) { return b.length; } }",
|
|
140
|
+
"{ WriteString(s) { return [s.length, null]; }, Write(b) { return [b.length, null]; } }",
|
|
141
|
+
},
|
|
142
|
+
sha256: {
|
|
143
|
+
Size: "32",
|
|
144
|
+
BlockSize: "64",
|
|
145
|
+
},
|
|
146
|
+
hex: {
|
|
147
|
+
ErrLength: '__error("encoding/hex: odd length hex string")',
|
|
148
|
+
},
|
|
149
|
+
base64: {
|
|
150
|
+
StdPadding: "61",
|
|
151
|
+
NoPadding: "-1",
|
|
152
|
+
StdEncoding: "__base64_std",
|
|
153
|
+
URLEncoding: "__base64_url",
|
|
154
|
+
RawStdEncoding: "__base64_raw_std",
|
|
155
|
+
RawURLEncoding: "__base64_raw_url",
|
|
156
|
+
},
|
|
157
|
+
binary: {
|
|
158
|
+
LittleEndian: "__binary_le",
|
|
159
|
+
BigEndian: "__binary_be",
|
|
160
|
+
},
|
|
161
|
+
rand: {
|
|
162
|
+
Reader: "__crypto_rand_reader",
|
|
90
163
|
},
|
|
91
164
|
os: { Args: "process.argv" },
|
|
92
165
|
time: {
|
|
166
|
+
Nanosecond: "1",
|
|
167
|
+
Microsecond: "1000",
|
|
93
168
|
Millisecond: "1000000",
|
|
94
169
|
Second: "1000000000",
|
|
95
170
|
Minute: "60000000000",
|
|
@@ -278,8 +353,22 @@ export const expressionGenMethods = {
|
|
|
278
353
|
expr._ifaceBoxing = true;
|
|
279
354
|
try {
|
|
280
355
|
this.useHelper("ifaceBox");
|
|
281
|
-
const fn =
|
|
282
|
-
|
|
356
|
+
const fn =
|
|
357
|
+
expr._ifaceBox === "ptr"
|
|
358
|
+
? "__ifp"
|
|
359
|
+
: expr._ifaceBox === "ptr_slice"
|
|
360
|
+
? "__ifps"
|
|
361
|
+
: expr._ifaceBox === "ptr_map"
|
|
362
|
+
? "__ifpm"
|
|
363
|
+
: expr._ifaceBox === "map"
|
|
364
|
+
? "__ifm"
|
|
365
|
+
: expr._ifaceBox === "slice"
|
|
366
|
+
? "__ifs"
|
|
367
|
+
: "__ifv";
|
|
368
|
+
const extra = expr._ifacePtrFields?.length
|
|
369
|
+
? `, ${JSON.stringify(expr._ifacePtrFields)}`
|
|
370
|
+
: "";
|
|
371
|
+
return `${fn}(${this.genExpr(expr)}${extra})`;
|
|
283
372
|
} finally {
|
|
284
373
|
expr._ifaceBoxing = false;
|
|
285
374
|
}
|
|
@@ -500,6 +589,13 @@ export const expressionGenMethods = {
|
|
|
500
589
|
) {
|
|
501
590
|
return this.genExpr(expr.operand);
|
|
502
591
|
}
|
|
592
|
+
if (
|
|
593
|
+
expr.operand.kind === "SelectorExpr" ||
|
|
594
|
+
expr.operand.kind === "IndexExpr"
|
|
595
|
+
) {
|
|
596
|
+
const inner = this.genExpr(expr.operand);
|
|
597
|
+
return `{ get value() { return ${inner}; }, set value(v) { ${inner} = v; } }`;
|
|
598
|
+
}
|
|
503
599
|
// For non-boxed vars (primitives, etc.), wrap in { value: x }
|
|
504
600
|
return `{ value: ${this.genExpr(expr.operand)} }`;
|
|
505
601
|
}
|
|
@@ -529,7 +625,27 @@ export const expressionGenMethods = {
|
|
|
529
625
|
}
|
|
530
626
|
if (expr.expr.kind === "Ident") {
|
|
531
627
|
const nsConst = NS_CONSTANTS[expr.expr.name]?.[expr.field];
|
|
532
|
-
if (nsConst !== undefined)
|
|
628
|
+
if (nsConst !== undefined) {
|
|
629
|
+
if (expr.expr.name === "strconv") {
|
|
630
|
+
this.useHelper("strconvError");
|
|
631
|
+
} else if (expr.expr.name === "path" || expr.expr.name === "filepath") {
|
|
632
|
+
if (expr.field === "ErrBadPattern") this.useHelper("pathError");
|
|
633
|
+
} else if (expr.expr.name === "io" && expr.field === "EOF") {
|
|
634
|
+
this.useHelper("ioEOF");
|
|
635
|
+
} else if (expr.expr.name === "binary") {
|
|
636
|
+
this.useHelper("binary");
|
|
637
|
+
} else if (expr.expr.name === "hex") {
|
|
638
|
+
this.useHelper("hex");
|
|
639
|
+
this.useHelper("error");
|
|
640
|
+
} else if (expr.expr.name === "base64") {
|
|
641
|
+
this.useHelper("base64");
|
|
642
|
+
} else if (expr.expr.name === "rand" && expr.field === "Reader") {
|
|
643
|
+
this.useHelper("cryptoRand");
|
|
644
|
+
} else if (expr.expr.name === "sha256") {
|
|
645
|
+
this.useHelper("sha256");
|
|
646
|
+
}
|
|
647
|
+
return nsConst;
|
|
648
|
+
}
|
|
533
649
|
}
|
|
534
650
|
const base = this.genExpr(expr.expr);
|
|
535
651
|
if (this.bundledPackages.has(base)) return expr.field;
|
|
@@ -705,12 +821,61 @@ export const expressionGenMethods = {
|
|
|
705
821
|
return this._genRegexpMethodCall(expr.func.field, expr);
|
|
706
822
|
if (recvName === "time.Time")
|
|
707
823
|
return this._genTimeMethodCall(expr.func.field, expr);
|
|
824
|
+
if (recvName === "time.Duration")
|
|
825
|
+
return this._genDurationMethodCall(expr.func.field, expr);
|
|
708
826
|
if (recvName === "testing.T")
|
|
709
827
|
return this._genTestingMethodCall(expr.func.field, expr);
|
|
828
|
+
if (recvName === "strings.Replacer") {
|
|
829
|
+
const recv = this.genExpr(expr.func.expr);
|
|
830
|
+
const arg = this.genExpr(expr.args[0]);
|
|
831
|
+
return `(${recv} ? ${recv}.Replace(${arg}) : ${arg})`;
|
|
832
|
+
}
|
|
710
833
|
if (recvName?.startsWith("shared.") && expr.func.field === "Subarray") {
|
|
711
834
|
const args = expr.args.map((a) => this.genExpr(a)).join(", ");
|
|
712
835
|
return `${this.genExpr(expr.func.expr)}.subarray(${args})`;
|
|
713
836
|
}
|
|
837
|
+
if (recvName === "sync.Mutex" || recvName === "sync.RWMutex") {
|
|
838
|
+
if (expr.func.field === "TryLock" || expr.func.field === "TryRLock")
|
|
839
|
+
return "true";
|
|
840
|
+
return "(void 0)";
|
|
841
|
+
}
|
|
842
|
+
if (recvName === "sync.Once" && expr.func.field === "Do") {
|
|
843
|
+
const recv = this.genExpr(expr.func.expr);
|
|
844
|
+
const f = this.genExpr(expr.args[0]);
|
|
845
|
+
return `((o, fn) => { if (!o.done) { o.done = 1; fn(); } })(${recv}, ${f})`;
|
|
846
|
+
}
|
|
847
|
+
if (recvName === "sync.WaitGroup") {
|
|
848
|
+
const recv = this.genExpr(expr.func.expr);
|
|
849
|
+
if (expr.func.field === "Add") {
|
|
850
|
+
return `((wg, d) => { wg.counter = (wg.counter || 0) + d; })(${recv}, ${this.genExpr(expr.args[0])})`;
|
|
851
|
+
}
|
|
852
|
+
if (expr.func.field === "Done") {
|
|
853
|
+
return `((wg) => { wg.counter = (wg.counter || 0) - 1; })(${recv})`;
|
|
854
|
+
}
|
|
855
|
+
if (expr.func.field === "Wait") return "(void 0)";
|
|
856
|
+
}
|
|
857
|
+
if (
|
|
858
|
+
recvName === "binary.LittleEndian" ||
|
|
859
|
+
recvName === "binary.BigEndian" ||
|
|
860
|
+
recvName === "encoding/binary.LittleEndian" ||
|
|
861
|
+
recvName === "encoding/binary.BigEndian" ||
|
|
862
|
+
recvName === "binary.ByteOrder" ||
|
|
863
|
+
recvName === "encoding/binary.ByteOrder"
|
|
864
|
+
) {
|
|
865
|
+
this.useHelper("binary");
|
|
866
|
+
const recv = this.genExpr(expr.func.expr);
|
|
867
|
+
const args = expr.args.map((a) => this.genExpr(a)).join(", ");
|
|
868
|
+
return `${recv}.${expr.func.field}(${args})`;
|
|
869
|
+
}
|
|
870
|
+
if (
|
|
871
|
+
recvName === "base64.Encoding" ||
|
|
872
|
+
recvName === "encoding/base64.Encoding"
|
|
873
|
+
) {
|
|
874
|
+
this.useHelper("base64");
|
|
875
|
+
const recv = this.genExpr(expr.func.expr);
|
|
876
|
+
const args = expr.args.map((a) => this.genExpr(a)).join(", ");
|
|
877
|
+
return `${recv}.${expr.func.field}(${args})`;
|
|
878
|
+
}
|
|
714
879
|
return undefined;
|
|
715
880
|
},
|
|
716
881
|
|
|
@@ -981,10 +1146,38 @@ export const expressionGenMethods = {
|
|
|
981
1146
|
return `new ${typeName}(${args.join(", ")})`;
|
|
982
1147
|
},
|
|
983
1148
|
|
|
1149
|
+
_genSliceOrArrayLit(t, expr) {
|
|
1150
|
+
const elems = expr.elems
|
|
1151
|
+
.map((e) => this.genValueExpr(e.kind === "KeyValueExpr" ? e.value : e))
|
|
1152
|
+
.join(", ");
|
|
1153
|
+
const elemNode =
|
|
1154
|
+
t.kind === "SliceType" || t.kind === "ArrayType" ? t.elem : null;
|
|
1155
|
+
const elemResolved =
|
|
1156
|
+
expr._type?.kind === "slice" || expr._type?.kind === "array"
|
|
1157
|
+
? expr._type.elem
|
|
1158
|
+
: null;
|
|
1159
|
+
const typedCtor =
|
|
1160
|
+
typedArrayConstructorForElem(elemResolved) ??
|
|
1161
|
+
(elemNode?.name
|
|
1162
|
+
? typedArrayConstructorForElem({
|
|
1163
|
+
kind: "basic",
|
|
1164
|
+
name: elemNode.name,
|
|
1165
|
+
})
|
|
1166
|
+
: null);
|
|
1167
|
+
if (typedCtor) {
|
|
1168
|
+
return `new ${typedCtor}([${elems}])`;
|
|
1169
|
+
}
|
|
1170
|
+
return `[${elems}]`;
|
|
1171
|
+
},
|
|
1172
|
+
|
|
984
1173
|
genCompositeLit(expr) {
|
|
985
1174
|
const t = expr.typeExpr;
|
|
986
1175
|
if (t === null) return this._genImplicitCompositeLit(expr);
|
|
987
1176
|
const typeName = this.getTypeName(t);
|
|
1177
|
+
if (typeName === "bytes.Buffer" || typeName === "Buffer")
|
|
1178
|
+
return "{ _buf: [] }";
|
|
1179
|
+
if (typeName === "strings.Builder" || typeName === "Builder")
|
|
1180
|
+
return '{ _buf: "" }';
|
|
988
1181
|
if (typeName && this.structNames.has(typeName))
|
|
989
1182
|
return this._genPositionalStructLit(typeName, expr);
|
|
990
1183
|
if (typeName && this.namedWrapperNames.has(typeName))
|
|
@@ -992,29 +1185,7 @@ export const expressionGenMethods = {
|
|
|
992
1185
|
if (expr.elems.some((e) => e._positionalField)) {
|
|
993
1186
|
if (typeName) return this._genPositionalStructLit(typeName, expr);
|
|
994
1187
|
}
|
|
995
|
-
if (this._isSliceOrArrayType(t))
|
|
996
|
-
const elems = expr.elems
|
|
997
|
-
.map((e) => this.genValueExpr(e.kind === "KeyValueExpr" ? e.value : e))
|
|
998
|
-
.join(", ");
|
|
999
|
-
const elemNode =
|
|
1000
|
-
t.kind === "SliceType" || t.kind === "ArrayType" ? t.elem : null;
|
|
1001
|
-
const elemResolved =
|
|
1002
|
-
expr._type?.kind === "slice" || expr._type?.kind === "array"
|
|
1003
|
-
? expr._type.elem
|
|
1004
|
-
: null;
|
|
1005
|
-
const typedCtor =
|
|
1006
|
-
typedArrayConstructorForElem(elemResolved) ??
|
|
1007
|
-
(elemNode?.name
|
|
1008
|
-
? typedArrayConstructorForElem({
|
|
1009
|
-
kind: "basic",
|
|
1010
|
-
name: elemNode.name,
|
|
1011
|
-
})
|
|
1012
|
-
: null);
|
|
1013
|
-
if (typedCtor) {
|
|
1014
|
-
return `new ${typedCtor}([${elems}])`;
|
|
1015
|
-
}
|
|
1016
|
-
return `[${elems}]`;
|
|
1017
|
-
}
|
|
1188
|
+
if (this._isSliceOrArrayType(t)) return this._genSliceOrArrayLit(t, expr);
|
|
1018
1189
|
if (this._isMapTypeNode(t))
|
|
1019
1190
|
return `{ ${this._genMapLitEntries(expr.elems)} }`;
|
|
1020
1191
|
return this._genFallbackCompositeLit(expr);
|
|
@@ -1049,19 +1220,7 @@ export const expressionGenMethods = {
|
|
|
1049
1220
|
const namedType = this.checker?.types.get(typeName);
|
|
1050
1221
|
const u = namedType?.underlying;
|
|
1051
1222
|
if (u?.kind === "map") {
|
|
1052
|
-
|
|
1053
|
-
.map((e) => {
|
|
1054
|
-
if (e.kind === "KeyValueExpr") {
|
|
1055
|
-
const k =
|
|
1056
|
-
e.key.litKind === "STRING"
|
|
1057
|
-
? JSON.stringify(e.key.value)
|
|
1058
|
-
: `[${this.genExpr(e.key)}]`;
|
|
1059
|
-
return `${k}: ${this.genValueExpr(e.value)}`;
|
|
1060
|
-
}
|
|
1061
|
-
return this.genValueExpr(e);
|
|
1062
|
-
})
|
|
1063
|
-
.join(", ");
|
|
1064
|
-
return `new ${typeName}({ ${entries} })`;
|
|
1223
|
+
return `new ${typeName}({ ${this._genMapLitEntries(expr.elems)} })`;
|
|
1065
1224
|
}
|
|
1066
1225
|
// Default: slice
|
|
1067
1226
|
const elems = expr.elems
|
|
@@ -1124,8 +1283,11 @@ export const expressionGenMethods = {
|
|
|
1124
1283
|
},
|
|
1125
1284
|
|
|
1126
1285
|
_zeroForNamedType(name) {
|
|
1127
|
-
|
|
1128
|
-
if (
|
|
1286
|
+
const entry = NAMED_ZERO_TABLE[name];
|
|
1287
|
+
if (entry) {
|
|
1288
|
+
if (entry[0]) this.useHelper(entry[0]);
|
|
1289
|
+
return entry[1];
|
|
1290
|
+
}
|
|
1129
1291
|
name = this._dequalify(name);
|
|
1130
1292
|
if (this.structNames.has(name)) return `new ${name}()`;
|
|
1131
1293
|
return "null";
|
|
@@ -1397,24 +1559,17 @@ export const expressionGenMethods = {
|
|
|
1397
1559
|
return inner;
|
|
1398
1560
|
},
|
|
1399
1561
|
|
|
1400
|
-
_isStringSource(srcType) {
|
|
1401
|
-
return (
|
|
1402
|
-
(srcType?.kind === "basic" && srcType?.name === "string") ||
|
|
1403
|
-
(srcType?.kind === "untyped" && srcType?.base === "string")
|
|
1404
|
-
);
|
|
1405
|
-
},
|
|
1406
|
-
|
|
1407
1562
|
_genSliceTypeConversion(expr, inner, t) {
|
|
1408
1563
|
const elem = t.elem?.name;
|
|
1409
1564
|
if (elem === "byte" || elem === "uint8") {
|
|
1410
|
-
if (this.
|
|
1565
|
+
if (this._isStringExprType(expr.expr._type))
|
|
1411
1566
|
return `new TextEncoder().encode(${inner})`;
|
|
1412
1567
|
return `new Uint8Array(${inner})`;
|
|
1413
1568
|
}
|
|
1414
1569
|
const typedCtor = typedArrayConstructorForElem(
|
|
1415
1570
|
t.elem ? { kind: "basic", name: t.elem.name } : null,
|
|
1416
1571
|
);
|
|
1417
|
-
const fromString = this.
|
|
1572
|
+
const fromString = this._isStringExprType(expr.expr._type);
|
|
1418
1573
|
if (typedCtor) {
|
|
1419
1574
|
return fromString
|
|
1420
1575
|
? `${typedCtor}.from(${inner}, __c => __c.codePointAt(0))`
|
|
@@ -1532,81 +1687,55 @@ export const expressionGenMethods = {
|
|
|
1532
1687
|
if (tName === "float32") {
|
|
1533
1688
|
return `Math.fround(${l} ${op} ${r})`;
|
|
1534
1689
|
}
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
if (op === "<<" || op === ">>") {
|
|
1542
|
-
return `((${r}) >= 32 ? (${op === ">>" ? `((${l}) < 0 ? -1 : 0)` : "0"}) : ((${l}) ${op} (${r}))) | 0`;
|
|
1543
|
-
}
|
|
1544
|
-
if (op === "&^") return `((${l}) & ~(${r})) | 0`;
|
|
1545
|
-
return `((${l} ${op} ${r}) | 0)`;
|
|
1546
|
-
}
|
|
1547
|
-
if (tName === "uint32") {
|
|
1690
|
+
const divZero =
|
|
1691
|
+
'(() => { throw new Error("runtime error: integer divide by zero"); })()';
|
|
1692
|
+
if (tName === "int32" || tName === "rune" || tName === "uint32") {
|
|
1693
|
+
const signed = tName !== "uint32";
|
|
1694
|
+
const cast = signed ? "| 0" : ">>> 0";
|
|
1695
|
+
if (signed && op === "*") return `Math.imul(${l}, ${r})`;
|
|
1548
1696
|
if (op === "/")
|
|
1549
|
-
return `((${r}) === 0 ?
|
|
1697
|
+
return `((${r}) === 0 ? ${divZero} : (Math.trunc((${l}) / (${r})) ${cast}))`;
|
|
1550
1698
|
if (op === "%")
|
|
1551
|
-
return `((${r}) === 0 ?
|
|
1699
|
+
return `((${r}) === 0 ? ${divZero} : (((${l}) % (${r})) ${cast}))`;
|
|
1552
1700
|
if (op === "<<" || op === ">>") {
|
|
1553
|
-
const
|
|
1554
|
-
|
|
1701
|
+
const ovf = signed && op === ">>" ? `((${l}) < 0 ? -1 : 0)` : "0";
|
|
1702
|
+
const jsOp = !signed && op === ">>" ? ">>>" : op;
|
|
1703
|
+
return `((${r}) >= 32 ? ${ovf} : ((${l}) ${jsOp} (${r}))) ${cast}`;
|
|
1555
1704
|
}
|
|
1556
|
-
if (op === "&^") return `((${l}) & ~(${r}))
|
|
1557
|
-
return `((${l} ${op} ${r})
|
|
1705
|
+
if (op === "&^") return `((${l}) & ~(${r})) ${cast}`;
|
|
1706
|
+
return `((${l} ${op} ${r}) ${cast})`;
|
|
1558
1707
|
}
|
|
1559
|
-
if (tName === "int8") {
|
|
1708
|
+
if (tName === "int8" || tName === "int16") {
|
|
1709
|
+
const bits = tName === "int8" ? 8 : 16;
|
|
1710
|
+
const sh = 32 - bits;
|
|
1560
1711
|
if (op === "/")
|
|
1561
|
-
return `((${r}) === 0 ?
|
|
1712
|
+
return `((${r}) === 0 ? ${divZero} : ((Math.trunc((${l}) / (${r})) << ${sh}) >> ${sh}))`;
|
|
1562
1713
|
if (op === "%")
|
|
1563
|
-
return `((${r}) === 0 ?
|
|
1714
|
+
return `((${r}) === 0 ? ${divZero} : (((((${l}) % (${r})) << ${sh}) >> ${sh})))`;
|
|
1564
1715
|
if (op === "<<" || op === ">>") {
|
|
1565
|
-
return `((${r}) >=
|
|
1716
|
+
return `((${r}) >= ${bits} ? (${op === ">>" ? `((${l}) < 0 ? -1 : 0)` : "0"}) : (((${l}) ${op} (${r})) << ${sh} >> ${sh}))`;
|
|
1566
1717
|
}
|
|
1567
|
-
if (op === "&^") return `((((${l}) & ~(${r})) <<
|
|
1568
|
-
return `((((${l} ${op} ${r})) <<
|
|
1718
|
+
if (op === "&^") return `((((${l}) & ~(${r})) << ${sh}) >> ${sh})`;
|
|
1719
|
+
return `((((${l} ${op} ${r})) << ${sh}) >> ${sh})`;
|
|
1569
1720
|
}
|
|
1570
|
-
if (tName === "
|
|
1721
|
+
if (tName === "uint8" || tName === "byte" || tName === "uint16") {
|
|
1722
|
+
const bits = tName === "uint16" ? 16 : 8;
|
|
1723
|
+
const mask = bits === 16 ? "0xFFFF" : "0xFF";
|
|
1571
1724
|
if (op === "/")
|
|
1572
|
-
return `((${r}) === 0 ?
|
|
1725
|
+
return `((${r}) === 0 ? ${divZero} : (Math.trunc((${l}) / (${r})) & ${mask}))`;
|
|
1573
1726
|
if (op === "%")
|
|
1574
|
-
return `((${r}) === 0 ?
|
|
1575
|
-
if (op === "<<" || op === ">>") {
|
|
1576
|
-
return `((${r}) >= 16 ? (${op === ">>" ? `((${l}) < 0 ? -1 : 0)` : "0"}) : (((${l}) ${op} (${r})) << 16 >> 16))`;
|
|
1577
|
-
}
|
|
1578
|
-
if (op === "&^") return `((((${l}) & ~(${r})) << 16) >> 16)`;
|
|
1579
|
-
return `((((${l} ${op} ${r})) << 16) >> 16)`;
|
|
1580
|
-
}
|
|
1581
|
-
if (tName === "uint8" || tName === "byte") {
|
|
1582
|
-
if (op === "/")
|
|
1583
|
-
return `((${r}) === 0 ? (() => { throw new Error("runtime error: integer divide by zero"); })() : (Math.trunc((${l}) / (${r})) & 0xFF))`;
|
|
1584
|
-
if (op === "%")
|
|
1585
|
-
return `((${r}) === 0 ? (() => { throw new Error("runtime error: integer divide by zero"); })() : (((${l}) % (${r})) & 0xFF))`;
|
|
1727
|
+
return `((${r}) === 0 ? ${divZero} : (((${l}) % (${r})) & ${mask}))`;
|
|
1586
1728
|
if (op === "<<" || op === ">>") {
|
|
1587
1729
|
const jsOp = op === ">>" ? ">>>" : "<<";
|
|
1588
|
-
return `((${r}) >=
|
|
1730
|
+
return `((${r}) >= ${bits} ? 0 : (((${l}) ${jsOp} (${r})) & ${mask}))`;
|
|
1589
1731
|
}
|
|
1590
|
-
if (op === "&^") return `(((${l}) & ~(${r})) &
|
|
1591
|
-
return `((${l} ${op} ${r}) &
|
|
1592
|
-
}
|
|
1593
|
-
if (tName === "uint16") {
|
|
1594
|
-
if (op === "/")
|
|
1595
|
-
return `((${r}) === 0 ? (() => { throw new Error("runtime error: integer divide by zero"); })() : (Math.trunc((${l}) / (${r})) & 0xFFFF))`;
|
|
1596
|
-
if (op === "%")
|
|
1597
|
-
return `((${r}) === 0 ? (() => { throw new Error("runtime error: integer divide by zero"); })() : (((${l}) % (${r})) & 0xFFFF))`;
|
|
1598
|
-
if (op === "<<" || op === ">>") {
|
|
1599
|
-
const jsOp = op === ">>" ? ">>>" : "<<";
|
|
1600
|
-
return `((${r}) >= 16 ? 0 : (((${l}) ${jsOp} (${r})) & 0xFFFF))`;
|
|
1601
|
-
}
|
|
1602
|
-
if (op === "&^") return `(((${l}) & ~(${r})) & 0xFFFF)`;
|
|
1603
|
-
return `((${l} ${op} ${r}) & 0xFFFF)`;
|
|
1732
|
+
if (op === "&^") return `(((${l}) & ~(${r})) & ${mask})`;
|
|
1733
|
+
return `((${l} ${op} ${r}) & ${mask})`;
|
|
1604
1734
|
}
|
|
1605
1735
|
if (this.isIntType(type)) {
|
|
1606
1736
|
if (op === "/")
|
|
1607
|
-
return `((${r}) === 0 ?
|
|
1608
|
-
if (op === "%")
|
|
1609
|
-
return `((${r}) === 0 ? (() => { throw new Error("runtime error: integer divide by zero"); })() : ((${l}) % (${r})))`;
|
|
1737
|
+
return `((${r}) === 0 ? ${divZero} : Math.trunc((${l}) / (${r})))`;
|
|
1738
|
+
if (op === "%") return `((${r}) === 0 ? ${divZero} : ((${l}) % (${r})))`;
|
|
1610
1739
|
}
|
|
1611
1740
|
return `${l} ${op} ${r}`;
|
|
1612
1741
|
},
|
package/src/backend/js/index.js
CHANGED
|
@@ -28,22 +28,34 @@ import { isComplex, isNumeric } from "../../typechecker/types.js";
|
|
|
28
28
|
import { expressionGenMethods } from "./expressions.js";
|
|
29
29
|
import {
|
|
30
30
|
HELPER_APPEND,
|
|
31
|
+
HELPER_BASE64,
|
|
32
|
+
HELPER_BINARY,
|
|
31
33
|
HELPER_CDIV,
|
|
32
34
|
HELPER_CMUL,
|
|
35
|
+
HELPER_CRYPTO_RAND,
|
|
36
|
+
HELPER_DURATION,
|
|
33
37
|
HELPER_EQUAL,
|
|
34
38
|
HELPER_ERROR,
|
|
39
|
+
HELPER_ERROR_AS,
|
|
35
40
|
HELPER_ERROR_IS,
|
|
41
|
+
HELPER_ERROR_JOIN,
|
|
42
|
+
HELPER_HEX,
|
|
36
43
|
HELPER_IFACE_BOX,
|
|
37
44
|
HELPER_INJECT_STYLES,
|
|
45
|
+
HELPER_IO_EOF,
|
|
38
46
|
HELPER_LEN,
|
|
39
47
|
HELPER_NIL_CALL,
|
|
40
48
|
HELPER_PANIC,
|
|
41
49
|
HELPER_PATH_CLEAN,
|
|
50
|
+
HELPER_PATH_ERROR,
|
|
42
51
|
HELPER_S,
|
|
43
52
|
HELPER_SCLONE,
|
|
53
|
+
HELPER_SHA256,
|
|
44
54
|
HELPER_SORT_SLICE,
|
|
45
55
|
HELPER_SPRINTF,
|
|
46
56
|
HELPER_STRCONV,
|
|
57
|
+
HELPER_STRCONV_ERROR,
|
|
58
|
+
HELPER_SYNC,
|
|
47
59
|
HELPER_TESTING,
|
|
48
60
|
HELPER_TIME_FMT,
|
|
49
61
|
HELPER_TIME_PARSE,
|
|
@@ -111,12 +123,24 @@ const HELPER_MAP = [
|
|
|
111
123
|
["sprintf", HELPER_SPRINTF],
|
|
112
124
|
["error", HELPER_ERROR],
|
|
113
125
|
["errorIs", HELPER_ERROR_IS],
|
|
126
|
+
["errorAs", HELPER_ERROR_AS],
|
|
127
|
+
["errorJoin", HELPER_ERROR_JOIN],
|
|
128
|
+
["strconvError", HELPER_STRCONV_ERROR],
|
|
129
|
+
["pathError", HELPER_PATH_ERROR],
|
|
130
|
+
["ioEOF", HELPER_IO_EOF],
|
|
114
131
|
["strconv", HELPER_STRCONV],
|
|
115
132
|
["pathClean", HELPER_PATH_CLEAN],
|
|
116
133
|
["sortSlice", HELPER_SORT_SLICE],
|
|
117
134
|
["timeFmt", HELPER_TIME_FMT],
|
|
118
135
|
["timeParse", HELPER_TIME_PARSE],
|
|
136
|
+
["duration", HELPER_DURATION],
|
|
119
137
|
["testing", HELPER_TESTING],
|
|
138
|
+
["sync", HELPER_SYNC],
|
|
139
|
+
["cryptoRand", HELPER_CRYPTO_RAND],
|
|
140
|
+
["sha256", HELPER_SHA256],
|
|
141
|
+
["binary", HELPER_BINARY],
|
|
142
|
+
["hex", HELPER_HEX],
|
|
143
|
+
["base64", HELPER_BASE64],
|
|
120
144
|
];
|
|
121
145
|
|
|
122
146
|
export class CodeGen {
|
|
@@ -428,6 +452,19 @@ export class CodeGen {
|
|
|
428
452
|
/** Marks a runtime helper (key of HELPER_MAP) as needed by the output. */
|
|
429
453
|
useHelper(name) {
|
|
430
454
|
this._helpers.add(name);
|
|
455
|
+
if (
|
|
456
|
+
name === "strconvError" ||
|
|
457
|
+
name === "pathError" ||
|
|
458
|
+
name === "ioEOF" ||
|
|
459
|
+
name === "base64" ||
|
|
460
|
+
name === "hex"
|
|
461
|
+
) {
|
|
462
|
+
this._helpers.add("error");
|
|
463
|
+
}
|
|
464
|
+
if (name === "binary") {
|
|
465
|
+
this.useHelper("ioEOF");
|
|
466
|
+
this._helpers.add("error");
|
|
467
|
+
}
|
|
431
468
|
}
|
|
432
469
|
|
|
433
470
|
_prependHelpers(isTest = false) {
|
|
@@ -570,7 +607,7 @@ export class CodeGen {
|
|
|
570
607
|
.map((f) => `${f.name}: ${binding(f)} = ${f.zero}`)
|
|
571
608
|
.join(", ");
|
|
572
609
|
this.line(
|
|
573
|
-
`if (typeof ${first} === "object" && ${first} !== null && ${first}.constructor === Object) ({ ${pattern} } = ${first});`,
|
|
610
|
+
`if (arguments.length === 1 && typeof ${first} === "object" && ${first} !== null && ${first}.constructor === Object) ({ ${pattern} } = ${first});`,
|
|
574
611
|
);
|
|
575
612
|
}
|
|
576
613
|
for (const f of fields) {
|