@fraczak/k 6.10.2 → 6.10.4

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 (45) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/DOCS/BIG_PICTURE.md +174 -100
  3. package/DOCS/CODECS.md +74 -29
  4. package/DOCS/CODEC_ARCHITECTURE.md +87 -31
  5. package/DOCS/CONVERGENCE.md +42 -11
  6. package/DOCS/DICTIONARY.md +69 -2
  7. package/DOCS/FILE_FORMATS.md +420 -0
  8. package/DOCS/KIR_V1.md +53 -42
  9. package/DOCS/KVM_EXECUTION_MODEL.md +189 -147
  10. package/DOCS/OBJECT_FILE_AND_PATTERN.md +35 -17
  11. package/DOCS/PATTERNS.md +10 -6
  12. package/DOCS/REPL.md +100 -60
  13. package/DOCS/TEXTUAL_VALUES.md +24 -19
  14. package/DOCS/TYPE_DERIVATION.md +68 -22
  15. package/Examples/karatsuba-mult.k +215 -0
  16. package/README.md +92 -58
  17. package/backends/arm64/scripts/run-tests.mjs +16 -0
  18. package/backends/llvm/bin/k-llvm-build.mjs +40 -14
  19. package/backends/llvm/bin/k-llvm-compile.mjs +29 -12
  20. package/backends/llvm/runtime/krt.c +10 -10
  21. package/backends/llvm/runtime/krt.h +6 -1
  22. package/backends/llvm/scripts/run-tests.mjs +16 -0
  23. package/backends/llvm/src/cli.mjs +1 -1
  24. package/backends/llvm/src/executable.mjs +36 -0
  25. package/backends/llvm/src/kvm2llvm.mjs +10 -4
  26. package/backends/llvm/tests/integration.sh +11 -0
  27. package/backends/llvm/tests/test-llvm.mjs +15 -1
  28. package/backends/wasm/scripts/run-tests.mjs +16 -0
  29. package/browser/vfs-data.mjs +1 -1
  30. package/codecs/README.md +78 -67
  31. package/core.k +5 -5
  32. package/objects/README.md +57 -37
  33. package/package.json +2 -1
  34. package/scripts/benchmark-idempotency.mjs +27 -0
  35. package/scripts/benchmark.mjs +51 -0
  36. package/scripts/build-repl-html.mjs +17 -0
  37. package/scripts/generate-dependency-graph.mjs +25 -1
  38. package/scripts/perf-ieee.mjs +75 -0
  39. package/scripts/perf-int.mjs +67 -0
  40. package/scripts/perf-multiplication.mjs +644 -0
  41. package/scripts/perf-poly.mjs +67 -0
  42. package/scripts/render-benchmark.mjs +25 -0
  43. package/scripts/run-tests.mjs +19 -0
  44. package/tests/README.md +28 -17
  45. package/tests/test-karatsuba.mjs +133 -0
