@fraczak/k 6.10.5 → 7.0.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.
Files changed (71) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/CLAUDE.md +1 -1
  3. package/DOCS/BIG_PICTURE.md +156 -172
  4. package/DOCS/BINARY_CODEC_STATUS_AND_TODO.md +3 -3
  5. package/DOCS/CODEC_ARCHITECTURE.md +2 -2
  6. package/DOCS/DICTIONARY.md +243 -250
  7. package/DOCS/DIVERGENCE_DETECTION.md +0 -1
  8. package/DOCS/FILE_FORMATS.md +5 -5
  9. package/DOCS/KIR_SPECIALIZATION_DESIGN.md +1 -1
  10. package/DOCS/OBJECT_FILE_AND_PATTERN.md +12 -12
  11. package/DOCS/PATTERNS.md +17 -17
  12. package/DOCS/PATTERNS_AND_TYPED_VALUES.md +1 -1
  13. package/DOCS/REPL.md +9 -19
  14. package/DOCS/TYPE_DERIVATION.md +2 -8
  15. package/DOCS/WEB_REPL_REQUIREMENTS.md +8 -8
  16. package/DOCS/book/01-introduction.md +8 -11
  17. package/DOCS/book/02-syntax-and-values.md +19 -20
  18. package/DOCS/book/03-types-as-finite-automata.md +42 -43
  19. package/DOCS/book/04-partial-functions-and-composition.md +2 -3
  20. package/DOCS/book/05-typing-filters-and-normalization.md +44 -46
  21. package/DOCS/book/06-values-in-memory.md +10 -10
  22. package/DOCS/book/08-operational-semantics-and-execution.md +21 -26
  23. package/DOCS/book/09-compiler-architecture.md +11 -11
  24. package/DOCS/book/10-from-ast-to-intermediate-representation.md +6 -7
  25. package/DOCS/book/14-canonical-serialization.md +2 -2
  26. package/DOCS/book/appendix-b-incorporating-external-predefined-types-and-functions.md +17 -17
  27. package/DOCS/book.md +5 -5
  28. package/Examples/arithmetics.k +49 -153
  29. package/Examples/bnat.k +13 -13
  30. package/Examples/byte.k +2 -50
  31. package/Examples/ieee.k +408 -423
  32. package/Examples/karatsuba-mult.k +30 -34
  33. package/Examples/nat.k +5 -6
  34. package/README.md +54 -49
  35. package/TODO.md +13 -18
  36. package/browser/repl-browser.mjs +40 -22
  37. package/browser/shims/fs.mjs +7 -10
  38. package/browser/vfs-data.mjs +12 -12
  39. package/codecs/BINARY_FORMAT.md +4 -4
  40. package/codecs/POLYMORPHIC_BINARY_FORMAT.md +4 -4
  41. package/codecs/README.md +6 -6
  42. package/codecs/ieee.mjs +15 -11
  43. package/codecs/int.mjs +9 -5
  44. package/codecs/string-codec.mjs +46 -47
  45. package/core.k +124 -175
  46. package/object.mjs +0 -7
  47. package/package.json +5 -2
  48. package/parser.jison +2 -41
  49. package/parser.mjs +55 -95
  50. package/pretty.mjs +11 -4
  51. package/repl.mjs +8 -63
  52. package/scripts/build-repl-html.mjs +18 -49
  53. package/tests/code-derivation/blowup.mjs +2 -4
  54. package/tests/code-derivation/bnat.mjs +2 -3
  55. package/tests/code-derivation/dot.mjs +5 -11
  56. package/tests/code-derivation/nat.mjs +2 -2
  57. package/tests/code-derivation/not-not.mjs +6 -6
  58. package/tests/code-derivation/pattern-envelope.mjs +4 -6
  59. package/tests/code-derivation/product.mjs +3 -6
  60. package/tests/code-derivation/rlz.mjs +4 -5
  61. package/tests/test-codecs.mjs +1 -1
  62. package/tests/test-fingerprint.mjs +36 -41
  63. package/tests/test-hash-normalization.mjs +4 -6
  64. package/tests/test-ieee-arithmetic.mjs +6 -7
  65. package/tests/test-k-object.mjs +11 -15
  66. package/tests/test-kir.mjs +0 -1
  67. package/tests/test-kvm-polymorphic.mjs +1 -2
  68. package/tests/test-kvm.mjs +8 -11
  69. package/tests/test-repl-html.mjs +86 -9
  70. package/tests/test-repl.mjs +38 -53
  71. package/tests/test.mjs +2 -3
