@amritk/nish-x86_64-linux 0.20.0 → 0.21.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 (70) hide show
  1. package/INSTALL.md +22 -10
  2. package/bin/nish +0 -0
  3. package/docs/AI.md +2759 -0
  4. package/package.json +2 -1
  5. package/runtime/browser.d.ts +14 -0
  6. package/runtime/browser.mjs +88 -0
  7. package/runtime/core/arrays.d.ts +18 -0
  8. package/runtime/core/arrays.mjs +125 -0
  9. package/runtime/core/checks.mjs +20 -0
  10. package/runtime/core/host.d.ts +70 -0
  11. package/runtime/core/host.mjs +311 -0
  12. package/runtime/core/numbers.d.ts +53 -0
  13. package/runtime/core/numbers.mjs +316 -0
  14. package/runtime/core/result.d.ts +41 -0
  15. package/runtime/core/result.mjs +127 -0
  16. package/runtime/core/strings.d.ts +14 -0
  17. package/runtime/core/strings.mjs +169 -0
  18. package/runtime/core.d.ts +9 -0
  19. package/runtime/core.mjs +55 -0
  20. package/runtime/host.d.ts +6 -0
  21. package/runtime/nish.d.ts +44 -0
  22. package/runtime/nish.h +75 -2
  23. package/runtime/nish.mjs +23 -3
  24. package/runtime/node.mjs +383 -0
  25. package/runtime/runtime-bytes.c +401 -0
  26. package/runtime/runtime-cross.c +1 -1
  27. package/runtime/runtime-host.c +1 -1
  28. package/runtime/runtime-os.c +1 -1
  29. package/runtime/runtime-parallel.c +1 -1
  30. package/runtime/runtime-simd.c +231 -7
  31. package/runtime/runtime-term.c +504 -0
  32. package/runtime/runtime-wasm.c +0 -11
  33. package/runtime/runtime.c +190 -6
  34. package/runtime/shim.mjs +6 -985
  35. package/runtime/sqlite/LICENSE.md +85 -0
  36. package/runtime/sqlite/README.md +45 -0
  37. package/runtime/sqlite/nish-sqlite.c +359 -0
  38. package/runtime/sqlite/sqlite3.c +271131 -0
  39. package/runtime/sqlite/sqlite3.h +14447 -0
  40. package/scripts/build.sh +261 -53
  41. package/std/LICENSE-fast-float +23 -0
  42. package/std/LICENSE-fdlibm +8 -0
  43. package/std/README.md +31 -11
  44. package/std/base64.ts +116 -0
  45. package/std/bytes.ts +256 -0
  46. package/std/cli.ts +328 -0
  47. package/std/collections.ts +6 -5
  48. package/std/crypto/LICENSE-crypt_blowfish +26 -0
  49. package/std/crypto/base64url.ts +125 -0
  50. package/std/crypto/bcrypt.ts +760 -0
  51. package/std/crypto/hmac.ts +138 -2
  52. package/std/crypto/x509.ts +11 -122
  53. package/std/json-tokenizer.ts +2998 -57
  54. package/std/json-value.ts +22 -3
  55. package/std/json.ts +83 -1
  56. package/std/math.ts +608 -0
  57. package/std/net/http1-server.ts +85 -8
  58. package/std/net/http3-server.ts +50 -12
  59. package/std/net/postgres.ts +1875 -0
  60. package/std/net/quic-listener.ts +20 -4
  61. package/std/regex.ts +4274 -0
  62. package/std/sqlite.ts +391 -0
  63. package/std/term-io.ts +978 -0
  64. package/std/term-pixels.ts +874 -0
  65. package/std/term-probe.ts +459 -0
  66. package/std/term-rate.ts +993 -0
  67. package/std/term.ts +2453 -0
  68. package/std/text.ts +90 -7
  69. package/std/yaml-lines.ts +141 -0
  70. package/std/yaml.ts +4675 -0
package/std/text.ts CHANGED
@@ -3,17 +3,18 @@
3
3
  *
4
4
  * The language gives a string `length`, `charCodeAt`, `substring`, `indexOf`,
5
5
  * `startsWith`, `endsWith` and `===` by content, and an array `join`. It does