@@ -0,0 +1,215 @@
1
+ -- Karatsuba multiplication O(n^1.585)
2
+ -- Self-contained and minimal implementation
3
+ -- for arbitrary-precision integers
4
+
5
+ $ yes_no = < {} yes, {} no >;
6
+ yes = {} | yes $yes_no;
7
+ no = {} | no $yes_no;
8
+
9
+ $ bits = < {} _, bits 0, bits 1 >;
10
+ 0b = {} | _;
11
+ 0 = 0b |0;
12
+ 1 = 0b |1;
13
+
14
+ $ unat = < {} _, unat 1 >;
15
+ 0u = {} | _ $unat;
16
+
17
+ empty = $bits < /_ yes, no >;
18
+ empty? = {empty /yes if, () then} .then;
19
+
20
+ inv = {()x, 0b r} _inv;
21
+ _inv = ${bits x, bits r}
22
+ <
23
+ {.x empty? if, .r then} .then,
24
+ <
25
+ {.x /0 x, .r |0 r},
26
+ {.x /1 x, .r |1 r}
27
+ > _inv
28
+ >;
29
+
30
+ concat = ${bits x, bits y} {.x inv x, .y y} concat_;
31
+ concat_ = ${bits x, bits y}
32
+ <
33
+ {.x empty? if, .y then} .then,
34
+ <
35
+ {.x /0 x, .y |0 y},
36
+ {.x /1 x, .y |1 y}
37
+ > concat_
38
+ >;
39
+
40
+ remove_leading_zeros = < /0 remove_leading_zeros, () >;
41
+ nat = remove_leading_zeros <empty? 0, ()>;
42
+
43
+ $ int = < bits '+', bits '-' >;
44
+ int = nat | '+' $int;
45
+ abs = $int </'+', /'-'>;
46
+
47
+ $ sign = < {} '+', {} '-' >;
48
+ sign_plus = {} | '+' $sign;
49
+ sign_minus = {} | '-' $sign;
50
+ swap_sign = < /'+' | '-', /'-' | '+' >;
51
+
52
+ $ carry = < {} 0, {} 1 >;
53
+ c0 = {} | 0 $carry;
54
+ c1 = {} | 1 $carry;
55
+
56
+ _plus = {.x x, .y y, .c c, 0b r} _plus_;
57
+ _plus_ = ${bits x, bits y, carry c, bits r}
58
+ <
59
+ {.x empty? if, .y empty? and, .c/0 c, .r inv then} .then,
60
+ {.x empty? if, .y empty? and, {.r x, 1 r} _inv then} .then,
61
+ {.x empty? if, .c/0 and, {.r x, .y r} _inv then} .then,
62
+ <
63
+ {.x y, .y empty? x, .c c, .r r},
64
+ {<.c/0 0, 1> x, .y y, .x empty? c0 c, .r r},
65
+ {.x /0 x, .y /0 y, .c/0 c0 c, .r |0 r},
66
+ {.x /0 x, .y /0 y, .c/1 c0 c, .r |1 r},
67
+ {.x /0 x, .y /1 y, .c/0 c0 c, .r |1 r},
68
+ {.x /0 x, .y /1 y, .c/1 c1 c, .r |0 r},
69
+ {.x /1 x, .y /0 y, .c/0 c0 c, .r |1 r},
70
+ {.x /1 x, .y /0 y, .c/1 c1 c, .r |0 r},
71
+ {.x /1 x, .y /1 y, .c/0 c1 c, .r |0 r},
72
+ {.x /1 x, .y /1 y, .c/1 c1 c, .r |1 r}
73
+ > _plus_
74
+ >;
75
+
76
+ _minus = {.x x, .y y, .c c, 0b r} _minus_;
77
+ _minus_ = ${bits x, bits y, carry c, bits r}
78
+ <
79
+ {.y empty? if, .c/0 and, {.r x, .x r} _inv then} .then,
80
+ <
81
+ {.x/0 x, .y empty? y, .c/1 c1 c, .r |1 r},
82
+ {.x/1 x, .y empty? y, .c/1 c0 c, .r |0 r},
83
+ {.x/0 x, .y/0 y, .c/0 c0 c, .r |0 r},
84
+ {.x/0 x, .y/0 y, .c/1 c1 c, .r |1 r},
85
+ {.x/0 x, .y/1 y, .c/0 c1 c, .r |1 r},
86
+ {.x/0 x, .y/1 y, .c/1 c1 c, .r |0 r},
87
+ {.x/1 x, .y/0 y, .c/0 c0 c, .r |1 r},
88
+ {.x/1 x, .y/0 y, .c/1 c0 c, .r |0 r},
89
+ {.x/1 x, .y/1 y, .c/0 c0 c, .r |0 r},
90
+ {.x/1 x, .y/1 y, .c/1 c1 c, .r |1 r}
91
+ > _minus_
92
+ >;
93
+
94
+ plus_bits = ${bits x, bits y} {.x inv x, .y inv y, c0 c} _plus inv nat;
95
+ minus_bits = ${bits x, bits y} {.x inv x, .y inv y, c0 c} _minus inv nat;
96
+
97
+ _times = ${bits result, bits _x, bits y}
98
+ <
99
+ {.y empty? if, .result then} .then,
100
+ <
101
+ {.result |0 result, ._x _x, .y /0 y},
102
+ {{._x x, .result |0 y, c0 c} _plus result, ._x _x, .y /1 y}
103
+ > _times
104
+ >;
105
+ times_bits = ${bits x, bits y} {0 result, .x inv _x, .y y} _times inv nat;
106
+
107
+ unat_to_zeros = $unat < /_ 0b, /1 unat_to_zeros |0 > $bits;
108
+ unat_to_double_zeros = $unat
109
+ < /_ 0b, /1 unat_to_double_zeros |0 |0 > $bits;
110
+
111
+ _peel2 = < </0,/1> </0,/1>, </0,/1>, () >;
112
+ _half_unat = ${bits x, bits y, unat m}
113
+ <
114
+ {.x empty? if, .y empty? and, .m then} .then,
115
+ {.x _peel2 x, .y _peel2 y, .m |1 m} _half_unat
116
+ >;
117
+ half_unat = {.x x, .y y, 0u m} _half_unat;
118
+
119
+ _split_rev_u = ${bits x_rev, unat m, bits low}
120
+ <
121
+ {.m /_ if, {.low nat low, .x_rev inv nat high} then} .then,
122
+ {.x_rev empty? if, {.low nat low, 0 high} then} .then,
123
+ <
124
+ {.x_rev /0 x_rev, .m /1 m, .low |0 low},
125
+ {.x_rev /1 x_rev, .m /1 m, .low |1 low}
126
+ > _split_rev_u
127
+ >;
128
+ split_at = {.x inv x_rev, .m m, 0b low} _split_rev_u;
129
+
130
+ at_least_256_u? = <
131
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
132
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
133
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
134
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
135
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
136
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
137
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
138
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
139
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
140
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
141
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
142
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
143
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
144
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
145
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
146
+ /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1 /1
147
+ yes, no
148
+ >;
149
+
150
+ shift_bits_u = ${bits val, unat m}
151
+ <
152
+ {.val empty? if, 0b then} .then,
153
+ {.val x, .m unat_to_zeros y} concat
154
+ >;
155
+
156
+ shift2_bits_u = ${bits val, unat m}
157
+ <
158
+ {.val empty? if, 0b then} .then,
159
+ {.val x, .m unat_to_double_zeros y} concat
160
+ >;
161
+
162
+ _karatsuba = ${bits x, bits y}
163
+ <
164
+ -- Base case: if m < 256 (< 512 bits), fall back to times_bits
165
+ {{.x x, .y y} half_unat m, .x x, .y y}
166
+ <
167
+ {
168
+ .m at_least_256_u? /no if,
169
+ {.x x, .y y} times_bits then
170
+ } .then,
171
+ -- Recursive Karatsuba:
172
+ {
173
+ {.x x, .m m} split_at sx,
174
+ {.y x, .m m} split_at sy,
175
+ .m m
176
+ }
177
+ {
178
+ {.sx.high x, .sy.high y} _karatsuba z2,
179
+ {.sx.low x, .sy.low y} _karatsuba z0,
180
+ {
181
+ {.sx.high x, .sx.low y} plus_bits x,
182
+ {.sy.high x, .sy.low y} plus_bits y
183
+ } _karatsuba z_sum,
184
+ .m m
185
+ }
186
+ {
187
+ .z2 z2,
188
+ .z0 z0,
189
+ {{.z_sum x, .z2 y} minus_bits x, .z0 y} minus_bits z1,
190
+ .m m
191
+ }
192
+ {
193
+ {.z2 val, .m m} shift2_bits_u z2_s,
194
+ {.z1 val, .m m} shift_bits_u z1_s,
195
+ .z0 z0
196
+ }
197
+ {{.z2_s x, .z1_s y} plus_bits x, .z0 y} plus_bits
198
+ >
199
+ >;
200
+
201
+ karatsuba = ${int x, int y}
202
+ {
203
+ <
204
+ {.x/'+' if, .y /'+' and} sign_plus,
205
+ {.x/'-' if, .y /'-' and} sign_plus,
206
+ sign_minus
207
+ > sign,
208
+ {.x abs x, .y abs y} _karatsuba result
209
+ }
210
+ <
211
+ {.sign/'+' if, .result int then} .then,
212
+ {.sign/'-' if, .result int swap_sign then} .then
213
+ >;
214
+
215
+ ()
package/README.md CHANGED
@@ -3,14 +3,15 @@
3
3
  **k is a small language for typed data transformations.**
