@fraczak/k 5.1.2 → 6.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 (99) hide show
  1. package/Code-derivation-tests/blowup.mjs +3 -3
  2. package/Code-derivation-tests/bnat.mjs +2 -2
  3. package/Code-derivation-tests/codec-witness-pattern.mjs +50 -0
  4. package/Code-derivation-tests/convergence-strategy.mjs +24 -0
  5. package/Code-derivation-tests/dot.mjs +12 -9
  6. package/Code-derivation-tests/filter-syntax.mjs +21 -0
  7. package/Code-derivation-tests/loop.mjs +8 -2
  8. package/Code-derivation-tests/nat.mjs +1 -1
  9. package/Code-derivation-tests/not-not.mjs +3 -3
  10. package/Code-derivation-tests/pattern-envelope.mjs +68 -0
  11. package/Code-derivation-tests/rlz.mjs +2 -2
  12. package/{BIG_PICTURE.md → DOCS/BIG_PICTURE.md} +103 -50
  13. package/DOCS/REPL.md +191 -0
  14. package/DOCS/book/01-introduction.md +51 -0
  15. package/DOCS/book/02-syntax-and-values.md +111 -0
  16. package/DOCS/book/03-types-as-finite-automata.md +156 -0
  17. package/DOCS/book/04-partial-functions-and-composition.md +146 -0
  18. package/DOCS/book/05-typing-filters-and-normalization.md +111 -0
  19. package/DOCS/book.md +54 -0
  20. package/README.md +204 -508
  21. package/TypeGraph.mjs +43 -0
  22. package/TypePatternGraph.mjs +251 -0
  23. package/Value.mjs +192 -0
  24. package/augmentation.mjs +198 -0
  25. package/codecs/BINARY_FORMAT.md +53 -0
  26. package/codecs/POLYMORPHIC_BINARY_FORMAT.md +303 -0
  27. package/codecs/README.md +215 -0
  28. package/codecs/example-pipeline.mjs +149 -0
  29. package/codecs/ieee.mjs +140 -0
  30. package/codecs/int.mjs +104 -0
  31. package/codecs/json-codec.mjs +215 -0
  32. package/codecs/json.mjs +40 -0
  33. package/codecs/k-parse.mjs +90 -0
  34. package/codecs/k-pattern.mjs +75 -0
  35. package/codecs/k-print.mjs +46 -0
  36. package/codecs/runtime/codec.mjs +768 -0
  37. package/codecs/runtime/ieee-pattern.mjs +30 -0
  38. package/codecs/runtime/pattern-json.mjs +96 -0
  39. package/codecs/runtime/prefix-codec.mjs +425 -0
  40. package/codecs/runtime/show-value.mjs +68 -0
  41. package/codecs/runtime/typeFromValue.mjs +34 -0
  42. package/codecs/runtime/unicode-string.mjs +220 -0
  43. package/codecs/show.mjs +41 -0
  44. package/codecs/string-codec.mjs +80 -0
  45. package/codecs/unit.mjs +51 -0
  46. package/codecs/utf16.mjs +66 -0
  47. package/codecs/utf8.mjs +37 -0
  48. package/codes.mjs +146 -44
  49. package/compiler.mjs +111 -0
  50. package/convergence.mjs +197 -0
  51. package/core.k +197 -0
  52. package/export.mjs +22 -32
  53. package/hash.mjs +29 -31
  54. package/index.mjs +41 -15
  55. package/k-vscode/.vscode/launch.json +14 -0
  56. package/k-vscode/README.md +65 -0
  57. package/k-vscode/language-configuration.json +42 -0
  58. package/k-vscode/package.json +57 -0
  59. package/k-vscode/snippets/k.json +92 -0
  60. package/k-vscode/syntaxes/k.tmLanguage.json +243 -0
  61. package/k.mjs +56 -54
  62. package/object.mjs +517 -0
  63. package/objects/README.md +38 -0
  64. package/objects/compile-lib.mjs +42 -0
  65. package/objects/compile.mjs +42 -0
  66. package/objects/decompile.mjs +32 -0
  67. package/package.json +18 -8
  68. package/parser.jison +27 -46
  69. package/parser.mjs +68 -100
  70. package/pretty.mjs +21 -40
  71. package/repl2.mjs +652 -0
  72. package/run.mjs +264 -231
  73. package/symbol-table.mjs +3 -17
  74. package/test-fingerprint.mjs +7 -7
  75. package/test-hash-fuzz.mjs +107 -0
  76. package/test-hash-normalization.mjs +134 -0
  77. package/test-k-object.mjs +74 -0
  78. package/test-repl2.mjs +95 -0
  79. package/test.mjs +45 -70
  80. package/tests.sh +10 -1
  81. package/typing.mjs +129 -676
  82. package/unification.mjs +157 -0
  83. package/valueIO.mjs +54 -0
  84. package/valueParser.jison +143 -0
  85. package/valueParser.mjs +713 -0
  86. package/Code-derivation-tests/built-in.mjs +0 -19
  87. package/Code-derivation-tests/vector.mjs +0 -19
  88. package/Filters/bug.k +0 -3
  89. package/Filters/composing.k +0 -15
  90. package/Filters/filter.k +0 -9
  91. package/TODO.md +0 -53
  92. package/TYPING.md +0 -365
  93. package/k-repl.cast +0 -1913
  94. package/k.cast +0 -618
  95. package/my-objects.json +0 -6
  96. package/patterns.mjs +0 -543
  97. package/repl.mjs +0 -213
  98. package/test-filters.mjs +0 -45
  99. package/typing-test.mjs +0 -40
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+
3
+ import assert from "node:assert/strict";
4
+ import { annotate } from "./index.mjs";
5
+
6
+ function mulberry32(seed) {
7
+ let t = seed >>> 0;
8
+ return function () {
9
+ t += 0x6d2b79f5;
10
+ let r = Math.imul(t ^ (t >>> 15), 1 | t);
11
+ r ^= r + Math.imul(r ^ (r >>> 7), 61 | r);
12
+ return ((r ^ (r >>> 14)) >>> 0) / 4294967296;
13
+ };
14
+ }
15
+
16
+ function randInt(rng, max) {
17
+ return Math.floor(rng() * max);
18
+ }
19
+
20
+ function permute(rng, arr) {
21
+ const out = [...arr];
22
+ for (let i = out.length - 1; i > 0; i--) {
23
+ const j = randInt(rng, i + 1);
24
+ [out[i], out[j]] = [out[j], out[i]];
25
+ }
26
+ return out;
27
+ }
28
+
29
+ function renameScript(script, mapping) {
30
+ let out = script;
31
+ const temps = {};
32
+ let i = 0;
33
+ for (const from of Object.keys(mapping)) {
34
+ temps[from] = `__TMP_${i++}__`;
35
+ }
36
+ for (const [from, tmp] of Object.entries(temps)) {
37
+ const re = new RegExp(`\\b${from}\\b`, "g");
38
+ out = out.replace(re, tmp);
39
+ }
40
+ for (const [from, to] of Object.entries(mapping)) {
41
+ const re = new RegExp(`\\b${temps[from]}\\b`, "g");
42
+ out = out.replace(re, to);
43
+ }
44
+ return out;
45
+ }
46
+
47
+ function getRelHash(script, name) {
48
+ const { relAlias } = annotate(script);
49
+ assert.ok(relAlias[name], `missing relAlias for ${name}`);
50
+ return relAlias[name];
51
+ }
52
+
53
+ function generateScript(rng, count) {
54
+ const names = Array.from({ length: count }, (_, i) => `f${i}`);
55
+ const defs = names.map((name) => {
56
+ const roll = randInt(rng, 2);
57
+ const refs = names;
58
+ if (roll === 0) {
59
+ return `${name} = ();`;
60
+ }
61
+ const ref1 = refs[randInt(rng, refs.length)];
62
+ const ref2 = refs[randInt(rng, refs.length)];
63
+ return `${name} = ${ref1} ${ref2};`;
64
+ });
65
+ const main = names[0];
66
+ return `${defs.join("\n")}\n${main}\n`;
67
+ }
68
+
69
+ function buildRenameMap(names, rng) {
70
+ const perm = permute(rng, names);
71
+ const map = {};
72
+ names.forEach((name, i) => {
73
+ map[name] = perm[i];
74
+ });
75
+ return map;
76
+ }
77
+
78
+ const rng = mulberry32(0xdeadbeef);
79
+ const iterations = 30;
80
+
81
+ for (let i = 0; i < iterations; i++) {
82
+ const count = 3 + randInt(rng, 4);
83
+ const script = generateScript(rng, count);
84
+ const names = Array.from({ length: count }, (_, j) => `f${j}`);
85
+
86
+ const baseHash = getRelHash(script, "f0");
87
+
88
+ const renameMap = buildRenameMap(names, rng);
89
+ const renamedScript = renameScript(script, renameMap);
90
+ const renamedMain = renameMap.f0;
91
+ const renamedHash = getRelHash(renamedScript, renamedMain);
92
+ assert.equal(baseHash, renamedHash, "renaming should not change hash");
93
+
94
+ const lines = script.trim().split("\n");
95
+ const defs = lines.slice(0, -1);
96
+ const main = lines[lines.length - 1];
97
+ const reordered = `${permute(rng, defs).join("\n")}\n${main}\n`;
98
+ const reorderedHash = getRelHash(reordered, "f0");
99
+ if (baseHash !== reorderedHash) {
100
+ console.error("Reorder mismatch:");
101
+ console.error("ORIGINAL:\n" + script);
102
+ console.error("REORDERED:\n" + reordered);
103
+ }
104
+ assert.equal(baseHash, reorderedHash, "reordering defs should not change hash");
105
+ }
106
+
107
+ console.log("test-hash-fuzz: ok");
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+
3
+ import assert from "node:assert/strict";
4
+ import { annotate } from "./index.mjs";
5
+ import { hash } from "./hash.mjs";
6
+
7
+ const nameRegex = /^[a-zA-Z0-9_+][a-zA-Z0-9_?!+]*$/;
8
+
9
+ function hashBody(h) {
10
+ assert.ok(h.startsWith("@"), "hash must start with @");
11
+ return h.slice(1);
12
+ }
13
+
14
+ function getRelHash(script, name) {
15
+ const { relAlias } = annotate(script);
16
+ assert.ok(relAlias[name], `missing relAlias for ${name}`);
17
+ return relAlias[name];
18
+ }
19
+
20
+ // Hash format invariants
21
+ {
22
+ const h = hash("abc");
23
+ assert.ok(nameRegex.test(hashBody(h)), "hash body must match k-name regex");
24
+ }
25
+
26
+ // Alpha-renaming of local references should not change hash
27
+ {
28
+ const scriptA = `
29
+ g = ();
30
+ f = g;
31
+ f
32
+ `;
33
+
34
+ const scriptB = `
35
+ h = ();
36
+ f = h;
37
+ f
38
+ `;
39
+
40
+ assert.equal(
41
+ getRelHash(scriptA, "f"),
42
+ getRelHash(scriptB, "f"),
43
+ "alpha renaming should be stable"
44
+ );
45
+ }
46
+
47
+ // Direct alias vs inline definition should not change hash
48
+ {
49
+ const scriptAlias = `
50
+ g = ();
51
+ f = g;
52
+ f
53
+ `;
54
+
55
+ const scriptInline = `
56
+ f = ();
57
+ f
58
+ `;
59
+
60
+ assert.equal(
61
+ getRelHash(scriptAlias, "f"),
62
+ getRelHash(scriptInline, "f"),
63
+ "alias vs inline should be stable"
64
+ );
65
+ }
66
+
67
+ // SCC order should not change hash
68
+ {
69
+ const scriptA = `
70
+ $bit = < {} 0, {} 1 >;
71
+ f = $bit < /0 |0 g, /1 >;
72
+ g = $bit < /0 |0 f, /1 >;
73
+ f
74
+ `;
75
+
76
+ const scriptB = `
77
+ $bit = < {} 0, {} 1 >;
78
+ g = $bit < /0 |0 f, /1 >;
79
+ f = $bit < /0 |0 g, /1 >;
80
+ f
81
+ `;
82
+
83
+ assert.equal(
84
+ getRelHash(scriptA, "f"),
85
+ getRelHash(scriptB, "f"),
86
+ "SCC order should be stable"
87
+ );
88
+ }
89
+
90
+ // Union ordering should be significant
91
+ {
92
+ const scriptA = `
93
+ x = < x, y >;
94
+ y = x;
95
+ x
96
+ `;
97
+
98
+ const scriptB = `
99
+ x = < y, x >;
100
+ y = x;
101
+ x
102
+ `;
103
+
104
+ assert.notEqual(
105
+ getRelHash(scriptA, "x"),
106
+ getRelHash(scriptB, "x"),
107
+ "union ordering should be significant"
108
+ );
109
+ }
110
+
111
+ // Product ordering should be significant
112
+ {
113
+ const scriptA = `
114
+ a = ();
115
+ b = ();
116
+ x = { a a, b b };
117
+ x
118
+ `;
119
+
120
+ const scriptB = `
121
+ a = ();
122
+ b = ();
123
+ y = { b b, a a };
124
+ y
125
+ `;
126
+
127
+ assert.notEqual(
128
+ getRelHash(scriptA, "x"),
129
+ getRelHash(scriptB, "y"),
130
+ "product ordering should be significant"
131
+ );
132
+ }
133
+
134
+ console.log("test-hash-normalization: ok");
@@ -0,0 +1,74 @@
1
+ import assert from "node:assert";
2
+ import fs from "node:fs";
3
+ import k from "./index.mjs";
4
+ import { parseValue } from "./valueIO.mjs";
5
+ import { decodeWire, encodeToWire, CORE_PATTERN_PROPERTY_LIST } from "./codecs/runtime/prefix-codec.mjs";
6
+ import { Product, Variant } from "./Value.mjs";
7
+ import { exportPatternGraph } from "./codecs/runtime/codec.mjs";
8
+ import { patternToPropertyList } from "./codecs/runtime/pattern-json.mjs";
9
+ import { compileObjectBuffer, decodeObject, objectToFunction, decompileObjectBuffer } from "./object.mjs";
10
+
11
+ const value = parseValue("{a:{b:x,c:{}}}");
12
+ const wire = encodeToWire(value, null);
13
+ const decodedWire = decodeWire(wire);
14
+ assert.deepEqual(decodedWire.pattern, [
15
+ ["open-union", [["a", 1]]],
16
+ ["closed-product", [["b", 2], ["c", 3]]],
17
+ ["open-union", [["x", 3]]],
18
+ ["closed-product", []]
19
+ ]);
20
+ assert.deepEqual(decodedWire.value.toJSON(), value.toJSON());
21
+
22
+ const unicodeLabelValue = new Product({
23
+ "é": new Variant("🙂", new Product({})),
24
+ "𐐷": new Product({})
25
+ });
26
+ const unicodeWire = encodeToWire(unicodeLabelValue, null);
27
+ const decodedUnicode = decodeWire(unicodeWire);
28
+ assert.deepEqual(decodedUnicode.value.toJSON(), unicodeLabelValue.toJSON());
29
+ assert(decodedUnicode.pattern.some(([, edges]) => edges.some(([label]) => label === "é")));
30
+ assert(decodedUnicode.pattern.some(([, edges]) => edges.some(([label]) => label === "🙂")));
31
+ assert(decodedUnicode.pattern.some(([, edges]) => edges.some(([label]) => label === "𐐷")));
32
+
33
+ const core = k.annotate(fs.readFileSync("core.k", "utf8"));
34
+ const coreMain = core.rels.__main__;
35
+ const corePatternId = coreMain.typePatternGraph.find(coreMain.def.patterns[0]);
36
+ const corePattern = patternToPropertyList(exportPatternGraph(coreMain.typePatternGraph, corePatternId));
37
+ assert.deepEqual(CORE_PATTERN_PROPERTY_LIST, corePattern);
38
+
39
+ const INT_PATTERN = [
40
+ ["closed-union", [["+", 1], ["-", 1]]],
41
+ ["closed-union", [["0", 1], ["1", 1], ["_", 2]]],
42
+ ["closed-product", []]
43
+ ];
44
+
45
+ const objectBuffer = compileObjectBuffer(`
46
+ $ bits = < {} _, bits 0, bits 1 >;
47
+ $ int = < bits +, bits - >;
48
+ {}|_|0|1|+ $int
49
+ `);
50
+ const objectFn = objectToFunction(decodeObject(objectBuffer));
51
+ const objectResult = objectFn(new Product({}));
52
+ assert.deepEqual(objectResult.pattern, INT_PATTERN);
53
+ assert.deepEqual(objectResult.toJSON(), { "+": { "1": { "0": "_" } } });
54
+
55
+ const decompiledSource = decompileObjectBuffer(objectBuffer);
56
+ const decompiledResult = k.compile(decompiledSource)(new Product({}));
57
+ assert.deepEqual(decompiledResult.pattern, INT_PATTERN);
58
+ assert.deepEqual(decompiledResult.toJSON(), objectResult.toJSON());
59
+ assert.match(decompiledSource, /^----- codes -----$/m);
60
+ assert.match(decompiledSource, /^----- rels -----$/m);
61
+ assert.match(decompiledSource, /^----- main -----$/m);
62
+ assert.match(decompiledSource, /\$ Nws3 =/);
63
+ assert.match(decompiledSource, /^7jfi = /m);
64
+ assert.match(decompiledSource, /^----- main -----\n\?\(\.\.\.\) 7jfi \$Nws3$/m);
65
+
66
+ assert.throws(() => k.compile("@A = (); @A"), /Parse error/);
67
+ assert.throws(() => k.compile("$ @A = {}; $@A"), /Parse error/);
68
+ assert.deepEqual(k.compile("7jfi = ?X0; 7jfi")(new Product({})).toJSON(), {});
69
+
70
+ const sccSource = decompileObjectBuffer(compileObjectBuffer("c = {}; b = c |x; a = b |y; a"));
71
+ assert.match(sccSource, /----- rels -----\nPQgV = .+\n\naQAD = .+\n\nN9UH = /s);
72
+ assert.deepEqual(k.compile(sccSource)(new Product({})).toJSON(), { y: "x" });
73
+
74
+ console.log("OK");
package/test-repl2.mjs ADDED
@@ -0,0 +1,95 @@
1
+ import assert from "node:assert";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+
6
+ import { completeInput, createState, evaluateInput } from "./repl2.mjs";
7
+ import { decodeObject, objectToFunction } from "./object.mjs";
8
+ import { Product } from "./Value.mjs";
9
+
10
+ const state = createState();
11
+
12
+ let output = await evaluateInput(":type nat = <{} zero, nat succ>", state);
13
+ assert.match(output[0], /^\$ nat = @/);
14
+
15
+ output = await evaluateInput(":rel succ = |succ", state);
16
+ assert.match(output[0], /^succ = @/);
17
+
18
+ output = await evaluateInput(":codes", state);
19
+ assert.match(output[0], /^nat = @/m);
20
+
21
+ output = await evaluateInput(":rels", state);
22
+ assert.match(output[0], /^succ = @/m);
23
+
24
+ output = await evaluateInput(":run succ", state);
25
+ assert.equal(output[0], "{}|succ ?<{} succ, ...>");
26
+
27
+ output = await evaluateInput(":t succ", state);
28
+ assert.match(output[0], /^succ : /);
29
+
30
+ output = await evaluateInput(":d succ", state);
31
+ assert.match(output[0], /^succ = /);
32
+
33
+ let completions = completeInput(":he", state)[0];
34
+ assert.deepEqual(completions, [":help"]);
35
+
36
+ const canonicalPartial = state.typeAliases.nat.slice(0, 8);
37
+ completions = completeInput(`:run ${canonicalPartial}`, state)[0];
38
+ assert(completions.some((line) => line.endsWith(state.typeAliases.nat)));
39
+
40
+ completions = completeInput(`(${canonicalPartial}`, state)[0];
41
+ assert(completions.includes(`(${state.typeAliases.nat}`));
42
+
43
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "k-repl2-"));
44
+ const libPath = path.join(tmpDir, "session.klib");
45
+ const koPath = path.join(tmpDir, "succ.ko");
46
+ const sourcePath = path.join(tmpDir, "session.k");
47
+ output = await evaluateInput(`:save ${libPath}`, state);
48
+ assert.equal(output[0], `saved ${libPath}`);
49
+
50
+ completions = completeInput(`:load ${tmpDir}/ses`, state)[0];
51
+ assert(completions.includes(`:load ${libPath}`));
52
+
53
+ output = await evaluateInput(`:ko ${koPath} succ`, state);
54
+ assert.equal(output[0], `saved ${koPath} (succ)`);
55
+ const objectFn = objectToFunction(decodeObject(fs.readFileSync(koPath)));
56
+ const objectResult = objectFn(new Product({}, [["closed-product", []]]));
57
+ assert.equal(objectResult.toJSON(), "succ");
58
+
59
+ fs.writeFileSync(sourcePath, "$ nat = <{} zero, nat succ>;\nsucc = |succ;\n");
60
+ const loadedSource = createState();
61
+ output = await evaluateInput(`:load ${sourcePath}`, loadedSource);
62
+ assert.equal(output[0], `loaded ${sourcePath}`);
63
+ output = await evaluateInput(":codes", loadedSource);
64
+ assert.match(output[0], /^nat = @/m);
65
+ output = await evaluateInput(":rels", loadedSource);
66
+ assert.match(output[0], /^succ = @/m);
67
+
68
+ const reloaded = createState();
69
+ output = await evaluateInput(`:load ${libPath}`, reloaded);
70
+ assert.equal(output[0], `loaded ${libPath}`);
71
+
72
+ output = await evaluateInput(":codes", reloaded);
73
+ assert.match(output[0], /^nat = @/m);
74
+
75
+ output = await evaluateInput(":rels", reloaded);
76
+ assert.match(output[0], /^succ = @/m);
77
+
78
+ output = await evaluateInput("succ", reloaded);
79
+ assert.equal(output[0], "{}|succ ?<{} succ, ...>");
80
+
81
+ const shorthand = createState();
82
+ output = await evaluateInput("$ nat = <{} zero, nat succ>;", shorthand);
83
+ assert.match(output[0], /^\$ nat = @/);
84
+ output = await evaluateInput("succ = |succ;", shorthand);
85
+ assert.match(output[0], /^succ = @/);
86
+ output = await evaluateInput("succ", shorthand);
87
+ assert.equal(output[0], "{}|succ ?<{} succ, ...>");
88
+
89
+ await assert.rejects(
90
+ () => evaluateInput("/type", createState()),
91
+ /Type Error|Unknown ref: 'type'|Parse error|Parse Error/
92
+ );
93
+
94
+ fs.rmSync(tmpDir, { recursive: true, force: true });
95
+ console.log("OK");
package/test.mjs CHANGED
@@ -1,101 +1,76 @@
1
1
  import k from "./index.mjs";
