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
|
@@ -184,8 +184,7 @@ export const statementGenMethods = {
|
|
|
184
184
|
this.line(`const ${tmp} = ${rhs[0]};`);
|
|
185
185
|
for (let i = 0; i < lhs.length; i++) {
|
|
186
186
|
if (lhs[i] === "_") continue;
|
|
187
|
-
|
|
188
|
-
this.line(`${prefix}${lhs[i]} = ${tmp}[${i}];`);
|
|
187
|
+
this._genDefineSingleVar([lhs[i]], [`${tmp}[${i}]`], [redecls[i]]);
|
|
189
188
|
}
|
|
190
189
|
} else {
|
|
191
190
|
for (let i = 0; i < lhs.length; i++) {
|
|
@@ -193,12 +192,20 @@ export const statementGenMethods = {
|
|
|
193
192
|
this.line(`${rhs[i]};`);
|
|
194
193
|
continue;
|
|
195
194
|
}
|
|
196
|
-
|
|
197
|
-
this.line(`${prefix}${lhs[i]} = ${rhs[i]};`);
|
|
195
|
+
this._genDefineSingleVar([lhs[i]], [rhs[i]], [redecls[i]]);
|
|
198
196
|
}
|
|
199
197
|
}
|
|
200
198
|
},
|
|
201
199
|
|
|
200
|
+
// Address-taken variables introduced by a destructuring declaration are
|
|
201
|
+
// re-bound to their { value } box.
|
|
202
|
+
_boxDeclaredNames(names) {
|
|
203
|
+
for (const n of names) {
|
|
204
|
+
if (n && n !== "_" && this._boxedVars.has(n))
|
|
205
|
+
this.line(`${n} = { value: ${n} };`);
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
|
|
202
209
|
_genDefineStmt(stmt) {
|
|
203
210
|
const rhsNode = stmt.rhs[0];
|
|
204
211
|
if (this._isCommaOkMapExpr(stmt, rhsNode)) {
|
|
@@ -221,6 +228,7 @@ export const statementGenMethods = {
|
|
|
221
228
|
const rhsStr = rhs.length === 1 ? rhs[0] : `[${rhs.join(", ")}]`;
|
|
222
229
|
const names = lhs.map((n) => (n === "_" ? "" : n));
|
|
223
230
|
this.line(`let [${names.join(", ")}] = ${rhsStr};`);
|
|
231
|
+
this._boxDeclaredNames(names);
|
|
224
232
|
} else {
|
|
225
233
|
this._genDefineMixedRedecl(lhs, rhs, redecls);
|
|
226
234
|
}
|
|
@@ -696,6 +704,39 @@ export const statementGenMethods = {
|
|
|
696
704
|
return nodeAssigns(node, name);
|
|
697
705
|
},
|
|
698
706
|
|
|
707
|
+
_genStringRangeFor(stmt, iteree, isAssign) {
|
|
708
|
+
this._loopDepth = this._loopDepth ?? 0;
|
|
709
|
+
const d = this._loopDepth++;
|
|
710
|
+
const [idxNode, valNode] = stmt.init.lhs;
|
|
711
|
+
const s = `__s${d}`;
|
|
712
|
+
const i = `__i${d}`;
|
|
713
|
+
const cp = `__cp${d}`;
|
|
714
|
+
this.line(
|
|
715
|
+
`for (let ${i} = 0, ${s} = Array.from(${iteree} ?? ""); ${i} < ${s}.length; ${i}++) {`,
|
|
716
|
+
);
|
|
717
|
+
this.indented(() => {
|
|
718
|
+
this._emitRangeVar(idxNode, i, isAssign);
|
|
719
|
+
if (valNode && valNode.name !== "_") {
|
|
720
|
+
this.line(`const ${cp} = ${s}[${i}].codePointAt(0);`);
|
|
721
|
+
this._emitRangeVar(valNode, cp, isAssign);
|
|
722
|
+
}
|
|
723
|
+
const declared = isAssign
|
|
724
|
+
? []
|
|
725
|
+
: [idxNode, valNode]
|
|
726
|
+
.filter((e) => e?.kind === "Ident" && e.name !== "_")
|
|
727
|
+
.map((e) => e.name);
|
|
728
|
+
if (this._bodyRedeclares(stmt.body, declared)) {
|
|
729
|
+
this.line("{");
|
|
730
|
+
this.indented(() => this.genBlock(stmt.body));
|
|
731
|
+
this.line("}");
|
|
732
|
+
} else {
|
|
733
|
+
this.genBlock(stmt.body);
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
this.line("}");
|
|
737
|
+
this._loopDepth--;
|
|
738
|
+
},
|
|
739
|
+
|
|
699
740
|
_genIterFor(init, iterType, iteree, lhs, body) {
|
|
700
741
|
const iterExpr = this._genRangeIterExpr(iterType, iteree, lhs);
|
|
701
742
|
const binding =
|
|
@@ -725,12 +766,17 @@ export const statementGenMethods = {
|
|
|
725
766
|
return;
|
|
726
767
|
}
|
|
727
768
|
|
|
728
|
-
if (
|
|
729
|
-
this.
|
|
769
|
+
if (this._isStringRangeType(iterType)) {
|
|
770
|
+
this._genStringRangeFor(stmt, iteree, init.kind === "AssignStmt");
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
if (this._isMapRangeType(iterType)) {
|
|
775
|
+
this._genIterFor(init, iterType, iteree, lhs, stmt.body);
|
|
730
776
|
return;
|
|
731
777
|
}
|
|
732
778
|
|
|
733
|
-
this.
|
|
779
|
+
this._genSliceRangeFor(stmt, iteree, init.kind === "AssignStmt");
|
|
734
780
|
},
|
|
735
781
|
|
|
736
782
|
_genRangeIterExpr(iterType, iteree, lhs) {
|
|
@@ -738,23 +784,14 @@ export const statementGenMethods = {
|
|
|
738
784
|
if (lhs.length === 1) return `Object.keys(${iteree})`;
|
|
739
785
|
return `Object.entries(${iteree})`;
|
|
740
786
|
}
|
|
741
|
-
if (this._isStringRangeType(iterType)) {
|
|
742
|
-
if (lhs.length === 1) return `Array.from(${iteree}).keys()`;
|
|
743
|
-
return `Array.from(${iteree}, (__c, __i) => [__i, __c.codePointAt(0)])`;
|
|
744
|
-
}
|
|
745
787
|
this.useHelper("sliceGuard");
|
|
746
788
|
if (lhs.length === 1) return `__s(${iteree}).keys()`;
|
|
747
789
|
return `__s(${iteree}).entries()`;
|
|
748
790
|
},
|
|
749
791
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
let iteree = this.genExpr(range.expr);
|
|
754
|
-
const yieldParams = range._yieldParams;
|
|
755
|
-
|
|
756
|
-
// Wrap bare function expressions to avoid "Function statements require a name"
|
|
757
|
-
if (range.expr.kind === "FuncLit") {
|
|
792
|
+
_genIteratorLoop(itereeExpr, paramsStr, body) {
|
|
793
|
+
let iteree = this.genExpr(itereeExpr);
|
|
794
|
+
if (itereeExpr.kind === "FuncLit") {
|
|
758
795
|
iteree = `(${iteree})`;
|
|
759
796
|
}
|
|
760
797
|
|
|
@@ -763,17 +800,13 @@ export const statementGenMethods = {
|
|
|
763
800
|
const retFlag = `__returned${d}`;
|
|
764
801
|
const retVar = `__retVal${d}`;
|
|
765
802
|
|
|
766
|
-
// Yield callback param names (blank vars get _$N to avoid JS syntax error)
|
|
767
|
-
const cbParams = lhs.map((n, i) => (n === "_" ? `_$${i}` : n));
|
|
768
|
-
|
|
769
803
|
this.line("{");
|
|
770
804
|
this.indented(() => {
|
|
771
805
|
this.line(`let ${breakFlag} = false;`);
|
|
772
806
|
this.line(`let ${retFlag} = false;`);
|
|
773
807
|
this.line(`let ${retVar};`);
|
|
774
808
|
|
|
775
|
-
|
|
776
|
-
this.line(`${iteree}(function(${params}) {`);
|
|
809
|
+
this.line(`${iteree}(function(${paramsStr}) {`);
|
|
777
810
|
this.indented(() => {
|
|
778
811
|
this.line(`if (${breakFlag}) return false;`);
|
|
779
812
|
const prev = {
|
|
@@ -787,7 +820,7 @@ export const statementGenMethods = {
|
|
|
787
820
|
this._iterReturnFlag = retFlag;
|
|
788
821
|
this._iterReturnVar = retVar;
|
|
789
822
|
|
|
790
|
-
this.genBlock(
|
|
823
|
+
this.genBlock(body);
|
|
791
824
|
|
|
792
825
|
this._inIteratorBody = prev.in;
|
|
793
826
|
this._iterBreakFlag = prev.break;
|
|
@@ -803,54 +836,17 @@ export const statementGenMethods = {
|
|
|
803
836
|
this._iterDepth--;
|
|
804
837
|
},
|
|
805
838
|
|
|
839
|
+
genIteratorFor(stmt) {
|
|
840
|
+
const range = stmt.init.rhs[0];
|
|
841
|
+
const lhs = stmt.init.lhs.map((e) => e.name ?? this.genExpr(e));
|
|
842
|
+
const cbParams = lhs.map((n, i) => (n === "_" ? `_$${i}` : n));
|
|
843
|
+
const params = range._yieldParams.length === 0 ? "" : cbParams.join(", ");
|
|
844
|
+
this._genIteratorLoop(range.expr, params, stmt.body);
|
|
845
|
+
},
|
|
846
|
+
|
|
806
847
|
// 0-param iterator: for range iter { body }
|
|
807
848
|
genIteratorForCond(stmt) {
|
|
808
|
-
|
|
809
|
-
let iteree = this.genExpr(range.expr);
|
|
810
|
-
|
|
811
|
-
if (range.expr.kind === "FuncLit") {
|
|
812
|
-
iteree = `(${iteree})`;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
const d = this._iterDepth++;
|
|
816
|
-
const breakFlag = `__broke${d}`;
|
|
817
|
-
const retFlag = `__returned${d}`;
|
|
818
|
-
const retVar = `__retVal${d}`;
|
|
819
|
-
|
|
820
|
-
this.line("{");
|
|
821
|
-
this.indented(() => {
|
|
822
|
-
this.line(`let ${breakFlag} = false;`);
|
|
823
|
-
this.line(`let ${retFlag} = false;`);
|
|
824
|
-
this.line(`let ${retVar};`);
|
|
825
|
-
|
|
826
|
-
this.line(`${iteree}(function() {`);
|
|
827
|
-
this.indented(() => {
|
|
828
|
-
this.line(`if (${breakFlag}) return false;`);
|
|
829
|
-
const prev = {
|
|
830
|
-
in: this._inIteratorBody,
|
|
831
|
-
break: this._iterBreakFlag,
|
|
832
|
-
ret: this._iterReturnFlag,
|
|
833
|
-
retVar: this._iterReturnVar,
|
|
834
|
-
};
|
|
835
|
-
this._inIteratorBody = true;
|
|
836
|
-
this._iterBreakFlag = breakFlag;
|
|
837
|
-
this._iterReturnFlag = retFlag;
|
|
838
|
-
this._iterReturnVar = retVar;
|
|
839
|
-
|
|
840
|
-
this.genBlock(stmt.body);
|
|
841
|
-
|
|
842
|
-
this._inIteratorBody = prev.in;
|
|
843
|
-
this._iterBreakFlag = prev.break;
|
|
844
|
-
this._iterReturnFlag = prev.ret;
|
|
845
|
-
this._iterReturnVar = prev.retVar;
|
|
846
|
-
|
|
847
|
-
this.line("return true;");
|
|
848
|
-
});
|
|
849
|
-
this.line("});");
|
|
850
|
-
this.line(`if (${retFlag}) return ${retVar};`);
|
|
851
|
-
});
|
|
852
|
-
this.line("}");
|
|
853
|
-
this._iterDepth--;
|
|
849
|
+
this._genIteratorLoop(stmt.cond.expr, "", stmt.body);
|
|
854
850
|
},
|
|
855
851
|
|
|
856
852
|
// Inline a statement as a for-init/post string (no semicolon)
|
|
@@ -875,14 +871,29 @@ export const statementGenMethods = {
|
|
|
875
871
|
}
|
|
876
872
|
},
|
|
877
873
|
|
|
874
|
+
// Interface-typed tags may hold boxed named values; cases compare with __ifeq.
|
|
875
|
+
_switchTagAndCases(stmt) {
|
|
876
|
+
const tag = stmt.tag ? this.genExpr(stmt.tag) : "true";
|
|
877
|
+
if (!stmt.tag || !this._isIfaceType(stmt.tag._type))
|
|
878
|
+
return { tag, caseExpr: (e) => this.genExpr(e) };
|
|
879
|
+
this.useHelper("ifeq");
|
|
880
|
+
this._swCounter = (this._swCounter ?? 0) + 1;
|
|
881
|
+
const tmp = `__sw${this._swCounter}`;
|
|
882
|
+
this.line(`const ${tmp} = ${tag};`);
|
|
883
|
+
return {
|
|
884
|
+
tag: "true",
|
|
885
|
+
caseExpr: (e) => `__ifeq(${tmp}, ${this._genIfaceOperand(e)})`,
|
|
886
|
+
};
|
|
887
|
+
},
|
|
888
|
+
|
|
878
889
|
genSwitch(stmt) {
|
|
879
890
|
const genBody = () => {
|
|
880
|
-
const tag
|
|
891
|
+
const { tag, caseExpr } = this._switchTagAndCases(stmt);
|
|
881
892
|
this.line(`switch (${tag}) {`);
|
|
882
893
|
this.indented(() => {
|
|
883
894
|
for (const c of stmt.cases) {
|
|
884
895
|
if (c.list) {
|
|
885
|
-
for (const e of c.list) this.line(`case ${
|
|
896
|
+
for (const e of c.list) this.line(`case ${caseExpr(e)}:`);
|
|
886
897
|
} else {
|
|
887
898
|
this.line("default:");
|
|
888
899
|
}
|
|
@@ -938,6 +949,13 @@ export const statementGenMethods = {
|
|
|
938
949
|
.join(" || ");
|
|
939
950
|
this.line(`${first ? "if" : "else if"} (${cond}) {`);
|
|
940
951
|
this.indented(() => {
|
|
952
|
+
// A single named non-struct case binds the unboxed value.
|
|
953
|
+
if (
|
|
954
|
+
stmt.assign &&
|
|
955
|
+
c.types.length === 1 &&
|
|
956
|
+
this._isNamedBoxTypeNode(c.types[0])
|
|
957
|
+
)
|
|
958
|
+
this.line(`const ${stmt.assign} = __tsw.__gfUnbox();`);
|
|
941
959
|
for (const s of c.stmts) this.genStmt(s);
|
|
942
960
|
});
|
|
943
961
|
this.line("}");
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/backend/js/stdlib/base64.js
|
|
2
|
+
// CodeGen for Go encoding/base64 package.
|
|
3
|
+
|
|
4
|
+
export const base64Methods = {
|
|
5
|
+
_genBase64(fn, a) {
|
|
6
|
+
this.useHelper("base64");
|
|
7
|
+
this.useHelper("error");
|
|
8
|
+
const args = a();
|
|
9
|
+
if (fn === "NewEncoding") return `__base64_make(${args[0]}, "=")`;
|
|
10
|
+
return undefined;
|
|
11
|
+
},
|
|
12
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// src/backend/js/stdlib/binary.js
|
|
2
|
+
// CodeGen for Go encoding/binary package.
|
|
3
|
+
|
|
4
|
+
function sizeOfGoType(gt) {
|
|
5
|
+
if (!gt) return -1;
|
|
6
|
+
if (gt.kind === "basic") {
|
|
7
|
+
switch (gt.name) {
|
|
8
|
+
case "bool":
|
|
9
|
+
case "int8":
|
|
10
|
+
case "uint8":
|
|
11
|
+
case "byte":
|
|
12
|
+
return 1;
|
|
13
|
+
case "int16":
|
|
14
|
+
case "uint16":
|
|
15
|
+
return 2;
|
|
16
|
+
case "int32":
|
|
17
|
+
case "uint32":
|
|
18
|
+
case "float32":
|
|
19
|
+
case "rune":
|
|
20
|
+
return 4;
|
|
21
|
+
case "int64":
|
|
22
|
+
case "uint64":
|
|
23
|
+
case "float64":
|
|
24
|
+
case "int":
|
|
25
|
+
case "uint":
|
|
26
|
+
case "uintptr":
|
|
27
|
+
return 8;
|
|
28
|
+
default:
|
|
29
|
+
return -1;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (gt.kind === "array" || gt.kind === "ArrayType") {
|
|
33
|
+
const es = sizeOfGoType(gt.elem);
|
|
34
|
+
const len = gt.len ?? gt.size ?? 0;
|
|
35
|
+
return es > 0 ? es * len : -1;
|
|
36
|
+
}
|
|
37
|
+
if (
|
|
38
|
+
gt.kind === "pointer" ||
|
|
39
|
+
gt.kind === "PointerType" ||
|
|
40
|
+
gt.kind === "StarExpr"
|
|
41
|
+
) {
|
|
42
|
+
return sizeOfGoType(gt.base ?? gt.expr ?? gt.operand);
|
|
43
|
+
}
|
|
44
|
+
if (gt.kind === "struct" || gt.kind === "StructType") {
|
|
45
|
+
let total = 0;
|
|
46
|
+
if (gt.fields instanceof Map) {
|
|
47
|
+
for (const fType of gt.fields.values()) {
|
|
48
|
+
const s = sizeOfGoType(fType);
|
|
49
|
+
if (s < 0) return -1;
|
|
50
|
+
total += s;
|
|
51
|
+
}
|
|
52
|
+
return total;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return -1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const binaryMethods = {
|
|
59
|
+
_genBinary(fn, a, expr) {
|
|
60
|
+
this.useHelper("binary");
|
|
61
|
+
this.useHelper("error");
|
|
62
|
+
const args = a();
|
|
63
|
+
if (fn === "Read") {
|
|
64
|
+
const targetType = expr?.args?.[2]?._type;
|
|
65
|
+
const baseType = targetType?.base ?? targetType;
|
|
66
|
+
const resolved =
|
|
67
|
+
baseType?.kind === "named"
|
|
68
|
+
? (baseType.underlying ?? baseType)
|
|
69
|
+
: baseType;
|
|
70
|
+
const sz = sizeOfGoType(resolved);
|
|
71
|
+
const typeTag =
|
|
72
|
+
resolved?.name ??
|
|
73
|
+
(resolved?.kind === "basic" ? resolved.name : (baseType?.name ?? ""));
|
|
74
|
+
return `__binary_read(${args[0]}, ${args[1]}, ${args[2]}${sz > 0 ? `, ${sz}` : ", 0"}, "${typeTag}")`;
|
|
75
|
+
}
|
|
76
|
+
if (fn === "Write") {
|
|
77
|
+
const targetType = expr?.args?.[2]?._type;
|
|
78
|
+
const baseType = targetType?.base ?? targetType;
|
|
79
|
+
const resolved =
|
|
80
|
+
baseType?.kind === "named"
|
|
81
|
+
? (baseType.underlying ?? baseType)
|
|
82
|
+
: baseType;
|
|
83
|
+
const sz = sizeOfGoType(resolved);
|
|
84
|
+
const typeTag =
|
|
85
|
+
resolved?.name ??
|
|
86
|
+
(resolved?.kind === "basic" ? resolved.name : (baseType?.name ?? ""));
|
|
87
|
+
return `__binary_write(${args[0]}, ${args[1]}, ${args[2]}${sz > 0 ? `, ${sz}` : ", 0"}, "${typeTag}")`;
|
|
88
|
+
}
|
|
89
|
+
if (fn === "Size") {
|
|
90
|
+
const sz = sizeOfGoType(expr?.args?.[0]?._type);
|
|
91
|
+
if (sz >= 0) return `${sz}`;
|
|
92
|
+
return `__binary_size(${args[0]})`;
|
|
93
|
+
}
|
|
94
|
+
if (fn === "AppendUint16")
|
|
95
|
+
return `__binary_le.AppendUint16(${args[0]}, ${args[1]})`;
|
|
96
|
+
if (fn === "AppendUint32")
|
|
97
|
+
return `__binary_le.AppendUint32(${args[0]}, ${args[1]})`;
|
|
98
|
+
if (fn === "AppendUint64")
|
|
99
|
+
return `__binary_le.AppendUint64(${args[0]}, ${args[1]})`;
|
|
100
|
+
return undefined;
|
|
101
|
+
},
|
|
102
|
+
};
|
|
@@ -19,7 +19,21 @@ const BITS_MAP = {
|
|
|
19
19
|
OnesCount64: ([x]) =>
|
|
20
20
|
`((() => { let v = BigInt.asUintN(64, BigInt(${x})); let c = 0; while (v > 0n) { if (v & 1n) c++; v >>= 1n; } return c; })())`,
|
|
21
21
|
RotateLeft64: ([x, k]) =>
|
|
22
|
-
`((() => { const s = BigInt(${k}) & 63n; const v = BigInt.asUintN(64, BigInt(${x})); return BigInt.asUintN(64, (v << s) | (v >> ((64n - s) & 63n))); })())`,
|
|
22
|
+
`((() => { const s = BigInt(${k}) & 63n; const v = BigInt.asUintN(64, BigInt(${x})); return Number(BigInt.asUintN(64, (v << s) | (v >> ((64n - s) & 63n)))); })())`,
|
|
23
|
+
|
|
24
|
+
Len32: ([x]) => `((v => 32 - Math.clz32(v >>> 0))(${x}))`,
|
|
25
|
+
Len64: ([x]) =>
|
|
26
|
+
`((() => { const v = BigInt.asUintN(64, BigInt(${x})); if (v === 0n) return 0; const hi = Number(v >> 32n); return hi !== 0 ? 64 - Math.clz32(hi) : 32 - Math.clz32(Number(v & 0xffffffffn)); })())`,
|
|
27
|
+
ReverseBytes16: ([x]) =>
|
|
28
|
+
`((v => ((v & 0xff) << 8) | ((v >>> 8) & 0xff))((${x}) & 0xffff))`,
|
|
29
|
+
ReverseBytes32: ([x]) =>
|
|
30
|
+
`((v => (((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v >>> 8) & 0xff00) | ((v >>> 24) & 0xff)) >>> 0)((${x}) >>> 0))`,
|
|
31
|
+
ReverseBytes64: ([x]) =>
|
|
32
|
+
`((() => { const v = BigInt.asUintN(64, BigInt(${x})); let r = 0n; for (let i = 0n; i < 8n; i++) r = (r << 8n) | ((v >> (i * 8n)) & 0xffn); return Number(r); })())`,
|
|
33
|
+
Reverse32: ([x]) =>
|
|
34
|
+
`((() => { let v = (${x}) >>> 0; v = ((v >>> 1) & 0x55555555) | ((v & 0x55555555) << 1); v = ((v >>> 2) & 0x33333333) | ((v & 0x33333333) << 2); v = ((v >>> 4) & 0x0f0f0f0f) | ((v & 0x0f0f0f0f) << 4); v = ((v >>> 8) & 0x00ff00ff) | ((v & 0x00ff00ff) << 8); return ((v >>> 16) | (v << 16)) >>> 0; })())`,
|
|
35
|
+
Reverse64: ([x]) =>
|
|
36
|
+
`((() => { const rev32 = (v) => { v = ((v >>> 1) & 0x55555555) | ((v & 0x55555555) << 1); v = ((v >>> 2) & 0x33333333) | ((v & 0x33333333) << 2); v = ((v >>> 4) & 0x0f0f0f0f) | ((v & 0x0f0f0f0f) << 4); v = ((v >>> 8) & 0x00ff00ff) | ((v & 0x00ff00ff) << 8); return ((v >>> 16) | (v << 16)) >>> 0; }; const v = BigInt.asUintN(64, BigInt(${x})); const lo = Number(v & 0xffffffffn); const hi = Number((v >> 32n) & 0xffffffffn); return Number((BigInt(rev32(lo)) << 32n) | BigInt(rev32(hi))); })())`,
|
|
23
37
|
};
|
|
24
38
|
|
|
25
39
|
/** @type {ThisType<CodeGen>} */
|
|
@@ -3,25 +3,40 @@
|
|
|
3
3
|
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
4
|
|
|
5
5
|
const BUILDER_STR = {
|
|
6
|
-
WriteString: (b, a) =>
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
WriteString: (b, a) =>
|
|
7
|
+
`((__s) => { ${b}._buf += __s; return [new TextEncoder().encode(__s).length, null]; })(${a[0]})`,
|
|
8
|
+
WriteByte: (b, a) => `(${b}._buf += String.fromCodePoint(${a[0]}), null)`,
|
|
9
|
+
WriteRune: (b, a) =>
|
|
10
|
+
`((cp) => { const r = (cp < 0 || cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff)) ? 0xfffd : cp; const s = String.fromCodePoint(r); ${b}._buf += s; return [new TextEncoder().encode(s).length, null]; })(${a[0]})`,
|
|
11
|
+
Write: (b, a) =>
|
|
12
|
+
`(${b}._buf += new TextDecoder().decode(new Uint8Array(${a[0]})), [${a[0]}.length, null])`,
|
|
9
13
|
String: (b) => `${b}._buf`,
|
|
10
14
|
Reset: (b) => `(${b}._buf = "")`,
|
|
15
|
+
Len: (b) => `new TextEncoder().encode(${b}._buf).length`,
|
|
16
|
+
Cap: (b) =>
|
|
17
|
+
`Math.max(${b}._cap ?? 0, new TextEncoder().encode(${b}._buf).length)`,
|
|
18
|
+
Grow: (b, a) =>
|
|
19
|
+
`((n) => { if (n < 0) throw new Error("strings.Builder.Grow: negative count"); ${b}._cap = Math.max(${b}._cap ?? 0, new TextEncoder().encode(${b}._buf).length) + n; })(${a[0]})`,
|
|
11
20
|
};
|
|
12
21
|
const BUILDER_BYTES = {
|
|
13
22
|
WriteString: (b, a) =>
|
|
14
|
-
`(
|
|
15
|
-
WriteByte: (b, a) =>
|
|
16
|
-
|
|
23
|
+
`((buf, s) => { const bytes = new TextEncoder().encode(s); for (let i = 0; i < bytes.length; i++) buf._buf.push(bytes[i]); return [bytes.length, null]; })(${b}, ${a[0]})`,
|
|
24
|
+
WriteByte: (b, a) => `(${b}._buf.push(${a[0]}), null)`,
|
|
25
|
+
WriteRune: (b, a) =>
|
|
26
|
+
`((buf, cp) => { const r = (cp < 0 || cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff)) ? 0xfffd : cp; const bytes = new TextEncoder().encode(String.fromCodePoint(r)); for (let i = 0; i < bytes.length; i++) buf._buf.push(bytes[i]); return [bytes.length, null]; })(${b}, ${a[0]})`,
|
|
27
|
+
Write: (b, a) =>
|
|
28
|
+
`((buf, d) => { for (let i = 0; i < d.length; i++) buf._buf.push(d[i]); return [d.length, null]; })(${b}, ${a[0]})`,
|
|
17
29
|
String: (b) => `new TextDecoder().decode(new Uint8Array(${b}._buf))`,
|
|
18
30
|
Reset: (b) => `(${b}._buf = [])`,
|
|
31
|
+
Read: (b, a) =>
|
|
32
|
+
`((buf, p) => { if (buf._buf.length === 0) return [0, __io_eof]; const n = Math.min(p.length, buf._buf.length); for (let i = 0; i < n; i++) p[i] = buf._buf.shift(); return [n, null]; })(${b}, ${a[0]})`,
|
|
19
33
|
};
|
|
20
34
|
const BUILDER_COMMON = {
|
|
21
|
-
|
|
22
|
-
Bytes: (b) => `${b}._buf.slice()`,
|
|
35
|
+
Bytes: (b) => `new Uint8Array(${b}._buf)`,
|
|
23
36
|
Len: (b) => `${b}._buf.length`,
|
|
24
|
-
|
|
37
|
+
Cap: (b) => `Math.max(${b}._cap ?? 0, ${b}._buf.length)`,
|
|
38
|
+
Grow: (b, a) =>
|
|
39
|
+
`((n) => { if (n < 0) throw new Error("bytes.Buffer.Grow: negative count"); ${b}._cap = Math.max(${b}._cap ?? 0, ${b}._buf.length) + n; })(${a[0]})`,
|
|
25
40
|
};
|
|
26
41
|
|
|
27
42
|
/** @type {ThisType<CodeGen>} */
|
|
@@ -30,6 +45,10 @@ export const builderMethods = {
|
|
|
30
45
|
const recv = expr.func.expr;
|
|
31
46
|
const base = this._unboxWriter(this.genExpr(recv));
|
|
32
47
|
const args = expr.args.map((a) => this.genExpr(a));
|
|
48
|
+
if (method === "Read") {
|
|
49
|
+
this.useHelper("ioEOF");
|
|
50
|
+
this.useHelper("error");
|
|
51
|
+
}
|
|
33
52
|
const isStr = typeName === "strings.Builder";
|
|
34
53
|
const table = isStr ? BUILDER_STR : BUILDER_BYTES;
|
|
35
54
|
const gen = table[method] ?? BUILDER_COMMON[method];
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
/** @typedef {import('../index.js').CodeGen} CodeGen */
|
|
4
4
|
|
|
5
|
-
const __bs = `(b => String.fromCharCode(
|
|
6
|
-
const __sb = `(s => [...s].map(c => c.charCodeAt(0)))`;
|
|
5
|
+
const __bs = `(b => typeof TextDecoder !== "undefined" ? new TextDecoder().decode(b instanceof Uint8Array ? b : new Uint8Array(b)) : String.fromCharCode.apply(null, b))`;
|
|
6
|
+
const __sb = `(s => typeof TextEncoder !== "undefined" ? new TextEncoder().encode(s) : new Uint8Array([...s].map(c => c.charCodeAt(0))))`;
|
|
7
7
|
|
|
8
8
|
const BYTES_DISPATCH = {
|
|
9
9
|
Contains: (a) => `${__bs}(${a[0]}).includes(${__bs}(${a[1]}))`,
|
|
@@ -16,49 +16,106 @@ const BYTES_DISPATCH = {
|
|
|
16
16
|
`((b, sep) => sep.length === 0 ? b.length + 1 : ${__bs}(b).split(${__bs}(sep)).length - 1)(${a[0]}, ${a[1]})`,
|
|
17
17
|
Repeat: (a) => `${__sb}(${__bs}(${a[0]}).repeat(${a[1]}))`,
|
|
18
18
|
Replace: (a) =>
|
|
19
|
-
`((b, o, n, cnt) => { let
|
|
20
|
-
ToUpper: (a) =>
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
`((b, o, n, cnt) => { let str = ${__bs}(b), os = ${__bs}(o), nw = ${__bs}(n); if (cnt < 0) return ${__sb}(str.replaceAll(os, () => nw)); let r = ""; let i = 0; for (; cnt > 0; cnt--) { const j = str.indexOf(os, i); if (j < 0) break; r += str.slice(i, j) + nw; i = j + os.length; if (os.length === 0) { if (i >= str.length) break; r += str[i]; i++; } } return ${__sb}(r + str.slice(i)); })(${a[0]}, ${a[1]}, ${a[2]}, ${a[3]})`,
|
|
20
|
+
ToUpper: (a) =>
|
|
21
|
+
`new TextEncoder().encode(new TextDecoder().decode(new Uint8Array(${a[0]})).toUpperCase())`,
|
|
22
|
+
ToLower: (a) =>
|
|
23
|
+
`new TextEncoder().encode(new TextDecoder().decode(new Uint8Array(${a[0]})).toLowerCase())`,
|
|
24
|
+
ToTitle: (a) =>
|
|
25
|
+
`new TextEncoder().encode(new TextDecoder().decode(new Uint8Array(${a[0]})).toUpperCase())`,
|
|
26
|
+
TrimSpace: (a) =>
|
|
27
|
+
`new TextEncoder().encode(new TextDecoder().decode(new Uint8Array(${a[0]})).trim())`,
|
|
23
28
|
Trim: (a) =>
|
|
24
|
-
|
|
29
|
+
`((b, c) => { const s = new TextDecoder().decode(new Uint8Array(b)); const cs = new Set(Array.from(c)); const chars = Array.from(s); let l = 0, r = chars.length; while (l < r && cs.has(chars[l])) l++; while (r > l && cs.has(chars[r - 1])) r--; return new TextEncoder().encode(chars.slice(l, r).join("")); })(${a[0]}, ${a[1]})`,
|
|
25
30
|
Equal: (a) =>
|
|
26
31
|
`((a, b) => { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false; return true; })(${a[0]}, ${a[1]})`,
|
|
27
32
|
Split: (a) => `${__bs}(${a[0]}).split(${__bs}(${a[1]})).map(p => ${__sb}(p))`,
|
|
28
33
|
Join: (a) => `${__sb}(${a[0]}.map(p => ${__bs}(p)).join(${__bs}(${a[1]})))`,
|
|
29
34
|
ReplaceAll: (a) =>
|
|
30
|
-
`((b, o, n) => { const r = []; let i = 0; while (i <= b.length - o.length) { if (o.length > 0 && o.every((v, j) => b[i + j] === v)) { r.push(...n); i += o.length; } else { r.push(b[i++]); } } for (; i < b.length; i++) r.push(b[i]); return
|
|
35
|
+
`((b, o, n) => { const r = []; let i = 0; while (i <= b.length - o.length) { if (o.length > 0 && o.every((v, j) => b[i + j] === v)) { r.push(...n); i += o.length; } else { r.push(b[i++]); } } for (; i < b.length; i++) r.push(b[i]); return new Uint8Array(r); })(${a[0]}, ${a[1]}, ${a[2]})`,
|
|
31
36
|
TrimPrefix: (a) =>
|
|
32
37
|
`((b, p) => p.every((v, i) => b[i] === v) ? b.slice(p.length) : b.slice())(${a[0]}, ${a[1]})`,
|
|
33
38
|
TrimSuffix: (a) =>
|
|
34
39
|
`((b, s) => s.length && s.every((v, i) => b[b.length - s.length + i] === v) ? b.slice(0, -s.length) : b.slice())(${a[0]}, ${a[1]})`,
|
|
35
40
|
TrimLeft: (a) =>
|
|
36
|
-
`((b, c) => { let
|
|
41
|
+
`((b, c) => { const s = new TextDecoder().decode(new Uint8Array(b)); const cs = new Set(Array.from(c)); const chars = Array.from(s); let l = 0, r = chars.length; while (l < r && cs.has(chars[l])) l++; return new TextEncoder().encode(chars.slice(l, r).join("")); })(${a[0]}, ${a[1]})`,
|
|
37
42
|
TrimRight: (a) =>
|
|
38
|
-
`((b, c) => {
|
|
43
|
+
`((b, c) => { const s = new TextDecoder().decode(new Uint8Array(b)); const cs = new Set(Array.from(c)); const chars = Array.from(s); let l = 0, r = chars.length; while (r > l && cs.has(chars[r - 1])) r--; return new TextEncoder().encode(chars.slice(l, r).join("")); })(${a[0]}, ${a[1]})`,
|
|
39
44
|
TrimFunc: (a) =>
|
|
40
|
-
`((b, f) => { let l = 0, r =
|
|
45
|
+
`((b, f) => { const s = new TextDecoder().decode(new Uint8Array(b)); const chars = Array.from(s); let l = 0, r = chars.length; while (l < r && f(chars[l].codePointAt(0))) l++; while (r > l && f(chars[r - 1].codePointAt(0))) r--; return new TextEncoder().encode(chars.slice(l, r).join("")); })(${a[0]}, ${a[1]})`,
|
|
41
46
|
IndexByte: (a) => `(${a[0]}).indexOf(${a[1]})`,
|
|
42
47
|
LastIndex: (a) =>
|
|
43
48
|
`((b, s) => { for (let i = b.length - s.length; i >= 0; i--) if (s.every((v, j) => b[i + j] === v)) return i; return -1; })(${a[0]}, ${a[1]})`,
|
|
44
49
|
LastIndexByte: (a) => `(${a[0]}).lastIndexOf(${a[1]})`,
|
|
45
50
|
Fields: (a) =>
|
|
46
|
-
`((b) => { const s =
|
|
51
|
+
`((b) => { const s = new TextDecoder().decode(new Uint8Array(b ?? [])).trim(); return s === '' ? [] : s.split(/\\s+/).map(w => new TextEncoder().encode(w)); })(${a[0]})`,
|
|
52
|
+
FieldsFunc: (a) =>
|
|
53
|
+
`((b, fn) => { const s = new TextDecoder().decode(new Uint8Array(b ?? [])); const res = []; let cur = ""; for (const ch of s) { const cp = ch.codePointAt(0); if (fn(cp)) { if (cur.length > 0) { res.push(new TextEncoder().encode(cur)); cur = ""; } } else { cur += ch; } } if (cur.length > 0) res.push(new TextEncoder().encode(cur)); return res; })(${a[0]}, ${a[1]})`,
|
|
54
|
+
Clone: (a) =>
|
|
55
|
+
`(${a[0]} ? (${a[0]}.slice ? ${a[0]}.slice() : Array.from(${a[0]})) : null)`,
|
|
47
56
|
Cut: (a) =>
|
|
48
|
-
`((b, sep) => { for (let i = 0; i <= b.length - sep.length; i++) if (sep.every((v, j) => b[i + j] === v)) return [b.slice(0, i), b.slice(i + sep.length), true]; return [b.slice(),
|
|
57
|
+
`((b, sep) => { for (let i = 0; i <= b.length - sep.length; i++) if (sep.every((v, j) => b[i + j] === v)) return [b.slice(0, i), b.slice(i + sep.length), true]; return [b.slice(), new Uint8Array(0), false]; })(${a[0]}, ${a[1]})`,
|
|
49
58
|
ContainsAny: (a) =>
|
|
50
|
-
`
|
|
51
|
-
ContainsRune: (a) =>
|
|
52
|
-
|
|
59
|
+
`((b, chars) => { const s = new TextDecoder().decode(new Uint8Array(b)); for (const c of chars) if (s.includes(c)) return true; return false; })(${a[0]}, ${a[1]})`,
|
|
60
|
+
ContainsRune: (a) =>
|
|
61
|
+
`((b, r) => { const s = new TextDecoder().decode(new Uint8Array(b)); return s.includes(String.fromCodePoint(r < 0 || r > 0x10ffff || (r >= 0xd800 && r <= 0xdfff) ? 0xfffd : r)); })(${a[0]}, ${a[1]})`,
|
|
62
|
+
Map: (a) =>
|
|
63
|
+
`((f, b) => { const s = new TextDecoder().decode(new Uint8Array(b)); let res = ""; for (const c of s) { const r = f(c.codePointAt(0)); if (r >= 0) res += String.fromCodePoint(r); } return new TextEncoder().encode(res); })(${a[0]}, ${a[1]})`,
|
|
53
64
|
SplitN: (a) =>
|
|
54
|
-
`((b, sep, n) => {
|
|
65
|
+
`((b, sep, n) => {
|
|
66
|
+
if (n === 0) return null;
|
|
67
|
+
if (sep.length === 0) {
|
|
68
|
+
if (n < 0 || b.length <= n) {
|
|
69
|
+
const r = [];
|
|
70
|
+
for (let k = 0; k < b.length; k++) r.push(b.slice(k, k + 1));
|
|
71
|
+
return r;
|
|
72
|
+
}
|
|
73
|
+
const r = [];
|
|
74
|
+
for (let k = 0; k < n - 1; k++) r.push(b.slice(k, k + 1));
|
|
75
|
+
r.push(b.slice(n - 1));
|
|
76
|
+
return r;
|
|
77
|
+
}
|
|
78
|
+
const findNext = (start) => {
|
|
79
|
+
for (let k = start; k <= b.length - sep.length; k++) {
|
|
80
|
+
let match = true;
|
|
81
|
+
for (let l = 0; l < sep.length; l++) {
|
|
82
|
+
if (b[k + l] !== sep[l]) { match = false; break; }
|
|
83
|
+
}
|
|
84
|
+
if (match) return k;
|
|
85
|
+
}
|
|
86
|
+
return -1;
|
|
87
|
+
};
|
|
88
|
+
if (n < 0) {
|
|
89
|
+
const r = [];
|
|
90
|
+
let i = 0;
|
|
91
|
+
while (i <= b.length) {
|
|
92
|
+
const j = findNext(i);
|
|
93
|
+
if (j < 0) break;
|
|
94
|
+
r.push(b.slice(i, j));
|
|
95
|
+
i = j + sep.length;
|
|
96
|
+
}
|
|
97
|
+
r.push(b.slice(i));
|
|
98
|
+
return r;
|
|
99
|
+
}
|
|
100
|
+
const r = [];
|
|
101
|
+
let i = 0;
|
|
102
|
+
for (let c = 1; c < n; c++) {
|
|
103
|
+
const j = findNext(i);
|
|
104
|
+
if (j < 0) break;
|
|
105
|
+
r.push(b.slice(i, j));
|
|
106
|
+
i = j + sep.length;
|
|
107
|
+
}
|
|
108
|
+
r.push(b.slice(i));
|
|
109
|
+
return r;
|
|
110
|
+
})(${a[0]}, ${a[1]}, ${a[2]})`,
|
|
55
111
|
NewReader: (a) =>
|
|
56
|
-
`{_src:
|
|
112
|
+
`((b) => ({ _src: b, _pos: 0, Read(p) { if (this._pos >= this._src.length) return [0, __io_eof]; const n = Math.min(p.length, this._src.length - this._pos); for (let i = 0; i < n; i++) p[i] = this._src[this._pos + i]; this._pos += n; return [n, null]; }, Len() { return Math.max(0, this._src.length - this._pos); }, Reset(b2) { this._src = b2; this._pos = 0; } }))(${a[0]})`,
|
|
57
113
|
};
|
|
58
114
|
|
|
59
115
|
/** @type {ThisType<CodeGen>} */
|
|
60
116
|
export const bytesMethods = {
|
|
61
117
|
_genBytes(fn, a) {
|
|
118
|
+
if (fn === "NewReader") this.useHelper("ioEOF");
|
|
62
119
|
const gen = BYTES_DISPATCH[fn];
|
|
63
120
|
return gen ? gen(a()) : undefined;
|
|
64
121
|
},
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/** @type {ThisType<CodeGen>} */
|
|
6
6
|
export const errorsMethods = {
|
|
7
|
-
_genErrors(fn, a) {
|
|
7
|
+
_genErrors(fn, a, expr) {
|
|
8
8
|
const args = a();
|
|
9
9
|
if (fn === "New") {
|
|
10
10
|
this.useHelper("error");
|
|
@@ -15,6 +15,30 @@ export const errorsMethods = {
|
|
|
15
15
|
return `__errorIs(${args[0]}, ${args[1]})`;
|
|
16
16
|
}
|
|
17
17
|
if (fn === "Unwrap") return `(${args[0]}?._cause ?? null)`;
|
|
18
|
+
if (fn === "As") {
|
|
19
|
+
this.useHelper("errorAs");
|
|
20
|
+
const targetGoType = expr?.args?.[1]?._type;
|
|
21
|
+
const baseGoType = targetGoType?.base ?? targetGoType;
|
|
22
|
+
const concreteGoType = baseGoType?.base ?? baseGoType;
|
|
23
|
+
const typeName = concreteGoType?.name;
|
|
24
|
+
if (concreteGoType?.kind === "interface" || typeName === "error") {
|
|
25
|
+
return `__errorAs(${args[0]}, ${args[1]}, (x) => x !== null && (typeof x === "object" ? typeof x.Error === "function" : true))`;
|
|
26
|
+
}
|
|
27
|
+
// Named non-struct error types sit in interfaces as boxes; store the raw value.
|
|
28
|
+
const namedBox = this._namedBoxInfo(concreteGoType);
|
|
29
|
+
if (namedBox) {
|
|
30
|
+
return `__errorAs(${args[0]}, ${args[1]}, (x) => x instanceof ${namedBox.cls}, (x) => x.__gfUnbox())`;
|
|
31
|
+
}
|
|
32
|
+
if (typeName) {
|
|
33
|
+
return `__errorAs(${args[0]}, ${args[1]}, (x) => (typeof ${typeName} === "function" && x instanceof ${typeName}) || x?.constructor?.name === "${typeName}" || x?.__struct === "${typeName}")`;
|
|
34
|
+
}
|
|
35
|
+
return `__errorAs(${args[0]}, ${args[1]})`;
|
|
36
|
+
}
|
|
37
|
+
if (fn === "Join") {
|
|
38
|
+
this.useHelper("error");
|
|
39
|
+
this.useHelper("errorJoin");
|
|
40
|
+
return `__errorJoin(${args.join(", ")})`;
|
|
41
|
+
}
|
|
18
42
|
return undefined;
|
|
19
43
|
},
|
|
20
44
|
};
|