4
4
 
5
5
  It describes data as algebraic shapes, programs as first-order partial
6
- functions, and runtime values as a binary `pattern + value` stream that can be
7
- parsed, transformed, printed, compiled, and inspected.
6
+ functions, and runtime values as a binary `pattern + value` stream
7
+ that can be parsed, transformed, printed, compiled, and inspected.
8
8
 
9
- Data descriptions and transformations share one syntax, so a k file can define
10
- both the shapes of values and the relations that move between them.
9
+ Data descriptions and transformations share one syntax, so a k file can
10
+ define both the shapes of values and the relations that move between them.
11
11
 
12
- k is experimental, but it already has a working parser, type-derivation engine,
13
- REPL, binary codec pipeline, object/library format, Node.js API, and test suite.
12
+ k is experimental, but it already has a working parser, type-derivation
13
+ engine, REPL, binary codec pipeline, object/library format, Node.js API,
14
+ and test suite.
14
15
 
15
16
  ## Why k?
16
17
 
@@ -21,9 +22,10 @@ Many systems need to answer the same questions:
21
22
  - What does a program accept, produce, or reject?
22
23
  - Can this transformation be serialized, tested, reused, or inspected?
23
24
 
24
- k explores a compact answer: define algebraic data shapes, compose partial
25
- transformations over them, derive input/output patterns automatically, and move
26
- values across process boundaries with a canonical binary representation.
25
+ k explores a compact answer: define algebraic data shapes, compose
26
+ partial transformations over them, derive input/output patterns
27
+ automatically, and move values across process boundaries with a canonical
28
+ binary representation.
27
29
 
