@amritk/nish-x86_64-linux 0.20.0 → 0.22.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.
Files changed (74) hide show
  1. package/INSTALL.md +52 -10
  2. package/bin/nish +0 -0
  3. package/docs/AI.md +2777 -0
  4. package/package.json +2 -1
  5. package/runtime/browser.d.ts +6 -0
  6. package/runtime/browser.mjs +77 -0
  7. package/runtime/core/arrays.d.ts +36 -0
  8. package/runtime/core/arrays.mjs +153 -0
  9. package/runtime/core/checks.mjs +20 -0
  10. package/runtime/core/host.d.ts +80 -0
  11. package/runtime/core/host.mjs +325 -0
  12. package/runtime/core/numbers.d.ts +66 -0
  13. package/runtime/core/numbers.mjs +343 -0
  14. package/runtime/core/result.d.ts +45 -0
  15. package/runtime/core/result.mjs +140 -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 +46 -2
  22. package/runtime/nish.h +75 -2
  23. package/runtime/nish.mjs +23 -3
  24. package/runtime/node.mjs +386 -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-net.c +12 -1
  29. package/runtime/runtime-os.c +1 -1
  30. package/runtime/runtime-parallel.c +1 -1
  31. package/runtime/runtime-simd.c +231 -7
  32. package/runtime/runtime-term.c +504 -0
  33. package/runtime/runtime-wasm.c +0 -11
  34. package/runtime/runtime.c +190 -6
  35. package/runtime/shim.mjs +6 -985
  36. package/runtime/sqlite/LICENSE.md +85 -0
  37. package/runtime/sqlite/README.md +45 -0
  38. package/runtime/sqlite/nish-sqlite.c +359 -0
  39. package/runtime/sqlite/sqlite3.c +271131 -0
  40. package/runtime/sqlite/sqlite3.h +14447 -0
  41. package/scripts/build.sh +311 -59
  42. package/std/LICENSE-fast-float +23 -0
  43. package/std/LICENSE-fdlibm +8 -0
  44. package/std/README.md +32 -12
  45. package/std/base64.ts +116 -0
  46. package/std/bytes.ts +256 -0
  47. package/std/cli.ts +344 -0
  48. package/std/collections.ts +6 -5
  49. package/std/crypto/LICENSE-crypt_blowfish +26 -0
  50. package/std/crypto/base64url.ts +125 -0
  51. package/std/crypto/bcrypt.ts +1557 -0
  52. package/std/crypto/hmac.ts +138 -2
  53. package/std/crypto/x509.ts +11 -122
  54. package/std/json-tokenizer.ts +2998 -57
  55. package/std/json-value.ts +22 -3
  56. package/std/json.ts +87 -8
  57. package/std/math.ts +608 -0
  58. package/std/net/http1-server.ts +282 -40
  59. package/std/net/http1.ts +40 -21
  60. package/std/net/http3-server.ts +50 -12
  61. package/std/net/postgres.ts +2294 -0
  62. package/std/net/prefork.ts +23 -3
  63. package/std/net/quic-listener.ts +20 -4
  64. package/std/random.ts +66 -4
  65. package/std/regex.ts +4274 -0
  66. package/std/sqlite.ts +391 -0
  67. package/std/term-io.ts +978 -0
  68. package/std/term-pixels.ts +874 -0
  69. package/std/term-probe.ts +459 -0
  70. package/std/term-rate.ts +993 -0
  71. package/std/term.ts +2453 -0
  72. package/std/text.ts +90 -7
  73. package/std/yaml-lines.ts +141 -0
  74. package/std/yaml.ts +4675 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amritk/nish-x86_64-linux",
3
- "version": "0.20.0",
3
+ "version": "0.22.1",
4
4
  "description": "The nish native compiler for Linux on x86_64",
5
5
  "license": "MIT",
