goscript 0.2.6 → 0.2.7

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 (264) hide show
  1. package/cmd/goscript/cmd-compile.go +7 -0
  2. package/cmd/goscript/cmd_compile_test.go +83 -0
  3. package/compiler/compile-request.go +3 -0
  4. package/compiler/compiler-cache.go +828 -0
  5. package/compiler/compiler-cache_test.go +705 -0
  6. package/compiler/config.go +2 -0
  7. package/compiler/index.test.ts +26 -1
  8. package/compiler/index.ts +5 -0
  9. package/compiler/lowered-program.go +31 -20
  10. package/compiler/lowering.go +349 -93
  11. package/compiler/lowering_bench_test.go +1 -0
  12. package/compiler/override-facts.go +309 -8
  13. package/compiler/override-parity-verifier.go +45 -1
  14. package/compiler/override-parity-verifier_test.go +100 -0
  15. package/compiler/override-registry_test.go +1 -0
  16. package/compiler/package-graph.go +40 -12
  17. package/compiler/package-graph_test.go +29 -0
  18. package/compiler/runtime-contract.go +8 -0
  19. package/compiler/service.go +98 -11
  20. package/compiler/skeleton_test.go +110 -14
  21. package/compiler/typescript-emitter.go +120 -23
  22. package/dist/compiler/index.d.ts +2 -0
  23. package/dist/compiler/index.js +3 -0
  24. package/dist/compiler/index.js.map +1 -1
  25. package/dist/gs/builtin/builtin.d.ts +24 -33
  26. package/dist/gs/builtin/builtin.js +54 -61
  27. package/dist/gs/builtin/builtin.js.map +1 -1
  28. package/dist/gs/builtin/hostio.d.ts +1 -0
  29. package/dist/gs/builtin/hostio.js +1 -1
  30. package/dist/gs/builtin/hostio.js.map +1 -1
  31. package/dist/gs/builtin/index.d.ts +1 -0
  32. package/dist/gs/builtin/index.js +1 -0
  33. package/dist/gs/builtin/index.js.map +1 -1
  34. package/dist/gs/builtin/panic.d.ts +18 -0
  35. package/dist/gs/builtin/panic.js +98 -0
  36. package/dist/gs/builtin/panic.js.map +1 -0
  37. package/dist/gs/builtin/slice.d.ts +10 -0
  38. package/dist/gs/builtin/slice.js +110 -53
  39. package/dist/gs/builtin/slice.js.map +1 -1
  40. package/dist/gs/builtin/type.js +15 -3
  41. package/dist/gs/builtin/type.js.map +1 -1
  42. package/dist/gs/builtin/varRef.d.ts +1 -1
  43. package/dist/gs/builtin/varRef.js +3 -2
  44. package/dist/gs/builtin/varRef.js.map +1 -1
  45. package/dist/gs/bytes/bytes.gs.js +51 -38
  46. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  47. package/dist/gs/bytes/reader.gs.d.ts +1 -1
  48. package/dist/gs/bytes/reader.gs.js +6 -7
  49. package/dist/gs/bytes/reader.gs.js.map +1 -1
  50. package/dist/gs/cmp/index.d.ts +1 -1
  51. package/dist/gs/cmp/index.js +43 -10
  52. package/dist/gs/cmp/index.js.map +1 -1
  53. package/dist/gs/context/context.d.ts +2 -2
  54. package/dist/gs/context/context.js +1 -1
  55. package/dist/gs/context/context.js.map +1 -1
  56. package/dist/gs/embed/index.js +1 -1
  57. package/dist/gs/embed/index.js.map +1 -1
  58. package/dist/gs/encoding/binary/index.js +201 -8
  59. package/dist/gs/encoding/binary/index.js.map +1 -1
  60. package/dist/gs/encoding/json/index.d.ts +5 -0
  61. package/dist/gs/encoding/json/index.js +388 -25
  62. package/dist/gs/encoding/json/index.js.map +1 -1
  63. package/dist/gs/errors/errors.js +17 -24
  64. package/dist/gs/errors/errors.js.map +1 -1
  65. package/dist/gs/fmt/fmt.js +129 -35
  66. package/dist/gs/fmt/fmt.js.map +1 -1
  67. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1 -1
  68. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -1
  69. package/dist/gs/internal/bytealg/index.js +43 -8
  70. package/dist/gs/internal/bytealg/index.js.map +1 -1
  71. package/dist/gs/internal/byteorder/index.d.ts +2 -2
  72. package/dist/gs/internal/byteorder/index.js +2 -2
  73. package/dist/gs/internal/byteorder/index.js.map +1 -1
  74. package/dist/gs/io/fs/format.js +2 -2
  75. package/dist/gs/io/fs/format.js.map +1 -1
  76. package/dist/gs/io/fs/fs.d.ts +1 -1
  77. package/dist/gs/io/fs/fs.js +1 -1
  78. package/dist/gs/io/fs/fs.js.map +1 -1
  79. package/dist/gs/io/io.d.ts +21 -21
  80. package/dist/gs/io/io.js +49 -50
  81. package/dist/gs/io/io.js.map +1 -1
  82. package/dist/gs/math/bits/index.js +26 -8
  83. package/dist/gs/math/bits/index.js.map +1 -1
  84. package/dist/gs/math/copysign.gs.js +10 -17
  85. package/dist/gs/math/copysign.gs.js.map +1 -1
  86. package/dist/gs/math/pow.gs.js +5 -0
  87. package/dist/gs/math/pow.gs.js.map +1 -1
  88. package/dist/gs/math/signbit.gs.js +6 -2
  89. package/dist/gs/math/signbit.gs.js.map +1 -1
  90. package/dist/gs/mime/index.js +1 -0
  91. package/dist/gs/mime/index.js.map +1 -1
  92. package/dist/gs/net/http/index.d.ts +6 -6
  93. package/dist/gs/net/http/index.js +507 -43
  94. package/dist/gs/net/http/index.js.map +1 -1
  95. package/dist/gs/os/stat.gs.d.ts +2 -2
  96. package/dist/gs/os/types.gs.d.ts +1 -1
  97. package/dist/gs/os/types.gs.js +1 -1
  98. package/dist/gs/os/types.gs.js.map +1 -1
  99. package/dist/gs/os/types_js.gs.d.ts +1 -1
  100. package/dist/gs/os/types_js.gs.js +7 -7
  101. package/dist/gs/os/types_js.gs.js.map +1 -1
  102. package/dist/gs/os/types_unix.gs.d.ts +1 -1
  103. package/dist/gs/os/types_unix.gs.js +1 -1
  104. package/dist/gs/os/types_unix.gs.js.map +1 -1
  105. package/dist/gs/os/zero_copy_posix.gs.d.ts +1 -1
  106. package/dist/gs/os/zero_copy_posix.gs.js +1 -1
  107. package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
  108. package/dist/gs/path/filepath/match.js +8 -4
  109. package/dist/gs/path/filepath/match.js.map +1 -1
  110. package/dist/gs/path/filepath/path.js +216 -42
  111. package/dist/gs/path/filepath/path.js.map +1 -1
  112. package/dist/gs/path/match.js +6 -3
  113. package/dist/gs/path/match.js.map +1 -1
  114. package/dist/gs/reflect/type.d.ts +5 -4
  115. package/dist/gs/reflect/type.js +29 -11
  116. package/dist/gs/reflect/type.js.map +1 -1
  117. package/dist/gs/slices/slices.js +11 -11
  118. package/dist/gs/slices/slices.js.map +1 -1
  119. package/dist/gs/strconv/atof.gs.js +156 -43
  120. package/dist/gs/strconv/atof.gs.js.map +1 -1
  121. package/dist/gs/strconv/atoi.gs.d.ts +3 -2
  122. package/dist/gs/strconv/atoi.gs.js +86 -67
  123. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  124. package/dist/gs/strconv/ftoa.gs.js +73 -3
  125. package/dist/gs/strconv/ftoa.gs.js.map +1 -1
  126. package/dist/gs/strconv/itoa.gs.d.ts +4 -4
  127. package/dist/gs/strconv/itoa.gs.js +5 -4
  128. package/dist/gs/strconv/itoa.gs.js.map +1 -1
  129. package/dist/gs/strconv/quote.gs.d.ts +1 -1
  130. package/dist/gs/strconv/quote.gs.js +311 -103
  131. package/dist/gs/strconv/quote.gs.js.map +1 -1
  132. package/dist/gs/strings/reader.d.ts +1 -1
  133. package/dist/gs/strings/reader.js +8 -8
  134. package/dist/gs/strings/reader.js.map +1 -1
  135. package/dist/gs/strings/strings.js +87 -61
  136. package/dist/gs/strings/strings.js.map +1 -1
  137. package/dist/gs/sync/atomic/doc_64.gs.d.ts +14 -14
  138. package/dist/gs/sync/atomic/doc_64.gs.js +10 -10
  139. package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
  140. package/dist/gs/sync/atomic/type.gs.d.ts +22 -22
  141. package/dist/gs/sync/atomic/type.gs.js +4 -4
  142. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  143. package/dist/gs/sync/sync.js +50 -12
  144. package/dist/gs/sync/sync.js.map +1 -1
  145. package/dist/gs/syscall/fs.d.ts +6 -6
  146. package/dist/gs/syscall/fs.js +1 -1
  147. package/dist/gs/syscall/fs.js.map +1 -1
  148. package/dist/gs/time/time.d.ts +18 -18
  149. package/dist/gs/time/time.js +58 -55
  150. package/dist/gs/time/time.js.map +1 -1
  151. package/dist/gs/unicode/tables.d.ts +11 -0
  152. package/dist/gs/unicode/tables.js +635 -0
  153. package/dist/gs/unicode/tables.js.map +1 -0
  154. package/dist/gs/unicode/unicode.d.ts +58 -38
  155. package/dist/gs/unicode/unicode.js +362 -278
  156. package/dist/gs/unicode/unicode.js.map +1 -1
  157. package/go.sum +13 -0
  158. package/gs/builtin/builtin.ts +83 -93
  159. package/gs/builtin/hostio.ts +1 -1
  160. package/gs/builtin/index.ts +1 -0
  161. package/gs/builtin/panic.test.ts +189 -0
  162. package/gs/builtin/panic.ts +107 -0
  163. package/gs/builtin/runtime-contract.test.ts +5 -5
  164. package/gs/builtin/slice.test.ts +23 -0
  165. package/gs/builtin/slice.ts +133 -95
  166. package/gs/builtin/type.ts +16 -3
  167. package/gs/builtin/varRef.ts +4 -2
  168. package/gs/builtin/wide-int.test.ts +41 -0
  169. package/gs/bytes/bytes.gs.ts +54 -41
  170. package/gs/bytes/bytes.test.ts +18 -1
  171. package/gs/bytes/reader.gs.ts +7 -8
  172. package/gs/cmp/index.test.ts +55 -0
  173. package/gs/cmp/index.ts +45 -9
  174. package/gs/context/context.ts +3 -3
  175. package/gs/embed/index.ts +2 -2
  176. package/gs/encoding/binary/index.test.ts +104 -0
  177. package/gs/encoding/binary/index.ts +259 -11
  178. package/gs/encoding/json/index.test.ts +107 -0
  179. package/gs/encoding/json/index.ts +400 -29
  180. package/gs/errors/errors.test.ts +44 -1
  181. package/gs/errors/errors.ts +15 -31
  182. package/gs/fmt/fmt.test.ts +70 -2
  183. package/gs/fmt/fmt.ts +128 -34
  184. package/gs/golang.org/x/crypto/cryptobyte/index.ts +1 -1
  185. package/gs/internal/bytealg/index.test.ts +26 -1
  186. package/gs/internal/bytealg/index.ts +44 -8
  187. package/gs/internal/byteorder/index.ts +6 -4
  188. package/gs/io/fs/format.ts +2 -2
  189. package/gs/io/fs/fs.ts +2 -2
  190. package/gs/io/fs/stat.test.ts +2 -2
  191. package/gs/io/fs/sub.test.ts +2 -2
  192. package/gs/io/fs/walk.test.ts +2 -2
  193. package/gs/io/io.test.ts +47 -5
  194. package/gs/io/io.ts +73 -73
  195. package/gs/io/limit.test.ts +103 -0
  196. package/gs/math/bits/index.test.ts +128 -0
  197. package/gs/math/bits/index.ts +26 -8
  198. package/gs/math/copysign.gs.test.ts +3 -1
  199. package/gs/math/copysign.gs.ts +10 -22
  200. package/gs/math/pow.gs.test.ts +4 -5
  201. package/gs/math/pow.gs.ts +5 -0
  202. package/gs/math/signbit.gs.test.ts +2 -1
  203. package/gs/math/signbit.gs.ts +6 -3
  204. package/gs/mime/index.ts +1 -0
  205. package/gs/net/http/index.test.ts +683 -2
  206. package/gs/net/http/index.ts +598 -57
  207. package/gs/net/http/meta.json +3 -0
  208. package/gs/os/stat.gs.ts +2 -2
  209. package/gs/os/types.gs.ts +2 -2
  210. package/gs/os/types_js.gs.ts +9 -9
  211. package/gs/os/types_unix.gs.ts +2 -2
  212. package/gs/os/zero_copy_posix.gs.ts +2 -2
  213. package/gs/path/filepath/match.test.ts +16 -0
  214. package/gs/path/filepath/match.ts +8 -4
  215. package/gs/path/filepath/path.test.ts +91 -9
  216. package/gs/path/filepath/path.ts +223 -49
  217. package/gs/path/match.test.ts +32 -0
  218. package/gs/path/match.ts +6 -3
  219. package/gs/reflect/deepequal.test.ts +1 -1
  220. package/gs/reflect/field.test.ts +1 -1
  221. package/gs/reflect/function-types.test.ts +6 -6
  222. package/gs/reflect/sliceat.test.ts +13 -13
  223. package/gs/reflect/structof.test.ts +4 -4
  224. package/gs/reflect/type.ts +34 -14
  225. package/gs/reflect/typefor.test.ts +5 -5
  226. package/gs/runtime/pprof/index.test.ts +20 -0
  227. package/gs/runtime/trace/index.test.ts +3 -0
  228. package/gs/slices/slices.test.ts +31 -0
  229. package/gs/slices/slices.ts +11 -11
  230. package/gs/strconv/append.test.ts +99 -0
  231. package/gs/strconv/atof.gs.ts +156 -42
  232. package/gs/strconv/atof.test.ts +45 -0
  233. package/gs/strconv/atoi.gs.ts +87 -69
  234. package/gs/strconv/atoi.test.ts +49 -0
  235. package/gs/strconv/ftoa.gs.ts +85 -10
  236. package/gs/strconv/ftoa.test.ts +43 -0
  237. package/gs/strconv/itoa.gs.ts +10 -9
  238. package/gs/strconv/quote.gs.ts +335 -108
  239. package/gs/strconv/quote.test.ts +111 -0
  240. package/gs/strings/reader.test.ts +10 -10
  241. package/gs/strings/reader.ts +9 -9
  242. package/gs/strings/strings.test.ts +18 -5
  243. package/gs/strings/strings.ts +81 -68
  244. package/gs/sync/atomic/doc_64.gs.ts +24 -24
  245. package/gs/sync/atomic/doc_64.test.ts +5 -5
  246. package/gs/sync/atomic/type.gs.ts +28 -28
  247. package/gs/sync/sync.test.ts +109 -1
  248. package/gs/sync/sync.ts +46 -12
  249. package/gs/syscall/fs.ts +8 -8
  250. package/gs/syscall/net.test.ts +1 -1
  251. package/gs/time/parse.test.ts +45 -0
  252. package/gs/time/time.test.ts +46 -23
  253. package/gs/time/time.ts +69 -66
  254. package/gs/unicode/gen.go +198 -0
  255. package/gs/unicode/tables.ts +646 -0
  256. package/gs/unicode/unicode.test.ts +69 -0
  257. package/gs/unicode/unicode.ts +396 -312
  258. package/package.json +1 -1
  259. package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +0 -20
  260. package/dist/gs/github.com/aperturerobotics/util/conc/index.js +0 -134
  261. package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +0 -1
  262. package/gs/github.com/aperturerobotics/util/conc/index.test.ts +0 -30
  263. package/gs/github.com/aperturerobotics/util/conc/index.ts +0 -172
  264. package/gs/github.com/aperturerobotics/util/conc/meta.json +0 -9
