@fraczak/k 6.8.0 → 6.10.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.
Files changed (45) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/CLAUDE.md +1 -1
  3. package/DOCS/BIG_PICTURE.md +3 -5
  4. package/DOCS/CODECS.md +80 -181
  5. package/DOCS/CODEC_ARCHITECTURE.md +194 -0
  6. package/DOCS/REPL.md +69 -51
  7. package/Examples/arithmetics.k +1 -0
  8. package/Examples/poly.k +46 -0
  9. package/backends/llvm/runtime/krt.c +4 -0
  10. package/backends/llvm/src/kvm2llvm.mjs +2 -2
  11. package/backends/llvm/tests/test-llvm.mjs +19 -0
  12. package/backends/wasm/src/kvm2wasm.mjs +4 -0
  13. package/backends/wasm/tests/test-wasm.mjs +4 -0
  14. package/browser/repl-browser.mjs +131 -779
  15. package/browser/shims/process.mjs +7 -0
  16. package/browser/tree-view.mjs +5 -2
  17. package/browser/vfs-data.mjs +14 -14
  18. package/codecs/README.md +7 -0
  19. package/codecs/ieee.mjs +50 -75
  20. package/codecs/int.mjs +83 -62
  21. package/codecs/json-codec.mjs +5 -77
  22. package/codecs/json.mjs +12 -56
  23. package/codecs/k-parse.mjs +3 -19
  24. package/codecs/runtime/codec-sdk.mjs +94 -0
  25. package/codecs/runtime/pattern-k.mjs +45 -0
  26. package/codecs/string-codec.mjs +48 -74
  27. package/codecs/unit.mjs +13 -61
  28. package/codecs/utf16.mjs +13 -56
  29. package/codecs/utf8.mjs +11 -55
  30. package/package.json +1 -1
  31. package/patterns/from-k.mjs +2 -22
  32. package/repl-codecs.mjs +69 -196
  33. package/repl.mjs +177 -281
  34. package/scripts/build-repl-html.mjs +114 -385
  35. package/scripts/run-tests.mjs +1 -0
  36. package/tests/test-codecs.mjs +186 -0
  37. package/tests/test-poly.mjs +44 -0
  38. package/tests/test-repl-html.mjs +163 -68
  39. package/tests/test-repl.mjs +210 -156
  40. package/tests/test-structural-values.mjs +17 -0
  41. package/tests/test-tree-view.mjs +3 -0
  42. package/codecs/example-pipeline.mjs +0 -163
  43. package/codecs/runtime/ieee-pattern.mjs +0 -30
  44. package/codecs/runtime/test-codec.mjs +0 -89
  45. 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
+ };
@@ -1,80 +1,54 @@
1
- import { NODE_KIND } from "./runtime/codec.mjs";
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 STRING_PATTERN = {
7
- dictionary: [
8
- "0", "1", "10",
9
- "ascii", "bmp_common", "bmp_private_use",
10
- "car", "cdr", "cons",
11
- "h08_0F", "h10_7F", "h80_CF", "hD0_D7", "hE0_EF", "hF0_F7", "hF8", "hF9", "hFA_FB", "hFC_FD", "hFE_FF",
12
- "hi",
13
- "lo",
14
- "mid",
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
- const STRING_PATTERN_PROPERTY_LIST = patternToPropertyList(STRING_PATTERN);
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
- function encodeText(text) {
72
- return encodeToWire(textToStringValue(text), STRING_PATTERN_PROPERTY_LIST);
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
- function decodeText(buffer) {
76
- const { value } = decodeWire(buffer);
77
- return stringValueToText(value);
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
- export { STRING_PATTERN, STRING_PATTERN_PROPERTY_LIST, textToStringValue, stringValueToText, encodeText, decodeText };
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 { stdin, stdout, argv, exit } from "node:process";
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
- function usage(stream = console.error) {
9
- stream(`Usage: ${argv[1]} --parse | --print`);
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
- function readAll(stream) {
22
- return new Promise((resolve, reject) => {
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
- function unitEncoding() {
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
- async function main() {
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 { UNIT_PATTERN, name, patterns, parse, print };
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 { stdin, stdout, argv, exit } from "node:process";
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 name = "utf16";
14
- const patterns = [STRING_PATTERN_PROPERTY_LIST];
10
+ export const doc = `
11
+ UTF-16 text codec (BOM-aware).
15
12
 
16
- function parse(text) {
17
- return textToStringValue(text);
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
- async function main() {
70
- const args = argv.slice(2);
71
- if (args.includes("-h") || args.includes("--help")) {
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
- if (isMainEntrypoint(import.meta.url, argv[1])) {
92
- main().catch(err => {
93
- console.error(err.message || String(err));
94
- exit(1);
95
- });
50
+ export function print(value) {
51
+ const text = stringValueToText(value);
52
+ return encodeUtf16Output(text);
96
53
  }
97
54
 
98
- export { name, patterns, parse, print };
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 { stdin, stdout, argv, exit } from "node:process";
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 name = "utf8";
14
- const patterns = [STRING_PATTERN_PROPERTY_LIST];
10
+ export const doc = `
11
+ UTF-8 text codec.
15
12
 
16
- function parse(text) {
17
- return textToStringValue(text);
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 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
- });
16
+ export function parse(text) {
17
+ const value = textToStringValue(text);
18
+ return withPattern(value, STRING_PATTERN_PROPERTY_LIST);
38
19
  }
39
20
 
40
- async function main() {
41
- const args = argv.slice(2);
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
- export { name, patterns, parse, print };
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.8.0",
3
+ "version": "6.10.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
  "exports": {
@@ -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 k from "../index.mjs";
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 annotated = k.annotate(script);
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
  }