@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.
- package/CHANGELOG.md +73 -0
- package/DOCS/BIG_PICTURE.md +174 -100
- package/DOCS/CODECS.md +74 -29
- package/DOCS/CODEC_ARCHITECTURE.md +87 -31
- package/DOCS/CONVERGENCE.md +42 -11
- package/DOCS/DICTIONARY.md +69 -2
- package/DOCS/FILE_FORMATS.md +420 -0
- package/DOCS/KIR_V1.md +53 -42
- package/DOCS/KVM_EXECUTION_MODEL.md +189 -147
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +35 -17
- package/DOCS/PATTERNS.md +10 -6
- package/DOCS/REPL.md +100 -60
- package/DOCS/TEXTUAL_VALUES.md +24 -19
- package/DOCS/TYPE_DERIVATION.md +68 -22
- package/Examples/karatsuba-mult.k +215 -0
- package/README.md +92 -58
- package/backends/arm64/scripts/run-tests.mjs +16 -0
- package/backends/llvm/bin/k-llvm-build.mjs +40 -14
- package/backends/llvm/bin/k-llvm-compile.mjs +29 -12
- package/backends/llvm/runtime/krt.c +10 -10
- package/backends/llvm/runtime/krt.h +6 -1
- package/backends/llvm/scripts/run-tests.mjs +16 -0
- package/backends/llvm/src/cli.mjs +1 -1
- package/backends/llvm/src/executable.mjs +36 -0
- package/backends/llvm/src/kvm2llvm.mjs +10 -4
- package/backends/llvm/tests/integration.sh +11 -0
- package/backends/llvm/tests/test-llvm.mjs +15 -1
- package/backends/wasm/scripts/run-tests.mjs +16 -0
- package/browser/vfs-data.mjs +1 -1
- package/codecs/README.md +78 -67
- package/core.k +5 -5
- package/objects/README.md +57 -37
- package/package.json +2 -1
- package/scripts/benchmark-idempotency.mjs +27 -0
- package/scripts/benchmark.mjs +51 -0
- package/scripts/build-repl-html.mjs +17 -0
- package/scripts/generate-dependency-graph.mjs +25 -1
- package/scripts/perf-ieee.mjs +75 -0
- package/scripts/perf-int.mjs +67 -0
- package/scripts/perf-multiplication.mjs +644 -0
- package/scripts/perf-poly.mjs +67 -0
- package/scripts/render-benchmark.mjs +25 -0
- package/scripts/run-tests.mjs +19 -0
- package/tests/README.md +28 -17
- 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
|
|
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
|
|
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
|
|
13
|
-
REPL, binary codec pipeline, object/library format, Node.js API,
|
|
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
|
|
25
|
-
transformations over them, derive input/output patterns
|
|
26
|
-
values across process boundaries with a canonical
|
|
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
|
|
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
|
|
53
|
-
from `x` to `y` and recurses. When that no longer applies, it
|
|
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
|
|
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
|
|
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
|
|
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
|
|
146
|
-
for diagnostics, REPL output, binary encoding, and object
|
|
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
|
|
172
|
+
`k` programs can be authored, compiled, and linked across four main
|
|
173
|
+
file formats:
|
|
167
174
|
|
|
168
|
-
- `.
|
|
169
|
-
- `.
|
|
170
|
-
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
|
219
|
-
for `k.mjs` itself. Source names that already include
|
|
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
|
|
227
|
-
WebAssembly artifacts. Powers both the CLI REPL (`wasm-in-process`)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
293
|
-
serialization, or teaching tools, there is room to shape the
|
|
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
|
|
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
|
|
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
|
|
313
|
-
upward with hierarchical significand adders, including comparison
|
|
314
|
-
floating-point `add`, `sub`, `mul`, and `div` relations. Those public
|
|
315
|
-
return `{ result, flags }`; compose with `.result` when only the
|
|
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
|
|
335
|
-
afterward. It stops immediately when a test fails.
|
|
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) -
|
|
351
|
-
|
|
352
|
-
- [DOCS/
|
|
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) -
|
|
355
|
-
|
|
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 {
|
|
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 .
|
|
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 .
|
|
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
|
|
28
|
-
stream(" --
|
|
29
|
-
stream(" --
|
|
30
|
-
stream("
|
|
31
|
-
stream("
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
93
|
+
compileObjectToExecutable(object, outputPath, { inputPattern });
|
|
94
|
+
}
|
|
69
95
|
} catch (error) {
|
|
70
96
|
console.error(error.stack || error.message || String(error));
|
|
71
97
|
usage();
|