@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 +1 -1
- package/CLAUDE.md +1 -1
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +4 -4
- package/README.md +1 -1
- package/k.mjs +15 -5
- package/kvm.mjs +2 -1
- package/objects/README.md +1 -1
- package/objects/compile.mjs +2 -1
- package/package.json +1 -1
- package/run.mjs +25 -26
- package/tests/integration.sh +26 -1
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
|
|
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
|
|
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
|
|
136
|
+
echo "..." | some-codec --parse | k path/to/program.ko | some-codec --print
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
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
|
|
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 ]
|
|
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
|
|
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
|
-
|
|
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
|
|
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]
|
|
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`,
|
package/objects/compile.mjs
CHANGED
|
@@ -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
|
|
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
|
+
"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
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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":
|
package/tests/integration.sh
CHANGED
|
@@ -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
|
-
|
|
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/'`
|