2
2
 
3
3
  [
4
- ["ANYTHING...", "()"],
5
- ["ANYTHING...", '{"ala" name, 23 age}'],
4
+ [{"unit": {}}, "()"],
5
+ [{"name": {"ala": {}}, "age": {"twentythree": {}}}, '{.name name, .age age}'],
6
6
  [
7
7
  {
8
- year: 2002,
9
- age: 19,
8
+ "year": {"twothousandtwo": {}},
9
+ "age": {"nineteen": {}},
10
10
  },
11
- "[.year, .age]",
12
- ],
13
- ["duplicate me", "[(), ()]"],
14
- ["nesting", "[[[()]]]"],
15
- ["nesting and accessing", "[[()]] {() nested, .0.0 val}"],
16
- [
17
- {
18
- test: "parse integer",
19
- },
20
- "0000",
21
- ],
22
- [
23
- {
24
- x: 3,
25
- y: 4,
26
- },
27
- "[.y,.x] PLUS",
11
+ "{.year year, .age age}",
28
12
  ],
13
+ [{"duplicate": {}}, "()"],
14
+ [{"nesting": {}}, "()"],
15
+ [{"test": {"parseunit": {}}}, "()"],
29
16
  ].map(function ([data, script]) {
30
17
  console.log(`k_expression = '${script}';`);
31
- console.log(`k.run(k_expression,${JSON.stringify(data)});`);
18
+ console.log(`k.run(k_expression,data});`);
32
19
  console.log(`// RETURNS: ${JSON.stringify(k.run(script, data))}`);
33
20
  return console.log("");
34
21
  });
