@amritk/nish-x86_64-linux 0.11.0 → 0.13.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/INSTALL.md +29 -13
- package/bin/nish +0 -0
- package/package.json +1 -1
- package/runtime/nish.d.ts +22 -1
- package/runtime/nish.h +31 -11
- package/runtime/nish.mjs +16 -3
- package/runtime/{runtime_os.c → runtime-os.c} +1 -1
- package/runtime/{runtime_parallel.c → runtime-parallel.c} +112 -4
- package/runtime/{runtime_wasm.c → runtime-wasm.c} +6 -1
- package/runtime/runtime.c +5 -5
- package/runtime/shim.mjs +6 -6
- package/scripts/build.sh +14 -9
- package/std/README.md +16 -11
- package/std/collections.ts +221 -178
- package/std/json.ts +136 -136
- package/std/map.ts +39 -0
- package/std/pair.ts +2 -2
- package/std/testing.ts +67 -67
- package/std/text.ts +54 -54
- package/std/threads.ts +126 -38
package/scripts/build.sh
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
# scripts/build.sh <module.ll> [more .ll/.c files...] -o <out> [--profile debug|speed|size|wasm]
|
|
5
5
|
#
|
|
6
6
|
# The C runtime is three translation units and is named as one: an input
|
|
7
|
-
# <dir>/runtime.c also compiles <dir>/
|
|
7
|
+
# <dir>/runtime.c also compiles <dir>/runtime-os.c, the half that wraps the
|
|
8
8
|
# system calls (files, directories, subprocesses, the environment, the clock),
|
|
9
|
-
# and <dir>/
|
|
9
|
+
# and <dir>/runtime-parallel.c, the half that divides a range of work across
|
|
10
10
|
# threads. Each of those files says why they are compiled and measured apart.
|
|
11
11
|
#
|
|
12
12
|
# Profiles:
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
# size -Oz + LTO + section GC + strip + no unwind tables. Rust
|
|
16
16
|
# `opt-level="z"`, `panic="abort"`, `strip=true` equivalent.
|
|
17
17
|
# wasm wasm32 freestanding module exporting every non-internal function;
|
|
18
|
-
# load it from Node. Add runtime/
|
|
18
|
+
# load it from Node. Add runtime/runtime-wasm.c to the inputs when a
|
|
19
19
|
# function uses arrays (the arena and the array cold paths, no libc);
|
|
20
20
|
# strings and I/O still need a WASI runtime and are not available.
|
|
21
21
|
# wasm wasm32 freestanding module exporting every non-internal function
|
|
@@ -84,12 +84,12 @@ done
|
|
|
84
84
|
[ -n "$out" ] || { echo "error: -o <out> is required" >&2; exit 2; }
|
|
85
85
|
|
|
86
86
|
# The runtime is three translation units, and a caller names one: whoever passes
|
|
87
|
-
# <dir>/runtime.c gets <dir>/
|
|
87
|
+
# <dir>/runtime.c gets <dir>/runtime-os.c and <dir>/runtime-parallel.c compiled
|
|
88
88
|
# beside it. They were one file until the operating-system half was split out
|
|
89
89
|
# for its own size budget, and the parallel half followed for the same reason
|
|
90
90
|
# (each file's header comment says why), and a link line is where those splits
|
|
91
91
|
# would otherwise leak: `nish --link` builds its command line in
|
|
92
|
-
#
|
|
92
|
+
# src/compile.ts, the published package's recipe in every document and
|
|
93
93
|
# README names runtime.c, and a user's own clang line does too. Pairing them
|
|
94
94
|
# here keeps every one of those correct, and keeps "the runtime" one thing to
|
|
95
95
|
# name from the outside. A caller that names one itself is left alone, because
|
|
@@ -97,7 +97,7 @@ done
|
|
|
97
97
|
for i in ${inputs[@]+"${inputs[@]}"}; do
|
|
98
98
|
case "$i" in
|
|
99
99
|
*/runtime.c|runtime.c)
|
|
100
|
-
for half in
|
|
100
|
+
for half in runtime-os.c runtime-parallel.c; do
|
|
101
101
|
side="${i%runtime.c}$half"
|
|
102
102
|
have=0
|
|
103
103
|
for j in "${inputs[@]}"; do
|
|
@@ -133,8 +133,12 @@ case "$(uname -s)" in
|
|
|
133
133
|
# of one input to one output path, and differing on a link to another. That
|
|
134
134
|
# is what scripts/bootstrap.sh links every comparable stage at one path for,
|
|
135
135
|
# and it is why `stage3 == stage2` holds on Mach-O with the load command in.
|
|
136
|
-
|
|
136
|
+
# shellcheck disable=SC2054 # -Wl,<flag> is one argument: the comma is the linker's
|
|
137
|
+
gc=(-Wl,-dead_strip)
|
|
138
|
+
# shellcheck disable=SC2054
|
|
139
|
+
strip_flag=(-Wl,-x) ;;
|
|
137
140
|
*)
|
|
141
|
+
# shellcheck disable=SC2054 # -Wl,<flag> is one argument: the comma is the linker's
|
|
138
142
|
gc=(-Wl,--gc-sections -Wl,--as-needed -Wl,-O2 -Wl,--build-id=none); strip_flag=(-s)
|
|
139
143
|
elf=(-fno-plt)
|
|
140
144
|
# GNU ld needs the gold plugin for LTO; prefer lld when clang can find it.
|
|
@@ -158,7 +162,7 @@ if [ "$debug" = 1 ]; then common+=(-g); strip_flag=(); fi
|
|
|
158
162
|
# own command line instead of using `common`; it is empty on every ordinary
|
|
159
163
|
# build, hence the bash 3.2 expansion spelling explained below.
|
|
160
164
|
#
|
|
161
|
-
# -pthread is for
|
|
165
|
+
# -pthread is for runtime-parallel.c, the translation unit that divides a range
|
|
162
166
|
# of work across threads: it is compiled in either configuration and only spawns
|
|
163
167
|
# under this macro, so this is the build where the flag has to be on the command
|
|
164
168
|
# line. On a current glibc the library half is already inside libc and the link
|
|
@@ -167,7 +171,7 @@ if [ "$debug" = 1 ]; then common+=(-g); strip_flag=(); fi
|
|
|
167
171
|
#
|
|
168
172
|
# It is deliberately in `common` and not in `tls`: `tls` is the wasm and wasi
|
|
169
173
|
# command lines, which have no threads to link against, and where
|
|
170
|
-
#
|
|
174
|
+
# runtime-parallel.c compiles to its sequential fallback because it tests
|
|
171
175
|
# __wasi__ and __wasm__ as well as the macro.
|
|
172
176
|
tls=()
|
|
173
177
|
if [ "$threads" = 1 ]; then
|
|
@@ -265,6 +269,7 @@ case "$profile" in
|
|
|
265
269
|
shared=(-shared -fPIC)
|
|
266
270
|
# macOS: the napi_* symbols come from the node binary at load time, so the
|
|
267
271
|
# linker must not insist on resolving them. ELF shared objects allow this.
|
|
272
|
+
# shellcheck disable=SC2054 # -Wl,<flag> is one argument: the comma is the linker's
|
|
268
273
|
case "$(uname -s)" in Darwin) shared+=(-Wl,-undefined,dynamic_lookup) ;; esac
|
|
269
274
|
# runtime/nish.h is the public ABI header the generated shim includes.
|
|
270
275
|
runtime_inc="$(cd "$(dirname "$0")/../runtime" && pwd)"
|
package/std/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# `std/` — the standard library
|
|
2
2
|
|
|
3
3
|
Nish modules written in Nish, for Nish programs to import. There is no magic
|
|
4
|
-
here and — with
|
|
5
|
-
the compiler knows about: a module in this directory is an ordinary Nish source file, compiled as part of
|
|
4
|
+
here and — with three exceptions, `threads.ts`, `collections.ts` and `map.ts` —
|
|
5
|
+
nothing the compiler knows about: a module in this directory is an ordinary Nish source file, compiled as part of
|
|
6
6
|
whatever program imports it, and subject to the same rules as `examples/` or
|
|
7
|
-
`
|
|
7
|
+
`src/` ([`docs/LANGUAGE.md`](../docs/LANGUAGE.md) is the style guide).
|
|
8
8
|
|
|
9
9
|
| Module | What it is |
|
|
10
10
|
| --- | --- |
|
|
@@ -12,7 +12,8 @@ whatever program imports it, and subject to the same rules as `examples/` or
|
|
|
12
12
|
| [`text.ts`](./text.ts) | the string operations a program would otherwise write inline: `splitLines`, `splitWhitespace`, `trim` and its halves, `contains`, `replaceAll`, and `firstDifference` over two arrays of lines |
|
|
13
13
|
| [`json.ts`](./json.ts) | `jsonField(object, name)`: the value of one field of one flat JSON object, which is the shape the compiler's own `--json` diagnostics have. A reader and not a parser — it answers text, answers `null` for a field that is not there, and does not validate |
|
|
14
14
|
| [`pair.ts`](./pair.ts) | `Pair<A, B>`: an interface with `first` and `second`, for a function that answers two values from one call. A type and nothing else — the caller writes an object literal at the return — and for returning two values rather than storing them side by side |
|
|
15
|
-
| [`collections.ts`](./collections.ts) | the global `Map<K, V>` and `Set<T>`: insertion-ordered tables whose buckets carry a hash fingerprint beside the entry index and whose entries keep their full hash, so every `get`, `set`, `add`, `has` and `delete` is one probe. `get` is not a method here: its `V | undefined` never crosses a call, so the compiler lowers it to `probe` and, where the key was found, `valueAt`. Nor are `keys()` and `values()`: an iterator is not a value, so a `for...of` over one is lowered to `walkOpen`, `walkNext`, `keyAt` or `valueAt`, and `walkClose`, and a count of live walks defers compaction until no loop is walking the table. A program never imports it: naming `Map` or `Set` loads it, and the compiler emits what a module uses of it into that module ([`docs/wp32-map.md`](../docs/wp32-map.md), [`docs/LANGUAGE.md`](../docs/LANGUAGE.md#map-and-set)). Its `hashKey` and `
|
|
15
|
+
| [`collections.ts`](./collections.ts) | the global `Map<K, V>` and `Set<T>`: insertion-ordered tables whose buckets carry a hash fingerprint beside the entry index and whose entries keep their full hash, so every `get`, `set`, `add`, `has` and `delete` is one probe. `get` is not a method here: its `V | undefined` never crosses a call, so the compiler lowers it to `probe` and, where the key was found, `valueAt`. Nor are `keys()` and `values()`: an iterator is not a value, so a `for...of` over one is lowered to `walkOpen`, `walkNext`, `keyAt` or `valueAt`, and `walkClose`, and a count of live walks defers compaction until no loop is walking the table. A program never imports it: naming `Map` or `Set` loads it, and the compiler emits what a module uses of it into that module ([`docs/wp32-map.md`](../docs/wp32-map.md), [`docs/LANGUAGE.md`](../docs/LANGUAGE.md#map-and-set)). Its `hashKey`, `sameKey` and `storedKey` are lowered by the compiler per key type |
|
|
16
|
+
| [`map.ts`](./map.ts) | `reserve(m, n)` and `getOrInsert(m, k, v)` for the global `Map`. Their bodies are the meaning, and what runs under Node: `reserve` does nothing, and `getOrInsert` is a `get`, and a `set` of `v` when the key was missing. Natively the compiler lowers every call in place — `reserve` to the table's `reserveSlots`, which grows the buckets once so that `n` entries fit without a rebuild, and `getOrInsert` to one `probe` and a `valueAt` or an `insertAt` through its answer — so, like `collections.ts`, it writes no `.ll` of its own ([`docs/wp32-map.md`](../docs/wp32-map.md) §9.2, [`docs/LANGUAGE.md`](../docs/LANGUAGE.md#map-and-set)) |
|
|
16
17
|
| [`threads.ts`](./threads.ts) | `parallelMapInto(src, dst, f)` and `parallelReduce(src, f, identity)`: a function over every element of an array, on as many threads as the length is worth. Its bodies are the sequential meaning, which is what runs under Node; the compiler recognises the two templates by module and name, lowers the one loop in each onto `nish_parallel_range`, holds the function to the rules that make that safe, and compiles an importing program with `--threads` ([`docs/LANGUAGE.md`](../docs/LANGUAGE.md#data-parallelism-nishthreads)). `tests/link/par_*` are its programs |
|
|
17
18
|
|
|
18
19
|
## How a program imports it
|
|
@@ -64,12 +65,16 @@ reasons that are only true of it:
|
|
|
64
65
|
package and is versioned with it, so "the `std/` beside this binary" is not a
|
|
65
66
|
guess a resolver makes — it is the only `std/` that can be correct for the
|
|
66
67
|
compiler reading it. No version can be skewed against it.
|
|
67
|
-
- It **is** what Node
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
`
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
- It **is** what Node and `tsc` resolve. The package is published as
|
|
69
|
+
`@amritk/nish`, so a bare `nish/text` is not a package self-reference on its
|
|
70
|
+
own; `runtime/nish.mjs`, the prelude a program runs under Node with
|
|
71
|
+
(`node --experimental-strip-types --import ./runtime/nish.mjs`), resolves
|
|
72
|
+
`nish/<module>` to `std/<module>.ts` beside itself, and the repository's
|
|
73
|
+
`tsconfig.json` maps `nish/*` to `./std/*`, which is what gives `tsc` and an
|
|
74
|
+
editor go-to-definition into the real source. `package.json` still declares
|
|
75
|
+
`"./*": "./std/*.ts"` in `exports`, so `@amritk/nish/text` reaches the same
|
|
76
|
+
file. The compiler short-circuits to that answer rather than walking
|
|
77
|
+
`node_modules` to reach it.
|
|
73
78
|
|
|
74
79
|
So this is WP21's first slice rather than a detour around it: the spelling is
|
|
75
80
|
the one WP21 specifies, and what is still missing is resolution for specifiers
|
|
@@ -125,7 +130,7 @@ that are *not* this package.
|
|
|
125
130
|
stdout. `tests/link/std_text_f64` is the same corpus under
|
|
126
131
|
`--number-mode f64`, which is where a module that spelled its widths and forgot
|
|
127
132
|
a `toI32` is caught.
|
|
128
|
-
- **`std/` is not on the compiler's dependency list.** Nothing in `
|
|
133
|
+
- **`std/` is not on the compiler's dependency list.** Nothing in `src/`
|
|
129
134
|
imports it, and nothing should: the compiler is the thing that has to
|
|
130
135
|
build before the library means anything.
|
|
131
136
|
|