6
- * **not** give `split`, `trim`, `toLowerCase` or a regular expression, and that
7
- * is a decision rather than a gap: each of those allocates, and several of them
8
- * need a locale or a character table that this runtime has no room for
6
+ * **not** give `split`, `trim`, `toLowerCase` or a regular expression (that is
7
+ * `std/regex`), and that is a decision rather than a gap: each allocates, and
8
+ * several need a locale or a character table this runtime has no room for
9
9
  * (`docs/wp7-runtime.md` keeps the runtime under a measured byte budget).
10
10
  *
11
11
  * So a program that reads a file and wants its lines writes the loop. This
12
12
  * module is that loop, written once. Every offset here is a **byte** offset,
13
- * like `s.length` itself, and every function is ASCII-only where it inspects
14
- * characters at all — a UTF-8 string passes through `splitLines` and `split`
15
- * untouched, because a newline and a space cannot appear inside a multi-byte
16
- * sequence.
13
+ * like `s.length` itself, and every function but one is ASCII-only where it
14
+ * inspects characters at all — a UTF-8 string passes through `splitLines` and
15
+ * `split` untouched, because a newline and a space cannot appear inside a
16
+ * multi-byte sequence. The one is `codePointLength`, which counts code points
17
+ * rather than bytes and answers the same natively and under Node; it says how.
17
18
  *
18
19
  * Every width this module declares is spelled (`i32`, never `number`) *and*
19
20
  * every value a builtin hands it is converted at the read: `s.length`,
@@ -268,3 +269,85 @@ const indexOfAnyFrom = (text: string, bytes: string, from: i32): i32 => {
268
269
  }
269
270
  return -1
270
271
  }
