@fraczak/k 6.4.0 → 6.6.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/CHANGELOG.md CHANGED
@@ -7,6 +7,23 @@ This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ---
9
9
 
10
+ ## [6.5.0] — 2026-09-22 — Tail-loop arena compaction & OOM diagnostics
11
+
12
+ ### WebAssembly Backend
13
+
14
+ - Added threshold-based arena compaction in self-tail-recursive loops to reclaim dead scratch space, allowing deep computations (e.g. multi-thousand-bit arithmetic) without exhausting linear memory.
15
+ - Added explicit Out-Of-Memory error reporting (`OutOfMemoryError`), tracking allocation failure and 32-bit offset overflow via exported runtime globals.
16
+
17
+ ### Runtime & REPL
18
+
19
+ - Replaced recursive traversal in `codecs/runtime/show-value.mjs` and `Value.mjs` with iterative loops, eliminating `Maximum call stack size exceeded` errors when rendering deep variant chains.
20
+
21
+ ### Examples
22
+
23
+ - Converted arithmetic helper functions in `Examples/arithmetics.k` to tail-recursive relations.
24
+
25
+ ---
26
+
10
27
  ## [6.2.3] — 2026-06-03 — Unified k compiler output
11
28
 
12
29
  ### Toolchain
@@ -39,22 +39,33 @@ empty? = {empty /yes if, () then} .then;
39
39
  concat = ${bits x, bits y} {.x inv x, .y y} concat_;
40
40
  concat_ = ${bits x, bits y}
41
41
  <
42
- {.x /0 x, .y |0 y} concat_,
43
- {.x /1 x, .y |1 y} concat_,
44
- .y
42
+ {.x empty? if, .y then} .then,
43
+ <
44
+ {.x /0 x, .y |0 y},
45
+ {.x /1 x, .y |1 y}
46
+ > concat_
45
47
  >;
46
48
  inv = {()x, 0b r} _inv;
47
- _inv = ${bits x, bits r} < {.x /0 x, .r |0 r} _inv, {.x /1 x, .r |1 r} _inv, .r >;
49
+ _inv = ${bits x, bits r}
50
+ <
51
+ {.x empty? if, .r then} .then,
52
+ <
53
+ {.x /0 x, .r |0 r},
54
+ {.x /1 x, .r |1 r}
55
+ > _inv
56
+ >;
48
57
 
49
58
  inOrder = ${bits x, bits y} {.x inv x, .y inv y, yes inOrder} inOrder_;
50
59
  inOrder_ = ${bits x, bits y, yes_no inOrder}
51
60
  <
52
- {.x /0 x, .y /0 y, .inOrder inOrder} inOrder_,
53
- {.x /1 x, .y /1 y, .inOrder inOrder} inOrder_,
54
- {.x /0 x, .y /1 y, .inOrder inOrder} inOrder_,
55
- {.x /1 y, .y /0 x, .inOrder swap_yes_no inOrder} inOrder_,
56
- {.x </0,/1> if, .inOrder swap_yes_no then} .then,
57
- .inOrder
61
+ {.x </0,/1> if1, .y /_ if2, .inOrder swap_yes_no then} .then,
62
+ {.x /_ if, .inOrder then} .then,
63
+ <
64
+ {.x /0 x, .y /0 y, .inOrder inOrder},
65
+ {.x /1 x, .y /1 y, .inOrder inOrder},
66
+ {.x /0 x, .y /1 y, .inOrder inOrder},
67
+ {.x /1 y, .y /0 x, .inOrder swap_yes_no inOrder}
68
+ > inOrder_
58
69
  >;
59
70
 
60
71
  GT = {inOrder /no if, () then} . then;
@@ -63,18 +74,21 @@ EQ = GT {.x y, .y x} GT;
63
74
 
64
75
  toBitList = {inv x, nil r} _toBitList;
65
76
  _toBitList = <
