@fraczak/k 6.2.4 → 6.3.1
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/Value.mjs +50 -40
- package/backend-api.mjs +1 -1
- package/codecs/example-pipeline.mjs +7 -7
- package/codecs/ieee.mjs +8 -8
- package/codecs/int.mjs +6 -6
- package/codecs/json-codec.mjs +15 -15
- package/codecs/runtime/codec.mjs +13 -13
- package/codecs/runtime/prefix-codec.mjs +18 -18
- package/codecs/runtime/show-value.mjs +3 -3
- package/codecs/runtime/test-codec.mjs +7 -7
- package/codecs/runtime/typeFromValue.mjs +4 -4
- package/codecs/runtime/unicode-string.mjs +30 -30
- package/codecs/unit.mjs +4 -4
- package/index.mjs +2 -2
- package/kvm.mjs +8 -8
- package/package.json +1 -1
- package/repl.mjs +2 -2
- package/run.mjs +9 -9
- package/scripts/run-tests.mjs +1 -0
- package/tests/code-derivation/codec-witness-pattern.mjs +4 -4
- package/tests/code-derivation/pattern-envelope.mjs +12 -12
- package/tests/test-deep-wire-value.mjs +4 -4
- package/tests/test-ieee-arithmetic.mjs +3 -3
- package/tests/test-k-object.mjs +10 -10
- package/tests/test-kvm.mjs +1 -1
- package/tests/test-repl.mjs +4 -4
- package/tests/test-structural-values.mjs +27 -0
- package/valueIO.mjs +1 -1
- package/valueParser.jison +9 -9
- package/valueParser.mjs +7 -7
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { deriveClosedPattern } from './codec.mjs';
|
|
7
7
|
import { encodeToWire, decodeWire } from './prefix-codec.mjs';
|
|
8
8
|
import { patternToPropertyList } from './pattern-json.mjs';
|
|
9
|
-
import {
|
|
9
|
+
import { Value, isProduct, isVariant } from '../../Value.mjs';
|
|
10
10
|
import hash from '../../hash.mjs';
|
|
11
11
|
|
|
12
12
|
// Type repository
|
|
@@ -44,7 +44,7 @@ function resolveType(typeName) {
|
|
|
44
44
|
|
|
45
45
|
// Test 1: Unit value
|
|
46
46
|
console.log('\n=== Test 1: Unit ===');
|
|
47
|
-
const unitValue =
|
|
47
|
+
const unitValue = Value.product({});
|
|
48
48
|
console.log('Encoding unit:', unitValue.toString());
|
|
49
49
|
|
|
50
50
|
const unitPattern = patternToPropertyList(deriveClosedPattern(unitTypeName, unitTypeDef, resolveType));
|
|
@@ -54,12 +54,12 @@ console.log('Hex:', unitEncoded.toString('hex'));
|
|
|
54
54
|
|
|
55
55
|
const unitDecoded = decodeWire(unitEncoded);
|
|
56
56
|
console.log('Decoded value:', unitDecoded.value.toString());
|
|
57
|
-
console.log('Match:', unitDecoded.value
|
|
57
|
+
console.log('Match:', isProduct(unitDecoded.value) &&
|
|
58
58
|
Object.keys(unitDecoded.value.product).length === 0);
|
|
59
59
|
|
|
60
60
|
// Test 2: Bool false
|
|
61
61
|
console.log('\n=== Test 2: Bool (false) ===');
|
|
62
|
-
const falseValue =
|
|
62
|
+
const falseValue = Value.variant('false', Value.product({}));
|
|
63
63
|
console.log('Encoding false:', falseValue.toString());
|
|
64
64
|
|
|
65
65
|
const boolPattern = patternToPropertyList(deriveClosedPattern(boolTypeName, boolTypeDef, resolveType));
|
|
@@ -69,12 +69,12 @@ console.log('Hex:', falseEncoded.toString('hex'));
|
|
|
69
69
|
|
|
70
70
|
const falseDecoded = decodeWire(falseEncoded);
|
|
71
71
|
console.log('Decoded value:', falseDecoded.value.toString());
|
|
72
|
-
console.log('Match:', falseDecoded.value
|
|
72
|
+
console.log('Match:', isVariant(falseDecoded.value) &&
|
|
73
73
|
falseDecoded.value.tag === 'false');
|
|
74
74
|
|
|
75
75
|
// Test 3: Bool true
|
|
76
76
|
console.log('\n=== Test 3: Bool (true) ===');
|
|
77
|
-
const trueValue =
|
|
77
|
+
const trueValue = Value.variant('true', Value.product({}));
|
|
78
78
|
console.log('Encoding true:', trueValue.toString());
|
|
79
79
|
|
|
80
80
|
const trueEncoded = encodeToWire(trueValue, boolPattern);
|
|
@@ -83,7 +83,7 @@ console.log('Hex:', trueEncoded.toString('hex'));
|
|
|
83
83
|
|
|
84
84
|
const trueDecoded = decodeWire(trueEncoded);
|
|
85
85
|
console.log('Decoded value:', trueDecoded.value.toString());
|
|
86
|
-
console.log('Match:', trueDecoded.value
|
|
86
|
+
console.log('Match:', isVariant(trueDecoded.value) &&
|
|
87
87
|
trueDecoded.value.tag === 'true');
|
|
88
88
|
|
|
89
89
|
console.log('\n=== All tests complete ===');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isProduct, isVariant } from "../../Value.mjs";
|
|
2
2
|
|
|
3
3
|
function typeDefsFromValue(value) {
|
|
4
4
|
let nextId = 0;
|
|
@@ -6,7 +6,7 @@ function typeDefsFromValue(value) {
|
|
|
6
6
|
|
|
7
7
|
function visit(node) {
|
|
8
8
|
const name = `:auto${nextId++}`;
|
|
9
|
-
if (node
|
|
9
|
+
if (isProduct(node)) {
|
|
10
10
|
const labels = Object.keys(node.product).sort();
|
|
11
11
|
const product = {};
|
|
12
12
|
for (const label of labels) {
|
|
@@ -16,7 +16,7 @@ function typeDefsFromValue(value) {
|
|
|
16
16
|
return name;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
if (node
|
|
19
|
+
if (isVariant(node)) {
|
|
20
20
|
const childName = visit(node.value);
|
|
21
21
|
defs[name] = { code: "union", union: { [node.tag]: childName } };
|
|
22
22
|
return name;
|
|
@@ -31,4 +31,4 @@ function typeDefsFromValue(value) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export { typeDefsFromValue };
|
|
34
|
-
export default { typeDefsFromValue };
|
|
34
|
+
export default { typeDefsFromValue };
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Value, isProduct, isVariant } from "../../Value.mjs";
|
|
2
2
|
|
|
3
|
-
const UNIT =
|
|
4
|
-
const BIT0 =
|
|
5
|
-
const BIT1 =
|
|
3
|
+
const UNIT = Value.product({});
|
|
4
|
+
const BIT0 = Value.variant("0", UNIT);
|
|
5
|
+
const BIT1 = Value.variant("1", UNIT);
|
|
6
6
|
|
|
7
7
|
function bitValue(bit) {
|
|
8
8
|
return bit === 0 ? BIT0 : BIT1;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
function requireProduct(value, where) {
|
|
12
|
-
if (!(value
|
|
12
|
+
if (!isProduct(value)) {
|
|
13
13
|
throw new Error(`${where}: expected Product`);
|
|
14
14
|
}
|
|
15
15
|
return value.product;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function requireVariant(value, where) {
|
|
19
|
-
if (!(value
|
|
19
|
+
if (!isVariant(value)) {
|
|
20
20
|
throw new Error(`${where}: expected Variant`);
|
|
21
21
|
}
|
|
22
22
|
return value;
|
|
@@ -27,7 +27,7 @@ function bitsProduct(width, n) {
|
|
|
27
27
|
for (let i = width - 1; i >= 0; i--) {
|
|
28
28
|
product[String(i)] = bitValue((n >> i) & 1);
|
|
29
29
|
}
|
|
30
|
-
return
|
|
30
|
+
return Value.product(product);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function parseBitsProduct(value, maxBit, where) {
|
|
@@ -52,14 +52,14 @@ function parseByteProduct(value, where) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
function encodeBmpCommonHi(hi) {
|
|
55
|
-
if (hi >= 0x08 && hi <= 0x0f) return
|
|
56
|
-
if (hi >= 0x10 && hi <= 0x7f) return
|
|
57
|
-
if (hi >= 0x80 && hi <= 0xcf) return
|
|
58
|
-
if (hi >= 0xd0 && hi <= 0xd7) return
|
|
59
|
-
if (hi === 0xf9) return
|
|
60
|
-
if (hi >= 0xfa && hi <= 0xfb) return
|
|
61
|
-
if (hi >= 0xfc && hi <= 0xfd) return
|
|
62
|
-
if (hi >= 0xfe && hi <= 0xff) return
|
|
55
|
+
if (hi >= 0x08 && hi <= 0x0f) return Value.variant("h08_0F", bitsProduct(3, hi - 0x08));
|
|
56
|
+
if (hi >= 0x10 && hi <= 0x7f) return Value.variant("h10_7F", bitsProduct(7, hi - 0x10));
|
|
57
|
+
if (hi >= 0x80 && hi <= 0xcf) return Value.variant("h80_CF", bitsProduct(7, hi - 0x80));
|
|
58
|
+
if (hi >= 0xd0 && hi <= 0xd7) return Value.variant("hD0_D7", bitsProduct(3, hi - 0xd0));
|
|
59
|
+
if (hi === 0xf9) return Value.variant("hF9", UNIT);
|
|
60
|
+
if (hi >= 0xfa && hi <= 0xfb) return Value.variant("hFA_FB", bitsProduct(1, hi - 0xfa));
|
|
61
|
+
if (hi >= 0xfc && hi <= 0xfd) return Value.variant("hFC_FD", bitsProduct(1, hi - 0xfc));
|
|
62
|
+
if (hi >= 0xfe && hi <= 0xff) return Value.variant("hFE_FF", bitsProduct(1, hi - 0xfe));
|
|
63
63
|
throw new Error(`Unsupported BMP common hi byte: 0x${hi.toString(16)}`);
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -77,9 +77,9 @@ function decodeBmpCommonHi(value) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
function encodeBmpPrivateHi(hi) {
|
|
80
|
-
if (hi >= 0xe0 && hi <= 0xef) return
|
|
81
|
-
if (hi >= 0xf0 && hi <= 0xf7) return
|
|
82
|
-
if (hi === 0xf8) return
|
|
80
|
+
if (hi >= 0xe0 && hi <= 0xef) return Value.variant("hE0_EF", bitsProduct(4, hi - 0xe0));
|
|
81
|
+
if (hi >= 0xf0 && hi <= 0xf7) return Value.variant("hF0_F7", bitsProduct(3, hi - 0xf0));
|
|
82
|
+
if (hi === 0xf8) return Value.variant("hF8", UNIT);
|
|
83
83
|
throw new Error(`Unsupported BMP private-use hi byte: 0x${hi.toString(16)}`);
|
|
84
84
|
}
|
|
85
85
|
|
|
@@ -92,10 +92,10 @@ function decodeBmpPrivateHi(value) {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
function encodePlane2To16(plane) {
|
|
95
|
-
if (plane >= 2 && plane <= 3) return
|
|
96
|
-
if (plane >= 4 && plane <= 7) return
|
|
97
|
-
if (plane >= 8 && plane <= 15) return
|
|
98
|
-
if (plane === 16) return
|
|
95
|
+
if (plane >= 2 && plane <= 3) return Value.variant("p02_03", bitsProduct(1, plane - 2));
|
|
96
|
+
if (plane >= 4 && plane <= 7) return Value.variant("p04_07", bitsProduct(2, plane - 4));
|
|
97
|
+
if (plane >= 8 && plane <= 15) return Value.variant("p08_0F", bitsProduct(3, plane - 8));
|
|
98
|
+
if (plane === 16) return Value.variant("p10", UNIT);
|
|
99
99
|
throw new Error(`Plane out of range for supplementary_planes2_16: ${plane}`);
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -117,34 +117,34 @@ function codePointToUnicodeValue(cp) {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
if (cp <= 0x7f) {
|
|
120
|
-
return
|
|
120
|
+
return Value.variant("ascii", bitsProduct(7, cp));
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
if (cp <= 0x7ff) {
|
|
124
|
-
return
|
|
124
|
+
return Value.variant("plane0", bitsProduct(11, cp));
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
if (cp <= 0xffff) {
|
|
128
128
|
const hi = (cp >> 8) & 0xff;
|
|
129
129
|
const lo = cp & 0xff;
|
|
130
130
|
if (hi >= 0xe0 && hi <= 0xf8) {
|
|
131
|
-
return
|
|
131
|
+
return Value.variant("bmp_private_use", Value.product({ hi: encodeBmpPrivateHi(hi), lo: byteProduct(lo) }));
|
|
132
132
|
}
|
|
133
|
-
return
|
|
133
|
+
return Value.variant("bmp_common", Value.product({ hi: encodeBmpCommonHi(hi), lo: byteProduct(lo) }));
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
const mid = (cp >> 8) & 0xff;
|
|
137
137
|
const lo = cp & 0xff;
|
|
138
138
|
|
|
139
139
|
if (cp <= 0x1ffff) {
|
|
140
|
-
return
|
|
140
|
+
return Value.variant("supplementary_plane1", Value.product({
|
|
141
141
|
mid: byteProduct(mid),
|
|
142
142
|
lo: byteProduct(lo)
|
|
143
143
|
}));
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
const plane = cp >> 16;
|
|
147
|
-
return
|
|
147
|
+
return Value.variant("supplementary_planes2_16", Value.product({
|
|
148
148
|
plane: encodePlane2To16(plane),
|
|
149
149
|
mid: byteProduct(mid),
|
|
150
150
|
lo: byteProduct(lo)
|
|
@@ -181,11 +181,11 @@ function unicodeValueToCodePoint(value) {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
function textToStringValue(text) {
|
|
184
|
-
let out =
|
|
184
|
+
let out = Value.variant("nil", UNIT);
|
|
185
185
|
const chars = Array.from(text);
|
|
186
186
|
for (let i = chars.length - 1; i >= 0; i--) {
|
|
187
187
|
const cp = chars[i].codePointAt(0);
|
|
188
|
-
out =
|
|
188
|
+
out = Value.variant("cons", Value.product({
|
|
189
189
|
car: codePointToUnicodeValue(cp),
|
|
190
190
|
cdr: out
|
|
191
191
|
}));
|
package/codecs/unit.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { stdin, stdout, argv, exit } from "node:process";
|
|
4
|
-
import {
|
|
4
|
+
import { Value, isProduct } from "../Value.mjs";
|
|
5
5
|
import { isMainEntrypoint } from "./runtime/cli-entry.mjs";
|
|
6
6
|
import { decodeWire, encodeToWire } from "./runtime/prefix-codec.mjs";
|
|
7
7
|
|
|
@@ -28,15 +28,15 @@ function readAll(stream) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
function unitEncoding() {
|
|
31
|
-
return encodeToWire(
|
|
31
|
+
return encodeToWire(Value.product({}), UNIT_PATTERN);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
function parse() {
|
|
35
|
-
return
|
|
35
|
+
return Value.product({});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function print(value) {
|
|
39
|
-
if (!(value
|
|
39
|
+
if (!isProduct(value) || Object.keys(value.product).length !== 0) {
|
|
40
40
|
throw new Error("Input is not a unit value");
|
|
41
41
|
}
|
|
42
42
|
return "{}";
|
package/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parse } from "./parser.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { fromObject, isValue } from "./Value.mjs";
|
|
3
3
|
import { parseValue } from "./valueIO.mjs";
|
|
4
4
|
import { compileTypes } from "./compiler.mjs";
|
|
5
5
|
import run from "./run.mjs";
|
|
@@ -19,7 +19,7 @@ compile.doc = "Transforms k-script (string) into a function";
|
|
|
19
19
|
|
|
20
20
|
function runScriptOnData(script, data, options = {}) {
|
|
21
21
|
let parsedData;
|
|
22
|
-
if (data
|
|
22
|
+
if (isValue(data)) {
|
|
23
23
|
parsedData = data;
|
|
24
24
|
} else if (typeof data === "string") {
|
|
25
25
|
parsedData = parseValue(data, null, null);
|
package/kvm.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import { argv, stdin, exit, stdout } from "node:process";
|
|
4
|
-
import {
|
|
4
|
+
import { Value, composePattern, withPattern, isProduct, isVariant } from "./Value.mjs";
|
|
5
5
|
import { exportPatternGraph } from "./codecs/runtime/codec.mjs";
|
|
6
6
|
import { patternToPropertyList } from "./codecs/runtime/pattern-json.mjs";
|
|
7
7
|
import {
|
|
@@ -281,7 +281,7 @@ function executeInstruction(inst, registers, context) {
|
|
|
281
281
|
}
|
|
282
282
|
case "project_field": {
|
|
283
283
|
const val = registers.get(inst.src);
|
|
284
|
-
if (!(val
|
|
284
|
+
if (!isProduct(val)) return undefined;
|
|
285
285
|
const fieldVal = val.product[inst.label];
|
|
286
286
|
if (fieldVal === undefined) return undefined;
|
|
287
287
|
|
|
@@ -295,7 +295,7 @@ function executeInstruction(inst, registers, context) {
|
|
|
295
295
|
}
|
|
296
296
|
case "project_variant": {
|
|
297
297
|
const val = registers.get(inst.src);
|
|
298
|
-
if (!(val
|
|
298
|
+
if (!isVariant(val) || val.tag !== inst.tag) return undefined;
|
|
299
299
|
|
|
300
300
|
if (options.envelopeFree) {
|
|
301
301
|
registers.set(inst.dest, val.value);
|
|
@@ -308,11 +308,11 @@ function executeInstruction(inst, registers, context) {
|
|
|
308
308
|
case "make_variant": {
|
|
309
309
|
const val = registers.get(inst.src);
|
|
310
310
|
if (options.envelopeFree) {
|
|
311
|
-
registers.set(inst.dest,
|
|
311
|
+
registers.set(inst.dest, Value.variant(inst.tag, val));
|
|
312
312
|
} else {
|
|
313
313
|
registers.set(
|
|
314
314
|
inst.dest,
|
|
315
|
-
|
|
315
|
+
Value.variant(inst.tag, val, composePattern("open-union", [[inst.tag, val.pattern]]))
|
|
316
316
|
);
|
|
317
317
|
}
|
|
318
318
|
return { type: "continue" };
|
|
@@ -375,13 +375,13 @@ function executeInstruction(inst, registers, context) {
|
|
|
375
375
|
}
|
|
376
376
|
let productValue;
|
|
377
377
|
if (options.envelopeFree) {
|
|
378
|
-
productValue =
|
|
378
|
+
productValue = Value.product(result);
|
|
379
379
|
} else {
|
|
380
380
|
const staticOutputPattern = inst.pattern;
|
|
381
381
|
if (staticOutputPattern) {
|
|
382
|
-
productValue =
|
|
382
|
+
productValue = Value.product(result, staticOutputPattern);
|
|
383
383
|
} else {
|
|
384
|
-
productValue =
|
|
384
|
+
productValue = Value.product(result, composePattern("closed-product", patternEntries));
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
387
|
registers.set(inst.dest, productValue);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fraczak/k",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.1",
|
|
4
4
|
"description": "k — a language for composing first-order partial functions over algebraic data types (products and tagged unions); includes runtime, type derivation, REPL, and codec toolchain",
|
|
5
5
|
"main": "index.mjs",
|
|
6
6
|
"scripts": {
|
package/repl.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import { argv, exit, stdin, stdout } from "node:process";
|
|
|
10
10
|
import { annotate, parse } from "./index.mjs";
|
|
11
11
|
import run from "./run.mjs";
|
|
12
12
|
import codes from "./codes.mjs";
|
|
13
|
-
import {
|
|
13
|
+
import { Value } from "./Value.mjs";
|
|
14
14
|
import { patterns2filters, prettyCode, prettyRel } from "./pretty.mjs";
|
|
15
15
|
import {
|
|
16
16
|
compileObject,
|
|
@@ -50,7 +50,7 @@ function cloneJSON(value) {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function emptyValue() {
|
|
53
|
-
return
|
|
53
|
+
return Value.product({}, [["closed-product", []]]);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function createState() {
|
package/run.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
|
-
import {
|
|
2
|
+
import { Value, edgeSubpattern, composePattern, withPattern, isProduct, isVariant } from "./Value.mjs"
|
|
3
3
|
import { exportPatternGraph, intersectPropertyListPatterns } from "./codecs/runtime/codec.mjs";
|
|
4
4
|
import { patternToPropertyList } from "./codecs/runtime/pattern-json.mjs";
|
|
5
5
|
|
|
@@ -261,14 +261,14 @@ function compiledExp(findCode, exp, typePatternGraph) {
|
|
|
261
261
|
` - product envelope: ${patternPreview(dynamicOutputPattern)}`
|
|
262
262
|
);
|
|
263
263
|
}
|
|
264
|
-
return
|
|
264
|
+
return Value.product(result, pattern);
|
|
265
265
|
};
|
|
266
266
|
break;
|
|
267
267
|
}
|
|
268
268
|
case "vid":
|
|
269
269
|
fn = (value) => {
|
|
270
270
|
if (value === undefined) return undefined;
|
|
271
|
-
return
|
|
271
|
+
return Value.variant(exp.vid, value, composePattern("open-union", [[exp.vid, value.pattern]]));
|
|
272
272
|
};
|
|
273
273
|
break;
|
|
274
274
|
default:
|
|
@@ -375,13 +375,13 @@ function compiledConvergedExp(findCode, exp, typePatternGraph, options = {}) {
|
|
|
375
375
|
break;
|
|
376
376
|
case "dot":
|
|
377
377
|
fn = (value) => {
|
|
378
|
-
if (value === undefined || !(value
|
|
378
|
+
if (value === undefined || !isProduct(value)) return undefined;
|
|
379
379
|
return Object.hasOwn(value.product, exp.dot) ? value.product[exp.dot] : undefined;
|
|
380
380
|
};
|
|
381
381
|
break;
|
|
382
382
|
case "div":
|
|
383
383
|
fn = (value) => {
|
|
384
|
-
if (value === undefined || !(value
|
|
384
|
+
if (value === undefined || !isVariant(value) || value.tag !== exp.div) return undefined;
|
|
385
385
|
return value.value;
|
|
386
386
|
};
|
|
387
387
|
break;
|
|
@@ -419,12 +419,12 @@ function compiledConvergedExp(findCode, exp, typePatternGraph, options = {}) {
|
|
|
419
419
|
if (r === undefined) return undefined;
|
|
420
420
|
result[labels[i]] = r;
|
|
421
421
|
}
|
|
422
|
-
return
|
|
422
|
+
return Value.product(result);
|
|
423
423
|
};
|
|
424
424
|
break;
|
|
425
425
|
}
|
|
426
426
|
case "vid":
|
|
427
|
-
fn = (value) => value === undefined ? undefined :
|
|
427
|
+
fn = (value) => value === undefined ? undefined : Value.variant(exp.vid, value);
|
|
428
428
|
break;
|
|
429
429
|
default:
|
|
430
430
|
assert(false,`Unknown operation: '${exp.op}'`);
|
|
@@ -440,7 +440,7 @@ function verify(findCode, code, value) {
|
|
|
440
440
|
code = findCode(code);
|
|
441
441
|
switch (code.code) {
|
|
442
442
|
case "product":
|
|
443
|
-
if (!
|
|
443
|
+
if (!isProduct(value)) return false;
|
|
444
444
|
else {
|
|
445
445
|
const fields = Object.keys(value.product);
|
|
446
446
|
if (fields.length !== Object.keys(code.product).length) return false;
|
|
@@ -449,7 +449,7 @@ function verify(findCode, code, value) {
|
|
|
449
449
|
);
|
|
450
450
|
}
|
|
451
451
|
case "union":
|
|
452
|
-
if (!
|
|
452
|
+
if (!isProduct(value)) return false;
|
|
453
453
|
else {
|
|
454
454
|
const fields = Object.keys(value.product);
|
|
455
455
|
if (fields.length !== 1) return false;
|
package/scripts/run-tests.mjs
CHANGED
|
@@ -18,6 +18,7 @@ const tests = [
|
|
|
18
18
|
["tests/test-fingerprint.mjs", node, ["tests/test-fingerprint.mjs"]],
|
|
19
19
|
["tests/test-hash-fuzz.mjs", node, ["tests/test-hash-fuzz.mjs"]],
|
|
20
20
|
["tests/test-hash-normalization.mjs", node, ["tests/test-hash-normalization.mjs"]],
|
|
21
|
+
["tests/test-structural-values.mjs", node, ["tests/test-structural-values.mjs"]],
|
|
21
22
|
["tests/test-deep-wire-value.mjs", node, ["tests/test-deep-wire-value.mjs"]],
|
|
22
23
|
["tests/test-k-object.mjs", node, ["tests/test-k-object.mjs"]],
|
|
23
24
|
["tests/test-repl.mjs", node, ["tests/test-repl.mjs"]],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from 'assert';
|
|
2
2
|
import { parseValue } from '../../valueIO.mjs';
|
|
3
3
|
import { encodeToWire, decodeWire } from '../../codecs/runtime/prefix-codec.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { isProduct, isVariant } from '../../Value.mjs';
|
|
5
5
|
|
|
6
6
|
const value = parseValue('{a:{b:x,c:{}}}');
|
|
7
7
|
const repeatedClosedValue = parseValue('{a:{m:{},n:{}},b:{m:{},n:{}}}');
|
|
@@ -27,9 +27,9 @@ assert.deepEqual(explicitProductWire.pattern, [
|
|
|
27
27
|
]);
|
|
28
28
|
|
|
29
29
|
const decoded = explicitProductWire.value;
|
|
30
|
-
assert(decoded
|
|
31
|
-
assert(decoded.product.a
|
|
32
|
-
assert(decoded.product.a.product.b
|
|
30
|
+
assert(isProduct(decoded));
|
|
31
|
+
assert(isProduct(decoded.product.a));
|
|
32
|
+
assert(isVariant(decoded.product.a.product.b));
|
|
33
33
|
assert.equal(decoded.product.a.product.b.tag, "x");
|
|
34
34
|
|
|
35
35
|
const repeatedClosedWire = decodeWire(encodeToWire(repeatedClosedValue, null));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import k from "../../index.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { Value, mergePatterns, withPattern } from "../../Value.mjs";
|
|
4
4
|
import { decodeWire, encodeToWire } from "../../codecs/runtime/prefix-codec.mjs";
|
|
5
5
|
import run from "../../run.mjs";
|
|
6
6
|
import codes from "../../codes.mjs";
|
|
@@ -17,16 +17,16 @@ const script = `
|
|
|
17
17
|
{}|_|0|1|+ $int
|
|
18
18
|
`;
|
|
19
19
|
|
|
20
|
-
const result = k.compile(script)(
|
|
20
|
+
const result = k.compile(script)(Value.product({}));
|
|
21
21
|
assert.deepEqual(result.pattern, INT_PATTERN);
|
|
22
22
|
|
|
23
23
|
const decoded = decodeWire(encodeToWire(result, result.pattern));
|
|
24
24
|
assert.deepEqual(decoded.pattern, INT_PATTERN);
|
|
25
25
|
|
|
26
|
-
const two =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const two = Value.variant("+",
|
|
27
|
+
Value.variant("1",
|
|
28
|
+
Value.variant("0",
|
|
29
|
+
Value.variant("_", Value.product({}))
|
|
30
30
|
)
|
|
31
31
|
)
|
|
32
32
|
);
|
|
@@ -53,13 +53,13 @@ const wrappedFloatPattern = [
|
|
|
53
53
|
["closed-product", []],
|
|
54
54
|
["closed-union", [["inexact", 5]]]
|
|
55
55
|
];
|
|
56
|
-
const wrappedFloat =
|
|
57
|
-
result:
|
|
58
|
-
sign:
|
|
59
|
-
exponent:
|
|
60
|
-
fraction:
|
|
56
|
+
const wrappedFloat = Value.product({
|
|
57
|
+
result: Value.product({
|
|
58
|
+
sign: Value.variant("+", Value.product({})),
|
|
59
|
+
exponent: Value.product({ 0: Value.variant("1", Value.product({})) }),
|
|
60
|
+
fraction: Value.product({ 0: Value.variant("0", Value.product({})) })
|
|
61
61
|
}),
|
|
62
|
-
flags:
|
|
62
|
+
flags: Value.variant("inexact", Value.product({}))
|
|
63
63
|
});
|
|
64
64
|
const resultProjection = k.compile(".result")(withPattern(wrappedFloat, wrappedFloatPattern));
|
|
65
65
|
assert.deepEqual(resultProjection.pattern, [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import {
|
|
2
|
+
import { Value } from "../Value.mjs";
|
|
3
3
|
import { decodeWire, encodeToWire } from "../codecs/runtime/prefix-codec.mjs";
|
|
4
4
|
|
|
5
5
|
const depth = 12000;
|
|
@@ -9,12 +9,12 @@ const pattern = [
|
|
|
9
9
|
["closed-product", []]
|
|
10
10
|
];
|
|
11
11
|
|
|
12
|
-
let bits =
|
|
12
|
+
let bits = Value.variant("_", Value.product({}));
|
|
13
13
|
for (let i = 0; i < depth; i++) {
|
|
14
|
-
bits =
|
|
14
|
+
bits = Value.variant("1", bits);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const wire = encodeToWire(
|
|
17
|
+
const wire = encodeToWire(Value.variant("+", bits), pattern);
|
|
18
18
|
const decoded = decodeWire(wire).value;
|
|
19
19
|
assert.equal(decoded.tag, "+");
|
|
20
20
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
|
|
3
3
|
import { createState, evaluateInput } from "../repl.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { Value, isProduct } from "../Value.mjs";
|
|
5
5
|
import codes from "../codes.mjs";
|
|
6
6
|
import { parse as parseFloat64, print as printFloat64 } from "../codecs/ieee.mjs";
|
|
7
7
|
import { singletonPatternToCodeHash, valueForCode } from "../repl-codecs.mjs";
|
|
@@ -21,7 +21,7 @@ function float64(text) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
function floatPair(x, y) {
|
|
24
|
-
return valueForCode(
|
|
24
|
+
return valueForCode(Value.product({
|
|
25
25
|
x: float64(x),
|
|
26
26
|
y: float64(y)
|
|
27
27
|
}), floatPairHash, codes.find);
|
|
@@ -46,7 +46,7 @@ function assertFloatResult(value, expected, label) {
|
|
|
46
46
|
|
|
47
47
|
async function assertOperation({ op, x, y, result, flags = null, projection = false }) {
|
|
48
48
|
const bundle = await runOperation(op, x, y);
|
|
49
|
-
assert.ok(bundle
|
|
49
|
+
assert.ok(isProduct(bundle), `${op} should return a result bundle`);
|
|
50
50
|
assert.deepEqual(Object.keys(bundle.product).sort(), ["flags", "result"]);
|
|
51
51
|
assertFloatResult(bundle.product.result, result, `${op}(${x}, ${y}).result`);
|
|
52
52
|
if (flags != null) {
|
package/tests/test-k-object.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import fs from "node:fs";
|
|
|
3
3
|
import k from "../index.mjs";
|
|
4
4
|
import { parseValue } from "../valueIO.mjs";
|
|
5
5
|
import { decodeWire, encodeToWire, CORE_PATTERN_PROPERTY_LIST } from "../codecs/runtime/prefix-codec.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { Value } from "../Value.mjs";
|
|
7
7
|
import { exportPatternGraph } from "../codecs/runtime/codec.mjs";
|
|
8
8
|
import { patternToPropertyList } from "../codecs/runtime/pattern-json.mjs";
|
|
9
9
|
import {
|
|
@@ -27,9 +27,9 @@ assert.deepEqual(decodedWire.pattern, [
|
|
|
27
27
|
]);
|
|
28
28
|
assert.deepEqual(decodedWire.value.toJSON(), value.toJSON());
|
|
29
29
|
|
|
30
|
-
const unicodeLabelValue =
|
|
31
|
-
"é":
|
|
32
|
-
"𐐷":
|
|
30
|
+
const unicodeLabelValue = Value.product({
|
|
31
|
+
"é": Value.variant("🙂", Value.product({})),
|
|
32
|
+
"𐐷": Value.product({})
|
|
33
33
|
});
|
|
34
34
|
const unicodeWire = encodeToWire(unicodeLabelValue, null);
|
|
35
35
|
const decodedUnicode = decodeWire(unicodeWire);
|
|
@@ -73,15 +73,15 @@ assert(object.meta[object.relAlias.__main__]?.origins?.some((origin) =>
|
|
|
73
73
|
));
|
|
74
74
|
|
|
75
75
|
const objectFn = objectToFunction(object);
|
|
76
|
-
const objectResult = objectFn(
|
|
76
|
+
const objectResult = objectFn(Value.product({}));
|
|
77
77
|
assert.deepEqual(objectResult.pattern, INT_PATTERN);
|
|
78
78
|
assert.deepEqual(objectResult.toJSON(), { "+": { "1": { "0": "_" } } });
|
|
79
|
-
const convergedObjectResult = runConvergedObject(object,
|
|
79
|
+
const convergedObjectResult = runConvergedObject(object, Value.product({}));
|
|
80
80
|
assert.deepEqual(convergedObjectResult.pattern, INT_PATTERN);
|
|
81
81
|
assert.deepEqual(convergedObjectResult.toJSON(), objectResult.toJSON());
|
|
82
82
|
|
|
83
83
|
const decompiledSource = decompileObjectBuffer(objectBuffer);
|
|
84
|
-
const decompiledResult = k.compile(decompiledSource)(
|
|
84
|
+
const decompiledResult = k.compile(decompiledSource)(Value.product({}));
|
|
85
85
|
assert.deepEqual(decompiledResult.pattern, INT_PATTERN);
|
|
86
86
|
assert.deepEqual(decompiledResult.toJSON(), objectResult.toJSON());
|
|
87
87
|
assert.match(decompiledSource, /^----- codes -----$/m);
|
|
@@ -112,11 +112,11 @@ assert.equal(arithmeticsRoundTripSource, arithmeticsDecompiledSource);
|
|
|
112
112
|
|
|
113
113
|
assert.throws(() => k.compile("@A = (); @A"), /Parse error/);
|
|
114
114
|
assert.throws(() => k.compile("$ @A = {}; $@A"), /Parse error/);
|
|
115
|
-
assert.deepEqual(k.compile("7jfi = ?X0; 7jfi")(
|
|
115
|
+
assert.deepEqual(k.compile("7jfi = ?X0; 7jfi")(Value.product({})).toJSON(), {});
|
|
116
116
|
|
|
117
117
|
const sccSource = decompileObjectBuffer(compileObjectBuffer("c = {}; b = c |x; a = b |y; a"));
|
|
118
118
|
assert.match(sccSource, /----- rels -----\nPQgV = .+\n\naQAD = .+\n\nN9UH = /s);
|
|
119
|
-
assert.deepEqual(k.compile(sccSource)(
|
|
119
|
+
assert.deepEqual(k.compile(sccSource)(Value.product({})).toJSON(), { y: "x" });
|
|
120
120
|
|
|
121
121
|
const libraryBuffer = compileLibraryBuffer("$ nat = <{} zero, nat succ>;\nsucc = |succ;\n", { source: "defs-only.k" });
|
|
122
122
|
assert.equal(libraryBuffer.subarray(0, 1).toString("utf8"), "{");
|
|
@@ -173,7 +173,7 @@ assert(derivedAliases.indexOf("other = @") < derivedAliases.indexOf("succ = @"))
|
|
|
173
173
|
}));
|
|
174
174
|
assert.equal(nonConverged.rels.__main__.typeDerivation.status, "not-converged");
|
|
175
175
|
assert.throws(
|
|
176
|
-
() => runConvergedObject(nonConverged,
|
|
176
|
+
() => runConvergedObject(nonConverged, Value.product({ x: Value.product({}) })),
|
|
177
177
|
/type derivation is not-converged/
|
|
178
178
|
);
|
|
179
179
|
} finally {
|
package/tests/test-kvm.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import assert from "node:assert";
|
|
|
2
2
|
import k from "../index.mjs";
|
|
3
3
|
import { lowerToKVM, executeKVM } from "../kvm.mjs";
|
|
4
4
|
import codes from "../codes.mjs";
|
|
5
|
-
import { fromObject
|
|
5
|
+
import { fromObject } from "../Value.mjs";
|
|
6
6
|
import run, { run_converged } from "../run.mjs";
|
|
7
7
|
|
|
8
8
|
function runKVM(script, data, options = {}) {
|