@fraczak/k 6.2.3 → 6.2.4

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/AGENTS.md CHANGED
@@ -12,7 +12,7 @@
12
12
  - `npm run prepare` regenerates `parser.mjs` and `valueParser.mjs` from `.jison` grammars.
13
13
  - `npm test` runs the full suite through `scripts/run-tests.mjs`.
14
14
  - `node repl.mjs` (or `k-repl`) starts the interactive REPL.
15
- - `./k.mjs -k <file.k>` executes a k script on binary pattern+value stream input from stdin or a file; use `k-parse` and `k-print` at the boundaries.
15
+ - `./k.mjs <file.k>` executes a k source/object file on binary pattern+value stream input from stdin or a file; if the argument is not an existing file, it is treated as an inline k expression.
16
16
 
17
17
  ## Coding Style & Naming Conventions
18
18
  - JavaScript uses ES modules (`.mjs`) with 2-space indentation and semicolons.
package/CLAUDE.md CHANGED
@@ -20,7 +20,7 @@ npm test # Run comprehensive test suite (unit tests, derivation tests, shell te
20
20
 
21
21
  **Running k programs:**
22
22
  ```bash
23
- ./k.mjs -k <file.k> # Execute k script
23
+ ./k.mjs <file.k> # Execute k source/object file
24
24
  ./repl.mjs # Start interactive REPL (or: k-repl)
25
25
  ```
26
26
 
@@ -133,12 +133,12 @@ Loading an object hydrates the type-pattern graphs back into runtime
133
133
  Object execution through `k.mjs`:
134
134
 
135
135
  ```sh
136
- echo "..." | some-codec --parse | k -k path/to/program.ko | some-codec --print
136
+ echo "..." | some-codec --parse | k path/to/program.ko | some-codec --print
137
137
  ```
138
138
 
139
- The `-k` option accepts either an object file or a source `.k` file. `k.mjs`
140
- tries to load the file as an object first, then falls back to source parsing and
141
- compilation.
139
+ When the first positional argument names an existing file, `k.mjs` loads it as
140
+ either an object file or a source `.k` file. It tries to load the file as an
141
+ object first, then falls back to source parsing and compilation.
142
142
 
143
143
  Standalone helpers live in `objects/`:
144
144
 
package/README.md CHANGED
@@ -163,7 +163,7 @@ program for backend inspection and execution experiments.
163
163
 
164
164
  | Command | Purpose |
165
165
  | --- | --- |
166
- | `k` | Execute a k expression, or `-k` source/object file, over a binary stream |
166
+ | `k` | Execute a k expression, or an existing source/object file, over a binary stream |
167
167
  | `k-repl` | Start the interactive interpreter |
168
168
 
169
169
  **Serialization boundaries**
package/k.mjs CHANGED
@@ -12,14 +12,23 @@ const prog = argv[1];
12
12
  let kScript, inputStream;
13
13
 
14
14
  function usage() {
15
- console.error(`Usage: ${prog} [ --lib lib-file ]... [ --export spec ]... ( k-expr | -k file ) [ input-file ]`);
15
+ console.error(`Usage: ${prog} [ --lib lib-file ] [ --export spec ]... ( k-expr | file ) [ input-file ]`);
16
16
  console.error(` E.g., echo '["zebara","ela"]' | k-parse --input-type '$x=<{} zebara, {} ela>; $v={x 0, x 1}; $v' | ${prog} '{.1 0}'`);
17
17
  console.error("Options:");
18
- console.error(" --lib file Load a .klib dependency before compiling. May be repeated.");
18
+ console.error(" --lib file Load one .klib dependency before compiling.");
19
19
  console.error(" --export spec Export a library alias into scope. 'name' or 'libname:localname'. May be repeated.");
20
20
  console.error(" -h, --help Show this help.");
21
21
  }
22
22
 