@@ -1,12 +1,85 @@
1
1
  import * as $ from "@goscript/builtin/index.js";
2
2
 
3
+ const hexConv = new DataView(new ArrayBuffer(8));
4
+
5
+ // formatHexFloat renders a non-negative finite float in Go's hexadecimal
6
+ // floating-point form: a normalized leading hex digit (1, or 0 for zero), an
7
+ // optional hex fraction, and a binary exponent printed with sign and at least
8
+ // two digits. prec < 0 emits the shortest exact fraction; prec >= 0 emits
9
+ // exactly prec fraction digits with round-half-to-even and carry renormalization.
10
+ // upper selects the 0X/P uppercase form.
11
+ function formatHexFloat(f: number, prec: number, upper: boolean): string {
12
+ hexConv.setFloat64(0, f);
13
+ const hi = hexConv.getUint32(0);
14
+ const lo = hexConv.getUint32(4);
15
+ const biasedExp = (hi >>> 20) & 0x7ff;
16
+ let frac = (BigInt(hi & 0xfffff) << 32n) | BigInt(lo >>> 0);
17
+
18
+ const xPrefix = upper ? "0X" : "0x";
19
+ const pChar = upper ? "P" : "p";
20
+
21
+ const assemble = (intDigit: string, fracHex: string, exp: number): string => {
22
+ if (upper) {
23
+ fracHex = fracHex.toUpperCase();
24
+ }
25
+ const expAbs = Math.abs(exp);
26
+ const expStr = (exp < 0 ? "-" : "+") + String(expAbs).padStart(2, "0");
27
+ const mantissa = fracHex.length > 0 ? intDigit + "." + fracHex : intDigit;
28
+ return xPrefix + mantissa + pChar + expStr;
29
+ };
30
+
31
+ if (biasedExp === 0 && frac === 0n) {
32
+ const fracHex = prec > 0 ? "0".repeat(prec) : "";
33
+ return assemble("0", fracHex, 0);
34
+ }
35
+
36
+ // Normalize to a 52-bit fraction with an implicit leading 1.
37
+ let exp: number;
38
+ if (biasedExp === 0) {
39
+ // Subnormal: shift the leading set bit up to bit 52.
40
+ let k = 51;
41
+ while ((frac & (1n << BigInt(k))) === 0n) {
42
+ k--;
43
+ }
44
+ exp = k - 1074;
45
+ frac = (frac << BigInt(52 - k)) & ((1n << 52n) - 1n);
46
+ } else {
47
+ exp = biasedExp - 1023;
48
+ }
49
+
50
+ let fracHex: string;
51
+ if (prec < 0) {
52
+ fracHex = frac.toString(16).padStart(13, "0").replace(/0+$/, "");
53
+ } else if (prec >= 13) {
54
+ fracHex = frac.toString(16).padStart(13, "0").padEnd(prec, "0");
55
+ } else {
56
+ const keepBits = BigInt(prec * 4);
57
+ const droppedBits = 52n - keepBits;
58
+ let kept = frac >> droppedBits;
59
+ const remainder = frac & ((1n << droppedBits) - 1n);
60
+ const half = 1n << (droppedBits - 1n);
61
+ if (remainder > half || (remainder === half && (kept & 1n) === 1n)) {
62
+ kept += 1n;
63
+ }
64
+ if (kept >= 1n << keepBits) {
65
+ // Carry past the kept digits renormalizes: the integer digit would
66
+ // become 2, so bump the exponent and zero the fraction.
67
+ exp += 1;
68
+ kept = 0n;
69
+ }
70
+ fracHex = prec === 0 ? "" : kept.toString(16).padStart(prec, "0");
71
+ }
72
+
73
+ return assemble("1", fracHex, exp);
74
+ }
75
+
3
76
  // FormatFloat converts the floating-point number f to a string,