28
30
  That makes k interesting as a foundation for:
29
31
 
@@ -35,8 +37,8 @@ That makes k interesting as a foundation for:
35
37
 
36
38
  ## A Small Example
37
39
 
38
- k can define recursive data and transformations in the same file. Peano natural
39
- numbers are either `0` or one more than another natural number:
40
+ k can define recursive data and transformations in the same file. Peano
41
+ natural numbers are either `0` or one more than another natural number:
40
42
 
41
43
  ```k
42
44
  $ nat = < {} 0, nat +1 >;
@@ -49,8 +51,9 @@ add = $ { nat x, nat y } <
49
51
  >;
50
52
  ```
51
53
 
52
- `add` takes a product `{ x, y }`. If `x` has a `+1`, it moves that successor
53
- from `x` to `y` and recurses. When that no longer applies, it returns `y`.
54
+ `add` takes a product `{ x, y }`. If `x` has a `+1`, it moves that
55
+ successor from `x` to `y` and recurses. When that no longer applies, it
56
+ returns `y`.
54
57
 
55
58
  In the REPL:
56
59
 
@@ -59,8 +62,8 @@ In the REPL:
59
62
  {}|0|+1|+1|+1 ?<X0 +1, {} 0>=X0
60
63
  ```
61
64
 
62
- That evaluates `2 + 1` to `3`: a value starts at `0`, and each `+1` tag adds
63
- one successor. The REPL also prints the inferred value envelope.
65
+ That evaluates `2 + 1` to `3`: a value starts at `0`, and each `+1` tag
66
+ adds one successor. The REPL also prints the inferred value envelope.
64
67
 
65
68
  ## Try It
66
69
 
@@ -69,7 +72,9 @@ one successor. The REPL also prints the inferred value envelope.
69
72
  Try k directly in your browser without installing anything:
70
73
  **[https://fraczak.github.io/k/](https://fraczak.github.io/k/)**
71
74
 
72
- The Web REPL is self-contained, powered by an in-process WebAssembly compiler and execution engine with built-in codecs, autocompletion, interactive input, and standard libraries.
75
+ The Web REPL is self-contained, powered by an in-process WebAssembly
76
+ compiler and execution engine with built-in codecs, autocompletion,
77
+ interactive input, and standard libraries.
73
78
 
74
79
  ### From Source
75
80
 
@@ -121,8 +126,8 @@ $ byte = { bit 0, bit 1, bit 2, bit 3, bit 4, bit 5, bit 6, bit 7 };
121
126
  $ bits = < {} _, bits 0, bits 1 >;
122
127
  ```
123
128
 
124
- There are no built-in primitive values. The empty product `{}` is the only leaf
125
- in a non-recursive definition.
129
+ There are no built-in primitive values. The empty product `{}` is the
130
+ only leaf in a non-recursive definition.
126
131
 
127
132
  **Composable partial functions**
