@fraczak/k 6.10.6 → 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.
- package/CHANGELOG.md +41 -0
- package/CLAUDE.md +1 -1
- package/DOCS/BIG_PICTURE.md +156 -172
- package/DOCS/BINARY_CODEC_STATUS_AND_TODO.md +3 -3
- package/DOCS/CODEC_ARCHITECTURE.md +2 -2
- package/DOCS/DICTIONARY.md +243 -250
- package/DOCS/DIVERGENCE_DETECTION.md +0 -1
- package/DOCS/FILE_FORMATS.md +5 -5
- package/DOCS/KIR_SPECIALIZATION_DESIGN.md +1 -1
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +12 -12
- package/DOCS/PATTERNS.md +17 -17
- package/DOCS/PATTERNS_AND_TYPED_VALUES.md +1 -1
- package/DOCS/REPL.md +9 -19
- package/DOCS/TYPE_DERIVATION.md +2 -8
- package/DOCS/WEB_REPL_REQUIREMENTS.md +8 -8
- package/DOCS/book/01-introduction.md +8 -11
- package/DOCS/book/02-syntax-and-values.md +19 -20
- package/DOCS/book/03-types-as-finite-automata.md +42 -43
- package/DOCS/book/04-partial-functions-and-composition.md +2 -3
- package/DOCS/book/05-typing-filters-and-normalization.md +44 -46
- package/DOCS/book/06-values-in-memory.md +10 -10
- package/DOCS/book/08-operational-semantics-and-execution.md +21 -26
- package/DOCS/book/09-compiler-architecture.md +11 -11
- package/DOCS/book/10-from-ast-to-intermediate-representation.md +6 -7
- package/DOCS/book/14-canonical-serialization.md +2 -2
- package/DOCS/book/appendix-b-incorporating-external-predefined-types-and-functions.md +17 -17
- package/DOCS/book.md +5 -5
- package/Examples/arithmetics.k +49 -153
- package/Examples/bnat.k +13 -13
- package/Examples/byte.k +2 -50
- package/Examples/ieee.k +408 -423
- package/Examples/karatsuba-mult.k +30 -34
- package/Examples/nat.k +5 -6
- package/README.md +54 -49
- package/TODO.md +13 -18
- package/browser/vfs-data.mjs +11 -11
- package/codecs/BINARY_FORMAT.md +4 -4
- package/codecs/POLYMORPHIC_BINARY_FORMAT.md +4 -4
- package/codecs/README.md +6 -6
- package/codecs/ieee.mjs +15 -11
- package/codecs/int.mjs +9 -5
- package/codecs/string-codec.mjs +46 -47
- package/core.k +123 -95
- package/object.mjs +0 -7
- package/package.json +5 -2
- package/parser.jison +2 -41
- package/parser.mjs +55 -95
- package/pretty.mjs +11 -4
- package/repl.mjs +8 -63
- package/scripts/build-repl-html.mjs +8 -38
- package/tests/code-derivation/blowup.mjs +2 -4
- package/tests/code-derivation/bnat.mjs +2 -3
- package/tests/code-derivation/dot.mjs +5 -11
- package/tests/code-derivation/nat.mjs +2 -2
- package/tests/code-derivation/not-not.mjs +6 -6
- package/tests/code-derivation/pattern-envelope.mjs +4 -6
- package/tests/code-derivation/product.mjs +3 -6
- package/tests/code-derivation/rlz.mjs +4 -5
- package/tests/test-codecs.mjs +1 -1
- package/tests/test-fingerprint.mjs +36 -41
- package/tests/test-hash-normalization.mjs +4 -6
- package/tests/test-ieee-arithmetic.mjs +6 -7
- package/tests/test-k-object.mjs +11 -15
- package/tests/test-kir.mjs +0 -1
- package/tests/test-kvm-polymorphic.mjs +1 -2
- package/tests/test-kvm.mjs +8 -11
- package/tests/test-repl-html.mjs +5 -2
- package/tests/test-repl.mjs +38 -53
- package/tests/test.mjs +2 -3
package/tests/test-repl.mjs
CHANGED
|
@@ -24,18 +24,16 @@ import { Value } from "../Value.mjs";
|
|
|
24
24
|
|
|
25
25
|
const state = createState();
|
|
26
26
|
|
|
27
|
-
let output = await evaluateInput("
|
|
28
|
-
output = await evaluateInput(":
|
|
29
|
-
assert.match(output[0],
|
|
27
|
+
let output = await evaluateInput("zero = {} | zero;", state);
|
|
28
|
+
output = await evaluateInput(":rel zero", state);
|
|
29
|
+
assert.match(output[0], /^zero = /);
|
|
30
30
|
|
|
31
31
|
output = await evaluateInput("succ = | succ;", state);
|
|
32
32
|
output = await evaluateInput(":rel succ", state);
|
|
33
33
|
assert.match(output[0], /^succ = /);
|
|
34
34
|
|
|
35
|
-
output = await evaluateInput(":types", state);
|
|
36
|
-
assert.match(output[0], /^nat = @/m);
|
|
37
|
-
|
|
38
35
|
output = await evaluateInput(":rels", state);
|
|
36
|
+
assert.match(output[0], /^zero = @/m);
|
|
39
37
|
assert.match(output[0], /^succ = @/m);
|
|
40
38
|
|
|
41
39
|
output = await evaluateInput("succ", state);
|
|
@@ -54,18 +52,18 @@ assert.match(output[0], /^succ = /);
|
|
|
54
52
|
let completions = completeInput(":he", state)[0];
|
|
55
53
|
assert.deepEqual(completions, [":help"]);
|
|
56
54
|
|
|
57
|
-
const canonicalPartial = state.
|
|
55
|
+
const canonicalPartial = state.relAliases.zero.slice(0, 8);
|
|
58
56
|
completions = completeInput(`:rel ${canonicalPartial}`, state)[0];
|
|
59
|
-
assert(completions.some((line) => line.endsWith(state.
|
|
57
|
+
assert(completions.some((line) => line.endsWith(state.relAliases.zero)));
|
|
60
58
|
|
|
61
59
|
completions = completeInput(`(${canonicalPartial}`, state)[0];
|
|
62
|
-
assert(completions.includes(`(${state.
|
|
60
|
+
assert(completions.includes(`(${state.relAliases.zero}`));
|
|
63
61
|
|
|
64
62
|
completions = completeInput(":rel su", state)[0];
|
|
65
63
|
assert(completions.includes(":rel succ"));
|
|
66
|
-
completions = completeInput(":
|
|
67
|
-
assert(completions.includes(":
|
|
68
|
-
assert(completions.includes(":
|
|
64
|
+
completions = completeInput(":re", state)[0];
|
|
65
|
+
assert(completions.includes(":rels"));
|
|
66
|
+
assert(completions.includes(":rel"));
|
|
69
67
|
|
|
70
68
|
await assert.rejects(
|
|
71
69
|
() => evaluateInput(":run succ", state),
|
|
@@ -83,27 +81,26 @@ await assert.rejects(
|
|
|
83
81
|
completions = completeInput(":co", state)[0];
|
|
84
82
|
assert(completions.includes(":codec"));
|
|
85
83
|
|
|
86
|
-
completions = completeInput("
|
|
87
|
-
assert(completions.includes("
|
|
84
|
+
completions = completeInput("ze", state)[0];
|
|
85
|
+
assert(completions.includes("zero"));
|
|
88
86
|
|
|
89
|
-
assert.deepEqual(aliasNames(state), ["
|
|
87
|
+
assert.deepEqual(aliasNames(state), ["succ", "zero"]);
|
|
90
88
|
assert.equal(lineTerminatesSnippet(";"), true);
|
|
91
89
|
assert.equal(lineTerminatesSnippet(" ; "), true);
|
|
92
90
|
assert.equal(lineTerminatesSnippet(" ; -- comment"), false);
|
|
93
91
|
assert.equal(lineTerminatesSnippet("succ"), false);
|
|
94
|
-
assert.equal(explicitSnippetTerminated("
|
|
92
|
+
assert.equal(explicitSnippetTerminated("bool = <{} true, {} false>;"), true);
|
|
95
93
|
assert.equal(lineHasExplicitContinuation("succ \\"), true);
|
|
96
|
-
assert.equal(analyzeRawSnippet("
|
|
97
|
-
assert.equal(analyzeAcceptedSnippet("
|
|
94
|
+
assert.equal(analyzeRawSnippet("bool = <{} true, {} false>").kind, "incomplete");
|
|
95
|
+
assert.equal(analyzeAcceptedSnippet("bool = <{} true, {} false>;", true).kind, "definitionsOnly");
|
|
98
96
|
assert.equal(analyzeRawSnippet("a =").kind, "incomplete");
|
|
99
97
|
assert.equal(analyzeRawSnippet("{} | succ").kind, "withMain");
|
|
100
98
|
|
|
101
99
|
const offsetState = createState();
|
|
102
|
-
await evaluateInput("
|
|
103
|
-
await evaluateInput("$ bool = < {} true, {} false >;", offsetState);
|
|
100
|
+
await evaluateInput("zero = {} | zero;\nsucc = | succ;", offsetState);
|
|
104
101
|
await assert.rejects(
|
|
105
|
-
() => evaluateInput("
|
|
106
|
-
/Type Error in '
|
|
102
|
+
() => evaluateInput("{} .x", offsetState),
|
|
103
|
+
/Type Error in 'comp' \(lines 1:1\.\.\.1:6\)/
|
|
107
104
|
);
|
|
108
105
|
|
|
109
106
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "k-repl-"));
|
|
@@ -117,13 +114,12 @@ output = await evaluateInput(`:klib ${libPath}`, state);
|
|
|
117
114
|
assert.equal(output[0], `saved ${libPath}`);
|
|
118
115
|
|
|
119
116
|
const recursiveState = createState();
|
|
120
|
-
await evaluateInput("
|
|
121
|
-
await evaluateInput("0? = $ nat < / _ {} | 0, / 0 0? >;", recursiveState);
|
|
117
|
+
await evaluateInput("0? = ?< {} _, X 0, X 1 > = X < / _ {} | 0, / 0 0? >;", recursiveState);
|
|
122
118
|
const staleZeroHash = recursiveState.relAliases["0?"];
|
|
123
|
-
await evaluateInput("0? =
|
|
119
|
+
await evaluateInput("0? = ?< {} _, X 0, X 1 > = X < / _ {} | _, / 0 0? >;", recursiveState);
|
|
124
120
|
const zeroHash = recursiveState.relAliases["0?"];
|
|
125
121
|
assert.notEqual(zeroHash, staleZeroHash);
|
|
126
|
-
await evaluateInput("{}|_|0|0
|
|
122
|
+
await evaluateInput("{}|_|0|0 0?", recursiveState);
|
|
127
123
|
assert.deepEqual(
|
|
128
124
|
Object.keys(recursiveState.rels).sort(),
|
|
129
125
|
[staleZeroHash, zeroHash].sort()
|
|
@@ -144,28 +140,21 @@ const objectFn = objectToFunction(decodeObject(fs.readFileSync(koPath)));
|
|
|
144
140
|
const objectResult = objectFn(Value.product({}, [["closed-product", []]]));
|
|
145
141
|
assert.equal(objectResult.toJSON(), "succ");
|
|
146
142
|
|
|
147
|
-
fs.writeFileSync(sourcePath, "
|
|
143
|
+
fs.writeFileSync(sourcePath, "succ = |succ;\ntwice = succ succ;\n");
|
|
148
144
|
const loadedSource = createState();
|
|
149
145
|
output = await evaluateInput(`:load ${sourcePath}`, loadedSource);
|
|
150
146
|
assert.equal(output[0], `loaded ${sourcePath}`);
|
|
151
|
-
output = await evaluateInput(":types", loadedSource);
|
|
152
|
-
assert.match(output[0], /^nat = @/m);
|
|
153
147
|
output = await evaluateInput(":rels", loadedSource);
|
|
154
148
|
assert.match(output[0], /^succ = @/m);
|
|
155
149
|
output = await evaluateInput(":rel twice", loadedSource);
|
|
156
|
-
assert.match(output[0], /^twice =
|
|
157
|
-
output = await evaluateInput(":C nat", loadedSource);
|
|
158
|
-
assert.match(output[0], /^\$ nat = < nat succ, @[^ ]+ zero >; -- @/);
|
|
150
|
+
assert.match(output[0], /^twice = .*succ succ.*; -- @/);
|
|
159
151
|
|
|
160
152
|
const codecState = createState();
|
|
161
|
-
output = await evaluateInput("$ bool = < {} true, {} false >;", codecState);
|
|
162
|
-
const boolHash = codecState.typeAliases.bool;
|
|
163
153
|
const valueModuleUrl = pathToFileURL(path.resolve("Value.mjs")).href;
|
|
164
154
|
fs.writeFileSync(codecPath, `
|
|
165
155
|
import { Value } from ${JSON.stringify(valueModuleUrl)};
|
|
166
156
|
|
|
167
157
|
export const name = "yn";
|
|
168
|
-
export const codes = [${JSON.stringify(boolHash)}];
|
|
169
158
|
|
|
170
159
|
export function parse(text) {
|
|
171
160
|
const tag = text.trim();
|
|
@@ -249,11 +238,9 @@ const reloaded = createState();
|
|
|
249
238
|
output = await evaluateInput(`:load ${libPath}`, reloaded);
|
|
250
239
|
assert.equal(output[0], `loaded ${libPath}`);
|
|
251
240
|
|
|
252
|
-
output = await evaluateInput(":types", reloaded);
|
|
253
|
-
assert.match(output[0], /^nat = @/m);
|
|
254
|
-
|
|
255
241
|
output = await evaluateInput(":rels", reloaded);
|
|
256
242
|
assert.match(output[0], /^succ = @/m);
|
|
243
|
+
assert.match(output[0], /^zero = @/m);
|
|
257
244
|
|
|
258
245
|
output = await evaluateInput("succ", reloaded);
|
|
259
246
|
assert.equal(output[0], "{}|succ ?<{} succ, ...>");
|
|
@@ -261,25 +248,22 @@ assert.equal(output[0], "{}|succ ?<{} succ, ...>");
|
|
|
261
248
|
const noAliasReloaded = createState();
|
|
262
249
|
output = await evaluateInput(`:load --no-alias ${libPath}`, noAliasReloaded);
|
|
263
250
|
assert.equal(output[0], `loaded ${libPath}`);
|
|
264
|
-
output = await evaluateInput(":types", noAliasReloaded);
|
|
265
|
-
assert.equal(output[0], "(none)");
|
|
266
251
|
output = await evaluateInput(":rels", noAliasReloaded);
|
|
267
252
|
assert.equal(output[0], "(none)");
|
|
268
253
|
|
|
269
254
|
const shorthand = createState();
|
|
270
|
-
output = await evaluateInput("
|
|
255
|
+
output = await evaluateInput("zero = {} | zero\n; succ = |succ\n;", shorthand);
|
|
271
256
|
assert.match(output[0], /\/\* comp: .* \*\//);
|
|
272
|
-
output = await evaluateInput(":types", shorthand);
|
|
273
|
-
assert.match(output[0], /^nat = @/m);
|
|
274
257
|
output = await evaluateInput(":rels", shorthand);
|
|
258
|
+
assert.match(output[0], /^zero = @/m);
|
|
275
259
|
assert.match(output[0], /^succ = @/m);
|
|
276
|
-
output = await evaluateInput("
|
|
260
|
+
output = await evaluateInput("not = </true | false, /false | true >\n; {} | true not", shorthand);
|
|
277
261
|
assert.match(output[0], /^\{\}\|false \?</);
|
|
278
262
|
assert.match(output[0], / false/);
|
|
279
263
|
assert.match(output[0], / true/);
|
|
280
|
-
output = await evaluateInput("
|
|
264
|
+
output = await evaluateInput("maybe = < /none {} | none, /some | some >;", shorthand);
|
|
281
265
|
assert.match(output[0], /\/\* comp: .* \*\//);
|
|
282
|
-
output = await evaluateInput(":
|
|
266
|
+
output = await evaluateInput(":rels", shorthand);
|
|
283
267
|
assert.match(output[0], /^maybe = @/m);
|
|
284
268
|
output = await evaluateInput("{} | true not", shorthand);
|
|
285
269
|
assert.match(output[0], /^\{\}\|false \?</);
|
|
@@ -291,8 +275,7 @@ await assert.rejects(
|
|
|
291
275
|
|
|
292
276
|
// Verify WebAssembly in-process backend supports TCO / stack safety on deep recursion
|
|
293
277
|
const tcoState = createState();
|
|
294
|
-
await evaluateInput("
|
|
295
|
-
await evaluateInput("countdown = $ nat < / zero {} | zero, / succ countdown >;", tcoState);
|
|
278
|
+
await evaluateInput("countdown = ?< {} zero, X succ > = X < / zero {} | zero, / succ countdown >;", tcoState);
|
|
296
279
|
|
|
297
280
|
let deepNat = Value.variant("zero", Value.product({}, [["closed-product", []]]), [["open-union", [["zero", 1]]], ["closed-product", []]]);
|
|
298
281
|
for (let i = 0; i < 5000; i++) {
|
|
@@ -336,7 +319,7 @@ assert.equal(output[0], "unloaded codec int.mjs");
|
|
|
336
319
|
output = await evaluateInput(":codecs", codecTestState);
|
|
337
320
|
assert.equal(output[0], "(none)");
|
|
338
321
|
|
|
339
|
-
output = await evaluateInput("
|
|
322
|
+
output = await evaluateInput("bool = < /true {} | true, /false {} | false >;", codecTestState);
|
|
340
323
|
registerCodec(codecTestState, {
|
|
341
324
|
name: "yn.mjs",
|
|
342
325
|
parse: (text) => Value.variant(text.trim() === "yes" ? "true" : "false", Value.product({})),
|
|
@@ -390,7 +373,9 @@ const ieeeAutoState = createState();
|
|
|
390
373
|
await evaluateInput(":load Examples/ieee.k", ieeeAutoState);
|
|
391
374
|
output = await evaluateInput(":codec load ./codecs/ieee.mjs", ieeeAutoState);
|
|
392
375
|
assert.match(output[0], /^loaded codec ieee\.mjs/);
|
|
393
|
-
assert.ok(ieeeAutoState.
|
|
376
|
+
assert.ok(ieeeAutoState.codecs["ieee.mjs"], "ieee codec should be registered");
|
|
377
|
+
output = await evaluateInput(":input ieee.mjs 1.5", ieeeAutoState);
|
|
378
|
+
assert.match(output[0], /ieee\.mjs: 1\.5/);
|
|
394
379
|
|
|
395
380
|
const jsonInputState = createState();
|
|
396
381
|
await evaluateInput(":load core.k", jsonInputState);
|
|
@@ -453,7 +438,7 @@ const polyAutoState = createState();
|
|
|
453
438
|
output = await evaluateInput(":load Examples/poly.k", polyAutoState);
|
|
454
439
|
assert.equal(output[0], "loaded Examples/poly.k");
|
|
455
440
|
assert.ok(polyAutoState.relAliases.reverse, "poly relations should be loaded");
|
|
456
|
-
assert.ok(polyAutoState.
|
|
441
|
+
assert.ok(polyAutoState.relAliases.int, "arithmetics int should be auto-loaded");
|
|
457
442
|
|
|
458
443
|
// Verify timing reporting is always on and reflects active engine
|
|
459
444
|
const timingState = createState();
|
|
@@ -510,11 +495,11 @@ assert(completions.includes(":engine js"));
|
|
|
510
495
|
const jsState = createState({ engine: "js" });
|
|
511
496
|
assert.equal(jsState.engine, "js");
|
|
512
497
|
|
|
513
|
-
output = await evaluateInput("
|
|
498
|
+
output = await evaluateInput("succ = | succ;\n{} | zero succ succ", jsState);
|
|
514
499
|
assert.match(output[0], /^\{\}\|zero\|succ\|succ/);
|
|
515
500
|
assert.match(output[1], /\(js\)/);
|
|
516
501
|
|
|
517
|
-
output = await evaluateInput("
|
|
502
|
+
output = await evaluateInput("not = </true | false, /false | true >;\n{} | true not", jsState);
|
|
518
503
|
assert.match(output[0], /^\{\}\|false/);
|
|
519
504
|
assert.match(output[1], /\(js\)/);
|
|
520
505
|
|
package/tests/test.mjs
CHANGED
|
@@ -22,9 +22,8 @@ import k from "../index.mjs";
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
let k_expression = `
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
false = {} | false $bool;
|
|
25
|
+
true = {} | true;
|
|
26
|
+
false = {} | false;
|
|
28
27
|
|
|
29
28
|
list? = ?< {} nil, {X car, Y cdr} cons > = Y;
|
|
30
29
|
nil = {}|nil list?;
|