272
+
273
+ /** The top two bits of a UTF-8 byte, which say whether it starts a code point. */
274
+ const UTF8_TOP_BITS: i32 = 0xc0
275
+
276
+ /** What those two bits are on a continuation byte: `10xxxxxx`, never a code point's first byte. */
277
+ const UTF8_CONTINUATION: i32 = 0x80
278
+
279
+ /** The first high surrogate, the unit that opens a UTF-16 pair. */
280
+ const HIGH_SURROGATE: i32 = 0xd800
281
+
282
+ /** The first low surrogate, the unit that closes a pair; the high ones end just below it. */
283
+ const LOW_SURROGATE: i32 = 0xdc00
284
+
285
+ /** One past the last low surrogate. */
286
+ const SURROGATE_END: i32 = 0xe000
287
+
288
+ /**
289
+ * Whether a string's units are UTF-8 bytes, as they are natively, rather than
290
+ * UTF-16 units, as they are under Node.
291
+ *
292
+ * `é` is two bytes and one UTF-16 unit, so its length says which host is
293
+ * running. It is written as an escape so that how this file is saved, `é` as
294
+ * one code point or as `e` and a combining accent, cannot change the answer.
295
+ * Natively the length of a literal is a load from a constant, and the
296
+ * optimiser folds this call to `true` and drops the other walk in
297
+ * `codePointLength`. The name is long for the reason `isTextBlankByte`'s is.
298
+ */
299
+ const textUnitsAreBytes = (): boolean => toI32("\u00e9".length) === 2
300
+
301
+ /**
302
+ * The number of Unicode code points in `text`: what JSON Schema's
303
+ * `minLength` and `maxLength` count, and not what `text.length` counts.
304
+ * `codePointLength("é")` is 1 where `"é".length` is 2, and
305
+ * `codePointLength("😀")` is 1 where its length is 4.
306
+ *
307
+ * Natively a string is its UTF-8 bytes, and every code point has exactly one
308
+ * byte that is not a continuation byte (`10xxxxxx`), so that is what is
309
+ * counted. Under Node the same `charCodeAt` reads UTF-16 units, where a byte
310
+ * rule would miscount: `"©®±"` is three units in `0x80`–`0xBF`, which are
311
+ * continuation bytes in UTF-8 but whole characters here. So the function asks
312
+ * which host it is on (`textUnitsAreBytes`) and, under Node, counts every unit
313
+ * except the low half of a surrogate pair. Both walks answer the same for any
314
+ * string literal, a lone surrogate escape included: it is three WTF-8 bytes
315
+ * with one leading byte natively, and one unit under Node. They differ for
316
+ * text built from bytes: `String.fromBytes` and `String.fromCharCode` give one
317
+ * unit per byte under Node, so a string decoded that way, as `nish/json`
318
+ * decodes a `\u` escape, counts its UTF-8 bytes there. They also differ for text
319
+ * that is not well-formed — bytes that are not UTF-8 natively, where each
320
+ * stray continuation byte counts nothing, or the two halves of a pair joined
321
+ * at run time, which are one string under Node and two lone surrogates
322
+ * natively.
323
+ */
324
+ export const codePointLength = (text: string): i32 => {
325
+ const length: i32 = toI32(text.length)
326
+ // `count` never passes `i`, which stays below `length`, so it never wraps.
327
+ // It is a `u32` because unsigned addition carries no overflow check: an
328
+ // `i32` would need a panic branch, or a `count < length` guard to prove it
329
+ // away, and either one keeps the byte walk from vectorizing.
330
+ let count: u32 = 0
331
+ let i: i32 = 0
332
+ if (textUnitsAreBytes()) {
333
+ while (i < length) {
334
+ if ((toI32(text.charCodeAt(i)) & UTF8_TOP_BITS) !== UTF8_CONTINUATION) {
335
+ count += 1
336
+ }
337
+ i += 1
338
+ }
339
+ return toI32(count)
340
+ }
341
+ // A low surrogate right after a high one closes a pair the high one already
342
+ // counted. Any other unit, a lone surrogate included, is a code point.
343
+ let afterHigh: boolean = false
344
+ while (i < length) {
345
+ const unit: i32 = toI32(text.charCodeAt(i))
346
+ if (!(afterHigh && unit >= LOW_SURROGATE && unit < SURROGATE_END)) {
347
+ count += 1
348
+ }
349
+ afterHigh = unit >= HIGH_SURROGATE && unit < LOW_SURROGATE
350
+ i += 1
351
+ }
352
+ return toI32(count)
353
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * `nish/yaml-lines` — byte offsets turned into the `line:column` a person reads.
3
+ *
4
+ * Every range `nish/yaml` reports — a node's `start` and `end`, a diagnostic's
5
+ * — is a byte offset into the text it parsed, because a byte offset is what a
6
+ * program slices with and what costs nothing to keep. A message for a person
7
+ * wants a line and a column instead, and this module turns one into the other:
8
+ *
9
+ * import { YamlLineIndex } from "nish/yaml-lines"
10
+ *
11
+ * const lines = new YamlLineIndex(text)
12
+ * lines.line(offset) // 1-based
13
+ * lines.column(offset) // 1-based, in characters
14
+ *
15
+ * The index scans the text once, with `indexOf`, to record where each line
16
+ * starts; every lookup after that is a binary search. A line break is LF, CR
17
+ * LF or a lone CR (YAML 1.2 §5.4, `b-break`), and CR LF is one break, not two,
18
+ * so a Windows file has as many lines as a Unix one.
19
+ *
20
+ * An offset is clamped to `[0, text.length]` first, so a range's `end`, one
21
+ * past its last byte, has a position too, and a slip below zero reads as the
22
+ * start rather than panicking. `column` counts characters: every byte that is
23
+ * not a UTF-8 continuation byte, so `é` is one column natively. `byteColumn`
24
+ * counts bytes, which is what an editor that indexes lines by byte wants.
25
+ * Under Node a string is UTF-16 and each unit counts, which is the same answer
26
+ * for ASCII and the JavaScript answer otherwise.
27
+ */
28
+
29
+ const YAML_LINES_LF: i32 = 10
30
+ /** A UTF-8 continuation byte is `10xxxxxx`: at least this and below `0xC0`. */
31
+ const YAML_LINES_CONTINUATION: i32 = 128
32
+ const YAML_LINES_LEAD: i32 = 192
33
+
34
+ /**
35
+ * Where each line of one text starts, for turning byte offsets into lines and
36
+ * columns. Its fields and its "Internal" methods are reachable, as every member
37
+ * in Nish is; use the others, and do not change the fields.
38
+ */
39
+ export class YamlLineIndex {
40
+ /** The text the index was built from. */
41
+ text: string
42
+ /** Internal: `starts[n]` is the byte at which line `n + 1` begins; line 1 begins at 0. */
43
+ starts: i32[]
44
+
45
+ constructor(text: string) {
46
+ this.text = text
47
+ this.starts = [0]
48
+ const length: i32 = toI32(text.length)
49
+ let nl: i32 = toI32(text.indexOf("\n"))
50
+ let cr: i32 = toI32(text.indexOf("\r"))
51
+ while (nl >= 0 || cr >= 0) {
52
+ if (cr >= 0 && (nl < 0 || cr < nl)) {
53
+ // CR LF is one break: step over both, and move the LF search past it.
54
+ if (cr + 1 < length && toI32(text.charCodeAt(cr + 1)) === YAML_LINES_LF) {
55
+ this.starts.push(cr + 2)
56
+ nl = toI32(text.indexOf("\n", cr + 2))
57
+ } else {
58
+ this.starts.push(cr + 1)
59
+ }
60
+ cr = toI32(text.indexOf("\r", cr + 1))
61
+ } else {
62
+ this.starts.push(nl + 1)
63
+ nl = toI32(text.indexOf("\n", nl + 1))
64
+ }
65
+ }
66
+ }
67
+
68
+ /** How many lines the text has: one more than its breaks, so `""` has one. */
69
+ lineCount(): i32 {
70
+ return toI32(this.starts.length)
71
+ }
72
+
73
+ /** The byte at which 1-based `line` begins; a line outside the text clamps to the first or last. */
74
+ lineStart(line: i32): i32 {
75
+ const count: i32 = toI32(this.starts.length)
76
+ let index: i32 = line - 1
77
+ if (index >= count) {
78
+ index = count - 1
79
+ }
80
+ if (index < 0) {
81
+ index = 0
82
+ }
83
+ return index < count ? this.starts[index] : 0
84
+ }
85
+
86
+ /** The 1-based line `offset` is on, after clamping it to `[0, text.length]`. */
87
+ line(offset: i32): i32 {
88
+ return this.lineIndexOf(this.clamp(offset)) + 1
89
+ }
90
+
91
+ /** The 1-based column of `offset` on its line, counting characters. */
92
+ column(offset: i32): i32 {
93
+ const at: i32 = this.clamp(offset)
94
+ const index: i32 = this.lineIndexOf(at)
95
+ const starts: i32[] = this.starts
96
+ let i: i32 = index >= 0 && index < toI32(starts.length) ? starts[index] : 0
97
+ const text: string = this.text
98
+ const length: i32 = toI32(text.length)
99
+ let column: i32 = 1
100
+ while (i >= 0 && i < at && i < length) {
101
+ const code: i32 = toI32(text.charCodeAt(i))
102
+ if (code < YAML_LINES_CONTINUATION || code >= YAML_LINES_LEAD) {
103
+ column += 1
104
+ }
105
+ i += 1
106
+ }
107
+ return column
108
+ }
109
+
110
+ /** The 1-based column of `offset` on its line, counting bytes. */
111
+ byteColumn(offset: i32): i32 {
112
+ const at: i32 = this.clamp(offset)
113
+ return at - this.lineStart(this.lineIndexOf(at) + 1) + 1
114
+ }
115
+
116
+ /** Internal: `offset` clamped to `[0, text.length]`. */
117
+ clamp(offset: i32): i32 {
118
+ const length: i32 = toI32(this.text.length)
119
+ if (offset < 0) {
120
+ return 0
121
+ }
122
+ return offset > length ? length : offset
123
+ }
124
+
125
+ /** Internal: the 0-based line holding byte `at`, by binary search over `starts`. */
126
+ lineIndexOf(at: i32): i32 {
127
+ const starts: i32[] = this.starts
128
+ let low: i32 = 0
129
+ let high: i32 = toI32(starts.length) - 1
130
+ while (low < high) {
131
+ const mid: i32 = (low + high + 1) >> 1
132
+ const start: i32 = mid >= 0 && mid < toI32(starts.length) ? starts[mid] : 0
133
+ if (start <= at) {
134
+ low = mid
135
+ } else {
136
+ high = mid - 1
137
+ }
138
+ }
139
+ return low
140
+ }
141
+ }