66
- {.x empty? if, .r then }.then,
67
- {.x /0 x, {0 car, .r cdr} cons r} _toBitList,
68
- {.x /1 x, {1 car, .r cdr} cons r} _toBitList
77
+ {.x empty? if, .r then}.then,
78
+ <
79
+ {.x /0 x, {0 car, .r cdr} cons r},
80
+ {.x /1 x, {1 car, .r cdr} cons r}
81
+ > _toBitList
69
82
  >;
70
- fromBitList =
71
- <
72
- cdr <
73
- {car /0 if, cdr fromBitList |0 then} .then,
74
- {car /1 if, cdr fromBitList |1 then} .then
75
- >,
76
- 0b
77
- > $bits;
83
+ fromBitList = {() l, 0b r} _fromBitList inv $bits;
84
+ _fromBitList =
85
+ <
86
+ {.l nil? if, .r then} .then,
87
+ <
88
+ {.l car /0 if, {.l cdr l, .r |0 r} then} .then,
89
+ {.l car /1 if, {.l cdr l, .r |1 r} then} .then
90
+ > _fromBitList
91
+ >;
78
92
 
79
93
  --------------------------------------
80
94
  $ int = < bits '+', bits '-' >;
@@ -99,9 +113,9 @@ inc = $int <
99
113
  > $int;
100
114
 
101
115
  _inc = ${bits x, bits y} <
116
+ {.x empty? if, .y |1 then} .then,
102
117
  {.x /0 x, .y |1 y} concat_,
103
- {.x /1 x, .y |0 y} _inc,
104
- .y |1
118
+ {.x /1 x, .y |0 y} _inc
105
119
  >;
106
120
 
107
121
  dec = $int <
@@ -149,38 +163,44 @@ _plus_ =
149
163
  {.x empty? if, .y empty? and, {.r x, 1 r} _inv then} .then,
150
164
  {.x empty? if, .c/0 and, {.r x, .y r} _inv then} .then,
151
165
 
152
- {.x y, .y empty? x, .c c, .r r} _plus_,
153
- {<.c/0 0, 1> x,
154
- .y y, .x empty? c0 c, .r r} _plus_,
166
+ <
167
+ {.x y, .y empty? x, .c c, .r r},
168
+ {<.c/0 0, 1> x, .y y, .x empty? c0 c, .r r},
155
169
 
156
- {.x /0 x, .y /0 y, .c/0 c0 c, .r |0 r} _plus_,
157
- {.x /0 x, .y /0 y, .c/1 c0 c, .r |1 r} _plus_,
170
+ {.x /0 x, .y /0 y, .c/0 c0 c, .r |0 r},
171
+ {.x /0 x, .y /0 y, .c/1 c0 c, .r |1 r},
158
172
 
159
- {.x /0 x, .y /1 y, .c/0 c0 c, .r |1 r} _plus_,
160
- {.x /0 x, .y /1 y, .c/1 c1 c, .r |0 r} _plus_,
161
- {.x /1 x, .y /0 y, .c/0 c0 c, .r |1 r} _plus_,
162
- {.x /1 x, .y /0 y, .c/1 c1 c, .r |0 r} _plus_,
173
+ {.x /0 x, .y /1 y, .c/0 c0 c, .r |1 r},
174
+ {.x /0 x, .y /1 y, .c/1 c1 c, .r |0 r},
175
+ {.x /1 x, .y /0 y, .c/0 c0 c, .r |1 r},
176
+ {.x /1 x, .y /0 y, .c/1 c1 c, .r |0 r},
163
177
 
164
- {.x /1 x, .y /1 y, .c/0 c1 c, .r |0 r} _plus_,
165
- {.x /1 x, .y /1 y, .c/1 c1 c, .r |1 r} _plus_
178
+ {.x /1 x, .y /1 y, .c/0 c1 c, .r |0 r},
179
+ {.x /1 x, .y /1 y, .c/1 c1 c, .r |1 r}
180
+ > _plus_
166
181
  >
167
182
  ;
168
183
 
169
- _minus =
170
- -- least significat bit first substraction with carry
171
- ${bits x, bits y, carry c}
184
+ _minus = {.x x, .y y, .c c, 0b r} _minus_;
185
+
186
+ _minus_ =
187
+ -- least significant bit first substraction with carry
188
+ ${bits x, bits y, carry c, bits r}
172
189
  <