35
22
 
36
- let k_expression =
37
- '{.name nom, <[.age, 18] GT "old", [.age, 12] GT "ado", "enfant"> age}';
38
-
39
- let k_fn = k.compile(k_expression);
40
-
41
- console.log(`var k_fn = k.compile('${k_expression}');`);
42
-
43
- console.log("");
44
-
45
- [
46
- {
47
- age: 23,
48
- name: "Emily",
49
- },
50
- {
51
- age: 16,
52
- name: "Katrina",
53
- },
54
- {
55
- age: 2,
56
- name: "Mark",
57
- },
58
- ].map(function (data) {
59
- console.log(`k_fn(${JSON.stringify(data)});`);
60
- console.log(`// RETURNS: ${JSON.stringify(k_fn(data))}`);
61
- return console.log("");
62
- });
63
-
64
23
 
65
- k_expression = "$ < < [ @int ] ints, [ @bool ] bools > list, @string None>";
24
+ let k_expression = `
25
+ $ bool = < {} true, {} false >;
26
+ true = {} | true $bool;
27
+ false = {} | false $bool;
28
+
29
+ list? = ?< {} nil, {X car, Y cdr} cons > = Y;
30
+ nil = {}|nil list?;
31
+ nil? = list? /nil nil;
32
+ car = list? /cons .car;
33
+ list? {
34
+ < nil? true, false > nil_test,
35
+ < car, {}|none > car
36
+ }
37
+ `
38
+ ;
66
39
 