4
77
  // according to the format fmt and precision prec. It rounds the
5
78
  // result assuming that the original was obtained from a floating-point
6
79
  // value of bitSize bits (32 for float32, 64 for float64).
7
80
  export function FormatFloat(f: number, fmt: number, prec: number, bitSize: number): string {
8
81
  const fmtChar = String.fromCharCode(fmt);
9
-
82
+
10
83
  // Handle special cases
11
84
  if (isNaN(f)) {
12
85
  return "NaN";
@@ -17,12 +90,18 @@ export function FormatFloat(f: number, fmt: number, prec: number, bitSize: numbe
17
90
  if (f === -Infinity) {
18
91
  return "-Inf";
19
92
  }
20
-
93
+
21
94
  // Convert to appropriate precision for float32
22
95
  if (bitSize === 32) {
23
96
  f = Math.fround(f);
24
97
  }
25
-
98
+
99
+ if (fmtChar === 'x' || fmtChar === 'X') {
100
+ hexConv.setFloat64(0, f);
101
+ const neg = (hexConv.getUint32(0) >>> 31) === 1;
102
+ return (neg ? "-" : "") + formatHexFloat(Math.abs(f), prec, fmtChar === 'X');
103
+ }
104
+
26
105
  switch (fmtChar.toLowerCase()) {
27
106
  case 'e':
28
107
  // Exponential notation
@@ -30,25 +109,21 @@ export function FormatFloat(f: number, fmt: number, prec: number, bitSize: numbe
30
109
  return f.toExponential();
31
110
  }
32
111
  return f.toExponential(prec);
33
-
112
+
34
113
  case 'f':
35
114
  // Fixed-point notation
36
115
  if (prec < 0) {
37
116
  return f.toString();
38
117
  }
39
118
  return f.toFixed(prec);
40
-
119
+
41
120
  case 'g':
42
121
  // Use the more compact of 'e' or 'f'
43
122
  if (prec < 0) {
44
123
  return f.toPrecision();
45
124
  }
46
125
  return f.toPrecision(prec + 1);
47
-
48
- case 'x':
49
- // Hexadecimal notation (simplified)
50
- return f.toString(16);
51
-
126
+
52
127
  default:
53
128
  // Default to 'g' format
54
129
  if (prec < 0) {
@@ -0,0 +1,43 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { FormatFloat } from './ftoa.gs.js'
4
+
5
+ const X = 'x'.charCodeAt(0)
6
+ const XU = 'X'.charCodeAt(0)
7
+
8
+ // Ground truth captured from go1.26.4 strconv.FormatFloat with the 'x' verb.
9
+ describe("strconv.FormatFloat 'x' (Go hex-float syntax)", () => {
10
+ it('emits normalized hex floats with a signed two-digit exponent', () => {
11
+ expect(FormatFloat(100, X, -1, 64)).toBe('0x1.9p+06')
12
+ expect(FormatFloat(1, X, -1, 64)).toBe('0x1p+00')
13
+ expect(FormatFloat(0.5, X, -1, 64)).toBe('0x1p-01')
14
+ expect(FormatFloat(3, X, -1, 64)).toBe('0x1.8p+01')
15
+ expect(FormatFloat(255, X, -1, 64)).toBe('0x1.fep+07')
16
+ expect(FormatFloat(0.1, X, -1, 64)).toBe('0x1.999999999999ap-04')
17
+ })
18
+
19
+ it('handles zero and negative values', () => {
20
+ expect(FormatFloat(0, X, -1, 64)).toBe('0x0p+00')
21
+ expect(FormatFloat(-100, X, -1, 64)).toBe('-0x1.9p+06')
22
+ expect(FormatFloat(-0, X, -1, 64)).toBe('-0x0p+00')
23
+ })
24
+
25
+ it('respects fixed precision with round-half-to-even and carry', () => {
26
+ expect(FormatFloat(100, X, 2, 64)).toBe('0x1.90p+06')
27
+ expect(FormatFloat(100, X, 4, 64)).toBe('0x1.9000p+06')
28
+ expect(FormatFloat(100, X, 13, 64)).toBe('0x1.9000000000000p+06')
29
+ expect(FormatFloat(1.9375, X, 0, 64)).toBe('0x1p+01')
30
+ expect(FormatFloat(1.96875, X, 1, 64)).toBe('0x1.0p+01')
31
+ expect(FormatFloat(255, X, 0, 64)).toBe('0x1p+08')
32
+ expect(FormatFloat(255, X, 1, 64)).toBe('0x1.0p+08')
33
+ })
34
+
35
+ it('formats the smallest subnormal and float32 values', () => {
36
+ expect(FormatFloat(5e-324, X, -1, 64)).toBe('0x1p-1074')
37
+ expect(FormatFloat(100, X, -1, 32)).toBe('0x1.9p+06')
38
+ })
39
+
40
+ it('uses the uppercase 0X/P form for the X verb', () => {
41
+ expect(FormatFloat(100, XU, -1, 64)).toBe('0X1.9P+06')
42
+ })
43
+ })
@@ -3,39 +3,40 @@ import * as $ from "@goscript/builtin/index.js";
3
3
  // FormatUint returns the string representation of i in the given base,
4
4
  // for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
5
5
  // for digit values >= 10.
6
- export function FormatUint(i: number, base: number): string {
6
+ export function FormatUint(i: number | bigint, base: number): string {
7
7
  if (base < 2 || base > 36) {
8
8
  throw new Error("FormatUint: illegal base");
9
9
  }
10
- // JavaScript's toString() handles bases 2-36 natively
11
- return Math.floor(Math.abs(i)).toString(base);
10
+ const v = typeof i === "bigint" ? i : BigInt(Math.trunc(i));
11
+ return BigInt.asUintN(64, v).toString(base);
12
12
  }
13
13
 
14
14
  // FormatInt returns the string representation of i in the given base,
15
15
  // for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
16
16
  // for digit values >= 10.
17
- export function FormatInt(i: number, base: number): string {
17
+ export function FormatInt(i: number | bigint, base: number): string {
18
18
  if (base < 2 || base > 36) {
19
19
  throw new Error("FormatInt: illegal base");
20
20
  }
21
- return Math.floor(i).toString(base);
21
+ const v = typeof i === "bigint" ? i : BigInt(Math.trunc(i));
22
+ return v.toString(base);
22
23
  }
23
24
 
24
25
  // Itoa is equivalent to FormatInt(i, 10).
25
26
  export function Itoa(i: number): string {
26
- return FormatInt(i, 10);
27
+ return FormatInt(BigInt(Math.trunc(i)), 10);
27
28
  }
28
29
 
29
30
  // AppendInt appends the string form of the integer i,
30
31
  // as generated by FormatInt, to dst and returns the extended buffer.
31
- export function AppendInt(dst: $.Bytes, i: number, base: number): $.Bytes {
32
+ export function AppendInt(dst: $.Bytes, i: number | bigint, base: number): $.Bytes {
32
33
  const str = FormatInt(i, base);
33
34
  return $.append(dst, ...$.stringToBytes(str)!);
34
35
  }
35
36
 
36
37
  // AppendUint appends the string form of the unsigned integer i,
37
38
  // as generated by FormatUint, to dst and returns the extended buffer.
38
- export function AppendUint(dst: $.Bytes, i: number, base: number): $.Bytes {
39
+ export function AppendUint(dst: $.Bytes, i: number | bigint, base: number): $.Bytes {
39
40
  const str = FormatUint(i, base);
40
41
  return $.append(dst, ...$.stringToBytes(str)!);
41
- }
42
+ }