@@ -16,7 +16,7 @@ Each external type has:
16
16
 
17
17
  | Field | Description |
18
18
  | --------------------- | ---------------------------------------------------------------------------- |
19
- | **Name** | symbolic name (e.g., `$int`, `$string`) |
19
+ | **Name** | symbolic name (e.g., `int`, `string`) |
20
20
  | **Hash** | unique stable identifier, just like canonical types |
21
21
  | **Runtime kind** | how the value is stored in memory (pointer, immediate integer, etc.) |
22
22
  | **Adapter functions** | conversion between the external representation and the standard `KNode` tree |
@@ -28,7 +28,7 @@ Example registry entry:
28
28
  "hash": "E001",
29
29
  "kind": "type",
30
30
  "external": true,
31
- "name": "$int",
31
+ "name": "int",
32
32
  "runtime_kind": "primitive_i64"
33
33
  }
34
34
  ```
@@ -40,11 +40,11 @@ The compiler treats such a type as an atomic node, represented internally as a s
40
40
  ## **B.3 External constructors**
41
41
 
42
42
  External types may provide special constructors or constants.
43
- For example, `$int` might include predefined constant functions:
43
+ For example, `int` might include predefined constant functions:
44
44
 
45
45
  ```
46
- zero = {} $int;
47
- one = {} $int;
46
+ zero = {} int;
47
+ one = {} int;
48
48
  ```
49
49
 
50
50
  At compile time these appear as constant functions returning fixed external nodes provided by the runtime.
@@ -59,8 +59,8 @@ They have known input and output types, possibly external.
59
59
  Declaration syntax:
60
60
 
61
61
  ```
62
- extern add : $int $int → $int;
63
- extern less : $int $int → $bool;
62
+ extern add : int int → int;
63
+ extern less : int int → bool;
64
64
  ```
65
65
 
66
66
  At compile time the compiler records the signature and associates it with a runtime symbol name such as `k_ext_add`.
@@ -82,15 +82,15 @@ They can appear as components in products or unions just like built-in ones.
82
82
 
83
83
  Example:
84
84
 
85
- ```
86
- $point = { $int x, $int y };
85
+ ```k-lang
86
+ point = ?{ int x, int y };
87
87
  ```
88
88
 
89
89
  Canonical form:
90
90
 
91
91
  ```
92
92
  $C0 = { C1 "x", C1 "y" };
93
- $C1 = external $int;
93
+ $C1 = external int;
94
94
  ```
95
95
 
96
96
  This allows normal serialization and type comparison; the external leaf is treated as opaque but identified by its hash.
@@ -111,10 +111,10 @@ All external codecs must be deterministic and version-stable to preserve canonic
111
111
 
112
112
  ## **B.7 Example**
113
113
 
114
- Suppose we introduce `$int` and external function `add`:
114
+ Suppose we introduce `int` and external function `add`:
115
115
 
116
- ```
117
- $pair_int = { $int a, $int b };
116
+ ```k-lang
117
+ pair_int = ?{ int a, int b };
118
118
  sum = { .a x, .b y } (add x y);
119
119
  ```
120
120
 
@@ -122,7 +122,7 @@ The compiler generates code that:
122
122
 
123
123
  * projects fields `.a` and `.b`,
124
124
  * passes them as `KVal` pointers to `@k_ext_add`,
125
- * and returns the result as a new `$int` node.
125
+ * and returns the result as a new `int` node.
126
126
 
127
127
  All logic outside arithmetic remains standard k code.
128
128
 
@@ -134,12 +134,12 @@ In a Python prototype:
134
134
 
135
135
  ```python
