@fraczak/k 6.2.0 → 6.2.2
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/DOCS/KIR_SPECIALIZATION_DESIGN.md +11 -2
- package/DOCS/KVM_EXECUTION_MODEL.md +413 -0
- package/Examples/arithmetics.k +452 -0
- package/Examples/bnat.k +291 -0
- package/Examples/byte.k +67 -0
- package/Examples/code.k +44 -0
- package/Examples/esc.k +9 -0
- package/Examples/ieee.k +15766 -0
- package/Examples/list.k +7 -0
- package/Examples/nat.k +12 -0
- package/Examples/vhdl_to_k.k +50 -0
- package/README.md +8 -0
- package/backend-api.mjs +12 -0
- package/codecs/runtime/codec.mjs +136 -72
- package/codecs/runtime/prefix-codec.mjs +98 -64
- package/kvm.mjs +523 -0
- package/package.json +3 -2
- package/run.mjs +1 -1
- package/scripts/run-tests.mjs +2 -0
- package/tests/README.md +35 -0
- package/tests/code-derivation/codec-witness-pattern.mjs +1 -1
- package/tests/integration.sh +8 -5
- package/tests/test-deep-wire-value.mjs +29 -0
- package/tests/test-kvm.mjs +163 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import k from "../index.mjs";
|
|
3
|
+
import { lowerToKVM, executeKVM } from "../kvm.mjs";
|
|
4
|
+
import codes from "../codes.mjs";
|
|
5
|
+
import { fromObject, Product, Variant } from "../Value.mjs";
|
|
6
|
+
import run, { run_converged } from "../run.mjs";
|
|
7
|
+
|
|
8
|
+
function runKVM(script, data, options = {}) {
|
|
9
|
+
const defs = k.annotate(script, {
|
|
10
|
+
convergence: { strategy: "auto" }
|
|
11
|
+
});
|
|
12
|
+
const mainRel = defs.rels.__main__;
|
|
13
|
+
const kvmFunc = lowerToKVM(mainRel, "__main__");
|
|
14
|
+
const context = { rels: defs.rels, findCode: codes.find, options };
|
|
15
|
+
return executeKVM(kvmFunc, fromObject(data), context);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function toJSON(value) {
|
|
19
|
+
if (value === undefined) return undefined;
|
|
20
|
+
return JSON.parse(JSON.stringify(value));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
console.log("==> Starting kVM Tests");
|
|
24
|
+
|
|
25
|
+
// Test 1: Identity
|
|
26
|
+
{
|
|
27
|
+
const result = runKVM("()", { unit: {} });
|
|
28
|
+
assert.deepEqual(toJSON(result), "unit");
|
|
29
|
+
console.log("Test 1 (Identity): Passed");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Test 2: Product field projection
|
|
33
|
+
{
|
|
34
|
+
const result = runKVM(".name", { name: { ala: {} }, age: { twentythree: {} } });
|
|
35
|
+
assert.deepEqual(toJSON(result), "ala");
|
|
36
|
+
console.log("Test 2 (Field projection): Passed");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Test 3: Variant projections and lifting
|
|
40
|
+
{
|
|
41
|
+
const result = runKVM("/tag |tag", { tag: { payload: {} } });
|
|
42
|
+
assert.deepEqual(toJSON(result), { tag: "payload" });
|
|
43
|
+
console.log("Test 3 (Variant projection & construction): Passed");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Test 4: Composition
|
|
47
|
+
{
|
|
48
|
+
const result = runKVM("(.x .y)", { x: { y: { ok: {}, dummy: {} }, dummy: {} }, dummy: {} });
|
|
49
|
+
assert.deepEqual(toJSON(result), { ok: {}, dummy: {} });
|
|
50
|
+
console.log("Test 4 (Composition): Passed");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Test 5: Union (Speculative choice)
|
|
54
|
+
{
|
|
55
|
+
const result1 = runKVM("< /x, /y >", { x: { val: {} } });
|
|
56
|
+
assert.deepEqual(toJSON(result1), "val");
|
|
57
|
+
|
|
58
|
+
const result2 = runKVM("< /x, /y >", { y: { val: {} } });
|
|
59
|
+
assert.deepEqual(toJSON(result2), "val");
|
|
60
|
+
|
|
61
|
+
const result3 = runKVM("< /x, /y >", { z: { val: {} } });
|
|
62
|
+
assert.equal(result3, undefined);
|
|
63
|
+
console.log("Test 5 (Union / Choice): Passed");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Test 6: Parallel Product
|
|
67
|
+
{
|
|
68
|
+
const result = runKVM("{ .x fieldA, .y fieldB }", { x: { valA: {} }, y: { valB: {} } });
|
|
69
|
+
assert.deepEqual(toJSON(result), {
|
|
70
|
+
fieldA: "valA",
|
|
71
|
+
fieldB: "valB"
|
|
72
|
+
});
|
|
73
|
+
console.log("Test 6 (Product): Passed");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Test 7: Filters & Types
|
|
77
|
+
{
|
|
78
|
+
const script = `
|
|
79
|
+
$ bool = < {} true, {} false >;
|
|
80
|
+
$ bool
|
|
81
|
+
`;
|
|
82
|
+
const result1 = runKVM(script, { true: {} });
|
|
83
|
+
assert.deepEqual(toJSON(result1), "true");
|
|
84
|
+
|
|
85
|
+
const result2 = runKVM(script, { unknown_tag: {} });
|
|
86
|
+
assert.deepEqual(toJSON(result2), "unknown_tag");
|
|
87
|
+
console.log("Test 7 (Filters & Type Guards): Passed");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Test 8: Recursive List traversal (Cons/Nil)
|
|
91
|
+
{
|
|
92
|
+
const script = `
|
|
93
|
+
$ bool = < {} true, {} false >;
|
|
94
|
+
true = {} | true $bool;
|
|
95
|
+
false = {} | false $bool;
|
|
96
|
+
|
|
97
|
+
list? = ?< {} nil, {X car, Y cdr} cons > = Y;
|
|
98
|
+
nil = {}|nil list?;
|
|
99
|
+
nil? = list? /nil nil;
|
|
100
|
+
car = list? /cons .car;
|
|
101
|
+
list? {
|
|
102
|
+
< nil? true, false > nil_test,
|
|
103
|
+
< car, {}|none > car
|
|
104
|
+
}
|
|
105
|
+
`;
|
|
106
|
+
|
|
107
|
+
// Test Nil list
|
|
108
|
+
const res1 = runKVM(script, { nil: {} });
|
|
109
|
+
assert.deepEqual(toJSON(res1), { nil_test: "true", car: "none" });
|
|
110
|
+
|
|
111
|
+
// Test Cons list
|
|
112
|
+
const res2 = runKVM(script, {
|
|
113
|
+
cons: {
|
|
114
|
+
car: { unit: {} },
|
|
115
|
+
cdr: { nil: {} }
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
assert.deepEqual(toJSON(res2), { nil_test: "false", car: "unit" });
|
|
119
|
+
console.log("Test 8 (Recursive lists): Passed");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Test 9: Comparing KVM execution vs Native JS run (Envelope-aware and Envelope-free)
|
|
123
|
+
{
|
|
124
|
+
const script = `
|
|
125
|
+
$ nat = < {} 0, nat +1 >;
|
|
126
|
+
0 = {} | 0 $ nat;
|
|
127
|
+
inc = | +1 $ nat;
|
|
128
|
+
dec = $ nat / +1;
|
|
129
|
+
add = $ { nat x, nat y } <
|
|
130
|
+
{ . x dec x, . y inc y } add,
|
|
131
|
+
. y
|
|
132
|
+
>;
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
const inputData = {
|
|
136
|
+
x: { "+1": { "+1": { "0": {} } } }, // 2
|
|
137
|
+
y: { "+1": { "0": {} } } // 1
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Run in native JS envelope-aware mode
|
|
141
|
+
const nativeAware = k.run(script + " add", inputData);
|
|
142
|
+
// Run in native JS envelope-free mode
|
|
143
|
+
const defs = k.annotate(script + " add", {
|
|
144
|
+
convergence: { strategy: "auto" }
|
|
145
|
+
});
|
|
146
|
+
run.defs = defs;
|
|
147
|
+
run_converged.defs = defs;
|
|
148
|
+
const nativeFree = run_converged(codes.find, defs.rels.__main__.def, fromObject(inputData), defs.rels.__main__.typePatternGraph);
|
|
149
|
+
|
|
150
|
+
// Run in kVM envelope-aware mode
|
|
151
|
+
const kvmAware = runKVM(script + " add", inputData, { envelopeFree: false });
|
|
152
|
+
// Run in kVM envelope-free mode
|
|
153
|
+
const kvmFree = runKVM(script + " add", inputData, { envelopeFree: true });
|
|
154
|
+
|
|
155
|
+
assert.deepEqual(toJSON(kvmAware), toJSON(nativeAware));
|
|
156
|
+
assert.deepEqual(toJSON(kvmFree), toJSON(nativeFree));
|
|
157
|
+
|
|
158
|
+
// Verify that the output is 3 (i.e. +1(+1(+1(0))))
|
|
159
|
+
assert.deepEqual(toJSON(kvmAware), { "+1": { "+1": { "+1": "0" } } });
|
|
160
|
+
console.log("Test 9 (KVM vs JS run equivalence & Peano addition): Passed");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
console.log("==> All kVM Tests Passed!");
|