128
133
 
@@ -142,8 +147,9 @@ Core expressions are deliberately small:
142
147
 
143
148
  **Derived input/output patterns**
144
149
 
145
- k derives structural constraints for expressions. Those patterns become useful
146
- for diagnostics, REPL output, binary encoding, and object metadata.
150
+ k derives structural constraints for expressions. Those patterns become
151
+ useful for diagnostics, REPL output, binary encoding, and object
152
+ metadata.
147
153
 
148
154
  **Binary-friendly runtime values**
149
155
 
@@ -163,15 +169,27 @@ k-print # binary pattern+value stream -> textual value
163
169
 
164
170
  **Inspectable objects and libraries**
165
171
 
166
- k programs can be compiled into:
172
+ `k` programs can be authored, compiled, and linked across four main
173
+ file formats:
167
174
 
168
- - `.klib`: library objects
169
- - `.ko`: executable binary object containers
170
- - `.kvm`: specialized kVM backend artifacts
175
+ - `.k`: human-readable source code defining algebraic types and relations.
176
+ - `.klib`: ahead-of-time (AOT) type-checked library objects (`main: null`)
177
+ storing canonical relation definitions, type codes, and local aliases.
178
+ - `.ko`: ahead-of-time (AOT) type-checked executable containers (`KOBJ\n`
179
+ magic header) with entrypoint `main: "__main__"`, skipping parsing and
180
+ type derivation at runtime.
181
+ - `.kvm`: polymorphic register-IR template artifacts (`layer: "KVM-P"`)
182
+ carrying principal pattern graphs for instant runtime specialization
183
+ (`specializeKVM`).
171
184
 
172
- Object and library files keep canonical code/relation definitions, aliases,
173
- metadata, and type-derivation status. The `.kvm` output is a lowered backend
174
- artifact for inspection and execution experiments.
185
+ In `k`, all relations and types are identified canonically by immutable
186
+ content-addressed hashes (`@hash`). There is no global symbol namespace;
187
+ friendly names (such as `plus`, `int`, or `5`) are local aliases stored
188
+ in metadata. Similarly, there are no primitive numbers: numerical
189
+ identifiers like `5` or `10` are nullary relations mapping `${} -> $bits`.
190
+
191
+ For a detailed guide to all four formats, commands, and workflows, see
192
+ [DOCS/FILE_FORMATS.md](DOCS/FILE_FORMATS.md).
175
193
 
176
194
  ## CLI Tour
177
195
 
@@ -215,20 +233,22 @@ artifact for inspection and execution experiments.
215
233
  | `k-llvm-build` / `k-llvm-compile` / `k-llvm-run` | Compile and run via LLVM backend |
216
234
  | `k-arm64` / `k-arm64-compile` / `k-arm64-run` | Compile and run via Linux ARM64 native backend |
217
235
 
218
- Installed binary names are `k-` plus the source basename without `.mjs`, except
219
- for `k.mjs` itself. Source names that already include `k-`, such as
220
- `codecs/k-parse.mjs`, keep that name.
236
+ Installed binary names are `k-` plus the source basename without
237
+ `.mjs`, except for `k.mjs` itself. Source names that already include
238
+ `k-`, such as `codecs/k-parse.mjs`, keep that name.
221
239
 
222
240
  ## Backends
223
241
 
224
242
  Backends live under [`backends/`](backends/) as npm workspaces:
225
243
 
226
- - [`backends/wasm`](backends/wasm/) lowers typed k programs through kVM into
227
- WebAssembly artifacts. Powers both the CLI REPL (`wasm-in-process`) and the standalone Web REPL.
228
- - [`backends/llvm`](backends/llvm/) lowers polymorphic kVM programs into LLVM IR and
229
- compiled native test executables.
230
- - [`backends/arm64`](backends/arm64/) lowers polymorphic kVM programs directly into
231
- standalone Linux ARM64 native executables without external compiler dependencies.
244
+ - [`backends/wasm`](backends/wasm/) lowers typed k programs through kVM
245
+ into WebAssembly artifacts. Powers both the CLI REPL (`wasm-in-process`)
246
+ and the standalone Web REPL.
247
+ - [`backends/llvm`](backends/llvm/) lowers polymorphic kVM programs into
248
+ LLVM IR and compiled native test executables.
249
+ - [`backends/arm64`](backends/arm64/) lowers polymorphic kVM programs
250
+ directly into standalone Linux ARM64 native executables without external
251
+ compiler dependencies.
232
252
 