136
136
  EXTERNAL_TYPES = {
137
- "$int": {"hash": "E001", "kind": "external", "runtime_kind": "primitive_i64"}
137
+ "int": {"hash": "E001", "kind": "external", "runtime_kind": "primitive_i64"}
138
138
  }
139
139
 
140
140
  EXTERNAL_FUNCS = {
141
- "add": {"inputs": ["$int", "$int"], "output": "$int", "symbol": "k_ext_add"},
142
- "less": {"inputs": ["$int", "$int"], "output": "$bool", "symbol": "k_ext_less"}
141
+ "add": {"inputs": ["int", "int"], "output": "int", "symbol": "k_ext_add"},
142
+ "less": {"inputs": ["int", "int"], "output": "bool", "symbol": "k_ext_less"}
143
143
  }
144
144
  ```
145
145
 
package/DOCS/book.md CHANGED
@@ -17,17 +17,17 @@ author: "W. Fraczak"
17
17
 
18
18
  # The k Book
19
19
 
20
- This book describes the k programming language: a minimal functional language
21
- for transforming tree-structured data using partial functions and algebraic
22
- data types.
20
+ This book describes the k programming language: a minimal language
21
+ for content-addressable schemas and data transformations over labeled trees
22
+ using partial relations and algebraic finite automata.
23
23
 
24
24
  ## Available Chapters
25
25
 
26
26
  - [Introduction](book/01-introduction.md)
27
27
  - [Syntax and Values](book/02-syntax-and-values.md)
28
- - [Types as Finite Automata](book/03-types-as-finite-automata.md)
28
+ - [Schemas as Finite Automata](book/03-types-as-finite-automata.md)
29
29
  - [Partial Functions and Composition](book/04-partial-functions-and-composition.md)
30
- - [Typing, Filters, and Normalization](book/05-typing-filters-and-normalization.md)
30
+ - [Schemas, Filters, and Contracts](book/05-typing-filters-and-normalization.md)
31
31
  - [Values in Memory](book/06-values-in-memory.md)
32
32
  - [The Partial Function ABI](book/07-the-partial-function-abi.md)
33
33
  - [Operational Semantics and Execution](book/08-operational-semantics-and-execution.md)
@@ -1,10 +1,9 @@
1
1
  -- Examples for defining arithmetic functions natively
2
- $ yes_no = < {} yes, {} no >;
3
- swap_yes_no = < /yes |no, /no |yes > $yes_no;
4
- yes = {}|yes $yes_no;
2
+ swap_yes_no = < /yes |no, /no |yes >;
3
+ yes = {}|yes;
5
4
  no = yes swap_yes_no;
6
5
 
7
- $ bits = < {} _, bits 0, bits 1 >;
6
+ bits = ?< {} _, bits 0, bits 1 > = bits;
8
7
 
9
8
  0b = {} | _;
10
9
  -- |1 = | 1;
@@ -25,11 +24,11 @@ succ = {inv x, 0b y} _inc;
25
24
  11 = 10 succ;
26
25
  12 = 11 succ;
27
26
 
28
- empty = $bits < /_ yes, no >;
27
+ empty = < /_ yes, no >;
29
28
  empty? = {empty /yes if, () then} .then;
30
29
 
31
- concat = ${bits x, bits y} {.x inv x, .y y} concat_;
32
- concat_ = ${bits x, bits y}
30
+ concat = {.x inv x, .y y} concat_;
31
+ concat_ = ?{ <X 0, X 1, {} _>=X x, ... }
33
32
  <
34
33
  {.x empty? if, .y then} .then,
35
34
  <
@@ -38,7 +37,7 @@ concat_ = ${bits x, bits y}
38
37
  > concat_
39
38
  >;
40
39
  inv = {()x, 0b r} _inv;
41
- _inv = ${bits x, bits r}
40
+ _inv = ?{ <X 0, X 1, {} _>=X x, ... }
42
41
  <
43
42
  {.x empty? if, .r then} .then,
44
43
  <
@@ -47,8 +46,8 @@ _inv = ${bits x, bits r}
47
46
  > _inv
48
47
  >;
49
48
 
50
- inOrder = ${bits x, bits y} {.x inv x, .y inv y, yes inOrder} inOrder_;
51
- inOrder_ = ${bits x, bits y, yes_no inOrder}
49
+ inOrder = {.x inv x, .y inv y, yes inOrder} inOrder_;
50
+ inOrder_ = ?{ <X 0, X 1, {} _>=X x, ... }
52
51
  <
53
52
  {.x </0,/1> if1, .y /_ if2, .inOrder swap_yes_no then} .then,
54
53
  {.x /_ if, .inOrder then} .then,
@@ -65,49 +64,48 @@ GT = {inOrder /no if, () then} . then;
65
64
  EQ = {inOrder /yes if, {.x y, .y x} inOrder /yes and, () then} .then;
66
65
 
67
66
  --------------------------------------
68
- $ int = < bits '+', bits '-' >;
67
+ int = ?< <bits 0, bits 1, {} _>=bits "+", bits "-" >;
69
68
 
70
69
  remove_leading_zeros = <
71
70
  /0 remove_leading_zeros,
72
71
  ()
73
72
  >;
74
73
  nat = remove_leading_zeros <empty? 0, ()>;
75
- int = nat | '+' $int;
76
- abs = $int </'+',/'-'>;
74
+ int = nat | '+';
75
+ abs = </'+',/'-'>;
77
76
 
78
- pos? = $int {/'+' remove_leading_zeros /1 if, () then} .then;
79
- neg? = $int {/'-' if, () then} .then;
80
- zero_int? = $int {/'+' /0 empty? if, () then} .then;
81
- minus_one? = $int {/'-' /1 empty? if, () then} .then;
77
+ pos? = {/'+' remove_leading_zeros /1 if, () then} .then;
78
+ neg? = {/'-' if, () then} .then;
79
+ zero_int? = {/'+' /0 empty? if, () then} .then;
80
+ minus_one? = {/'-' /1 empty? if, () then} .then;
82
81
 
83
- inc = $int <
82
+ inc = <
84
83
  /'+' {inv x, 0b y} _inc nat |'+',
85
84
  minus_one? 0 int,
86
85
  /'-' {inv x, 0b y} _dec nat |'-'
87
- > $int;
86
+ >;
88
87
 
89
- _inc = ${bits x, bits y} <
88
+ _inc = ?{ <X 0, X 1, {} _>=X x, ... } <
90
89
  {.x empty? if, .y |1 then} .then,
91
90
  {.x /0 x, .y |1 y} concat_,
92
91
  {.x /1 x, .y |0 y} _inc
93
92
  >;
94
93
 
95
- dec = $int <
94
+ dec = <
96
95
  zero_int? 1 |'-',
97
96
  /'+' {inv x, 0b y} _dec nat |'+',
98
97
  /'-' {inv x, 0b y} _inc nat |'-'
99
- > $int;
98
+ >;
100
99
 
101
- _dec = ${bits x, bits y} <
100
+ _dec = ?{ <X 0, X 1, {} _>=X x, ... } <
102
101
  {.x /1 x, .y |0 y} concat_,
103
102
  {.x /0 x, .y |1 y} _dec
104
103
  >;
105
104
 
106
- $ carry = <{} 0, {} 1>;
107
- c0 = {}|0 $carry;
108
- c1 = {}|1 $carry;
105
+ c0 = {}|0;
106
+ c1 = {}|1;
109
107
 
110
- plus = ${int x, int y}
108
+ plus =
111
109
  <
112
110
  {.x/'+' inv x, .y/'+' inv y, c0 c } _plus inv nat | '+',
113
111
  {.x/'-' inv x, .y/'-' inv y, c0 c } _plus inv nat | '-',
@@ -115,8 +113,7 @@ plus = ${int x, int y}
115
113
  {.x/'+' inv x, .y/'-' inv y, c0 c} _minus inv nat |'+',
116
114
  {.x/'-' x, .y/'+' y} GT {.x inv x, .y inv y, c0 c} _minus inv nat | '-',
117
115
  {.y/'+' inv x, .x/'-' inv y, c0 c} _minus inv nat | '+'
118
- >
119
- $int;
116
+ >;
120
117
 
121
118
  swap_sign = <
122
119
  zero_int?,
@@ -124,14 +121,14 @@ swap_sign = <
124
121
  /'-' | '+'
125
122
  >;
126
123
 
127
- minus = ${int x, int y}
124
+ minus =
128
125
  {.x x, .y swap_sign y} plus;
129
126
 
130
127
  _plus = {.x x, .y y, .c c, 0b r} _plus_;
131
128
 
132
129
  _plus_ =
133
130
  -- least significant bit first addition with carry
134
- ${bits x, bits y, carry c, bits r}
131
+ ?{ <X 0, X 1, {} _>=X x, ... }
135
132
  <
136
133
  {.x empty? if, .y empty? and, .c/0 c, .r inv then} .then,
137
134
  {.x empty? if, .y empty? and, {.r x, 1 r} _inv then} .then,
@@ -159,7 +156,7 @@ _minus = {.x x, .y y, .c c, 0b r} _minus_;
159
156
 
160
157
  _minus_ =
161
158
  -- least significant bit first substraction with carry
162
- ${bits x, bits y, carry c, bits r}
159
+ ?{ <X 0, X 1, {} _>=X x, ... }
163
160
  <
164
161
  {.y empty? if, .c/0 and, {.r x, .x r} _inv then} .then,
165
162
  <
@@ -178,12 +175,11 @@ _minus_ =
178
175
  >
179
176
  ;
180
177
 
181
- $ sign = < {} '+' , {} '-' >;
182
- sign_plus = {}|'+' $sign;
183
- sign_minus = {}|'-' $sign;
184
- get_sign = $int </'+' sign_plus, /'-' sign_minus>;
178
+ sign_plus = {}|'+';
179
+ sign_minus = {}|'-';
180
+ get_sign = </'+' sign_plus, /'-' sign_minus>;
185
181
 
186
- times = ${int x, int y}
182
+ times =
187
183
  {
188
184
  <
189
185
  {.x/'+' if, .y /'+' and} sign_plus,
@@ -203,7 +199,7 @@ times = ${int x, int y}
203
199
  ;
204
200
 
205
201
  _times =
206
- ${bits result, bits _x, bits y}
202
+ ?{ <Y 0, Y 1, {} _>=Y y, ... }
207
203
  <
208
204
  { .y empty? if, .result then } .then,
209
205
  <
@@ -221,40 +217,16 @@ _times =
221
217
  >
222
218
  ;
223
219
 
224
-
225
-
226
-
227
-
228
220
  // ----------------------------------------------------------------------
229
221
  // Integer Division: Adaptive Hybrid Algorithm
230
- //
231
- // Combines two complementary strategies based on the bit-length
232
- // comparison between dividend x and divisor y (|x| vs |y|):
233
- //
234
- // 1. Down-Shift Division (|x| < 2|y|, y is large relative to x):
235
- // - Scales y up to y_max = y * 2^k to match length(x) via 'y inv'
236
- // and prepending k zeros (|0).
237
- // - In each step: trial subtraction x = x - y_scaled, then down-shifts
238
- // y_scaled by 1 bit in O(1) by popping the outer zero (/_0).
239
- // - Runs in exactly (|x| - |y| + 1) iterations. When y ~= x, this
240
- // terminates in 1-2 steps rather than looping through all bits of x.
241
- //
242
- // 2. Restoring Division (|x| >= 2|y|, y is small relative to x):
243
- // - Consumes bits of x from MSB to LSB into remainder accumulator r.
244
- // - Remainder r stays small (r <= 2y), so trial subtractions operate
245
- // on tiny numbers of length |y| rather than full-length |x|.
246
- //
247
- // The crossover condition |x| < 2|y| is evaluated structurally in
248
- // O(min(|y|, |x|/2)) by consuming 2 bits of x for every 1 bit of y.
249
222
  // ----------------------------------------------------------------------
250
223
 
251
- // Helpers for Restoring Division (shift-and-subtract)
252
224
  shift_in_0 = inv |0 inv nat;
253
225
  shift_in_1 = inv |1 inv nat;
254
- sub_bits = ${bits x, bits y} {.x inv x, .y inv y, c0 c} _minus inv nat;
226
+ sub_bits = {.x inv x, .y inv y, c0 c} _minus inv nat;
255
227
 
256
228
  _div_restoring =
257
- ${bits x, bits y, bits r, bits q}
229
+ ?{ <X 0, X 1, {} _>=X x, ... }
258
230
  <
259
231
  {.x empty? if, {.q inv int div, .r rem} then} .then,
260
232
  <
@@ -275,9 +247,7 @@ _div_restoring =
275
247
  _div_restoring
276
248
  >;
277
249
 
278
- // Helpers for Down-Shift Division (align and shift divisor down)
279
- // Phase 1: pad _y with |0 to match length of x, counting shift steps
280
- _pad_down = ${bits x, bits _y, bits steps}
250
+ _pad_down = ?{ <X 0, X 1, {} _>=X x, <S 0, S 1, {} _>=S steps, ... }
281
251
  <
282
252
  {.x empty? if, {._y _y, .steps steps} then} .then,
283
253
  {
@@ -287,22 +257,19 @@ _pad_down = ${bits x, bits _y, bits steps}
287
257
  } _pad_down
288
258
  >;
289
259
 
290
- _align_down = ${bits x, bits y, bits _y}
260
+ _align_down = ?{ <X 0, X 1, {} _>=X x, <Y 0, Y 1, {} _>=Y y, ... }
291
261
  <
292
- // Both x and y have bits remaining: advance both
293
262
  {
294
263
  .x </0, /1> x,
295
264
  .y </0, /1> y,
296
265
  ._y _y
297
266
  } _align_down,
298
267
 
299
- // y is empty while x remains: pad _y with shift zeros
300
268
  {
301
269
  .y empty? if,
302
270
  {.x x, ._y _y, 0b steps} _pad_down then
303
271
  } .then,
304
272
 
305
- // Both x and y are empty: lengths equal (0 shift steps)
306
273
  {
307
274
  .x empty? if,
308
275
  .y empty? and,
@@ -310,8 +277,7 @@ _align_down = ${bits x, bits y, bits _y}
310
277
  } .then
311
278
  >;
312
279
 
313
- // Phase 2: down-shift trial subtraction
314
- _div_down = ${bits x, bits _y, bits steps, bits q}
280
+ _div_down = ?{ <X 0, X 1, {} _>=X steps, ... }
315
281
  {
316
282
  .x x,
317
283
  ._y _y,
@@ -328,7 +294,6 @@ _div_down = ${bits x, bits _y, bits steps, bits q}
328
294
  {.y_scaled x, .x y} inOrder test
329
295
  }
330
296
  <
331
- // If x >= y_scaled, subtract and emit quotient bit 1
332
297
  {
333
298
  .test /yes if,
334
299
  {
@@ -338,19 +303,16 @@ _div_down = ${bits x, bits _y, bits steps, bits q}
338
303
  .steps steps
339
304
  } then
340
305
  } .then,
341
- // If x < y_scaled, keep x and emit quotient bit 0
342
306
  {
343
307
  .test /no if,
344
308
  {.x x, .q |0 q, ._y _y, .steps steps} then
345
309
  } .then
346
310
  >
347
311
  <
348
- // If no more shift steps remaining, division is complete
349
312
  {
350
313
  .steps empty? if,
351
314
  {.q inv int div, .x rem} then
352
315
  } .then,
353
- // Otherwise down-shift: remove the last 0 from _y and steps
354
316
  {
355
317
  .x x,
356
318
  ._y /0 _y,
@@ -359,26 +321,18 @@ _div_down = ${bits x, bits _y, bits steps, bits q}
359
321
  } _div_down
360
322
  >;
361
323
 
362
- $ choose_div = < {} down_shift, {} restore >;
363
-
364
- // Evaluates whether |x| < 2|y| by advancing 2 bits of x per 1 bit of y
365
- _check_2y = ${bits x, bits y}
324
+ _check_2y = ?{ <X 0, X 1, {} _>=X x, <Y 0, Y 1, {} _>=Y y, ... }
366
325
  <
367
- // x is empty -> |x| < 2|y| (choose down_shift)
368
- {.x empty? if, {} | down_shift $choose_div then} .then,
369
- // y is empty while x remains -> |x| >= 2|y| (choose restore)
370
- {.y empty? if, {} | restore $choose_div then} .then,
371
- // x has only 1 bit left while y remains -> |x| < 2|y|
372
- {.x </0, /1> empty? if, {} | down_shift $choose_div then} .then,
373
- // Advance 2 bits from x and 1 bit from y
326
+ {.x empty? if, {} | down_shift then} .then,
327
+ {.y empty? if, {} | restore then} .then,
328
+ {.x </0, /1> empty? if, {} | down_shift then} .then,
374
329
  {
375
330
  .x </0, /1> </0, /1> x,
376
331
  .y </0, /1> y
377
332
  } _check_2y
378
333
  >;
379
334
 
380
- // Public division interface
381
- div = ${int x, int y}
335
+ div =
382
336
  {
383
337
  <
384
338
  { .x/'+' if, .y get_sign then } .then,
@@ -388,17 +342,14 @@ div = ${int x, int y}
388
342
  .y abs remove_leading_zeros y_norm
389
343
  }
390
344
  <
391
- // Case 1: x == 0 -> quotient 0, remainder 0
392
345
  {
393
346
  .x_norm empty? if,
394
347
  { 0 int div, 0 rem } then
395
348
  } .then,
396
- // Case 2: |x| < |y| -> x < y, quotient 0, remainder x
397
349
  {
398
350
  {.y_norm x, .x_norm y} GT if,
399
351
  { 0 int div, .x_norm rem } then
400
352
  } .then,
401
- // Case 3: general division via adaptive hybrid choice
402
353
  {
403
354
  .sign sign,
404
355
  {
@@ -407,7 +358,6 @@ div = ${int x, int y}
407
358
  {.x_norm x, .y_norm y} _check_2y choice
408
359
  }
409
360
  <
410
- // If |x| < 2|y|, use down-shift division
411
361
  {
412
362
  .choice /down_shift if,
413
363
  {
@@ -421,7 +371,6 @@ div = ${int x, int y}
421
371
  0b q
422
372
  } _div_down then
423
373
  } .then,
424
- // If |x| >= 2|y|, use restoring long division
425
374
  {
426
375
  .choice /restore if,
427
376
  {.x x, .y y, 0 r, 0b q} _div_restoring then
@@ -434,31 +383,22 @@ div = ${int x, int y}
434
383
  >
435
384
  >;
436
385
 
437
-
438
- // ----------------------------------------------------------------------
439
- // Number Theory: Modulo, Greatest Common Divisor, Least Common Multiple
440
- // ----------------------------------------------------------------------
441
-
442
- // Modulo: remainder of x divided by y in $bits, delegated to div
443
- mod = ${bits x, bits y}
386
+ mod =
444
387
  {{.x int x, .y int y} div .rem rem} .rem;
445
388
 
446
- // Greatest common divisor (Euclidean algorithm)
447
- gcd = ${bits x, bits y}
389
+ gcd =
448
390
  <
449
391
  {.y x, .x y} GT,
450
392
  ()
451
393
  > _gcd
452
394
  ;
453
395
 
454
- _gcd = <
396
+ _gcd = ?{ <X 0, X 1, {} _>=X x, ... } <
455
397
  { .y remove_leading_zeros empty? if, .x nat then } .then,
456
398
  { .y x, mod y } _gcd
457
399
  >;
458
400
 
459
- // Least common multiple: (x / gcd(x, y)) * y
460
401
  lcm =
461
- ${bits x, bits y}
462
402
  {{.x int x, gcd int y} div .div x, .y int y} times abs
463
403
  ;
464
404
 
@@ -477,16 +417,13 @@ fib_ =
477
417
  >
478
418
  ;
479
419
 
480
- fib = {$bits n, {1 int x, 0 int y} "fib(n),fib(n.1)"} fib_ .x;
481
-
420
+ fib = {() n, {1 int x, 0 int y} "fib(n),fib(n.1)"} fib_ .x;
482
421
 
483
422
  --------------------
484
- $ rat = { int n, int d };
485
423
 
486
- rat = ${bits n, bits d} {.n int n, .d int d } normalize_rat;
424
+ rat = {.n int n, .d int d } normalize_rat;
487
425
 
488
426
  normalize_rat =
489
- $rat
490
427
  <
491
428
  { .d/"-" if,
492
429
  {
@@ -501,12 +438,9 @@ normalize_rat =
501
438
  {.x.n x,.y y} div .div n,
502
439
  {.x.d x,.y y} div .div d
503
440
  }
504
- $rat
505
441
  ;
506
442
 
507
-
508
443
  plus_rat =
509
- ${rat x, rat y}
510
444
  {
511
445
  .x x,
512
446
  .y y,
@@ -522,18 +456,14 @@ plus_rat =
522
456
  normalize_rat
523
457
  ;
524
458
 
525
-
526
459
  times_rat =
527
- ${rat x, rat y}
528
460
  {
529
461
  {.x.n x,.y.n y} times n,
530
462
  {.x.d x,.y.d y} times d
531
463
  }
532
464
  normalize_rat;
533
-
534
465
 
535
466
  minus_rat =
536
- ${rat x, rat y}
537
467
  {
538
468
  .x x,
539
469
  .y {.n swap_sign n, .d d} y
@@ -541,51 +471,17 @@ minus_rat =
541
471
  plus_rat;
542
472
 
543
473
  inverse_rat =
544
- $rat
545
474
  { .d n, .n d }
546
475
  normalize_rat
547
476
  ;
548
477
 
549
478
  div_rat =
550
- ${rat x, rat y}
551
479
  { .x x, .y inverse_rat y} times_rat
552
480
  ;
553
481
 
554
-
555
- --------------------
556
-
557
482
  int_rat =
558
- $rat
559
483
  { .n n, .d d, {.n x,.d y} div div }
560
484
  { .div.div int, {.div.rem int n, .d d} rat}
561
- ${int int, rat rat}
562
485
  ;
563
486
 
564
- /*
565
- ratToString =
566
- -- $rat
567
- [
568
- .n toJSON,
569
- "/",
570
- .d toJSON,
571
- " = ",
572
- normalize_rat
573
- <
574
- [.d,.n] GT [.1 toJSON ,"/", .0 toJSON] CONCAT,
575
- {.n 0,[.d,1] EQ 1} [.0 toJSON] CONCAT,
576
- int_rat [.int toJSON,"+",.rat.n toJSON,"/",.rat.d toJSON] CONCAT
577
- >
578
- ] CONCAT
579
- -- $@string
580
- ;
581
-
582
- _rat! = $rat {
583
- () carryOn,
584
- ratToString drop
585
- } .carryOn;
586
-
587
-
588
-
589
- */
590
-
591
487
  ()