173
- {.x then, .y empty? if, .c/0 and} .then,
174
- {.x/1 then, .y empty? if, .c/1 and} .then |0,
175
- {.x/0 x, .y empty? y, .c/1 c1 c} _minus |1,
176
- {.x/0 x, .y/0 y, .c/0 c0 c} _minus |0,
177
- {.x/0 x, .y/0 y, .c/1 c1 c} _minus |1,
178
- {.x/0 x, .y/1 y, .c/0 c1 c} _minus |1,
179
- {.x/0 x, .y/1 y, .c/1 c1 c} _minus |0,
180
- {.x/1 x, .y/0 y, .c/0 c0 c} _minus |1,
181
- {.x/1 x, .y/0 y, .c/1 c0 c} _minus |0,
182
- {.x/1 x, .y/1 y, .c/0 c0 c} _minus |0,
183
- {.x/1 x, .y/1 y, .c/1 c1 c} _minus |1
190
+ {.y empty? if, .c/0 and, {.r x, .x r} _inv then} .then,
191
+ <
192
+ {.x/0 x, .y empty? y, .c/1 c1 c, .r |1 r},
193
+ {.x/1 x, .y empty? y, .c/1 c0 c, .r |0 r},
194
+
195
+ {.x/0 x, .y/0 y, .c/0 c0 c, .r |0 r},
196
+ {.x/0 x, .y/0 y, .c/1 c1 c, .r |1 r},
197
+ {.x/0 x, .y/1 y, .c/0 c1 c, .r |1 r},
198
+ {.x/0 x, .y/1 y, .c/1 c1 c, .r |0 r},
199
+ {.x/1 x, .y/0 y, .c/0 c0 c, .r |1 r},
200
+ {.x/1 x, .y/0 y, .c/1 c0 c, .r |0 r},
201
+ {.x/1 x, .y/1 y, .c/0 c0 c, .r |0 r},
202
+ {.x/1 x, .y/1 y, .c/1 c1 c, .r |1 r}
203
+ > _minus_
184
204
  >
185
205
  ;
186
206
 
@@ -212,16 +232,18 @@ _times =
212
232
  ${bits result, bits _x, bits y}
213
233
  <
214
234
  { .y empty? if, .result then } .then,
215
- {
216
- .result |0 result,
217
- ._x _x,
218
- .y /0 y
219
- } _times,
220
- {
221
- {._x x, .result |0 y, c0 c } _plus result,
222
- ._x _x,
223
- .y /1 y
224
- } _times
235
+ <
236
+ {
237
+ .result |0 result,
238
+ ._x _x,
239
+ .y /0 y
240
+ },
241
+ {
242
+ {._x x, .result |0 y, c0 c } _plus result,
243
+ ._x _x,
244
+ .y /1 y
245
+ }
246
+ > _times
225
247
  >
226
248
  ;
227
249
 
@@ -327,17 +349,18 @@ lcm =
327
349
  {{.x int x, .y int y} times x, gcd int y} div .div abs
328
350
  ;
329
351
 
330
- factorial = <
331
- zero_int? 1 int,
332
- /"+" int {dec factorial x, () y} times
352
+ factorial = {()n, 1 int acc} factorial_;
353
+ factorial_ = <
354
+ {.n zero_int? if, .acc then} .then,
355
+ {.n pos? dec n, {.n x, .acc y} times acc} factorial_
333
356
  >;
334
357
 
335
358
  fib_ =
336
359
  <
360
+ {.n int zero_int? if, ."fib(n),fib(n.1)" then} .then,
337
361
  { .n int dec /"+" n,
338
362
  ."fib(n),fib(n.1)" {plus x, .x y} "fib(n),fib(n.1)"
339
- } fib_,
340
- ."fib(n),fib(n.1)"
363
+ } fib_
341
364
  >
342
365
  ;
343
366
 