6
6
  "os": [
@@ -17,6 +17,7 @@
17
17
  "runtime",
18
18
  "scripts",
19
19
  "std",
20
+ "docs",
20
21
  "LICENSE",
21
22
  "INSTALL.md"
22
23
  ],
@@ -0,0 +1,6 @@
1
+ /**
2
+ * `nish/runtime/browser`: importing it installs the browser host on the core
3
+ * in `nish/runtime` (docs/guide/using-nish/to-typescript.md).
4
+ */
5
+
6
+ export { NishExit } from "./core/host.js";
@@ -0,0 +1,77 @@
1
+ /**
2
+ * The browser host (WP33 R3): importing this installs, on the core in
3
+ * `runtime/core.mjs`, the answers a web page can give. It names no `node:`
4
+ * module and reads only web globals (`console`, `performance`,
5
+ * `queueMicrotask`), so it loads in a page, a worker or any engine that has
6
+ * those.
7
+ *
8
+ * - Output goes to the console a line at a time: what `write` leaves without
9
+ * a newline waits for the next one, for `exit`, or for the program to yield.
10
+ * - `exit(code)` throws a `NishExit` carrying the code, since a page cannot
11
+ * end itself; the caller that started the program catches it, and does
12
+ * not call the module again (docs/security/runtime-browser.md, BROWSER-2).
13
+ * - `monotonicNanos` reads `performance.now()`, `getenv` answers `null`,
14
+ * `isTerminal` answers `false` and `terminalSize` `[-25, 0]`, and `argv()`
15
+ * is the program alone.
16
+ * - Every file-system, process and machine call panics, naming itself and
17
+ * the browser.
18
+ */
19
+ import { installHost, NishExit, panic } from "./core/host.mjs";
20
+
21
+ export { NishExit };
22
+
23
+ /**
24
+ * One console stream, buffered to the next newline. The `"%s"` keeps a `%d`
25
+ * or `%o` in the program's text from being read as a format directive.
26
+ */
27
+ function lineStream(print) {
28
+ let pending = "";
29
+ let scheduled = false;
30
+ const flush = () => {
31
+ scheduled = false;
32
+ if (pending !== "") print("%s", pending);
33
+ pending = "";
34
+ };
35
+ return {
36
+ write(s) {
37
+ // Only the text up to the last newline is split, so a run of writes
38
+ // with no newline costs their length once, not once per write.
39
+ const text = String(s);
40
+ const last = text.lastIndexOf("\n");
41
+ if (last < 0) {
42
+ pending += text;
43
+ } else {
44
+ const lines = (pending + text.slice(0, last)).split("\n");
45
+ pending = text.slice(last + 1);
46
+ for (const line of lines) print("%s", line);
47
+ }
48
+ if (pending !== "" && !scheduled) {
49
+ scheduled = true;
50
+ queueMicrotask(flush);
51
+ }
52
+ },
53
+ flush,
54
+ };
55
+ }
56
+
57
+ const out = lineStream((...a) => console.log(...a));
58
+ const err = lineStream((...a) => console.error(...a));
59
+
60
+ installHost({
61
+ writeOut: out.write,
62
+ writeErr: err.write,
63
+ exit(code) {
64
+ out.flush();
65
+ err.flush();
66
+ throw new NishExit(code);
67
+ },
68
+ argv: () => ["main"],
69
+ call(name) {
70
+ if (name === "getenv") return null;
71
+ if (name === "monotonicNanos") return BigInt(Math.round(performance.now() * 1e6));
72
+ // A page has no terminal, which `nish:term` answers as a pipe does.
73
+ if (name === "isTerminal") return false;
74
+ if (name === "terminalSize") return [-25, 0];
75
+ return panic(`${name} is not available in a browser`);
76
+ },
77
+ });
@@ -0,0 +1,36 @@
1
+ /** The array half of the core: bounds-checked access, and the arena stubs. */
2
+ import type { i32, i64 } from "./numbers.js";
3
+ export declare function idx<T>(a: readonly T[], i: number | bigint): T;
4
+ export declare function pop<T>(a: T[]): T;
5
+ export declare function setIdx<T>(a: T[], i: number | bigint, v: T): T;
6
+ export declare function updIdx<T>(a: T[], i: number | bigint, f: (old: T) => T): T;
7
+ export declare function uncheckedGet<T extends number | bigint>(xs: readonly T[], i: i32): T;
8
+ export declare function uncheckedSet<T extends number | bigint>(xs: T[], i: i32, v: T): void;
9
+ export declare function copyIn<T>(v: T): T;
10
+ export declare function storeIdx<T>(a: T[], i: number | bigint, v: T): T;
11
+ export declare function arraySet<T>(dst: T[], src: readonly T[], offset?: number): void;
12
+ /** `dst.set(src, offset)` as `--emit-ts` writes it: a 64-bit offset is a bigint, checked exactly. */
13
+ export declare function arraySetAt<T>(dst: T[], src: readonly T[], offset?: number | bigint): void;
14
+ /** `new Array<T>(n)`: `--emit-ts` writes `T` out, so the zero it fills with is not what `T` is read from. */
15
+ export declare function newArray<T>(n: number | bigint, zero: unknown): T[];
16
+ export declare function arenaUsed(): i64;
17
+ export declare function arenaMark(): i64;
18
+ export declare function arenaRelease(m?: unknown): void;
19
+ export declare function arenaReset(): void;
20
+ /**
21
+ * The protocol `using` reads, declared here as `nish.d.ts` does, so `using a =
22
+ * arena()` type-checks with no `"esnext.disposable"` in a program's `lib`.
23
+ */
24
+ declare global {
25
+ interface SymbolConstructor {
26
+ readonly dispose: unique symbol;
27
+ }
28
+ }
29
+
30
+ /** What `arena()` answers: its `Symbol.dispose` does nothing. */
31
+ export interface ArenaHandle {
32
+ [Symbol.dispose](): void;
33
+ }
34
+
35
+ /** `using a = arena()`: the arena is the collector's, so leaving it frees nothing. */
36
+ export declare function arena(): ArenaHandle;
@@ -0,0 +1,153 @@
1
+ import { panicIndex, panicSlice, toIndex } from "./checks.mjs";
2
+
3
+ // The native check compares the index as an unsigned 64-bit number, so a
4
+ // negative one fails, and prints, as that number: `-1` is 18446744073709551615.
5
+ // A NaN or infinite `number` has no such number and prints as it is.
6
+ function outOfRange(i, len) {
7
+ const n = toIndex(i);
8
+ if (typeof i !== "bigint" && !Number.isFinite(n)) panicIndex(n, len);
9
+ const k = typeof i === "bigint" ? i : BigInt(n);
10
+ panicIndex(k < 0n ? BigInt.asUintN(64, k) : k, len);
11
+ }
12
+
13
+ /** `a[i]` read with the WP4 bounds check (negative indices fail like the unsigned compare does). */
14
+ export function idx(a, i) {
15
+ const k = toIndex(i);
16
+ if (!(k >= 0 && k < a.length)) outOfRange(i, a.length);
17
+ return a[k];
18
+ }
19
+
20
+ /** `a.pop()`: the last element, or the bounds panic — Nish has no `undefined` to return. */
21
+ export function pop(a) {
22
+ if (a.length === 0) panicIndex(0, 0);
23
+ return a.pop();
24
+ }
25
+
26
+ /** `a[i] = v`: evaluates `a`, `i`, `v`, then checks and stores; yields `v`. */
27
+ export function setIdx(a, i, v) {
28
+ const k = toIndex(i);
29
+ if (!(k >= 0 && k < a.length)) outOfRange(i, a.length);
30
+ a[k] = v;
31
+ return v;
32
+ }
33
+
34
+ /**
35
+ * `a[i] op= v`: evaluates `a`, `i`, checks, loads, then `f(old)` computes the
36
+ * new element, and checks again before the store, as `f` can shrink `a`.
37
+ */
38
+ export function updIdx(a, i, f) {
39
+ const k = toIndex(i);
40
+ if (!(k >= 0 && k < a.length)) outOfRange(i, a.length);
41
+ const v = f(a[k]);
42
+ if (!(k < a.length)) outOfRange(i, a.length);
43
+ a[k] = v;
44
+ return v;
45
+ }
46
+
47
+ /** `nish:unsafe`'s `uncheckedGet(a, i)`: the element with no bounds check, as the native load is. */
48
+ export function uncheckedGet(a, i) {
49
+ return a[i];
50
+ }
51
+
52
+ /** `nish:unsafe`'s `uncheckedSet(a, i, v)`: the store with no bounds check. */
53
+ export function uncheckedSet(a, i, v) {
54
+ a[i] = v;
55
+ }
56
+
57
+ // A record an array holds inline is an object literal here, and nothing else
58
+ // is a plain object: a class instance has its class's prototype, and an array
59
+ // has Array's.
60
+ function isRecord(v) {
61
+ return v !== null && typeof v === "object" && Object.getPrototypeOf(v) === Object.prototype;
62
+ }
63
+
64
+ /** A value put into an array slot from a generic body: a copy when it is a record, as a slot holds it inline. */
65
+ export function copyIn(v) {
66
+ return isRecord(v) ? { ...v } : v;
67
+ }
68
+
69
+ /**
70
+ * `a[i] = v` from a generic body: as `setIdx`, but a record is written field
71
+ * by field into the record already in the slot, as an inline element is.
72
+ */
73
+ export function storeIdx(a, i, v) {
74
+ const k = toIndex(i);
75
+ if (!(k >= 0 && k < a.length)) outOfRange(i, a.length);
76
+ const old = a[k];
77
+ if (isRecord(old) && isRecord(v)) Object.assign(old, v);
78
+ else a[k] = v;
79
+ return v;
80
+ }
81
+
82
+ /**
83
+ * `dst.set(src, offset)` as `nish --emit-ts` writes it: an `i64` or `u64`
84
+ * offset, a bigint here, is compared as one, so a value past 2^53 fails with
85
+ * the native panic rather than being rounded into range, and one in range is
86
+ * the number `arraySet` takes. `runtime/nish.mjs` keeps `arraySet`, whose
87
+ * bigint offset throws as `docs/LANGUAGE.md` says.
88
+ */
89
+ export function arraySetAt(dst, src, offset) {
90
+ if (typeof offset === "bigint") {
91
+ const end = offset + BigInt(src.length);
92
+ if (offset < 0n || end > BigInt(dst.length)) panicSlice(offset, end, dst.length);
93
+ offset = Number(offset);
94
+ }
95
+ arraySet(dst, src, offset);
96
+ }
97
+
98
+ /**
99
+ * `dst.set(src, offset)` (WP34 N2): `TypedArray.prototype.set`'s copy on the
100
+ * plain array a `u8[]` is here. The source is copied first, so a self-copy or
101
+ * an overlapping one reads what was there before, as `memmove` does natively;
102
+ * a range past the end fails with the native panic and its words, where a
103
+ * typed array would throw a `RangeError` for the same offsets.
104
+ */
105
+ export function arraySet(dst, src, offset) {
106
+ // `ToIntegerOrInfinity`: NaN is 0, as `llvm.fptosi.sat` makes it natively.
107
+ // `Math.trunc` rather than `toIndex`, which converts a bigint: an `i64` or
108
+ // `u64` offset is a bigint here, and it throws the `TypeError` the typed
109
+ // array and `Array.prototype.fill` throw for one, instead of being rounded
110
+ // to the nearest double past 2^53 (docs/RUN_UNDER_NODE.md).
111
+ const at = offset === undefined ? 0 : Math.trunc(offset) || 0;
112
+ const end = at + src.length;
113
+ if (!(at >= 0 && end <= dst.length)) panicSlice(...saturatedRange(at, src.length), dst.length);
114
+ // Two plain arrays overlap only when they are one array, which is the one
115
+ // case that must read the source before writing it.
116
+ const from = src === dst ? src.slice() : src;
117
+ for (let i = 0; i < from.length; i++) dst[at + i] = from[i];
118
+ }
119
+
120
+ /**
121
+ * `[at, at + n)` as the native panic spells it: the offset saturated into an
122
+ * `i64`, as `llvm.fptosi.sat` leaves it, and the end wrapped, so `1e300` is
123
+ * `9223372036854775807` and its end `-9223372036854775808`.
124
+ */
125
+ function saturatedRange(at, n) {
126
+ if (Number.isSafeInteger(at + n)) return [at, at + n];
127
+ const max = 2n ** 63n - 1n;
128
+ const start = at === Infinity || at >= 2 ** 63 ? max : at <= -(2 ** 63) ? -max - 1n : BigInt(at);
129
+ return [start, BigInt.asIntN(64, start + BigInt(n))];
130
+ }
131
+
132
+ /** `new Array<T>(n)`: `n` zero-filled elements (`0`, `0n`, or `false`). */
133
+ export function newArray(n, zero) {
134
+ return new Array(toIndex(n)).fill(zero);
135
+ }
136
+
137
+ // Arena introspection has no JS counterpart: the stubs keep programs that only
138
+ // compare `Arena.used()` before/after (a "stayed flat" check) in agreement, while
139
+ // programs that print raw byte counts are listed as known differences.
140
+ //
141
+ // `nish --threads` makes the native arena thread-local (WP20 T0) and nothing
142
+ // here moves with it: a rewritten program runs on the one thread Node gives it,
143
+ // so "the arena of the calling thread" and "the arena" are the same object, and
144
+ // these stubs answer for both. If T1 ever lands a spawn the rewrite can reach,
145
+ // that is when this file grows a second arena to keep count of.
146
+ export function arenaUsed() { return 0n; }
147
+ export function arenaMark() { return 0n; }
148
+ export function arenaRelease() {}
149
+ export function arenaReset() {}
150
+ /** `using a = arena()`: a disposable whose disposal does nothing, because there is no arena to release. */
151
+ export function arena() {
152
+ return { [Symbol.dispose]() {} };
153
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The checks the strings and arrays share: an index as the compiler converts
3
+ * it, and the two bounds panics with their native words. Internal to the core:
4
+ * `runtime/core.mjs` does not re-export them.
5
+ */
6
+ import { panic } from "./host.mjs";
7
+
8
+ /** Index conversion as in the compiler: `sext` from i32, `fptosi` (truncation) from f64. */
9
+ export function toIndex(i) {
10
+ return typeof i === "bigint" ? Number(i) : Math.trunc(i);
11
+ }
12
+
13
+ export function panicIndex(i, len) {
14
+ panic(`index out of range: ${i} >= ${len}`);
15
+ }
16
+
17
+ /** `nish_panic_slice`: the failed range check of `s.slice(start, end)`; the offsets print signed. */
18
+ export function panicSlice(start, end, len) {
19
+ panic(`slice out of range: [${start}, ${end}) of length ${len}`);
20
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The host the core runs on, and every builtin that asks it. Import
3
+ * `nish/runtime/node` or `nish/runtime/browser` to install one; until then each
4
+ * of these throws a `NishNoHost`.
5
+ */
6
+ import type { f64, i32, i64, u8 } from "./numbers.js";
7
+
8
+ /** What an adapter installs: `exit` never returns, and `call` answers the builtin `name`. */
9
+ export interface Host {
10
+ writeOut(s: string): void;
11
+ writeErr(s: string): void;
12
+ exit(code: number): never;
13
+ argv(): string[];
14
+ call(name: string, args: unknown[]): unknown;
15
+ }
16
+
17
+ /** What every member of the default host throws: no adapter has been imported. */
18
+ export declare class NishNoHost extends Error {
19
+ constructor(name: string);
20
+ readonly requested: string;
21
+ }
22
+
23
+ /**
24
+ * What the browser host's `exit(code)`, and every panic there, throws: a page
25
+ * cannot end itself. Tell it apart with `instanceof`, not by its `name`.
26
+ */
27
+ export declare class NishExit extends Error {
28
+ /** The 8-bit status a native exit would leave: `code & 0xff`. */
29
+ readonly code: number;
30
+ constructor(code: number);
31
+ }
32
+
33
+ export declare function installHost(next: Host): void;
34
+ export declare function log(x: unknown): void;
35
+ export declare function error(x: unknown): void;
36
+ export declare function write(s: string): void;
37
+ export declare function writeError(s: string): void;
38
+ export declare function panic(message: string): never;
39
+ export declare function exit(code: i32): never;
40
+ export declare function argv(): string[];
41
+ export declare function readFileSync(path: string): string;
42
+ export declare function readFileSyncOrNull(path: string): string | null;
43
+ export declare function readFileBytesSync(path: string): u8[] | null;
44
+ export declare function writeFileSync(path: string, data: string): void;
45
+ export declare function appendFileSync(path: string, data: string): void;
46
+ export declare function mkdirSync(path: string): boolean;
47
+ export declare function isDirectorySync(path: string): boolean;
48
+ export declare function readdirSync(path: string): string[] | null;
49
+ export declare function realpathSync(path: string): string | null;
50
+ export declare function platform(): string;
51
+ export declare function arch(): string;
52
+ export declare function getenv(name: string): string | null;
53
+ export declare function spawnSync(argv: string[]): number;
54
+ export declare function spawnSyncTo(argv: string[], stdoutPath: string, stderrPath: string): number;
55
+ export declare function kill(pid: i32, sig: i32): i32;
56
+ export declare function availableParallelism(): i32;
57
+ export declare function totalMemory(): i64;
58
+ export declare function monotonicNanos(): i64;
59
+ export declare function statMtimeSync(path: string): f64;
60
+ export declare function lstatOwnerModeSync(path: string): i64;
61
+ export declare function geteuid(): i64;
62
+ export declare function isExecutableSync(path: string): boolean;
63
+ export declare function isTerminal(fd: i32): boolean;
64
+ export declare function terminalSize(): i32[];
65
+ /** `crypto.getRandomValues(bytes)` for a `u8[]`; a typed array goes straight through. */
66
+ export declare function getRandomValues<T extends u8[] | Uint8Array>(bytes: T): T;
67
+ /** These four have no synchronous reading: each throws, naming itself, and is typed as `runtime/nish.d.ts` types it. */
68
+ export declare function spawn(argv: string[]): i32;
69
+ export declare function waitPid(pid: i32, flags: i32): i32[];
70
+ export declare function signalFd(): i32;
71
+ export declare function readSignal(fd: i32): i32;
72
+ /** What each `nish:net` function is under the core: a throw naming `name`. */
73
+ export declare function noNetReading(name: string): never;
74
+ /** What `readStdin`, `waitStdin`, `setRawMode` and `setTerminalRestore` are under the core: a throw naming `name`. */
75
+ export declare function noTermReading(name: string): never;
76
+ /** `nish:term`'s four that have no reading under Node: each throws, naming itself. */
77
+ export declare function readStdin(buf: u8[], off: i32, len: i32): i32;
78
+ export declare function waitStdin(timeoutMs: i32): boolean;
79
+ export declare function setRawMode(on: boolean): i32;
80
+ export declare function setTerminalRestore(bytes: string): i32;