@fraczak/k 6.2.4 → 6.3.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/Value.mjs +50 -40
- package/a.klib +1 -1
- package/a.kvm +142676 -0
- package/a.wasm +0 -0
- package/backend-api.mjs +1 -1
- package/benchmark-results.html +532 -0
- package/benchmark-results.json +480 -0
- 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 +86 -19
- package/package.json +4 -1
- package/repl.mjs +2 -2
- package/run.mjs +9 -9
- package/scripts/benchmark.mjs +393 -0
- package/scripts/git-hooks/pre-commit +10 -0
- package/scripts/render-benchmark.mjs +343 -0
- package/scripts/run-tests.mjs +2 -0
- package/tests/code-derivation/codec-witness-pattern.mjs +4 -4
- package/tests/code-derivation/pattern-envelope.mjs +12 -12
- package/tests/integration.sh +7 -0
- package/tests/test-arithmetics.mjs +95 -0
- 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
package/codecs/json-codec.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Value, isProduct, isVariant } from "../Value.mjs";
|
|
2
2
|
import { STRING_PATTERN_PROPERTY_LIST, textToStringValue, stringValueToText } from "./string-codec.mjs";
|
|
3
3
|
import { FLOAT64_PATTERN } from "./runtime/ieee-pattern.mjs";
|
|
4
4
|
|
|
5
|
-
const UNIT =
|
|
5
|
+
const UNIT = Value.product({});
|
|
6
6
|
const BOOL_PATTERN = [
|
|
7
7
|
["closed-union", [["false", 1], ["true", 1]]],
|
|
8
8
|
["closed-product", []]
|
|
@@ -13,7 +13,7 @@ const NULL_PATTERN = [
|
|
|
13
13
|
];
|
|
14
14
|
|
|
15
15
|
function bitValue(bit) {
|
|
16
|
-
return
|
|
16
|
+
return Value.variant(bit === 0 ? "0" : "1", UNIT);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
function bitsProduct(width, value) {
|
|
@@ -22,7 +22,7 @@ function bitsProduct(width, value) {
|
|
|
22
22
|
for (let i = width - 1; i >= 0; i--) {
|
|
23
23
|
product[String(i)] = bitValue(Number((big >> BigInt(i)) & 1n));
|
|
24
24
|
}
|
|
25
|
-
return
|
|
25
|
+
return Value.product(product);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function encodeNumberToValue(number) {
|
|
@@ -33,22 +33,22 @@ function encodeNumberToValue(number) {
|
|
|
33
33
|
const exponent = Number((bits >> 52n) & 0x7ffn);
|
|
34
34
|
const fraction = bits & ((1n << 52n) - 1n);
|
|
35
35
|
|
|
36
|
-
return
|
|
37
|
-
sign:
|
|
36
|
+
return Value.product({
|
|
37
|
+
sign: Value.variant(sign === 0 ? "+" : "-", UNIT),
|
|
38
38
|
exponent: bitsProduct(11, exponent),
|
|
39
39
|
fraction: bitsProduct(52, fraction)
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
function requireProduct(value, where) {
|
|
44
|
-
if (!(value
|
|
44
|
+
if (!isProduct(value)) {
|
|
45
45
|
throw new Error(`${where}: expected Product`);
|
|
46
46
|
}
|
|
47
47
|
return value.product;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
function requireVariant(value, where) {
|
|
51
|
-
if (!(value
|
|
51
|
+
if (!isVariant(value)) {
|
|
52
52
|
throw new Error(`${where}: expected Variant`);
|
|
53
53
|
}
|
|
54
54
|
return value;
|
|
@@ -88,10 +88,10 @@ function decodeValueToNumber(value) {
|
|
|
88
88
|
|
|
89
89
|
function fromJsonValue(value) {
|
|
90
90
|
if (value === null) {
|
|
91
|
-
return
|
|
91
|
+
return Value.variant("null", UNIT);
|
|
92
92
|
}
|
|
93
93
|
if (typeof value === "boolean") {
|
|
94
|
-
return
|
|
94
|
+
return Value.variant(value ? "true" : "false", UNIT);
|
|
95
95
|
}
|
|
96
96
|
if (typeof value === "number") {
|
|
97
97
|
if (!Number.isFinite(value)) {
|
|
@@ -103,7 +103,7 @@ function fromJsonValue(value) {
|
|
|
103
103
|
return textToStringValue(value);
|
|
104
104
|
}
|
|
105
105
|
if (Array.isArray(value)) {
|
|
106
|
-
return
|
|
106
|
+
return Value.product(
|
|
107
107
|
value.reduce((product, item, index) => {
|
|
108
108
|
product[String(index)] = fromJsonValue(item);
|
|
109
109
|
return product;
|
|
@@ -111,7 +111,7 @@ function fromJsonValue(value) {
|
|
|
111
111
|
);
|
|
112
112
|
}
|
|
113
113
|
if (value && typeof value === "object") {
|
|
114
|
-
return
|
|
114
|
+
return Value.product(
|
|
115
115
|
Object.keys(value).reduce((product, key) => {
|
|
116
116
|
product[key] = fromJsonValue(value[key]);
|
|
117
117
|
return product;
|
|
@@ -161,7 +161,7 @@ function patternFromJsonValue(value) {
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
function toJsonValue(value) {
|
|
164
|
-
if (value
|
|
164
|
+
if (isVariant(value)) {
|
|
165
165
|
if (value.tag === "null") {
|
|
166
166
|
requireProduct(value.value, "json.null");
|
|
167
167
|
return null;
|
|
@@ -184,8 +184,8 @@ function toJsonValue(value) {
|
|
|
184
184
|
if (isArray) {
|
|
185
185
|
return keys.map((key) => {
|
|
186
186
|
const child = product[key];
|
|
187
|
-
if (child
|
|
188
|
-
if (child
|
|
187
|
+
if (isVariant(child)) return toJsonValue(child);
|
|
188
|
+
if (isProduct(child)) {
|
|
189
189
|
try {
|
|
190
190
|
return decodeValueToNumber(child);
|
|
191
191
|
} catch {}
|
package/codecs/runtime/codec.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* K pattern graph runtime helpers.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Value, isProduct, isVariant } from "../../Value.mjs";
|
|
6
6
|
import { TypePatternGraph } from "../../TypePatternGraph.mjs";
|
|
7
7
|
import { getCompressed } from "../../typing.mjs";
|
|
8
8
|
import { finalize as finalizeCodes } from "../../codes.mjs";
|
|
@@ -501,7 +501,7 @@ function refinePatternForValue(pattern, value) {
|
|
|
501
501
|
|
|
502
502
|
case NODE_KIND.CLOSED_PRODUCT:
|
|
503
503
|
case NODE_KIND.OPEN_PRODUCT: {
|
|
504
|
-
if (!(frame.currentValue
|
|
504
|
+
if (!isProduct(frame.currentValue)) {
|
|
505
505
|
throw new Error(`Expected Product for pattern node ${frame.patternNodeId}`);
|
|
506
506
|
}
|
|
507
507
|
const actualLabels = Object.keys(frame.currentValue.product).sort();
|
|
@@ -542,7 +542,7 @@ function refinePatternForValue(pattern, value) {
|
|
|
542
542
|
|
|
543
543
|
case NODE_KIND.CLOSED_UNION:
|
|
544
544
|
case NODE_KIND.OPEN_UNION: {
|
|
545
|
-
if (!(frame.currentValue
|
|
545
|
+
if (!isVariant(frame.currentValue)) {
|
|
546
546
|
throw new Error(`Expected Variant for pattern node ${frame.patternNodeId}`);
|
|
547
547
|
}
|
|
548
548
|
const explicitTargets = new Map(patternNode.edges.map((edge) => [edge.label, edge.target]));
|
|
@@ -583,8 +583,8 @@ function refinePatternForValue(pattern, value) {
|
|
|
583
583
|
return { kind: NODE_KIND.ANY, edges: [] };
|
|
584
584
|
}
|
|
585
585
|
|
|
586
|
-
const allProducts = values.every(
|
|
587
|
-
const allVariants = values.every(
|
|
586
|
+
const allProducts = values.every(isProduct);
|
|
587
|
+
const allVariants = values.every(isVariant);
|
|
588
588
|
if (!allProducts && !allVariants) {
|
|
589
589
|
throw new Error("Cannot refine pattern from mixed product/union values");
|
|
590
590
|
}
|
|
@@ -642,7 +642,7 @@ function refinePatternForValue(pattern, value) {
|
|
|
642
642
|
let labels = [...explicit.keys()].sort();
|
|
643
643
|
if (values.length > 0) {
|
|
644
644
|
const actual = sameSortedKeys(values, "product pattern", (node) => {
|
|
645
|
-
if (!(node
|
|
645
|
+
if (!isProduct(node)) throw new Error("Expected Product while refining product pattern");
|
|
646
646
|
return Object.keys(node.product);
|
|
647
647
|
});
|
|
648
648
|
if (baseNode.kind === NODE_KIND.CLOSED_PRODUCT) {
|
|
@@ -673,7 +673,7 @@ function refinePatternForValue(pattern, value) {
|
|
|
673
673
|
let tags = [...explicit.keys()].sort((a, b) => Buffer.compare(Buffer.from(a, "utf8"), Buffer.from(b, "utf8")));
|
|
674
674
|
if (values.length > 0) {
|
|
675
675
|
const observed = [...new Set(values.map((node) => {
|
|
676
|
-
if (!(node
|
|
676
|
+
if (!isVariant(node)) throw new Error("Expected Variant while refining union pattern");
|
|
677
677
|
return node.tag;
|
|
678
678
|
}))].sort((a, b) => Buffer.compare(Buffer.from(a, "utf8"), Buffer.from(b, "utf8")));
|
|
679
679
|
if (baseNode.kind === NODE_KIND.CLOSED_UNION) {
|
|
@@ -764,16 +764,16 @@ function coerceValueForPattern(pattern, value) {
|
|
|
764
764
|
case NODE_KIND.CLOSED_PRODUCT:
|
|
765
765
|
case NODE_KIND.OPEN_PRODUCT: {
|
|
766
766
|
let productValue = frame.currentValue;
|
|
767
|
-
if (frame.currentValue
|
|
768
|
-
productValue =
|
|
767
|
+
if (isVariant(frame.currentValue)) {
|
|
768
|
+
productValue = Value.product({ [frame.currentValue.tag]: frame.currentValue.value });
|
|
769
769
|
}
|
|
770
|
-
if (!(productValue
|
|
770
|
+
if (!isProduct(productValue)) {
|
|
771
771
|
throw new Error(`Expected Product for pattern node ${frame.patternNodeId}`);
|
|
772
772
|
}
|
|
773
773
|
|
|
774
774
|
const explicitTargets = new Map(patternNode.edges.map((edge) => [edge.label, edge.target]));
|
|
775
775
|
const product = {};
|
|
776
|
-
frame.assign(
|
|
776
|
+
frame.assign(Value.product(product));
|
|
777
777
|
const entries = Object.entries(productValue.product);
|
|
778
778
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
779
779
|
const [label, childValue] = entries[i];
|
|
@@ -800,11 +800,11 @@ function coerceValueForPattern(pattern, value) {
|
|
|
800
800
|
|
|
801
801
|
case NODE_KIND.CLOSED_UNION:
|
|
802
802
|
case NODE_KIND.OPEN_UNION: {
|
|
803
|
-
if (!(frame.currentValue
|
|
803
|
+
if (!isVariant(frame.currentValue)) {
|
|
804
804
|
throw new Error(`Expected Variant for pattern node ${frame.patternNodeId}`);
|
|
805
805
|
}
|
|
806
806
|
const target = patternNode.edges.find((edge) => edge.label === frame.currentValue.tag)?.target;
|
|
807
|
-
const variant =
|
|
807
|
+
const variant = Value.variant(frame.currentValue.tag, undefined);
|
|
808
808
|
frame.assign(variant);
|
|
809
809
|
if (target == null) {
|
|
810
810
|
variant.value = frame.currentValue.value;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Value, withPattern, isProduct, isVariant } from "../../Value.mjs";
|
|
2
2
|
import { refinePatternForValue, coerceValueForPattern, NODE_KIND } from "./codec.mjs";
|
|
3
3
|
import { patternToPropertyList, propertyListToPattern } from "./pattern-json.mjs";
|
|
4
4
|
import { textToStringValue, stringValueToText } from "./unicode-string.mjs";
|
|
@@ -33,7 +33,7 @@ const CORE_PATTERN_PROPERTY_LIST = [
|
|
|
33
33
|
];
|
|
34
34
|
|
|
35
35
|
const CORE_PATTERN_PATTERN = propertyListToPattern(CORE_PATTERN_PROPERTY_LIST);
|
|
36
|
-
const UNIT =
|
|
36
|
+
const UNIT = Value.product({});
|
|
37
37
|
|
|
38
38
|
class BitWriter {
|
|
39
39
|
constructor() {
|
|
@@ -135,7 +135,7 @@ function encodeNode(writer, value, pattern, patternNodeId) {
|
|
|
135
135
|
|
|
136
136
|
case NODE_KIND.OPEN_PRODUCT:
|
|
137
137
|
case NODE_KIND.CLOSED_PRODUCT: {
|
|
138
|
-
if (!(frame.value
|
|
138
|
+
if (!isProduct(frame.value)) {
|
|
139
139
|
throw new Error(`Expected Product for pattern node ${frame.patternNodeId}`);
|
|
140
140
|
}
|
|
141
141
|
const actual = Object.keys(frame.value.product).sort((a, b) => Buffer.compare(Buffer.from(a, "utf8"), Buffer.from(b, "utf8")));
|
|
@@ -152,7 +152,7 @@ function encodeNode(writer, value, pattern, patternNodeId) {
|
|
|
152
152
|
|
|
153
153
|
case NODE_KIND.OPEN_UNION:
|
|
154
154
|
case NODE_KIND.CLOSED_UNION: {
|
|
155
|
-
if (!(frame.value
|
|
155
|
+
if (!isVariant(frame.value)) {
|
|
156
156
|
throw new Error(`Expected Variant for pattern node ${frame.patternNodeId}`);
|
|
157
157
|
}
|
|
158
158
|
const tagOrdinal = patternNode.edges.findIndex((edge) => edge.label === frame.value.tag);
|
|
@@ -194,7 +194,7 @@ function decodeNode(reader, pattern, patternNodeId) {
|
|
|
194
194
|
case NODE_KIND.OPEN_PRODUCT:
|
|
195
195
|
case NODE_KIND.CLOSED_PRODUCT: {
|
|
196
196
|
const product = {};
|
|
197
|
-
frame.assign(
|
|
197
|
+
frame.assign(Value.product(product));
|
|
198
198
|
for (let i = patternNode.edges.length - 1; i >= 0; i--) {
|
|
199
199
|
const edge = patternNode.edges[i];
|
|
200
200
|
stack.push({
|
|
@@ -218,7 +218,7 @@ function decodeNode(reader, pattern, patternNodeId) {
|
|
|
218
218
|
throw new Error(`Choice ${tagOrdinal} is out of range for pattern node ${frame.patternNodeId}`);
|
|
219
219
|
}
|
|
220
220
|
const edge = patternNode.edges[tagOrdinal];
|
|
221
|
-
const variant =
|
|
221
|
+
const variant = Value.variant(edge.label, undefined);
|
|
222
222
|
frame.assign(variant);
|
|
223
223
|
stack.push({
|
|
224
224
|
patternNodeId: edge.target,
|
|
@@ -250,7 +250,7 @@ function deriveClosedPatternFromValue(value) {
|
|
|
250
250
|
|
|
251
251
|
function visit(node) {
|
|
252
252
|
const nodeId = nodes.length;
|
|
253
|
-
if (node
|
|
253
|
+
if (isProduct(node)) {
|
|
254
254
|
const placeholder = { kind: NODE_KIND.CLOSED_PRODUCT, edges: [] };
|
|
255
255
|
nodes.push(placeholder);
|
|
256
256
|
const labels = Object.keys(node.product).sort((a, b) => Buffer.compare(Buffer.from(a, "utf8"), Buffer.from(b, "utf8")));
|
|
@@ -261,7 +261,7 @@ function deriveClosedPatternFromValue(value) {
|
|
|
261
261
|
}));
|
|
262
262
|
return nodeId;
|
|
263
263
|
}
|
|
264
|
-
if (node
|
|
264
|
+
if (isVariant(node)) {
|
|
265
265
|
const placeholder = { kind: NODE_KIND.OPEN_UNION, edges: [] };
|
|
266
266
|
nodes.push(placeholder);
|
|
267
267
|
placeholder.edges = [{
|
|
@@ -291,23 +291,23 @@ function deriveClosedPatternFromValue(value) {
|
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
function requireProduct(value, where) {
|
|
294
|
-
if (!(value
|
|
294
|
+
if (!isProduct(value)) {
|
|
295
295
|
throw new Error(`${where}: expected Product`);
|
|
296
296
|
}
|
|
297
297
|
return value.product;
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
function requireVariant(value, where) {
|
|
301
|
-
if (!(value
|
|
301
|
+
if (!isVariant(value)) {
|
|
302
302
|
throw new Error(`${where}: expected Variant`);
|
|
303
303
|
}
|
|
304
304
|
return value;
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
function listToK(items) {
|
|
308
|
-
let result =
|
|
308
|
+
let result = Value.variant("nil", UNIT);
|
|
309
309
|
for (let i = items.length - 1; i >= 0; i--) {
|
|
310
|
-
result =
|
|
310
|
+
result = Value.variant("cons", Value.product({
|
|
311
311
|
car: items[i],
|
|
312
312
|
cdr: result
|
|
313
313
|
}));
|
|
@@ -354,7 +354,7 @@ function integerToBits(value) {
|
|
|
354
354
|
if (!Number.isSafeInteger(value) || value < 0) {
|
|
355
355
|
throw new Error(`bits target must be a non-negative safe integer, got ${value}`);
|
|
356
356
|
}
|
|
357
|
-
if (value === 0) return
|
|
357
|
+
if (value === 0) return Value.variant("_", UNIT);
|
|
358
358
|
|
|
359
359
|
const bits = [];
|
|
360
360
|
let n = value;
|
|
@@ -363,15 +363,15 @@ function integerToBits(value) {
|
|
|
363
363
|
n = Math.floor(n / 2);
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
-
let result =
|
|
366
|
+
let result = Value.variant("_", UNIT);
|
|
367
367
|
for (let i = bits.length - 1; i >= 0; i--) {
|
|
368
|
-
result =
|
|
368
|
+
result = Value.variant(bits[i] ? "1" : "0", result);
|
|
369
369
|
}
|
|
370
370
|
return result;
|
|
371
371
|
}
|
|
372
372
|
|
|
373
373
|
function edgeToK([label, target]) {
|
|
374
|
-
return
|
|
374
|
+
return Value.product({
|
|
375
375
|
label: textToStringValue(label),
|
|
376
376
|
target: integerToBits(target)
|
|
377
377
|
});
|
|
@@ -395,9 +395,9 @@ function patternToKValue(propertyList) {
|
|
|
395
395
|
}
|
|
396
396
|
const [kind, edges] = node;
|
|
397
397
|
if (kind === "any") {
|
|
398
|
-
return
|
|
398
|
+
return Value.variant("any", UNIT);
|
|
399
399
|
}
|
|
400
|
-
return
|
|
400
|
+
return Value.variant(kind, listToK(edges.map(edgeToK)));
|
|
401
401
|
}));
|
|
402
402
|
}
|
|
403
403
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isProduct, isVariant } from "../../Value.mjs";
|
|
2
2
|
|
|
3
3
|
const nameRE = /^[a-zA-Z0-9_+-][a-zA-Z0-9_?!+-]*$/;
|
|
4
4
|
|
|
@@ -50,8 +50,8 @@ function propertyListToFilter(propertyList) {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function valueToK(v) {
|
|
53
|
-
if (v
|
|
54
|
-
if (v
|
|
53
|
+
if (isVariant(v)) return `${valueToK(v.value)}|${pLabel(v.tag).trimStart()}`;
|
|
54
|
+
if (isProduct(v)) {
|
|
55
55
|
const keys = Object.keys(v.product);
|
|
56
56
|
if (keys.length === 0) return "{}";
|
|
57
57
|
const fields = keys.map((k) => `${valueToK(v.product[k])}${pLabel(k)}`);
|
|
@@ -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);
|