package/Value.mjs CHANGED
@@ -176,8 +176,14 @@ class Value {
176
176
 
177
177
  toString() {
178
178
  if (isVariant(this)) {
179
- // return `{${JSON.stringify(this.tag)}:${this.value.toString()}}`;
180
- return `${this.value.toString()}|${pLabel(this.tag)}`;
179
+ const tags = [];
180
+ let curr = this;
181
+ while (isVariant(curr)) {
182
+ tags.push(pLabel(curr.tag));
183
+ curr = curr.value;
184
+ }
185
+ const base = curr ? curr.toString() : "";
186
+ return tags.length === 0 ? base : `${base}|${tags.reverse().join("|")}`;
181
187
  }
182
188
  if (isProduct(this)) {
183
189
  return `{${Object.entries(this.product).map(([k, v]) => `${JSON.stringify(k)}:${v.toString()}`).join(',')}}`;
@@ -5,7 +5,21 @@
5
5
  #include <string.h>
6
6
  #include <time.h>
7
7
 
8
- #define ARENA_CAPACITY (64 * 1024 * 1024)
8
+ #define DEFAULT_ARENA_CAPACITY (256 * 1024 * 1024)
9
+
10
+ static int parse_size_arg(const char *text, size_t *out);
11
+
12
+ static size_t get_arena_capacity(void) {
13
+ const char *env = getenv("K_ARENA_CAPACITY_MB");
14
+ if (!env || !*env) env = getenv("K_ARENA_MB");
15
+ if (env && *env) {
16
+ size_t mb = 0;
17
+ if (parse_size_arg(env, &mb) && mb > 0) {
18
+ return mb * 1024 * 1024;
19
+ }
20
+ }
21
+ return DEFAULT_ARENA_CAPACITY;
22
+ }
9
23
 
10
24
  typedef enum {
11
25
  K_VALUE_UNIT,
@@ -601,8 +615,10 @@ static int run_bench_main(void *arena_mem, const char *count_text) {
601
615
  int main(int argc, char **argv) {
602
616
  init_tag_registry();
603
617
 
618
+ size_t arena_capacity = get_arena_capacity();
619
+
604
620
  if (argc == 2 && strcmp(argv[1], "--server") == 0) {
605
- void *arena_mem = malloc(ARENA_CAPACITY);
621
+ void *arena_mem = malloc(arena_capacity);
606
622
  if (!arena_mem) return 1;
607
623
  int rc = run_server(arena_mem);
608
624
  free(arena_mem);
@@ -610,7 +626,7 @@ int main(int argc, char **argv) {
610
626
  }
611
627
 
612
628
  if (argc == 3 && strcmp(argv[1], "--bench-main") == 0) {
613
- void *arena_mem = malloc(ARENA_CAPACITY);
629
+ void *arena_mem = malloc(arena_capacity);
614
630
  if (!arena_mem) return 1;
615
631
  int rc = run_bench_main(arena_mem, argv[2]);
616
632
  free(arena_mem);
@@ -647,7 +663,7 @@ int main(int argc, char **argv) {
647
663
  }
648
664
  }
649
665
 
650
- void *arena_mem = malloc(ARENA_CAPACITY);
666
+ void *arena_mem = malloc(arena_capacity);
651
667
  if (!arena_mem) {
652
668
  if (in_fp != stdin) fclose(in_fp);
653
669
  return 1;
@@ -105,7 +105,7 @@ node "$K_ROOT/backends/arm64/bin/k-arm64-compile.mjs" \
105
105
  '{succ int x,int y}+' \
106
106
  -o "$TMP_DIR/lib-add"
107
107
 
108
- node "$K_ROOT/codecs/k-parse.mjs" <<< '{"x":{"succ":"zero"},"y":{"succ":{"succ":"zero"}}}' |
108
+ node "$K_ROOT/codecs/k-parse.mjs" <<< '{"x":{"0":"_"},"y":{"+":{"0":"_"}}}' |
109
109
  "$TMP_DIR/lib-add" --json |
110
110
  grep -Fxq '{"+":{"1":"_"}}'
111
111