@fraczak/k 6.7.0 → 6.9.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 +10 -0
- package/DOCS/CODECS.md +80 -181
- package/DOCS/CODEC_ARCHITECTURE.md +194 -0
- package/DOCS/REPL.md +49 -60
- package/Examples/arithmetics.k +1 -0
- package/Examples/poly.k +46 -0
- package/TODO.md +112 -0
- package/browser/repl-browser.mjs +112 -733
- package/browser/shims/process.mjs +7 -0
- package/browser/tree-view.mjs +5 -2
- package/browser/vfs-data.mjs +14 -12
- package/codecs/README.md +7 -0
- package/codecs/ieee.mjs +50 -75
- package/codecs/int.mjs +83 -62
- package/codecs/json-codec.mjs +5 -77
- package/codecs/json.mjs +12 -56
- package/codecs/k-parse.mjs +3 -19
- package/codecs/runtime/codec-sdk.mjs +94 -0
- package/codecs/runtime/pattern-k.mjs +45 -0
- package/codecs/string-codec.mjs +48 -74
- package/codecs/unit.mjs +13 -61
- package/codecs/utf16.mjs +13 -56
- package/codecs/utf8.mjs +11 -55
- package/package.json +1 -1
- package/patterns/from-k.mjs +2 -22
- package/repl-codecs.mjs +78 -184
- package/repl.mjs +168 -226
- package/scripts/build-repl-html.mjs +273 -424
- package/scripts/run-tests.mjs +1 -0
- package/tests/test-codecs.mjs +186 -0
- package/tests/test-poly.mjs +44 -0
- package/tests/test-repl-html.mjs +190 -53
- package/tests/test-repl.mjs +150 -114
- package/tests/test-structural-values.mjs +17 -0
- package/tests/test-tree-view.mjs +3 -0
- package/codecs/example-pipeline.mjs +0 -163
- package/codecs/runtime/ieee-pattern.mjs +0 -30
- package/codecs/runtime/test-codec.mjs +0 -89
- package/codecs/runtime/typeFromValue.mjs +0 -34
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { stdin, stdout, stderr, exit } from "node:process";
|
|
6
|
+
import { Value, isProduct, isVariant, withPattern } from "../../Value.mjs";
|
|
7
|
+
import { decodeWire, encodeToWire } from "./prefix-codec.mjs";
|
|
8
|
+
import { isMainEntrypoint } from "./cli-entry.mjs";
|
|
9
|
+
import { patternFromFilter } from "./pattern-k.mjs";
|
|
10
|
+
|
|
11
|
+
function readAll(stream) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const chunks = [];
|
|
14
|
+
stream.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
15
|
+
stream.on("end", () => resolve(Buffer.concat(chunks)));
|
|
16
|
+
stream.on("error", reject);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function printUsage(fileName, doc) {
|
|
21
|
+
stdout.write(`Usage: ${fileName} --parse | --print\n\n`);
|
|
22
|
+
if (doc) {
|
|
23
|
+
stdout.write(`${doc.trim()}\n\n`);
|
|
24
|
+
}
|
|
25
|
+
stdout.write("Options:\n");
|
|
26
|
+
stdout.write(" --parse Read external text from stdin, write binary pattern+value stream to stdout.\n");
|
|
27
|
+
stdout.write(" --print Read binary pattern+value stream from stdin, write external text to stdout.\n");
|
|
28
|
+
stdout.write(" -h, --help Show this help.\n");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function runCodecCLI(metaUrl, codec) {
|
|
32
|
+
if (typeof process === "undefined" || !process.argv) return;
|
|
33
|
+
if (!isMainEntrypoint(metaUrl, process.argv[1])) return;
|
|
34
|
+
|
|
35
|
+
const filePath = fileURLToPath(metaUrl);
|
|
36
|
+
const fileName = path.basename(filePath);
|
|
37
|
+
const args = process.argv.slice(2);
|
|
38
|
+
|
|
39
|
+
if (args.includes("-h") || args.includes("--help")) {
|
|
40
|
+
printUsage(fileName, codec.doc);
|
|
41
|
+
exit(0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (args.length !== 1 || (args[0] !== "--parse" && args[0] !== "--print")) {
|
|
45
|
+
stderr.write(`Usage: ${fileName} --parse | --print\n`);
|
|
46
|
+
stderr.write("Try '--help' for more information.\n");
|
|
47
|
+
exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const mode = args[0];
|
|
51
|
+
|
|
52
|
+
(async () => {
|
|
53
|
+
if (mode === "--parse") {
|
|
54
|
+
let parsed;
|
|
55
|
+
if (typeof codec.parse === "function" && codec.parse.length === 0) {
|
|
56
|
+
parsed = codec.parse();
|
|
57
|
+
} else {
|
|
58
|
+
const buf = await readAll(stdin);
|
|
59
|
+
if (codec.readBuffer) {
|
|
60
|
+
parsed = codec.parse(buf);
|
|
61
|
+
} else {
|
|
62
|
+
parsed = codec.parse(buf.toString("utf8"));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const pattern = parsed?.pattern || codec.pattern || null;
|
|
66
|
+
const wire = encodeToWire(parsed, pattern);
|
|
67
|
+
stdout.write(wire);
|
|
68
|
+
} else {
|
|
69
|
+
const buf = await readAll(stdin);
|
|
70
|
+
const { value } = decodeWire(buf);
|
|
71
|
+
const output = codec.print(value);
|
|
72
|
+
if (Buffer.isBuffer(output) || codec.addNewline === false) {
|
|
73
|
+
stdout.write(output);
|
|
74
|
+
} else {
|
|
75
|
+
stdout.write(`${output}\n`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
})().catch((err) => {
|
|
79
|
+
stderr.write(`${fileName}: ${err.message || String(err)}\n`);
|
|
80
|
+
exit(1);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
Value,
|
|
86
|
+
isProduct,
|
|
87
|
+
isVariant,
|
|
88
|
+
withPattern,
|
|
89
|
+
encodeToWire,
|
|
90
|
+
decodeWire,
|
|
91
|
+
isMainEntrypoint,
|
|
92
|
+
runCodecCLI,
|
|
93
|
+
patternFromFilter
|
|
94
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { annotate } from "../../index.mjs";
|
|
2
|
+
import { exportPatternGraph } from "./codec.mjs";
|
|
3
|
+
import { patternToPropertyList } from "./pattern-json.mjs";
|
|
4
|
+
|
|
5
|
+
const patternCache = new Map();
|
|
6
|
+
|
|
7
|
+
export function rootPatternIdFromMainRel(mainRel) {
|
|
8
|
+
if (!mainRel || !mainRel.typePatternGraph) {
|
|
9
|
+
throw new Error("Could not resolve __main__ relation");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
switch (mainRel.def.op) {
|
|
13
|
+
case "filter":
|
|
14
|
+
case "code":
|
|
15
|
+
return mainRel.typePatternGraph.find(mainRel.def.patterns[0]);
|
|
16
|
+
default:
|
|
17
|
+
throw new Error(`Main expression must be a filter or a type name, got '${mainRel.def.op}'`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function patternFromFilter(script, options = {}) {
|
|
22
|
+
if (!script || typeof script !== "string") {
|
|
23
|
+
throw new Error("patternFromFilter requires a k script string");
|
|
24
|
+
}
|
|
25
|
+
const cacheKey = script.trim();
|
|
26
|
+
if (options && Object.keys(options).length === 0 && patternCache.has(cacheKey)) {
|
|
27
|
+
return patternCache.get(cacheKey);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const annotated = annotate(script, options);
|
|
31
|
+
const mainRel = annotated.rels.__main__;
|
|
32
|
+
const root = rootPatternIdFromMainRel(mainRel);
|
|
33
|
+
const pattern = exportPatternGraph(mainRel.typePatternGraph, root);
|
|
34
|
+
const propertyList = patternToPropertyList(pattern);
|
|
35
|
+
|
|
36
|
+
if (options && Object.keys(options).length === 0) {
|
|
37
|
+
patternCache.set(cacheKey, propertyList);
|
|
38
|
+
}
|
|
39
|
+
return propertyList;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default {
|
|
43
|
+
patternFromFilter,
|
|
44
|
+
rootPatternIdFromMainRel
|
|
45
|
+
};
|
package/codecs/string-codec.mjs
CHANGED
|
@@ -1,80 +1,54 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { decodeWire, encodeToWire } from "./runtime/prefix-codec.mjs";
|
|
3
|
-
import { patternToPropertyList } from "./runtime/pattern-json.mjs";
|
|
1
|
+
import { patternFromFilter } from "./runtime/codec-sdk.mjs";
|
|
4
2
|
import { textToStringValue, stringValueToText } from "./runtime/unicode-string.mjs";
|
|
5
3
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"nil",
|
|
16
|
-
"p02_03", "p04_07", "p08_0F", "p10",
|
|
17
|
-
"plane", "plane0",
|
|
18
|
-
"supplementary_plane1", "supplementary_planes2_16",
|
|
19
|
-
"2", "3", "4", "5", "6", "7", "8", "9"
|
|
20
|
-
],
|
|
21
|
-
nodes: [
|
|
22
|
-
{ kind: NODE_KIND.CLOSED_UNION, edges: [ { label: "nil", target: 1 }, { label: "cons", target: 2 } ] },
|
|
23
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [] },
|
|
24
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [ { label: "car", target: 3 }, { label: "cdr", target: 0 } ] },
|
|
25
|
-
{ kind: NODE_KIND.CLOSED_UNION, edges: [
|
|
26
|
-
{ label: "ascii", target: 4 },
|
|
27
|
-
{ label: "plane0", target: 6 },
|
|
28
|
-
{ label: "bmp_common", target: 7 },
|
|
29
|
-
{ label: "bmp_private_use", target: 10 },
|
|
30
|
-
{ label: "supplementary_plane1", target: 12 },
|
|
31
|
-
{ label: "supplementary_planes2_16", target: 13 }
|
|
32
|
-
] },
|
|
33
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [
|
|
34
|
-
{ label: "6", target: 5 }, { label: "5", target: 5 }, { label: "4", target: 5 },
|
|
35
|
-
{ label: "3", target: 5 }, { label: "2", target: 5 }, { label: "1", target: 5 }, { label: "0", target: 5 }
|
|
36
|
-
] },
|
|
37
|
-
{ kind: NODE_KIND.CLOSED_UNION, edges: [ { label: "0", target: 1 }, { label: "1", target: 1 } ] },
|
|
38
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [
|
|
39
|
-
{ label: "10", target: 5 }, { label: "9", target: 5 }, { label: "8", target: 5 }, { label: "7", target: 5 },
|
|
40
|
-
{ label: "6", target: 5 }, { label: "5", target: 5 }, { label: "4", target: 5 }, { label: "3", target: 5 },
|
|
41
|
-
{ label: "2", target: 5 }, { label: "1", target: 5 }, { label: "0", target: 5 }
|
|
42
|
-
] },
|
|
43
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [ { label: "hi", target: 8 }, { label: "lo", target: 9 } ] },
|
|
44
|
-
{ kind: NODE_KIND.CLOSED_UNION, edges: [
|
|
45
|
-
{ label: "h08_0F", target: 15 }, { label: "h10_7F", target: 16 }, { label: "h80_CF", target: 16 },
|
|
46
|
-
{ label: "hD0_D7", target: 15 }, { label: "hF9", target: 1 },
|
|
47
|
-
{ label: "hFA_FB", target: 17 }, { label: "hFC_FD", target: 17 }, { label: "hFE_FF", target: 17 }
|
|
48
|
-
] },
|
|
49
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [
|
|
50
|
-
{ label: "7", target: 5 }, { label: "6", target: 5 }, { label: "5", target: 5 }, { label: "4", target: 5 },
|
|
51
|
-
{ label: "3", target: 5 }, { label: "2", target: 5 }, { label: "1", target: 5 }, { label: "0", target: 5 }
|
|
52
|
-
] },
|
|
53
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [ { label: "hi", target: 11 }, { label: "lo", target: 9 } ] },
|
|
54
|
-
{ kind: NODE_KIND.CLOSED_UNION, edges: [ { label: "hE0_EF", target: 18 }, { label: "hF0_F7", target: 15 }, { label: "hF8", target: 1 } ] },
|
|
55
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [ { label: "mid", target: 9 }, { label: "lo", target: 9 } ] },
|
|
56
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [ { label: "plane", target: 14 }, { label: "mid", target: 9 }, { label: "lo", target: 9 } ] },
|
|
57
|
-
{ kind: NODE_KIND.CLOSED_UNION, edges: [ { label: "p02_03", target: 17 }, { label: "p04_07", target: 19 }, { label: "p08_0F", target: 15 }, { label: "p10", target: 1 } ] },
|
|
58
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [ { label: "2", target: 5 }, { label: "1", target: 5 }, { label: "0", target: 5 } ] },
|
|
59
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [
|
|
60
|
-
{ label: "6", target: 5 }, { label: "5", target: 5 }, { label: "4", target: 5 },
|
|
61
|
-
{ label: "3", target: 5 }, { label: "2", target: 5 }, { label: "1", target: 5 }, { label: "0", target: 5 }
|
|
62
|
-
] },
|
|
63
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [ { label: "0", target: 5 } ] },
|
|
64
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [ { label: "3", target: 5 }, { label: "2", target: 5 }, { label: "1", target: 5 }, { label: "0", target: 5 } ] },
|
|
65
|
-
{ kind: NODE_KIND.CLOSED_PRODUCT, edges: [ { label: "1", target: 5 }, { label: "0", target: 5 } ] }
|
|
66
|
-
]
|
|
67
|
-
};
|
|
4
|
+
const STRING_PATTERN_PROPERTY_LIST = patternFromFilter(`
|
|
5
|
+
$bit = < {} 0, {} 1 >;
|
|
6
|
+
$bits1 = { bit 0 };
|
|
7
|
+
$bits2 = { bit 0, bit 1 };
|
|
8
|
+
$bits3 = { bit 0, bit 1, bit 2 };
|
|
9
|
+
$bits4 = { bit 0, bit 1, bit 2, bit 3 };
|
|
10
|
+
$bits7 = { bit 0, bit 1, bit 2, bit 3, bit 4, bit 5, bit 6 };
|
|
11
|
+
$bits8 = { bit 0, bit 1, bit 2, bit 3, bit 4, bit 5, bit 6, bit 7 };
|
|
12
|
+
$bits11 = { bit 0, bit 1, bit 2, bit 3, bit 4, bit 5, bit 6, bit 7, bit 8, bit 9, bit 10 };
|
|
68
13
|
|
|
69
|
-
|
|
14
|
+
$bmp_common_hi = <
|
|
15
|
+
bits3 h08_0F,
|
|
16
|
+
bits7 h10_7F,
|
|
17
|
+
bits7 h80_CF,
|
|
18
|
+
bits3 hD0_D7,
|
|
19
|
+
{} hF9,
|
|
20
|
+
bits1 hFA_FB,
|
|
21
|
+
bits1 hFC_FD,
|
|
22
|
+
bits1 hFE_FF
|
|
23
|
+
>;
|
|
24
|
+
$bmp_common = { bmp_common_hi hi, bits8 lo };
|
|
70
25
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
26
|
+
$bmp_private_hi = <
|
|
27
|
+
bits4 hE0_EF,
|
|
28
|
+
bits3 hF0_F7,
|
|
29
|
+
{} hF8
|
|
30
|
+
>;
|
|
31
|
+
$bmp_private_use = { bmp_private_hi hi, bits8 lo };
|
|
74
32
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
33
|
+
$plane2_16 = <
|
|
34
|
+
bits1 p02_03,
|
|
35
|
+
bits2 p04_07,
|
|
36
|
+
bits3 p08_0F,
|
|
37
|
+
{} p10
|
|
38
|
+
>;
|
|
39
|
+
$supplementary_planes2_16 = { plane2_16 plane, bits8 mid, bits8 lo };
|
|
40
|
+
$supplementary_plane1 = { bits8 mid, bits8 lo };
|
|
79
41
|
|
|
80
|
-
|
|
42
|
+
$unicode_scalar = <
|
|
43
|
+
bits7 ascii,
|
|
44
|
+
bits11 plane0,
|
|
45
|
+
bmp_common bmp_common,
|
|
46
|
+
bmp_private_use bmp_private_use,
|
|
47
|
+
supplementary_plane1 supplementary_plane1,
|
|
48
|
+
supplementary_planes2_16 supplementary_planes2_16
|
|
49
|
+
>;
|
|
50
|
+
|
|
51
|
+
?< {} nil, { $unicode_scalar car, str cdr } cons > = str
|
|
52
|
+
`);
|
|
53
|
+
|
|
54
|
+
export { STRING_PATTERN_PROPERTY_LIST, textToStringValue, stringValueToText };
|
package/codecs/unit.mjs
CHANGED
|
@@ -1,76 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { Value, isProduct } from "../Value.mjs";
|
|
5
|
-
import { isMainEntrypoint } from "./runtime/cli-entry.mjs";
|
|
6
|
-
import { decodeWire, encodeToWire } from "./runtime/prefix-codec.mjs";
|
|
3
|
+
import { Value, isProduct, withPattern, patternFromFilter, runCodecCLI } from "./runtime/codec-sdk.mjs";
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
stream(" --parse Ignore stdin and write the unit binary pattern+value stream.");
|
|
11
|
-
stream(" --print Validate the unit binary pattern+value stream and write {}.");
|
|
12
|
-
stream(" -h, --help Show this help.");
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const UNIT_PATTERN = [
|
|
16
|
-
["closed-product", []]
|
|
17
|
-
];
|
|
18
|
-
const name = "unit";
|
|
19
|
-
const patterns = [UNIT_PATTERN];
|
|
5
|
+
export const doc = `
|
|
6
|
+
Unit codec for {}.
|
|
20
7
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const chunks = [];
|
|
24
|
-
stream.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
25
|
-
stream.on("end", () => resolve(Buffer.concat(chunks)));
|
|
26
|
-
stream.on("error", reject);
|
|
27
|
-
});
|
|
28
|
-
}
|
|
8
|
+
Translates the empty product {} to/from binary pattern+value stream.
|
|
9
|
+
`;
|
|
29
10
|
|
|
30
|
-
|
|
31
|
-
return encodeToWire(Value.product({}), UNIT_PATTERN);
|
|
32
|
-
}
|
|
11
|
+
const UNIT_PATTERN = patternFromFilter("?{}");
|
|
33
12
|
|
|
34
|
-
function parse() {
|
|
35
|
-
return Value.product({});
|
|
13
|
+
export function parse() {
|
|
14
|
+
return withPattern(Value.product({}), UNIT_PATTERN);
|
|
36
15
|
}
|
|
37
16
|
|
|
38
|
-
function print(value) {
|
|
17
|
+
export function print(value) {
|
|
39
18
|
if (!isProduct(value) || Object.keys(value.product).length !== 0) {
|
|
40
19
|
throw new Error("Input is not a unit value");
|
|
41
20
|
}
|
|
42
21
|
return "{}";
|
|
43
22
|
}
|
|
44
23
|
|
|
45
|
-
|
|
46
|
-
const args = argv.slice(2);
|
|
47
|
-
if (args.includes("-h") || args.includes("--help")) {
|
|
48
|
-
usage(console.log);
|
|
49
|
-
exit(0);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (args.length !== 1 || (args[0] !== "--parse" && args[0] !== "--print")) {
|
|
53
|
-
usage();
|
|
54
|
-
exit(1);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const expected = unitEncoding();
|
|
58
|
-
|
|
59
|
-
if (args[0] === "--parse") {
|
|
60
|
-
stdout.write(expected);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const input = await readAll(stdin);
|
|
65
|
-
const { value } = decodeWire(input);
|
|
66
|
-
stdout.write(print(value));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (isMainEntrypoint(import.meta.url, argv[1])) {
|
|
70
|
-
main().catch((error) => {
|
|
71
|
-
console.error(error.message || String(error));
|
|
72
|
-
exit(1);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
24
|
+
runCodecCLI(import.meta.url, { parse, print, doc });
|
|
75
25
|
|
|
76
|
-
export {
|
|
26
|
+
export {
|
|
27
|
+
UNIT_PATTERN
|
|
28
|
+
};
|
package/codecs/utf16.mjs
CHANGED
|
@@ -1,44 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { isMainEntrypoint } from "./runtime/cli-entry.mjs";
|
|
3
|
+
import { withPattern, runCodecCLI } from "./runtime/codec-sdk.mjs";
|
|
5
4
|
import {
|
|
6
5
|
STRING_PATTERN_PROPERTY_LIST,
|
|
7
|
-
encodeText,
|
|
8
|
-
decodeText,
|
|
9
6
|
textToStringValue,
|
|
10
7
|
stringValueToText
|
|
11
8
|
} from "./string-codec.mjs";
|
|
12
9
|
|
|
13
|
-
const
|
|
14
|
-
|
|
10
|
+
export const doc = `
|
|
11
|
+
UTF-16 text codec (BOM-aware).
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function print(value) {
|
|
21
|
-
return stringValueToText(value);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function usage(stream = console.error) {
|
|
25
|
-
stream(`Usage: ${argv[1]} --parse | --print`);
|
|
26
|
-
stream(" --parse Read UTF-16 text from stdin (BOM-aware), write binary pattern+value stream of k string.");
|
|
27
|
-
stream(" --print Read binary pattern+value stream of k string, write UTF-16LE text with BOM.");
|
|
28
|
-
stream(" -h, --help Show this help.");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function readAll(stream) {
|
|
32
|
-
return new Promise((resolve, reject) => {
|
|
33
|
-
const chunks = [];
|
|
34
|
-
stream.on("data", c => chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c)));
|
|
35
|
-
stream.on("end", () => resolve(Buffer.concat(chunks)));
|
|
36
|
-
stream.on("error", reject);
|
|
37
|
-
});
|
|
38
|
-
}
|
|
13
|
+
Reads UTF-16 text (LE/BE with BOM or LE without BOM), outputs UTF-16LE with BOM.
|
|
14
|
+
`;
|
|
39
15
|
|
|
40
16
|
function decodeUtf16Input(buf) {
|
|
41
|
-
if (buf.length === 0) return "";
|
|
17
|
+
if (!buf || buf.length === 0) return "";
|
|
42
18
|
|
|
43
19
|
if (buf.length >= 2 && buf[0] === 0xfe && buf[1] === 0xff) {
|
|
44
20
|
const src = buf.subarray(2);
|
|
@@ -66,33 +42,14 @@ function encodeUtf16Output(text) {
|
|
|
66
42
|
return Buffer.concat([bomLe, Buffer.from(text, "utf16le")]);
|
|
67
43
|
}
|
|
68
44
|
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
usage(console.log);
|
|
73
|
-
exit(0);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (args.length !== 1 || (args[0] !== "--parse" && args[0] !== "--print")) {
|
|
77
|
-
usage();
|
|
78
|
-
exit(1);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const buf = await readAll(stdin);
|
|
82
|
-
|
|
83
|
-
if (args[0] === "--parse") {
|
|
84
|
-
const text = decodeUtf16Input(buf);
|
|
85
|
-
stdout.write(encodeText(text));
|
|
86
|
-
} else {
|
|
87
|
-
stdout.write(encodeUtf16Output(decodeText(buf)));
|
|
88
|
-
}
|
|
45
|
+
export function parse(input) {
|
|
46
|
+
const text = Buffer.isBuffer(input) ? decodeUtf16Input(input) : String(input);
|
|
47
|
+
return withPattern(textToStringValue(text), STRING_PATTERN_PROPERTY_LIST);
|
|
89
48
|
}
|
|
90
49
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
exit(1);
|
|
95
|
-
});
|
|
50
|
+
export function print(value) {
|
|
51
|
+
const text = stringValueToText(value);
|
|
52
|
+
return encodeUtf16Output(text);
|
|
96
53
|
}
|
|
97
54
|
|
|
98
|
-
|
|
55
|
+
runCodecCLI(import.meta.url, { parse, print, doc, readBuffer: true, addNewline: false });
|
package/codecs/utf8.mjs
CHANGED
|
@@ -1,69 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { isMainEntrypoint } from "./runtime/cli-entry.mjs";
|
|
3
|
+
import { withPattern, runCodecCLI } from "./runtime/codec-sdk.mjs";
|
|
5
4
|
import {
|
|
6
5
|
STRING_PATTERN_PROPERTY_LIST,
|
|
7
|
-
encodeText,
|
|
8
|
-
decodeText,
|
|
9
6
|
textToStringValue,
|
|
10
7
|
stringValueToText
|
|
11
8
|
} from "./string-codec.mjs";
|
|
12
9
|
|
|
13
|
-
const
|
|
14
|
-
|
|
10
|
+
export const doc = `
|
|
11
|
+
UTF-8 text codec.
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function print(value) {
|
|
21
|
-
return stringValueToText(value);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function usage(stream = console.error) {
|
|
25
|
-
stream(`Usage: ${argv[1]} --parse | --print`);
|
|
26
|
-
stream(" --parse Read UTF-8 text from stdin, write binary pattern+value stream of k string.");
|
|
27
|
-
stream(" --print Read binary pattern+value stream of k string, write UTF-8 text.");
|
|
28
|
-
stream(" -h, --help Show this help.");
|
|
29
|
-
}
|
|
13
|
+
Encodes/decodes text strings to/from the canonical k string pattern.
|
|
14
|
+
`;
|
|
30
15
|
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
stream.on("data", c => chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c)));
|
|
35
|
-
stream.on("end", () => resolve(Buffer.concat(chunks)));
|
|
36
|
-
stream.on("error", reject);
|
|
37
|
-
});
|
|
16
|
+
export function parse(text) {
|
|
17
|
+
const value = textToStringValue(text);
|
|
18
|
+
return withPattern(value, STRING_PATTERN_PROPERTY_LIST);
|
|
38
19
|
}
|
|
39
20
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (args.includes("-h") || args.includes("--help")) {
|
|
43
|
-
usage(console.log);
|
|
44
|
-
exit(0);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (args.length !== 1 || (args[0] !== "--parse" && args[0] !== "--print")) {
|
|
48
|
-
usage();
|
|
49
|
-
exit(1);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const buf = await readAll(stdin);
|
|
53
|
-
|
|
54
|
-
if (args[0] === "--parse") {
|
|
55
|
-
const text = buf.toString("utf8");
|
|
56
|
-
stdout.write(encodeText(text));
|
|
57
|
-
} else {
|
|
58
|
-
stdout.write(decodeText(buf));
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (isMainEntrypoint(import.meta.url, argv[1])) {
|
|
63
|
-
main().catch(err => {
|
|
64
|
-
console.error(err.message || String(err));
|
|
65
|
-
exit(1);
|
|
66
|
-
});
|
|
21
|
+
export function print(value) {
|
|
22
|
+
return stringValueToText(value);
|
|
67
23
|
}
|
|
68
24
|
|
|
69
|
-
|
|
25
|
+
runCodecCLI(import.meta.url, { parse, print, doc, addNewline: false });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fraczak/k",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.9.0",
|
|
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
|
"exports": {
|
package/patterns/from-k.mjs
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import { argv, exit, stdin, stdout } from "node:process";
|
|
5
|
-
import
|
|
6
|
-
import { exportPatternGraph } from "../codecs/runtime/codec.mjs";
|
|
7
|
-
import { patternToPropertyList } from "../codecs/runtime/pattern-json.mjs";
|
|
5
|
+
import { patternFromFilter } from "../codecs/runtime/pattern-k.mjs";
|
|
8
6
|
|
|
9
7
|
function usage(prog) {
|
|
10
8
|
console.error(`Usage: ${prog} [script-or-file]`);
|
|
@@ -33,20 +31,6 @@ function readAll(stream) {
|
|
|
33
31
|
});
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
function rootPatternIdFromMainRel(mainRel) {
|
|
37
|
-
if (!mainRel || !mainRel.typePatternGraph) {
|
|
38
|
-
throw new Error("Could not resolve __main__ relation");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
switch (mainRel.def.op) {
|
|
42
|
-
case "filter":
|
|
43
|
-
case "code":
|
|
44
|
-
return mainRel.typePatternGraph.find(mainRel.def.patterns[0]);
|
|
45
|
-
default:
|
|
46
|
-
throw new Error("Main expression must be a filter or a type name");
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
34
|
async function main() {
|
|
51
35
|
const prog = argv[1];
|
|
52
36
|
const args = argv.slice(2);
|
|
@@ -60,11 +44,7 @@ async function main() {
|
|
|
60
44
|
}
|
|
61
45
|
|
|
62
46
|
const script = args.length === 1 ? maybeReadFile(args[0]) : await readAll(stdin);
|
|
63
|
-
const
|
|
64
|
-
const mainRel = annotated.rels.__main__;
|
|
65
|
-
const rootPatternId = rootPatternIdFromMainRel(mainRel);
|
|
66
|
-
const pattern = exportPatternGraph(mainRel.typePatternGraph, rootPatternId);
|
|
67
|
-
const propertyList = patternToPropertyList(pattern);
|
|
47
|
+
const propertyList = patternFromFilter(script);
|
|
68
48
|
|
|
69
49
|
stdout.write(`${JSON.stringify(propertyList)}\n`);
|
|
70
50
|
}
|