23
+ function isFile(filePath) {
24
+ try {
25
+ return fs.statSync(filePath).isFile();
26
+ } catch (error) {
27
+ if (error?.code === "ENOENT" || error?.code === "ENOTDIR") return false;
28
+ throw error;
29
+ }
30
+ }
31
+
23
32
  function compileFile(filePath, libraries, preamble) {
24
33
  const buffer = fs.readFileSync(filePath);
25
34
  try {
@@ -44,6 +53,7 @@ function compileFile(filePath, libraries, preamble) {
44
53
  args.shift();
45
54
  const libPath = args.shift();
46
55
  if (!libPath) throw new Error("--lib requires a file argument");
56
+ if (libraries.length > 0) throw new Error("--lib may be specified at most once");
47
57
  const libBuffer = fs.readFileSync(libPath);
48
58
  libraries.push(loadLibrary(decodeObject(libBuffer)));
49
59
  } else if (args[0] === "--export") {
@@ -86,10 +96,10 @@ function compileFile(filePath, libraries, preamble) {
86
96
  throw new Error("Missing script argument");
87
97
  }
88
98
  if (arg === "-k") {
89
- return compileFile(args.shift(), libraries, buildExportPreamble());
90
- } else {
91
- return buildExportPreamble() + arg;
99
+ throw new Error("-k is no longer supported; pass the source/object file path directly");
92
100
  }
101
+ if (isFile(arg)) return compileFile(arg, libraries, buildExportPreamble());
102
+ return buildExportPreamble() + arg;
93
103
  })(args.shift());
94
104
  let kScript = typeof kScriptStr === "function" ? kScriptStr : k.compile(kScriptStr, { libraries });
95
105
  inputStream = (function (arg) {
package/kvm.mjs CHANGED
@@ -430,7 +430,7 @@ function usage() {
430
430
  const prog = argv[1] || "kvm.mjs";
431
431
  console.error(`Usage: node ${prog} [ options ] ( k-expr | -k file ) [ input-file ]`);
432
432
  console.error("Options:");
433
- console.error(" --lib file Load a .klib dependency before compiling. May be repeated.");
433
+ console.error(" --lib file Load one .klib dependency before compiling.");
434
434
  console.error(" --envelope-free Run the interpreter in envelope-free mode.");
435
435
  console.error(" -h, --help Show this help.");
436
436
  }
@@ -454,6 +454,7 @@ async function main() {
454
454
  args.shift();
455
455
  const libPath = args.shift();
456
456
  if (!libPath) throw new Error("--lib requires a file argument");
457
+ if (libraries.length > 0) throw new Error("--lib may be specified at most once");
457
458
  const libBuffer = fs.readFileSync(libPath);
458
459
  libraries.push(loadLibrary(decodeObject(libBuffer)));
459
460
  } else {
package/objects/README.md CHANGED
@@ -11,7 +11,7 @@ Compiles `.k` source into an executable object file (`.ko`), library file
11
11
  extension, or from `--format`.
12
12
 
13
13
  ```bash
14
- k-compile [--lib lib-file]... [--format ko|klib|kvm] [source-snippet | input-file [output-file]]
14
+ k-compile [--lib lib-file] [--format ko|klib|kvm] [source-snippet | input-file [output-file]]
15
15
  ```
16
16
 
17
17
  Existing input paths are read as files. A non-existing input with `.k`, `.ko`,
@@ -25,7 +25,7 @@ function helpText() {
25
25
  " output-file Output path (.ko, .klib, or .kvm). Writes to stdout when omitted.",
26
26
  "",
27
27
  "Options:",
28
- " --lib file Load a .klib dependency before compiling. May be repeated.",
28
+ " --lib file Load one .klib dependency before compiling.",
29
29
  " --export spec Export a library alias into the source scope. May be repeated.",
30
30
  " spec is 'name' or 'libname:localname'.",
31
31
  " --format fmt Output format: ko, klib, or kvm. Overrides extension detection.",
@@ -168,6 +168,7 @@ try {
168
168
  args.shift();
169
169
  const libPath = args.shift();
170
170
  if (!libPath) throw new Error("--lib requires a file argument");
171
+ if (libraries.length > 0) throw new Error("--lib may be specified at most once");
171
172
  libraries.push(loadLibrary(decodeObject(fs.readFileSync(libPath))));
172
173
  } else if (args[0] === "--export") {
173
174
  args.shift();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fraczak/k",
3
- "version": "6.2.3",
3
+ "version": "6.2.4",
4
4
  "description": "k — a language for composing first-order partial functions over algebraic data types (products and tagged unions); includes runtime, type derivation, REPL, and codec toolchain",
5
5
  "main": "index.mjs",
6
6
  "scripts": {
package/run.mjs CHANGED
@@ -238,32 +238,31 @@ function compiledExp(findCode, exp, typePatternGraph) {
238
238
  case "product": {
239
239
  const labels = exp.product.map(({ label }) => label);
240
240
  const fieldFns = exp.product.map(({ exp: e }) => compiledExp(findCode, e, typePatternGraph));
241
- if (staticOutputPattern) {
242
- fn = (value) => {
243
- if (value === undefined) return undefined;
244
- const result = {};
245
- for (let i = 0, len = labels.length; i < len; i++) {
246
- const r = fieldFns[i](value);
247
- if (r === undefined) return undefined;
248
- result[labels[i]] = r;
249
- }
250
- return new Product(result, staticOutputPattern);
251
- };
252
- } else {
253
- fn = (value) => {
254
- if (value === undefined) return undefined;
255
- const result = {};
256
- const patternEntries = [];
257
- for (let i = 0, len = labels.length; i < len; i++) {
258
- const r = fieldFns[i](value);
259
- if (r === undefined) return undefined;
260
- const label = labels[i];
261
- result[label] = r;
262
- patternEntries.push([label, r.pattern]);
263
- }
264
- return new Product(result, composePattern("closed-product", patternEntries));
265
- };
266
- }
241
+ fn = (value) => {
242
+ if (value === undefined) return undefined;
243
+ const result = {};
244
+ const patternEntries = [];
245
+ for (let i = 0, len = labels.length; i < len; i++) {
246
+ const r = fieldFns[i](value);
247
+ if (r === undefined) return undefined;
248
+ const label = labels[i];
249
+ result[label] = r;
250
+ patternEntries.push([label, r.pattern]);
251
+ }
252
+ const dynamicOutputPattern = composePattern("closed-product", patternEntries);
253
+ const pattern = staticOutputPattern && dynamicOutputPattern
254
+ ? intersectPatterns(staticOutputPattern, dynamicOutputPattern)
255
+ : staticOutputPattern || dynamicOutputPattern;
256
+ if (!pattern && staticOutputPattern && dynamicOutputPattern) {
257
+ throw new TypeError(
258
+ `Type Error in '${exp.op}'${expLocation(exp)}\n` +
259
+ ` - Product value envelope does not intersect expression output pattern.\n` +
260
+ ` - output pattern: ${patternPreview(staticOutputPattern)}\n` +
261
+ ` - product envelope: ${patternPreview(dynamicOutputPattern)}`
262
+ );
263
+ }
264
+ return new Product(result, pattern);
265
+ };
267
266
  break;
268
267
  }
269
268
  case "vid":
@@ -19,6 +19,22 @@ grep -q '"__main__"' "$TMP_DIR/stdin.kvm"
19
19
  ./objects/compile.mjs --lib "$TMP_DIR/export.klib" --export id:alias 'alias' "$TMP_DIR/export.ko"
20
20
  ./objects/decompile.mjs "$TMP_DIR/export.ko" | grep -q '^----- main -----$'
21
21
  node ./codecs/unit.mjs --parse | ./k.mjs --lib "$TMP_DIR/export.klib" --export id:alias 'alias' | node ./codecs/unit.mjs --print | grep -qx '{}'
22
+ node ./codecs/unit.mjs --parse | ./k.mjs "$TMP_DIR/export.ko" | node ./codecs/unit.mjs --print | grep -qx '{}'
23
+ if ./k.mjs --lib "$TMP_DIR/export.klib" --lib "$TMP_DIR/export.klib" '()' > "$TMP_DIR/two-lib.out" 2> "$TMP_DIR/two-lib.err"; then
24
+ echo "expected repeated --lib to fail" >&2
25
+ exit 1
26
+ fi
27
+ grep -q -- '--lib may be specified at most once' "$TMP_DIR/two-lib.err"
28
+ if ./objects/compile.mjs --lib "$TMP_DIR/export.klib" --lib "$TMP_DIR/export.klib" '()' "$TMP_DIR/two-lib.ko" > "$TMP_DIR/two-lib-compile.out" 2> "$TMP_DIR/two-lib-compile.err"; then
29
+ echo "expected repeated k-compile --lib to fail" >&2
30
+ exit 1
31
+ fi
32
+ grep -q -- '--lib may be specified at most once' "$TMP_DIR/two-lib-compile.err"
33
+ if ./kvm.mjs --lib "$TMP_DIR/export.klib" --lib "$TMP_DIR/export.klib" '()' > "$TMP_DIR/two-lib-kvm.out" 2> "$TMP_DIR/two-lib-kvm.err"; then
34
+ echo "expected repeated k-vm --lib to fail" >&2
35
+ exit 1
36
+ fi
37
+ grep -q -- '--lib may be specified at most once' "$TMP_DIR/two-lib-kvm.err"
22
38
  if ./objects/compile.mjs "$TMP_DIR/missing.k" > "$TMP_DIR/missing.out" 2> "$TMP_DIR/missing.err"; then
23
39
  echo "expected missing .k input to fail" >&2
24
40
  exit 1
@@ -27,11 +43,20 @@ grep -q 'Input file not found:' "$TMP_DIR/missing.err"
27
43
 
28
44
  echo '["zebara", "ela", "kupa", ala, owca]' | node ./codecs/k-parse.mjs | ./k.mjs '{.1 0,.3 1}' | node ./codecs/k-print.mjs
29
45
  echo
46
+ echo "a" | ./codecs/k-parse.mjs --input-type '?< {} a, X b, ...>' | ./k.mjs '{() i, /a o}' | ./codecs/show.mjs > "$TMP_DIR/polymorphic-relation.wire" 2> "$TMP_DIR/polymorphic-relation.show"
47
+ grep -Fqx '{{}|a i, {} o} ?{<{}=X0 a, (...) b, ...> i, X0 o}' "$TMP_DIR/polymorphic-relation.show"
48
+ ./codecs/k-print.mjs "$TMP_DIR/polymorphic-relation.wire" | grep -qx '{"i":"a","o":{}}'
49
+ echo
30
50
  echo '-21' | node ./codecs/int.mjs --parse | node ./codecs/int.mjs --print | grep -qx -- '-21'
31
51
  echo
32
52
  node ./codecs/unit.mjs --parse | node ./codecs/unit.mjs --print | grep -qx '{}'
33
53
  echo
34
- printf 'A🙂\nBé~\t' | ./codecs/utf8.mjs --parse | ./k.mjs -k Examples/byte.k |./codecs/utf8.mjs --print
54
+ if ./k.mjs -k Examples/byte.k > "$TMP_DIR/dash-k.out" 2> "$TMP_DIR/dash-k.err"; then
55
+ echo "expected -k to fail" >&2
56
+ exit 1
57
+ fi
58
+ grep -q -- '-k is no longer supported' "$TMP_DIR/dash-k.err"
59
+ printf 'A🙂\nBé~\t' | ./codecs/utf8.mjs --parse | ./k.mjs Examples/byte.k |./codecs/utf8.mjs --print
35
60
  echo
36
61
  ./objects/compile.mjs Examples/ieee.k "$TMP_DIR/ieee.klib"
37
62
  MUL=`./objects/extract-aliases.mjs "$TMP_DIR/ieee.klib" | grep '^mul = @' | sed 's/^mul = \(@[^;]*\);.*$/\1/'`