@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/codecs/README.md CHANGED
@@ -79,6 +79,8 @@ notation for k values. That notation is documented in
79
79
  [`../DOCS/TEXTUAL_VALUES.md`](../DOCS/TEXTUAL_VALUES.md). It is a readable
80
80
  notation for k values, not a separate JSON container format.
81
81
 
82
+ For the codec architecture and specification, see
83
+ [`../DOCS/CODEC_ARCHITECTURE.md`](../DOCS/CODEC_ARCHITECTURE.md).
82
84
  For the contributor-facing guide to writing a new external codec module, see
83
85
  [`../DOCS/CODECS.md`](../DOCS/CODECS.md).
84
86
 
@@ -238,6 +240,10 @@ The new codec work is split into layers:
238
240
 
239
241
  ## Files
240
242
 
243
+ - [`../DOCS/CODEC_ARCHITECTURE.md`](../DOCS/CODEC_ARCHITECTURE.md):
244
+ comprehensive architecture specification for k codecs.
245
+ - [`../DOCS/CODECS.md`](../DOCS/CODECS.md):
246
+ practical guide to writing, running, and testing codecs.
241
247
  - [`POLYMORPHIC_BINARY_FORMAT.md`](./POLYMORPHIC_BINARY_FORMAT.md):
242
248
  main design document for the new pattern-plus-prefix-tree codec.
243
249
  - [`BINARY_FORMAT.md`](./BINARY_FORMAT.md):
@@ -247,3 +253,4 @@ The new codec work is split into layers:
247
253
 
248
254
  The active command-line pipeline emits and consumes the self-hosted binary
249
255
  pattern+value stream.
256
+
package/codecs/ieee.mjs CHANGED
@@ -1,20 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { stdin, stdout, argv, exit } from "node:process";
4
- import { Value, isProduct, isVariant } from "../Value.mjs";
5
- import { isMainEntrypoint } from "./runtime/cli-entry.mjs";
6
- import { decodeWire, encodeToWire } from "./runtime/prefix-codec.mjs";
7
- import { FLOAT64_PATTERN } from "./runtime/ieee-pattern.mjs";
3
+ import { Value, isProduct, isVariant, withPattern, patternFromFilter, runCodecCLI } from "./runtime/codec-sdk.mjs";
4
+
5
+ export const doc = `
6
+ IEEE 754 64-bit float codec.
7
+
8
+ Parses decimal floats, Infinity, -Infinity, NaN to 64-bit IEEE products.
9
+ `;
10
+
11
+ const FLOAT64_PATTERN = patternFromFilter(`
12
+ $bit = < {} 0, {} 1 >;
13
+ $sign = < {} "+", {} "-" >;
14
+ $exp11 = {bit 0, bit 1, bit 2, bit 3, bit 4, bit 5, bit 6, bit 7, bit 8, bit 9, bit 10};
15
+ $frac52 = {bit 0, bit 1, bit 2, bit 3, bit 4, bit 5, bit 6, bit 7, bit 8, bit 9,
16
+ bit 10, bit 11, bit 12, bit 13, bit 14, bit 15, bit 16, bit 17, bit 18, bit 19,
17
+ bit 20, bit 21, bit 22, bit 23, bit 24, bit 25, bit 26, bit 27, bit 28, bit 29,
18
+ bit 30, bit 31, bit 32, bit 33, bit 34, bit 35, bit 36, bit 37, bit 38, bit 39,
19
+ bit 40, bit 41, bit 42, bit 43, bit 44, bit 45, bit 46, bit 47, bit 48, bit 49,
20
+ bit 50, bit 51};
21
+ $float64 = {sign sign, exp11 exponent, frac52 fraction};
22
+ ?$float64
23
+ `);
24
+
8
25
  const UNIT = Value.product({});
9
- const name = "ieee";
10
- const patterns = [FLOAT64_PATTERN];
11
-
12
- function usage(stream = console.error) {
13
- stream(`Usage: ${argv[1]} --parse | --print`);
14
- stream(" --parse Read a float literal from stdin, write binary pattern+value stream.");
15
- stream(" --print Read binary pattern+value stream from stdin, write a float literal.");
16
- stream(" -h, --help Show this help.");
17
- }
18
26
 