233
253
  All backends integrate with the compiler and binary codecs through
234
254
  [`backend-api.mjs`](backend-api.mjs).
@@ -255,8 +275,8 @@ console.log(annotated.compileStats);
255
275
 
256
276
  ## Project Status
257
277
 
258
- k is usable as an experimental language and toolkit, not a stable production
259
- platform yet.
278
+ k is usable as an experimental language and toolkit, not a stable
279
+ production platform yet.
260
280
 
261
281
  Working today:
262
282
 
@@ -266,7 +286,8 @@ Working today:
266
286
  - binary pattern+value codec
267
287
  - object and library files
268
288
  - Node.js API
269
- - regression tests for runtime, codecs, objects, hashes, and type derivation
289
+ - regression tests for runtime, codecs, objects, hashes, and type
290
+ derivation
270
291
 
271
292
  Still evolving:
272
293
 
@@ -281,20 +302,24 @@ Still evolving:
281
302
 
282
303
  k is small enough to study, but there are several useful directions:
283
304
 
284
- - examples: schema transformations, codecs, protocol examples, teaching tasks
305
+ - examples: schema transformations, codecs, protocol examples, teaching
306
+ tasks
285
307
  - documentation: tutorials, diagrams, and clearer language walkthroughs
286
- - tooling: formatter, editor integration, better diagnostics, REPL ergonomics
308
+ - tooling: formatter, editor integration, better diagnostics, REPL
309
+ ergonomics
287
310
  - compiler work: optimization, object inspection, backend experiments
288
311
  - theory: normalization, equivalence, convergence, and pattern derivation
289
- - applications: hardware modeling, asynchronous/synchronous test pipelines,
312
+ - applications: hardware modeling, asynchronous/synchronous pipelines,
290
313
  schema repositories, and data migration tooling
291
314
 
292
- If you are interested in languages, compilers, data modeling, formal methods,
293
- serialization, or teaching tools, there is room to shape the project.
315
+ If you are interested in languages, compilers, data modeling, formal
316
+ methods, serialization, or teaching tools, there is room to shape the
317
+ project.
294
318
 
295
319
  ## Examples
296
320
 
297
- The [`Examples/`](Examples/) directory contains language demonstrations and standard libraries:
321
+ The [`Examples/`](Examples/) directory contains language demonstrations
322
+ and standard libraries:
298
323
 
299
324
  | File | Contents |
300
325
  | --- | --- |
@@ -307,13 +332,14 @@ The [`Examples/`](Examples/) directory contains language demonstrations and stan
307
332
  | `bnat.k` | Binary natural numbers |
308
333
  | `buda.k` | Compact relational data transformations |
309
334
 
310
- `list.k` is also useful as a focused demonstration of filters and patterns.
335
+ `list.k` is also useful as a focused demonstration of filters and
336
+ patterns.
311
337
 
312
- `ieee.k` is a complete IEEE-754 binary64 model built from bit-level types
313
- upward with hierarchical significand adders, including comparison and
314
- floating-point `add`, `sub`, `mul`, and `div` relations. Those public aliases
315
- return `{ result, flags }`; compose with `.result` when only the floating-point
316
- value is needed.
338
+ `ieee.k` is a complete IEEE-754 binary64 model built from bit-level
339
+ types upward with hierarchical significand adders, including comparison
340
+ and floating-point `add`, `sub`, `mul`, and `div` relations. Those public
341
+ aliases return `{ result, flags }`; compose with `.result` when only the
342
+ floating-point value is needed.
317
343
 
318
344
  ## Development
319
345
 
@@ -331,8 +357,9 @@ npm run perf:int # run integer arithmetic benchmark across backends
331
357
  npm run perf:ieee # run IEEE-754 arithmetic benchmark across backends
