gofront 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README.md +3 -3
  2. package/package.json +5 -4
  3. package/src/backend/js/expressions.js +849 -371
  4. package/src/backend/js/index.js +241 -147
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +512 -2547
  7. package/src/backend/js/statements.js +506 -103
  8. package/src/backend/js/stdlib/index.js +45 -93
  9. package/src/backend/js/templ.js +32 -45
  10. package/src/backend/js/type-info.js +177 -13
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +63 -171
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +490 -965
  15. package/src/backend/wasm/emit-builtins.js +643 -256
  16. package/src/backend/wasm/emit-exprs.js +124 -57
  17. package/src/backend/wasm/emit-maps.js +17 -367
  18. package/src/backend/wasm/emit-stmts.js +325 -75
  19. package/src/backend/wasm/emit.js +104 -13
  20. package/src/backend/wasm/globals.js +47 -8
  21. package/src/backend/wasm/glue.js +2 -4
  22. package/src/backend/wasm/index.js +36 -530
  23. package/src/backend/wasm/method-expr.js +12 -1
  24. package/src/backend/wasm/module-emitter.js +92 -717
  25. package/src/backend/wasm/monomorph.js +103 -6
  26. package/src/backend/wasm/natives.js +596 -0
  27. package/src/backend/wasm/prescan.js +5 -153
  28. package/src/backend/wasm/prune-funcs.js +89 -0
  29. package/src/backend/wasm/stdlib/index.js +2 -32
  30. package/src/backend/wasm/types.js +68 -20
  31. package/src/backend/wasm/variadic.js +3 -3
  32. package/src/cli/cli-core.js +5 -1
  33. package/src/cli/test-runner.js +115 -342
  34. package/src/compiler.js +108 -130
  35. package/src/lexer/lexer.js +105 -11
  36. package/src/lexer/templ-lexer.js +61 -18
  37. package/src/lexer/tokens.js +1 -0
  38. package/src/link/stdlib.js +354 -132
  39. package/src/link/type-names.js +148 -0
  40. package/src/link/wasm.js +30 -6
  41. package/src/lower/bounds.js +153 -0
  42. package/src/lower/captures.js +92 -33
  43. package/src/lower/embedding.js +32 -3
  44. package/src/lower/errors-as.js +196 -0
  45. package/src/lower/fmt-formatters.js +905 -0
  46. package/src/lower/functions.js +2 -0
  47. package/src/lower/gen-types.js +274 -0
  48. package/src/lower/index.js +7 -1
  49. package/src/lower/json-codecs.js +228 -247
  50. package/src/lower/ownership.js +25 -7
  51. package/src/lower/reachability.js +69 -51
  52. package/src/lower/walk.js +12 -0
  53. package/src/parser/declarations.js +28 -5
  54. package/src/parser/expressions.js +86 -16
  55. package/src/parser/statements.js +1 -0
  56. package/src/parser/templ.js +44 -5
  57. package/src/parser/types.js +1 -0
  58. package/src/resolver.js +1 -2
  59. package/src/typechecker/assignability.js +124 -11
  60. package/src/typechecker/const-fold.js +70 -27
  61. package/src/typechecker/constants.js +32 -6
  62. package/src/typechecker/expressions.js +326 -98
  63. package/src/typechecker/index.js +208 -33
  64. package/src/typechecker/init-order.js +136 -40
  65. package/src/typechecker/operand-text.js +40 -0
  66. package/src/typechecker/resolve.js +192 -36
  67. package/src/typechecker/statements.js +122 -11
  68. package/src/typechecker/stdlib/excluded.js +9 -5
  69. package/src/typechecker/stdlib/index.js +25 -9
  70. package/src/typechecker/termination.js +10 -1
  71. package/src/typechecker/types.js +203 -573
  72. package/stdlib/bytes/buffer.go +479 -0
  73. package/stdlib/bytes/bytes.go +1010 -0
  74. package/stdlib/bytes/reader.go +161 -0
  75. package/stdlib/context/context.go +115 -0
  76. package/stdlib/crypto/rand/rand.go +34 -0
  77. package/stdlib/crypto/sha256/sha256.go +249 -0
  78. package/stdlib/encoding/base64/base64.go +331 -0
  79. package/stdlib/encoding/binary/binary.go +332 -0
  80. package/stdlib/encoding/hex/hex.go +140 -0
  81. package/stdlib/encoding/json/json.go +62 -0
  82. package/stdlib/errors/errors.go +174 -0
  83. package/stdlib/fmt/errors.go +110 -0
  84. package/stdlib/fmt/format.go +732 -0
  85. package/stdlib/fmt/print.go +1232 -0
  86. package/stdlib/gom/gom.go +293 -0
  87. package/stdlib/html/html.go +251 -0
  88. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  89. package/stdlib/internal/jsonrt/dec.go +171 -38
  90. package/stdlib/internal/jsonrt/enc.go +186 -36
  91. package/stdlib/internal/jsonrt/scanner.go +17 -8
  92. package/stdlib/io/io.go +157 -1
  93. package/stdlib/maps/maps.go +131 -0
  94. package/stdlib/math/bits/bits.go +507 -0
  95. package/stdlib/math/extra.go +16 -14
  96. package/stdlib/math/math.go +439 -0
  97. package/stdlib/math/rand/rand.go +297 -0
  98. package/stdlib/os/os.go +93 -0
  99. package/stdlib/path/filepath/filepath.go +47 -0
  100. package/stdlib/path/path.go +394 -0
  101. package/stdlib/regexp/regexp.go +231 -0
  102. package/stdlib/slices/slices.go +526 -0
  103. package/stdlib/slices/sort.go +209 -0
  104. package/stdlib/slices/zsort_cmp.go +480 -0
  105. package/stdlib/slices/zsort_ordered.go +482 -0
  106. package/stdlib/sort/sort.go +391 -452
  107. package/stdlib/sort/zsort_func.go +480 -0
  108. package/stdlib/sort/zsort_iface.go +480 -0
  109. package/stdlib/strconv/float.go +1699 -0
  110. package/stdlib/strconv/isprint.go +752 -0
  111. package/stdlib/strconv/quote.go +235 -50
  112. package/stdlib/strconv/strconv.go +616 -0
  113. package/stdlib/strings/builder.go +95 -0
  114. package/stdlib/strings/reader.go +163 -0
  115. package/stdlib/strings/replacer.go +102 -0
  116. package/stdlib/strings/strings.go +807 -0
  117. package/stdlib/sync/sync.go +268 -0
  118. package/stdlib/testing/async_js.go +61 -0
  119. package/stdlib/testing/benchmark.go +297 -0
  120. package/stdlib/testing/testing.go +523 -0
  121. package/stdlib/time/duration.go +233 -0
  122. package/stdlib/time/format.go +745 -0
  123. package/stdlib/time/parse.go +790 -0
  124. package/stdlib/time/sleep_js.go +63 -0
  125. package/stdlib/time/time.go +834 -0
  126. package/stdlib/unicode/unicode.go +141 -3
  127. package/stdlib/unicode/utf8/utf8.go +464 -0
  128. package/src/backend/js/fmt-runtime.js +0 -573
  129. package/src/backend/js/stdlib/base64.js +0 -12
  130. package/src/backend/js/stdlib/binary.js +0 -102
  131. package/src/backend/js/stdlib/bits.js +0 -119
  132. package/src/backend/js/stdlib/builder.js +0 -98
  133. package/src/backend/js/stdlib/bytes.js +0 -368
  134. package/src/backend/js/stdlib/errors.js +0 -45
  135. package/src/backend/js/stdlib/fmt.js +0 -517
  136. package/src/backend/js/stdlib/gom.js +0 -155
  137. package/src/backend/js/stdlib/hex.js +0 -17
  138. package/src/backend/js/stdlib/html.js +0 -20
  139. package/src/backend/js/stdlib/io.js +0 -137
  140. package/src/backend/js/stdlib/json.js +0 -1167
  141. package/src/backend/js/stdlib/maps.js +0 -37
  142. package/src/backend/js/stdlib/math.js +0 -85
  143. package/src/backend/js/stdlib/os.js +0 -13
  144. package/src/backend/js/stdlib/path.js +0 -48
  145. package/src/backend/js/stdlib/rand.js +0 -32
  146. package/src/backend/js/stdlib/regexp.js +0 -54
  147. package/src/backend/js/stdlib/sha256.js +0 -12
  148. package/src/backend/js/stdlib/shared.js +0 -17
  149. package/src/backend/js/stdlib/simd.js +0 -34
  150. package/src/backend/js/stdlib/slices.js +0 -107
  151. package/src/backend/js/stdlib/sort.js +0 -30
  152. package/src/backend/js/stdlib/strconv.js +0 -79
  153. package/src/backend/js/stdlib/strings.js +0 -301
  154. package/src/backend/js/stdlib/sync.js +0 -13
  155. package/src/backend/js/stdlib/testing.js +0 -41
  156. package/src/backend/js/stdlib/time.js +0 -152
  157. package/src/backend/js/stdlib/unicode.js +0 -25
  158. package/src/backend/js/stdlib/utf8.js +0 -26
  159. package/src/backend/wasm/stdlib/bytes.js +0 -6716
  160. package/src/backend/wasm/stdlib/core.js +0 -10278
  161. package/src/backend/wasm/stdlib/io.js +0 -3578
  162. package/src/backend/wasm/stdlib/packages.js +0 -2402
  163. package/src/backend/wasm/stdlib/pure.js +0 -720
  164. package/src/backend/wasm/stdlib/time.js +0 -2229
  165. package/src/typechecker/stdlib/core.js +0 -1079
  166. package/src/typechecker/stdlib/extended.js +0 -1210
  167. package/stdlib/bytes/iter.go +0 -192
  168. package/stdlib/bytes/search.go +0 -240
  169. package/stdlib/bytes/split.go +0 -218
  170. package/stdlib/errors/overlay.go +0 -12
  171. package/stdlib/maps/iter.go +0 -65
  172. package/stdlib/slices/extra.go +0 -73
  173. package/stdlib/slices/iter.go +0 -113
  174. package/stdlib/strings/extra.go +0 -35
  175. package/stdlib/strings/iter.go +0 -122
  176. package/stdlib/sync/extra.go +0 -105
  177. package/stdlib/unicode/utf8/bytes.go +0 -239