67
- k_fn = k.compile(k_expression);
40
+ let k_fn = k.compile(k_expression);
68
41
 
69
42
  console.log(`var k_fn = k.compile('${k_expression}');`);
70
43
 
71
44
  console.log("");
72
45
 
73
46
  [
47
+ {"None": {}},
48
+ {"nil": {}},
74
49
  {
75
- None: "None",
76
- },
77
- {
78
- list: {
79
- ints: [],
80
- },
81
- },
82
- {
83
- list: {
84
- ints: [1, 2, 3],
85
- },
86
- },
87
- {
88
- list: {
89
- bools: [true, false],
50
+ "cons": {
51
+ "car": {"unit": {}},
52
+ "cdr": {
53
+ "cons": {
54
+ "car": {"unit": {}},
55
+ "cdr": {"nil": {}}
56
+ }
57
+ }
90
58
  },
91
59
  },
92
60
  {
93
- list: {
94
- bools: [true, 0],
61
+ "cons": {
62
+ "car": {"on": {}},
63
+ "cdr": {
64
+ "cons": {
65
+ "car": {"off": {}},
66
+ "cdr": {"nil": {}}
67
+
68
+ }
69
+ }
95
70
  },
96
71
  },
97
72
  ].map(function (data) {
98
73
  console.log(`k_fn(${JSON.stringify(data)});`);
99
- console.log(`// RETURNS: ${JSON.stringify(k_fn(data))}`);
74
+ console.log(`// RETURNS: ${JSON.stringify(k_fn(k.fromObject(data)))}`);
100
75
  return console.log("");
101
76
  });
package/tests.sh CHANGED
@@ -3,4 +3,13 @@
3
3
 
4
4
  echo "Running './tests.sh' ..."
5
5
 
6
- echo '[4,2,19,1]' | ./k.mjs -k Examples/rec-code.k -1
6
+ echo '["zebara", "ela", "kupa", ala, owca]' | node ./codecs/k-parse.mjs | ./k.mjs '{.1 0,.3 1}' | node ./codecs/k-print.mjs
7
+ echo
8
+ echo '-21' | node ./codecs/int.mjs --parse | node ./codecs/int.mjs --print | grep -qx -- '-21'
9
+ echo
10
+ node ./codecs/unit.mjs --parse | node ./codecs/unit.mjs --print | grep -qx '{}'
11
+ echo
12
+ printf 'A🙂\nBé~\t' | ./codecs/utf8.mjs --parse | ./k.mjs -k Examples/byte.k |./codecs/utf8.mjs --print
13
+ echo
14
+ echo "1031" | ./codecs/ieee.mjs --parse | ./k.mjs -k Examples/ieee.k | ./codecs/ieee.mjs --print
15
+ echo