19
27
  function bitValue(bit) {
20
28
  return Value.variant(bit === 0 ? "0" : "1", UNIT);
@@ -29,10 +37,11 @@ function bitsProduct(width, value) {
29
37
  return Value.product(product);
30
38
  }
31
39
 
32
- function encodeNumberToValue(number) {
33
- const buf = Buffer.alloc(8);
34
- buf.writeDoubleBE(number, 0);
35
- const bits = buf.readBigUInt64BE(0);
40
+ const floatView = new DataView(new ArrayBuffer(8));
41
+
42
+ export function encodeNumberToValue(number) {
43
+ floatView.setFloat64(0, number, false);
44
+ const bits = floatView.getBigUint64(0, false);
36
45
  const sign = Number((bits >> 63n) & 1n);
37
46
  const exponent = Number((bits >> 52n) & 0x7ffn);
38
47
  const fraction = bits & ((1n << 52n) - 1n);
@@ -71,7 +80,7 @@ function parseBitsProduct(value, maxBit, where) {
71
80
  return n;
72
81
  }
73
82
 
74
- function decodeValueToNumber(value) {
83
+ export function decodeValueToNumber(value) {
75
84
  const product = requireProduct(value, "float64");
76
85
  const sign = requireVariant(product.sign, "float64.sign");
77
86
  if (sign.tag !== "+" && sign.tag !== "-") {
@@ -85,9 +94,8 @@ function decodeValueToNumber(value) {
85
94
  (exponent << 52n) |
86
95
  fraction;
87
96
 
88
- const buf = Buffer.alloc(8);
89
- buf.writeBigUInt64BE(bits, 0);
90
- return buf.readDoubleBE(0);
97
+ floatView.setBigUint64(0, bits, false);
98
+ return floatView.getFloat64(0, false);
91
99
  }
92
100
 
93
101
  function parseFloatText(text) {
@@ -98,68 +106,35 @@ function parseFloatText(text) {
98
106
 
99
107
  if (/^[+-]?nan$/i.test(trimmed)) return NaN;
100
108
  if (/^[+]?inf(inity)?$/i.test(trimmed)) return Infinity;
101
- if (/^-inf(inity)?$/i.test(trimmed)) return -Infinity;
109
+ if (/^[-](inf|infinity)$/i.test(trimmed)) return -Infinity;
102
110
 
103
- const value = Number(trimmed);
104
- if (Number.isNaN(value)) {
105
- throw new Error(`Invalid floating-point literal: ${JSON.stringify(trimmed)}`);
111
+ const n = Number(trimmed);
112
+ if (Number.isNaN(n)) {
113
+ throw new Error(`Invalid float literal ${JSON.stringify(trimmed)}`);
106
114
  }
107
- return value;
115
+ return n;
108
116
  }
109
117
 
110
- function printFloatText(number) {
111
- if (Number.isNaN(number)) return "NaN";
112
- if (number === Infinity) return "Infinity";
113
- if (number === -Infinity) return "-Infinity";
114
- if (Object.is(number, -0)) return "-0";
115
- return String(number);
118
+ function printFloatText(n) {
119
+ if (Number.isNaN(n)) return "NaN";
120
+ if (n === Infinity) return "Infinity";
121
+ if (n === -Infinity) return "-Infinity";
122
+ if (Object.is(n, -0)) return "-0";
123
+ return String(n);
116
124
  }
117
125
 
118
- function parse(text) {
119
- return encodeNumberToValue(parseFloatText(text));
126
+ export function parse(text) {
127
+ const n = parseFloatText(text);
128
+ const value = encodeNumberToValue(n);
129
+ return withPattern(value, FLOAT64_PATTERN);
120
130
  }
121
131
 
122
- function print(value) {
132
+ export function print(value) {
123
133
  return printFloatText(decodeValueToNumber(value));
124
134
  }
125
135
 
126
- function readAll(stream) {
127
- return new Promise((resolve, reject) => {
128
- const chunks = [];
129
- stream.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
130
- stream.on("end", () => resolve(Buffer.concat(chunks)));
131
- stream.on("error", reject);
132
- });
133
- }
134
-
135
- async function main() {
136
- const args = argv.slice(2);
137
- if (args.includes("-h") || args.includes("--help")) {
138
- usage(console.log);
139
- exit(0);
140
- }
141
-
142
- if (args.length !== 1 || (args[0] !== "--parse" && args[0] !== "--print")) {
143
- usage();
144
- exit(1);
145
- }
146
-
147
- const buf = await readAll(stdin);
148
-
149
- if (args[0] === "--parse") {
150
- const value = encodeNumberToValue(parseFloatText(buf.toString("utf8")));
151
- stdout.write(encodeToWire(value, FLOAT64_PATTERN));
152
- } else {
153
- const { value } = decodeWire(buf);
154
- stdout.write(`${printFloatText(decodeValueToNumber(value))}\n`);
155
- }
156
- }
157
-
158
- if (isMainEntrypoint(import.meta.url, argv[1])) {
159
- main().catch((error) => {
160
- console.error(error.message || String(error));
161
- exit(1);
162
- });
163
- }
136
+ runCodecCLI(import.meta.url, { parse, print, doc });
164
137
 
165
- export { FLOAT64_PATTERN, name, patterns, parse, print };
138
+ export {
139
+ FLOAT64_PATTERN
140
+ };
package/codecs/int.mjs CHANGED
@@ -1,48 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * int: parse/print integers in the k 'int' binary pattern+value stream.
4
+ * int: parse/print integers and integer lists as enveloped k values.
5
5
  *
6
6
  * $ bits = < {} _, bits 0, bits 1 >;
7
7
  * $ int = < bits '+', bits '-' >;
8
- *
9
- * Bits are stored MSB-outermost (remove_leading_zeros strips outermost 0s).
10
- *
11
- * Usage:
12
- * echo "-21" | int.mjs --parse # decimal → binary pattern+value stream
13
- * <wire> | int.mjs --print # binary pattern+value stream → decimal
8
+ * list = < {} nil, {int car, list cdr} cons >;
14
9
  */
15
10
 
16
- import { stdin, stdout, argv, exit } from "node:process";
17
- import { Value, isVariant } from "../Value.mjs";
18
- import { isMainEntrypoint } from "./runtime/cli-entry.mjs";
19
- import { decodeWire, encodeToWire } from "./runtime/prefix-codec.mjs";
11
+ import { Value, isProduct, isVariant, withPattern, patternFromFilter, runCodecCLI } from "./runtime/codec-sdk.mjs";
20
12
 
21
- function usage(stream = console.error) {
22
- stream(`Usage: ${argv[1]} --parse | --print`);
23
- stream(" --parse Read a decimal integer from stdin, write binary pattern+value stream.");
24
- stream(" --print Read binary pattern+value stream from stdin, write decimal integer.");
25
- stream(" -h, --help Show this help.");
26
- }
13
+ export const doc = `
14
+ Decimal integers and integer lists.
15
+
16
+ Syntax:
17
+ Decimal integer (e.g. 42, -15) or bracketed integer list (e.g. [0, 1, 2], []).
18
+ `;
27
19
 
28
20
  // Closed pattern for $ int = < bits '+', bits '-' >
29
21
  // with $ bits = < {} _, bits 0, bits 1 >
30
- const INT_PATTERN = [
31
- ["closed-union", [["+", 1], ["-", 1]]],
32
- ["closed-union", [["0", 1], ["1", 1], ["_", 2]]],
33
- ["closed-product", []]
34
- ];
35
- const name = "int";
36
- const patterns = [INT_PATTERN];
22
+ const INT_PATTERN = patternFromFilter('?< <bits 0, bits 1, {} _>=bits "+", bits "-">');
37
23
 
38
- function readAll(stream) {
39
- return new Promise((resolve, reject) => {
40
- const chunks = [];
41
- stream.on("data", c => chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c)));
42
- stream.on("end", () => resolve(Buffer.concat(chunks)));
43
- stream.on("error", reject);
44
- });
45
- }
24
+ // Closed pattern for list of int:
25
+ // list = < {} nil, {int car, list cdr} cons >
26
+ const INT_LIST_PATTERN = patternFromFilter(
27
+ '$ bits = < bits 0, bits 1, {} _ >; $ int = < bits "+", bits "-" >; ?< {} nil, { $int car, list cdr } cons > = list'
28
+ );
46
29
 
47
30
  // Build bits Value (MSB outermost) from a non-negative BigInt.
48
31
  function buildBits(n) {
@@ -54,7 +37,7 @@ function buildBits(n) {
54
37
  return v;
55
38
  }
56
39
 
57
- // Parse a decimal integer string ([-+]?[ ]*[1-9][0-9]*|0) into a k int Value.
40
+ // Parse a decimal integer string into a k int Value.
58
41
  function parseIntStr(str) {
59
42
  str = str.trim();
60
43
  let sign = "+";
@@ -64,12 +47,44 @@ function parseIntStr(str) {
64
47
  throw new Error(`Invalid integer syntax: ${JSON.stringify(str)}`);
65
48
  }
66
49
  const n = BigInt(str);
67
- if (n === 0n) sign = "+"; // zero is always '+'
50
+ if (n === 0n) sign = "+";
68
51
  return Value.variant(sign, buildBits(n));
69
52
  }
70
53
 
71
- // Walk a decoded int Value (Variant sign → bits) and return a decimal string.
72
- function printIntValue(value) {
54
+ // Parse a list of decimal integers, e.g. "[0,1,2]" or "[]"
55
+ function parseIntListStr(str) {
56
+ str = str.trim();
57
+ if (!str.startsWith("[") || !str.endsWith("]")) {
58
+ throw new Error(`Invalid integer list syntax: ${JSON.stringify(str)}`);
59
+ }
60
+ const inner = str.slice(1, -1).trim();
61
+ if (inner === "") {
62
+ return Value.variant("nil", Value.product({}));
63
+ }
64
+ const parts = inner.split(",");
65
+ const items = parts.map((part) => parseIntStr(part));
66
+ let result = Value.variant("nil", Value.product({}));
67
+ for (let i = items.length - 1; i >= 0; i--) {
68
+ result = Value.variant("cons", Value.product({
69
+ car: items[i],
70
+ cdr: result
71
+ }));
72
+ }
73
+ return result;
74
+ }
75
+
76
+ // Parse a decimal integer string or integer list into an enveloped k Value.
77
+ export function parse(str) {
78
+ str = str.trim();
79
+ const raw = str.startsWith("[") ? parseIntListStr(str) : parseIntStr(str);
80
+ const pattern = isVariant(raw) && (raw.tag === "nil" || raw.tag === "cons")
81
+ ? INT_LIST_PATTERN
82
+ : INT_PATTERN;
83
+ return withPattern(raw, pattern);
84
+ }
85
+
86
+ // Walk a decoded int Value and return a decimal string.
87
+ function printSingleInt(value) {
73
88
  if (!isVariant(value) || (value.tag !== "+" && value.tag !== "-")) {
74
89
  throw new Error("Not a valid k int value");
75
90
  }
@@ -80,42 +95,48 @@ function printIntValue(value) {
80
95
  bits += node.tag;
81
96
  node = node.value;
82
97
  }
83
- // bits is MSB-first binary string (may be empty for zero represented as "0")
84
98
  const n = bits === "" ? 0n : BigInt("0b" + bits);
85
99
  const digits = n.toString(10);
86
100
  if (n === 0n) return "0";
87
101
  return (sign === "-" ? "-" : "") + digits;
88
102
  }
89
103
 
90
- async function main() {
91
- const args = argv.slice(2);
92
- if (args.includes("-h") || args.includes("--help")) {
93
- usage(console.log);
94
- exit(0);
104
+ // Walk a decoded int list Value and return a bracketed string like "[0,1,2]".
105
+ function printIntList(value) {
106
+ const items = [];
107
+ let node = value;
108
+ while (isVariant(node) && node.tag === "cons") {
109
+ const product = isProduct(node.value) ? node.value.product : null;
110
+ if (!product || !product.car || !product.cdr) {
111
+ throw new Error("Invalid list cons node");
112
+ }
113
+ items.push(printSingleInt(product.car));
114
+ node = product.cdr;
95
115
  }
96
-
97
- if (args.length !== 1 || (args[0] !== "--parse" && args[0] !== "--print")) {
98
- usage();
99
- exit(1);
116
+ if (!isVariant(node) || node.tag !== "nil") {
117
+ throw new Error("Not a valid k int list: does not terminate in nil");
100
118
  }
119
+ return `[${items.join(",")}]`;
120
+ }
101
121
 
102
- const buf = await readAll(stdin);
103
-
104
- if (args[0] === "--parse") {
105
- const text = buf.toString("utf8").trim();
106
- const value = parseIntStr(text);
107
- stdout.write(encodeToWire(value, INT_PATTERN));
108
- } else {
109
- const { value } = decodeWire(buf);
110
- stdout.write(printIntValue(value) + "\n");
122
+ // Walk a decoded int or int list Value and return a formatted string.
123
+ export function print(value) {
124
+ if (isVariant(value)) {
125
+ if (value.tag === "nil" || value.tag === "cons") {
126
+ return printIntList(value);
127
+ }
128
+ if (value.tag === "+" || value.tag === "-") {
129
+ return printSingleInt(value);
130
+ }
111
131
  }
132
+ throw new Error("Not a valid k int or int list value");
112
133
  }
113
134
 
114
- if (isMainEntrypoint(import.meta.url, argv[1])) {
115
- main().catch(err => {
116
- console.error(err.message || String(err));
117
- exit(1);
118
- });
119
- }
135
+ runCodecCLI(import.meta.url, { parse, print, doc });
120
136
 
121
- export { INT_PATTERN, name, patterns, parseIntStr as parse, printIntValue as print };
137
+ export {
138
+ INT_PATTERN,
139
+ INT_LIST_PATTERN,
140
+ parseIntStr,
141
+ parseIntListStr
142
+ };
@@ -1,44 +1,11 @@
1
1
  import { Value, isProduct, isVariant } from "../Value.mjs";
2
+ import { patternFromFilter } from "./runtime/codec-sdk.mjs";
2
3
  import { STRING_PATTERN_PROPERTY_LIST, textToStringValue, stringValueToText } from "./string-codec.mjs";
3
- import { FLOAT64_PATTERN } from "./runtime/ieee-pattern.mjs";
4
+ import { FLOAT64_PATTERN, encodeNumberToValue, decodeValueToNumber } from "./ieee.mjs";
4
5
 
5
6
  const UNIT = Value.product({});
6
- const BOOL_PATTERN = [
7
- ["closed-union", [["false", 1], ["true", 1]]],
8
- ["closed-product", []]
9
- ];
10
- const NULL_PATTERN = [
11
- ["closed-union", [["null", 1]]],
12
- ["closed-product", []]
13
- ];
14
-
15
- function bitValue(bit) {
16
- return Value.variant(bit === 0 ? "0" : "1", UNIT);
17
- }
18
-
19
- function bitsProduct(width, value) {
20
- const big = BigInt(value);
21
- const product = {};
22
- for (let i = width - 1; i >= 0; i--) {
23
- product[String(i)] = bitValue(Number((big >> BigInt(i)) & 1n));
24
- }
25
- return Value.product(product);
26
- }
27
-
28
- function encodeNumberToValue(number) {
29
- const buf = Buffer.alloc(8);
30
- buf.writeDoubleBE(number, 0);
31
- const bits = buf.readBigUInt64BE(0);
32
- const sign = Number((bits >> 63n) & 1n);
33
- const exponent = Number((bits >> 52n) & 0x7ffn);
34
- const fraction = bits & ((1n << 52n) - 1n);
35
-
36
- return Value.product({
37
- sign: Value.variant(sign === 0 ? "+" : "-", UNIT),
38
- exponent: bitsProduct(11, exponent),
39
- fraction: bitsProduct(52, fraction)
40
- });
41
- }
7
+ const BOOL_PATTERN = patternFromFilter("?< {} false, {} true >");
8
+ const NULL_PATTERN = patternFromFilter("?< {} null >");
42
9
 
43
10
  function requireProduct(value, where) {
44
11
  if (!isProduct(value)) {
@@ -47,45 +14,6 @@ function requireProduct(value, where) {
47
14
  return value.product;
48
15
  }
49
16
 
50
- function requireVariant(value, where) {
51
- if (!isVariant(value)) {
52
- throw new Error(`${where}: expected Variant`);
53
- }
54
- return value;
55
- }
56
-
57
- function parseBitsProduct(value, maxBit, where) {
58
- const product = requireProduct(value, where);
59
- let n = 0n;
60
- for (let i = maxBit; i >= 0; i--) {
61
- const entry = requireVariant(product[String(i)], `${where}.bit${i}`);
62
- if (entry.tag !== "0" && entry.tag !== "1") {
63
- throw new Error(`${where}.bit${i}: expected tag 0 or 1`);
64
- }
65
- n = (n << 1n) | BigInt(entry.tag === "1" ? 1 : 0);
66
- }
67
- return n;
68
- }
69
-
70
- function decodeValueToNumber(value) {
71
- const product = requireProduct(value, "json.number");
72
- const sign = requireVariant(product.sign, "json.number.sign");
73
- if (sign.tag !== "+" && sign.tag !== "-") {
74
- throw new Error(`json.number.sign: expected + or -, got ${sign.tag}`);
75
- }
76
- const exponent = parseBitsProduct(product.exponent, 10, "json.number.exponent");
77
- const fraction = parseBitsProduct(product.fraction, 51, "json.number.fraction");
78
-
79
- const bits =
80
- (BigInt(sign.tag === "-" ? 1 : 0) << 63n) |
81
- (exponent << 52n) |
82
- fraction;
83
-
84
- const buf = Buffer.alloc(8);
85
- buf.writeBigUInt64BE(bits, 0);
86
- return buf.readDoubleBE(0);
87
- }
88
-
89
17
  function fromJsonValue(value) {
90
18
  if (value === null) {
91
19
  return Value.variant("null", UNIT);
@@ -153,7 +81,7 @@ function patternFromJsonValue(value) {
153
81
  return composePattern(
154
82
  "closed-product",
155
83
  Object.keys(value)
156
- .sort((a, b) => Buffer.compare(Buffer.from(a, "utf8"), Buffer.from(b, "utf8")))
84
+ .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
157
85
  .map((key) => [key, patternFromJsonValue(value[key])])
158
86
  );
159
87
  }
package/codecs/json.mjs CHANGED
@@ -1,67 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { stdin, stdout, argv, exit } from "node:process";
4
- import { decodeWire, encodeToWire } from "./runtime/prefix-codec.mjs";
5
- import { isMainEntrypoint } from "./runtime/cli-entry.mjs";
3
+ import { withPattern, runCodecCLI } from "./runtime/codec-sdk.mjs";
6
4
  import { fromJsonValue, toJsonValue, patternFromJsonValue } from "./json-codec.mjs";
7
5
 
8
- const name = "json";
9
- const universal = true;
6
+ export const doc = `
7
+ JSON codec (RFC 8259).
10
8
 
11
- function usage(stream = console.error) {
12
- stream(`Usage: ${argv[1]} --parse | --print`);
13
- stream(" --parse Read JSON from stdin, write binary pattern+value stream.");
14
- stream(" --print Read binary pattern+value stream from stdin, write JSON.");
15
- stream(" -h, --help Show this help.");
16
- }
17
-
18
- function readAll(stream) {
19
- return new Promise((resolve, reject) => {
20
- const chunks = [];
21
- stream.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
22
- stream.on("end", () => resolve(Buffer.concat(chunks)));
23
- stream.on("error", reject);
24
- });
25
- }
9
+ Translates JSON data to/from self-describing enveloped k values.
10
+ `;
26
11
 
27
- function parse(text) {
28
- return fromJsonValue(JSON.parse(text));
12
+ export function parse(text) {
13
+ const json = JSON.parse(text);
14
+ const value = fromJsonValue(json);
15
+ const pattern = patternFromJsonValue(json);
16
+ return withPattern(value, pattern);
29
17
  }
30
18
 
31
- function print(value) {
19
+ export function print(value) {
32
20
  return JSON.stringify(toJsonValue(value));
33
21
  }
34
22
 
35
- async function main() {
36
- const args = argv.slice(2);
37
- if (args.includes("-h") || args.includes("--help")) {
38
- usage(console.log);
39
- exit(0);
40
- }
41
-
42
- if (args.length !== 1 || (args[0] !== "--parse" && args[0] !== "--print")) {
43
- usage();
44
- exit(1);
45
- }
46
-
47
- const buf = await readAll(stdin);
48
-
49
- if (args[0] === "--parse") {
50
- const text = buf.toString("utf8");
51
- const json = JSON.parse(text);
52
- const value = fromJsonValue(json);
53
- stdout.write(encodeToWire(value, patternFromJsonValue(json)));
54
- } else {
55
- const { value } = decodeWire(buf);
56
- stdout.write(`${print(value)}\n`);
57
- }
58
- }
59
-
60
- if (isMainEntrypoint(import.meta.url, argv[1])) {
61
- main().catch((error) => {
62
- console.error(error.stack || error.message || String(error));
63
- exit(1);
64
- });
65
- }
66
-
67
- export { name, universal, parse, print };
23
+ runCodecCLI(import.meta.url, { parse, print, doc });
@@ -2,11 +2,9 @@
2
2
 
3
3
  import fs from "node:fs";
4
4
  import { argv, stdin, exit, stdout } from "node:process";
5
- import k from "../index.mjs";
6
5
  import { parseValue } from "../valueIO.mjs";
7
6
  import { isMainEntrypoint } from "./runtime/cli-entry.mjs";
8
- import { exportPatternGraph } from "./runtime/codec.mjs";
9
- import { patternToPropertyList } from "./runtime/pattern-json.mjs";
7
+ import { patternFromFilter } from "./runtime/pattern-k.mjs";
10
8
  import { encodeToWire } from "./runtime/prefix-codec.mjs";
11
9
 
12
10
  function usage(prog) {
@@ -32,20 +30,6 @@ function readAll(stream) {
32
30
  });
33
31
  }
34
32
 
35
- function propertyListFromScript(script) {
36
- const annotated = k.annotate(script);
37
- const mainRel = annotated.rels.__main__;
38
- if (!mainRel || !mainRel.typePatternGraph) {
39
- throw new Error("Could not resolve __main__ relation");
40
- }
41
- if (mainRel.def.op !== "filter" && mainRel.def.op !== "code") {
42
- throw new Error("Input script must end with a filter or a type name");
43
- }
44
- const rootPatternId = mainRel.typePatternGraph.find(mainRel.def.patterns[0]);
45
- const pattern = exportPatternGraph(mainRel.typePatternGraph, rootPatternId);
46
- return patternToPropertyList(pattern);
47
- }
48
-
49
33
  async function main() {
50
34
  const prog = argv[1];
51
35
  const args = argv.slice(2);
@@ -82,8 +66,8 @@ async function main() {
82
66
  const value = parseValue(inputText, null, null);
83
67
 
84
68
  const propertyList = (() => {
85
- if (inputTypeArg != null) return propertyListFromScript(maybeReadFile(inputTypeArg));
86
- if (inputPatternArg != null) return propertyListFromScript(maybeReadFile(inputPatternArg));
69
+ if (inputTypeArg != null) return patternFromFilter(maybeReadFile(inputTypeArg));
70
+ if (inputPatternArg != null) return patternFromFilter(maybeReadFile(inputPatternArg));
87
71
  return null;
88
72
  })();
89
73