332
358
  ```
333
359
 
334
- The test runner prints each test before execution and reports its elapsed time
335
- afterward. It stops immediately when a test fails. The suite covers:
360
+ The test runner prints each test before execution and reports its
361
+ elapsed time afterward. It stops immediately when a test fails.
362
+ The suite covers:
336
363
 
337
364
  - core runtime and parser behavior
338
365
  - type derivation cases in `tests/code-derivation/`
@@ -345,14 +372,21 @@ afterward. It stops immediately when a test fails. The suite covers:
345
372
 
346
373
  ## Further Reading
347
374
 
375
+ - [DOCS/FILE_FORMATS.md](DOCS/FILE_FORMATS.md) - guide to
376
+ .k, .ko, .klib, and .kvm file formats and workflows
348
377
  - [DOCS/DICTIONARY.md](DOCS/DICTIONARY.md) - concept names and terminology
349
378
  - [DOCS/REPL.md](DOCS/REPL.md) - interactive interpreter and codec details
350
- - [DOCS/WEB_REPL_REQUIREMENTS.md](DOCS/WEB_REPL_REQUIREMENTS.md) - Web REPL architecture and requirements
351
- - [DOCS/KVM_EXECUTION_MODEL.md](DOCS/KVM_EXECUTION_MODEL.md) - kVM execution model and bytecode design
352
- - [DOCS/TEXTUAL_VALUES.md](DOCS/TEXTUAL_VALUES.md) - textual boundary notation
379
+ - [DOCS/WEB_REPL_REQUIREMENTS.md](DOCS/WEB_REPL_REQUIREMENTS.md) -
380
+ Web REPL architecture and requirements
381
+ - [DOCS/KVM_EXECUTION_MODEL.md](DOCS/KVM_EXECUTION_MODEL.md) -
382
+ kVM execution model and bytecode design
383
+ - [DOCS/TEXTUAL_VALUES.md](DOCS/TEXTUAL_VALUES.md) -
384
+ textual boundary notation
353
385
  - [DOCS/PATTERNS.md](DOCS/PATTERNS.md) - pattern representation
354
- - [DOCS/OBJECT_FILE_AND_PATTERN.md](DOCS/OBJECT_FILE_AND_PATTERN.md) - object format
355
- - [DOCS/PROFILING_AND_TRACING.md](DOCS/PROFILING_AND_TRACING.md) - execution phase tracing and function call profiling across backends
386
+ - [DOCS/OBJECT_FILE_AND_PATTERN.md](DOCS/OBJECT_FILE_AND_PATTERN.md) -
387
+ object format and pattern encoding
388
+ - [DOCS/PROFILING_AND_TRACING.md](DOCS/PROFILING_AND_TRACING.md) -
389
+ execution phase tracing and function call profiling across backends
356
390
  - [DOCS/CODECS.md](DOCS/CODECS.md) - writing external codecs
357
391
  - [codecs/README.md](codecs/README.md) - binary codec internals
358
392
  - [objects/README.md](objects/README.md) - object/library tools
@@ -6,6 +6,22 @@ import { fileURLToPath } from "node:url";
6
6
 
7
7
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
8
8
  const node = process.execPath;
9
+
10
+ function printHelp() {
11
+ console.log(`Usage: node backends/arm64/scripts/run-tests.mjs [options]
12
+
13
+ Runs ARM64 backend test suite and integration tests.
14
+
15
+ Options:
16
+ -h, --help
17
+ Show this help message and exit.`);
18
+ }
19
+
20
+ if (process.argv.includes("-h") || process.argv.includes("--help")) {
21
+ printHelp();
22
+ process.exit(0);
23
+ }
24
+
9
25
  const tests = [
10
26
  ["tests/test-arm64.mjs", node, ["tests/test-arm64.mjs"]],
11
27
  ["tests/integration.sh", path.join(root, "tests/integration.sh"), []]
@@ -1,21 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import fs from "node:fs";
3
4
  import { argv, exit, stdin } from "node:process";
4
5
  import {
5
6
  compileProgramInputToObject,
6
7
  parseCompileOptions,
7
8
  resolveProgramInput
8
9
  } from "../src/cli.mjs";
9
- import { compileObjectToExecutable } from "../src/executable.mjs";
10
+ import {
11
+ compileKVMToExecutable,
12
+ compileObjectToExecutable
13
+ } from "../src/executable.mjs";
10
14
 
11
15
  function usage(stream = console.error) {
12
16
  const prog = argv[1] || "k-llvm-build.mjs";
13
17
  stream(`Usage: node ${prog} [options] [source-snippet | input-file [output-exe]]`);
14
- stream("Compile k source, .ko, or .klib input into a native executable.");
18
+ stream("Compile k source, .ko, .klib, or .kvm input into a native executable.");
15
19
  stream("");
16
20
  stream("Arguments:");
17
21
  stream(" source-snippet Inline k source, in the same style as k.mjs.");
18
- stream(" input-file Source .k, .ko, or .klib file. Reads UTF-8 source from stdin when omitted.");
22
+ stream(" input-file Source .k, .ko, .klib, or .kvm file. Reads UTF-8 source from stdin when omitted.");
19
23
  stream(" output-exe Output executable path.");
20
24
  stream("");
21
25
  stream("The executable reads a binary k pattern+value envelope from stdin and");
@@ -24,11 +28,21 @@ function usage(stream = console.error) {
24
28
  stream("stdout is encoded with the compiled output pattern.");
25
29
  stream("");
26
30
  stream("Options:");
27
- stream(" -o, --output path Specify output file path explicitly.");
28
- stream(" --lib file Load one .klib dependency before compiling.");
29
- stream(" --export spec Export a library alias into source scope. May be repeated.");
30
- stream(" spec is 'name' or 'libname:localname'.");
31
- stream(" -h, --help Show this help.");
31
+ stream(" -o, --output path Specify output file path explicitly.");
32
+ stream(" --input-pattern pattern Input pattern JSON or file path for specialization.");
33
+ stream(" --lib file Load one .klib dependency before compiling.");
34
+ stream(" --export spec Export a library alias into source scope. May be repeated.");
35
+ stream(" spec is 'name' or 'libname:localname'.");
36
+ stream(" -h, --help Show this help.");
37
+ }
38
+
39
+ function readMaybeFile(textOrPath) {
40
+ return fs.existsSync(textOrPath) ? fs.readFileSync(textOrPath, "utf8") : textOrPath;
41
+ }
42
+
43
+ function readPattern(inputPattern) {
44
+ if (inputPattern == null) return null;
45
+ return JSON.parse(readMaybeFile(inputPattern));
32
46
  }
33
47
 
34
48
  try {
@@ -39,6 +53,7 @@ try {
39
53
  }
40
54
 
41
55
  let explicitOutput = null;
56
+ let rawInputPattern = null;
42
57
  const remainingArgs = [];
43
58
  while (args.length > 0) {
44
59
  const arg = args[0];
@@ -46,11 +61,17 @@ try {
46
61
  args.shift();
47
62
  explicitOutput = args.shift();
48
63
  if (!explicitOutput) throw new Error("-o/--output requires a file argument");
64
+ } else if (arg === "--input-pattern") {
65
+ args.shift();
66
+ rawInputPattern = args.shift();
67
+ if (!rawInputPattern) throw new Error("--input-pattern requires a JSON or file argument");
49
68
  } else {
50
69
  remainingArgs.push(args.shift());
51
70
  }
52
71
  }
53
72
 
73
+ const inputPattern = readPattern(rawInputPattern);
74
+
54
75
  const { libraries, exportSpecs } = parseCompileOptions(remainingArgs);
55
76
  const input = resolveProgramInput(remainingArgs, { allowStdinSource: true });
56
77
  const positionalOutput = remainingArgs.shift();
@@ -59,13 +80,18 @@ try {
59
80
  const outputPath = explicitOutput || positionalOutput || null;
60
81
  if (outputPath == null) throw new Error("Output executable path is required (pass output-exe or -o/--output)");
61
82
 
62
- const object = await compileProgramInputToObject(input, {
63
- libraries,
64
- exportSpecs,
65
- stdin
66
- });
83
+ if (input.kind === "kvm") {
84
+ const kvm = JSON.parse(fs.readFileSync(input.path, "utf8"));
85
+ compileKVMToExecutable(kvm, outputPath, { inputPattern });
86
+ } else {
87
+ const object = await compileProgramInputToObject(input, {
88
+ libraries,
89
+ exportSpecs,
90
+ stdin
91
+ });
67
92
 
68
- compileObjectToExecutable(object, outputPath);
93
+ compileObjectToExecutable(object, outputPath, { inputPattern });
94
+ }
69
95
  } catch (error) {
70
96
  console.error(error.stack || error.message || String(error));
71
97
  usage();