@@ -0,0 +1,196 @@
1
+ // src/lower/errors-as.js
2
+ // errors.As as generated Go source.
3
+ //
4
+ // `errors.As(err, &x)` stores through a pointer whose type only the checker
5
+ // knows. Each call site gets a function generated for its static target
6
+ // type; it walks the error tree like the real package and honours custom
7
+ // `As(any) bool` methods. The functions are ordinary Go, parsed and checked
8
+ // as part of the package's generated file (src/link/stdlib.js), so both
9
+ // backends compile the same code.
10
+
11
+ import {
12
+ importsFor,
13
+ mentionsTypeParam,
14
+ TypeSpeller,
15
+ walkNodes,
16
+ } from "./gen-types.js";
17
+
18
+ const ERRORS_PATH = "errors";
19
+ const NOT_POINTER =
20
+ "errors.As: second argument must be a non-nil pointer to a type that implements error or to any interface type";
21
+
22
+ // The names the file imports `errors` as.
23
+ function errorsAliases(program) {
24
+ const aliases = new Set();
25
+ for (const imp of program.imports ?? [])
26
+ for (const spec of imp.imports)
27
+ if (spec.path === ERRORS_PATH && spec.alias !== "_")
28
+ aliases.add(spec.alias ?? "errors");
29
+ return aliases;
30
+ }
31
+
32
+ const isAsRef = (node, aliases) =>
33
+ node.kind === "SelectorExpr" &&
34
+ node.expr?.kind === "Ident" &&
35
+ node.expr._type?.kind === "namespace" &&
36
+ aliases.has(node.expr.name) &&
37
+ node.field === "As";
38
+
39
+ const isAsCall = (node, aliases) =>
40
+ node.kind === "CallExpr" && isAsRef(node.func, aliases);
41
+
42
+ // Marks `call` to call the generated function `name`. The function takes the
43
+ // typed pointer: the target is not boxed into an interface the way
44
+ // errors.As's `any` parameter asked.
45
+ function markCall(call, name) {
46
+ call.func._genEntry = name;
47
+ const arg = call.args[1];
48
+ arg._ifaceBox = undefined;
49
+ arg._ifaceSrc = undefined;
50
+ arg._ifaceNamedType = undefined;
51
+ arg._ifacePtrFields = undefined;
52
+ }
53
+
54
+ // One function per distinct target type; `tparams` ("[T any]") makes it the
55
+ // shared function for targets that are a type parameter.
56
+ function asFunction(name, target, tparams = "") {
57
+ return `func ${name}${tparams}(err error, target *${target}) bool {
58
+ if target == nil {
59
+ panic("errors: target must be a non-nil pointer")
60
+ }
61
+ for err != nil {
62
+ if v, ok := err.(${target}); ok {
63
+ *target = v
64
+ return true
65
+ }
66
+ if a, ok := err.(interface{ As(any) bool }); ok && a.As(target) {
67
+ return true
68
+ }
69
+ switch u := err.(type) {
70
+ case interface{ Unwrap() error }:
71
+ err = u.Unwrap()
72
+ case interface{ Unwrap() []error }:
73
+ for _, e := range u.Unwrap() {
74
+ if e != nil && ${name}${tparams ? "[T]" : ""}(e, target) {
75
+ return true
76
+ }
77
+ }
78
+ return false
79
+ default:
80
+ return false
81
+ }
82
+ }
83
+ return false
84
+ }`;
85
+ }
86
+
87
+ // The `errors.As` calls of the programs, and a diagnostic for each use of
88
+ // errors.As that is not a call.
89
+ function findSites(programs) {
90
+ const sites = [];
91
+ const diagnostics = [];
92
+ for (const program of programs) {
93
+ const aliases = errorsAliases(program);
94
+ if (aliases.size === 0) continue;
95
+ const callees = new Set();
96
+ const refs = [];
97
+ walkNodes(program.decls, (node) => {
98
+ if (isAsCall(node, aliases)) {
99
+ sites.push({ call: node, program });
100
+ callees.add(node.func);
101
+ } else if (isAsRef(node, aliases)) {
102
+ refs.push(node);
103
+ }
104
+ });
105
+ for (const node of refs)
106
+ if (!callees.has(node))
107
+ diagnostics.push({
108
+ program,
109
+ node: node.expr,
110
+ message: "errors.As cannot be used as a value",
111
+ hint: "call errors.As directly",
112
+ });
113
+ }
114
+ return { sites, diagnostics };
115
+ }
116
+
117
+ // What a call's target type allows: { base } for a target to generate for, or
118
+ // { message, hint } for one the generator rejects.
119
+ function classifyTarget(call) {
120
+ const argType = call.args[1]?._type;
121
+ if (argType?.kind !== "pointer") return { message: NOT_POINTER };
122
+ const base = argType.base;
123
+ if (base?.kind === "interface" && !base.name && base.methods?.size > 0)
124
+ return {
125
+ message:
126
+ "errors.As with a target of an anonymous interface type is not yet available",
127
+ hint: "declare a named interface type for the target",
128
+ };
129
+ if (base?.kind !== "typeParam" && mentionsTypeParam(base))
130
+ return {
131
+ message:
132
+ "errors.As with a target that mentions a type parameter is not yet available",
133
+ hint: "use a target that is a type parameter itself, or a concrete type",
134
+ };
135
+ return { base };
136
+ }
137
+
138
+ // Generates the `errors.As` functions for a package's call sites. Returns
139
+ // null when it has none; otherwise { body, imports, diagnostics, link } and
140
+ // marks each call's SelectorExpr with `_genEntry`.
141
+ export function generateErrorsAs(programs, _checker, pkgName) {
142
+ const { sites, diagnostics } = findSites(programs);
143
+ if (sites.length + diagnostics.length === 0) return null;
144
+ const qualifiers = new Map();
145
+ const speller = new TypeSpeller(pkgName, qualifiers, programs);
146
+ const prefix = `gfe_${String(pkgName).replace(/[^A-Za-z0-9_]/g, "_")}_as_`;
147
+ const names = new Map(); // spelled target -> function name
148
+ const out = [];
149
+ const sharedSites = []; // targets that are a type parameter
150
+ for (const { call, program } of sites) {
151
+ const { base, message, hint } = classifyTarget(call);
152
+ let target;
153
+ try {
154
+ if (base?.kind === "typeParam") sharedSites.push(call);
155
+ else if (base) target = speller.spell(base);
156
+ } catch (e) {
157
+ diagnostics.push({
158
+ program,
159
+ node: call.func.expr,
160
+ message: `errors.As: ${e.message}`,
161
+ });
162
+ continue;
163
+ }
164
+ if (!base) {
165
+ diagnostics.push({ program, node: call.func.expr, message, hint });
166
+ continue;
167
+ }
168
+ if (target === undefined) continue;
169
+ if (!names.has(target)) {
170
+ names.set(target, `${prefix}${names.size}`);
171
+ out.push(asFunction(names.get(target), target));
172
+ }
173
+ markCall(call, names.get(target));
174
+ }
175
+ const sharedName = `${prefix}t`;
176
+ if (sharedSites.length > 0) out.push(asFunction(sharedName, "T", "[T any]"));
177
+ for (const call of sharedSites) markCall(call, sharedName);
178
+ // The shared function is generic: once it is checked, its call sites take
179
+ // the type arguments the checker would have inferred.
180
+ const link = (chk) => {
181
+ const generic = chk.globals.symbols.get(sharedName);
182
+ for (const call of sharedSites) {
183
+ const typeArgs = [call.args[1]._type.base];
184
+ for (const n of [call, call.func]) {
185
+ n._typeArgs = typeArgs;
186
+ n._genericFnType = generic;
187
+ }
188
+ }
189
+ };
190
+ return {
191
+ body: out.join("\n\n"),
192
+ imports: importsFor(qualifiers),
193
+ diagnostics,
194
+ link,
195
+ };
196
+ }