@fraczak/k 6.5.0 → 6.7.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/backends/arm64/README.md +0 -1
- package/backends/arm64/bin/k-arm64-compile.mjs +0 -8
- package/backends/arm64/src/runtime.c +20 -4
- package/backends/arm64/tests/integration.sh +1 -1
- package/backends/llvm/README.md +13 -11
- package/backends/llvm/bin/k-llvm-build.mjs +40 -38
- package/backends/llvm/bin/k-llvm-compile.mjs +42 -32
- package/backends/llvm/runtime/krt.c +387 -2
- package/backends/llvm/runtime/krt.h +1 -0
- package/backends/llvm/src/cli.mjs +153 -0
- package/backends/llvm/src/executable.mjs +1 -1
- package/backends/llvm/src/kvm2llvm.mjs +109 -30
- package/backends/llvm/tests/integration.sh +18 -22
- package/backends/llvm/tests/perf-support.mjs +1 -1
- package/backends/wasm/bin/k-wasm-compile.mjs +19 -4
- package/browser/repl-browser.mjs +24 -7
- package/browser/tree-view.mjs +599 -0
- package/package.json +1 -1
- package/repl.mjs +4 -0
- package/scripts/build-repl-html.mjs +301 -0
- package/scripts/perf-ieee.mjs +5 -2
- package/scripts/perf-int.mjs +331 -0
- package/scripts/run-tests.mjs +1 -0
- package/tests/test-repl-html.mjs +141 -0
- package/tests/test-tree-view.mjs +185 -0
package/backends/arm64/README.md
CHANGED
|
@@ -78,7 +78,6 @@ All tools accept `--help`.
|
|
|
78
78
|
|
|
79
79
|
- `-S, --assembly`: Emit GNU ARM64 assembly text (`.s`) instead of an ELF binary.
|
|
80
80
|
- `-o, --output <file>`: Specify the output file path.
|
|
81
|
-
- `--entry <name>`: Specify the entry relation (defaults to `__main__`).
|
|
82
81
|
- `--lib <file>`: Load one `.klib` or `.k` library dependency.
|
|
83
82
|
- `--export <spec>`: Export library symbols into source scope (`name` or `libname:localname`).
|
|
84
83
|
- `--json`: Format output as JSON instead of binary wire format.
|
|
@@ -22,7 +22,6 @@ function usage(stream = console.error) {
|
|
|
22
22
|
stream("Options:");
|
|
23
23
|
stream(" -S, --assembly Emit GNU ARM64 assembly (.s) instead of an executable binary.");
|
|
24
24
|
stream(" -o, --output Specify output file path explicitly.");
|
|
25
|
-
stream(" --entry name Specify entry relation name.");
|
|
26
25
|
stream(" --lib file Load one .klib dependency before compiling.");
|
|
27
26
|
stream(" --export spec Export a library alias into source scope. May be repeated.");
|
|
28
27
|
stream(" spec is 'name' or 'libname:localname'.");
|
|
@@ -38,8 +37,6 @@ try {
|
|
|
38
37
|
|
|
39
38
|
let emitAssembly = false;
|
|
40
39
|
let explicitOutput = null;
|
|
41
|
-
let entry = null;
|
|
42
|
-
|
|
43
40
|
// Extract ARM64-specific flags
|
|
44
41
|
const remainingArgs = [];
|
|
45
42
|
while (args.length > 0) {
|
|
@@ -51,10 +48,6 @@ try {
|
|
|
51
48
|
args.shift();
|
|
52
49
|
explicitOutput = args.shift();
|
|
53
50
|
if (!explicitOutput) throw new Error("-o/--output requires a file argument");
|
|
54
|
-
} else if (arg === "--entry") {
|
|
55
|
-
args.shift();
|
|
56
|
-
entry = args.shift();
|
|
57
|
-
if (!entry) throw new Error("--entry requires a name argument");
|
|
58
51
|
} else {
|
|
59
52
|
remainingArgs.push(args.shift());
|
|
60
53
|
}
|
|
@@ -71,7 +64,6 @@ try {
|
|
|
71
64
|
libraries,
|
|
72
65
|
exportSpecs,
|
|
73
66
|
stdin,
|
|
74
|
-
entry,
|
|
75
67
|
emit: emitAssembly ? "assembly" : null,
|
|
76
68
|
outputPath: (!emitAssembly && outputPath) ? outputPath : null
|
|
77
69
|
});
|
|
@@ -5,7 +5,21 @@
|
|
|
5
5
|
#include <string.h>
|
|
6
6
|
#include <time.h>
|
|
7
7
|
|
|
8
|
-
#define
|
|
8
|
+
#define DEFAULT_ARENA_CAPACITY (256 * 1024 * 1024)
|
|
9
|
+
|
|
10
|
+
static int parse_size_arg(const char *text, size_t *out);
|
|
11
|
+
|
|
12
|
+
static size_t get_arena_capacity(void) {
|
|
13
|
+
const char *env = getenv("K_ARENA_CAPACITY_MB");
|
|
14
|
+
if (!env || !*env) env = getenv("K_ARENA_MB");
|
|
15
|
+
if (env && *env) {
|
|
16
|
+
size_t mb = 0;
|
|
17
|
+
if (parse_size_arg(env, &mb) && mb > 0) {
|
|
18
|
+
return mb * 1024 * 1024;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return DEFAULT_ARENA_CAPACITY;
|
|
22
|
+
}
|
|
9
23
|
|
|
10
24
|
typedef enum {
|
|
11
25
|
K_VALUE_UNIT,
|
|
@@ -601,8 +615,10 @@ static int run_bench_main(void *arena_mem, const char *count_text) {
|
|
|
601
615
|
int main(int argc, char **argv) {
|
|
602
616
|
init_tag_registry();
|
|
603
617
|
|
|
618
|
+
size_t arena_capacity = get_arena_capacity();
|
|
619
|
+
|
|
604
620
|
if (argc == 2 && strcmp(argv[1], "--server") == 0) {
|
|
605
|
-
void *arena_mem = malloc(
|
|
621
|
+
void *arena_mem = malloc(arena_capacity);
|
|
606
622
|
if (!arena_mem) return 1;
|
|
607
623
|
int rc = run_server(arena_mem);
|
|
608
624
|
free(arena_mem);
|
|
@@ -610,7 +626,7 @@ int main(int argc, char **argv) {
|
|
|
610
626
|
}
|
|
611
627
|
|
|
612
628
|
if (argc == 3 && strcmp(argv[1], "--bench-main") == 0) {
|
|
613
|
-
void *arena_mem = malloc(
|
|
629
|
+
void *arena_mem = malloc(arena_capacity);
|
|
614
630
|
if (!arena_mem) return 1;
|
|
615
631
|
int rc = run_bench_main(arena_mem, argv[2]);
|
|
616
632
|
free(arena_mem);
|
|
@@ -647,7 +663,7 @@ int main(int argc, char **argv) {
|
|
|
647
663
|
}
|
|
648
664
|
}
|
|
649
665
|
|
|
650
|
-
void *arena_mem = malloc(
|
|
666
|
+
void *arena_mem = malloc(arena_capacity);
|
|
651
667
|
if (!arena_mem) {
|
|
652
668
|
if (in_fp != stdin) fclose(in_fp);
|
|
653
669
|
return 1;
|
|
@@ -105,7 +105,7 @@ node "$K_ROOT/backends/arm64/bin/k-arm64-compile.mjs" \
|
|
|
105
105
|
'{succ int x,int y}+' \
|
|
106
106
|
-o "$TMP_DIR/lib-add"
|
|
107
107
|
|
|
108
|
-
node "$K_ROOT/codecs/k-parse.mjs" <<< '{"x":{"
|
|
108
|
+
node "$K_ROOT/codecs/k-parse.mjs" <<< '{"x":{"0":"_"},"y":{"+":{"0":"_"}}}' |
|
|
109
109
|
"$TMP_DIR/lib-add" --json |
|
|
110
110
|
grep -Fxq '{"+":{"1":"_"}}'
|
|
111
111
|
|
package/backends/llvm/README.md
CHANGED
|
@@ -23,7 +23,7 @@ backend from `backends/llvm`:
|
|
|
23
23
|
npm install
|
|
24
24
|
cd backends/llvm
|
|
25
25
|
node ../../objects/compile.mjs '()' /tmp/id.ko
|
|
26
|
-
node ./bin/k-llvm-compile.mjs
|
|
26
|
+
node ./bin/k-llvm-compile.mjs /tmp/id.ko /tmp/id.ll
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
The generated `.ll` embeds the envelope-specialized KIR-P contract as module
|
|
@@ -44,24 +44,26 @@ status in `k_result`. These operations can compose through KIR `comp`.
|
|
|
44
44
|
## CLI
|
|
45
45
|
|
|
46
46
|
```sh
|
|
47
|
-
k-llvm-build [options]
|
|
48
|
-
k-llvm-compile [options]
|
|
47
|
+
k-llvm-build [options] [source-snippet | input-file [output-exe]]
|
|
48
|
+
k-llvm-compile [options] [source-snippet | input-file [output.ll]]
|
|
49
49
|
k-llvm-jit [options] object.ko
|
|
50
50
|
k-llvm-run [options] object.ko [input.kv]
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Options:
|
|
54
54
|
|
|
55
|
-
-
|
|
56
|
-
|
|
57
|
-
- `--
|
|
58
|
-
|
|
59
|
-
- `--
|
|
60
|
-
|
|
55
|
+
- `-o, --output path`: specify output file path explicitly.
|
|
56
|
+
- `--lib file`: load one `.klib` or `.k` dependency before compiling.
|
|
57
|
+
- `--export spec`: export a library alias into source scope (`name` or `libname:localname`). May be repeated.
|
|
58
|
+
- `--input-pattern json-or-file`: for `k-llvm-run`, KIR property-list input pattern.
|
|
59
|
+
- `--retype rel`: for `k-llvm-run`, relation to specialize (defaults to object main).
|
|
60
|
+
- `--expect value-or-file`: for `k-llvm-run`, compare the output value against expected value text.
|
|
61
61
|
- `-h`, `--help`: show usage.
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
The compile commands follow the unified k CLI input convention: pass inline
|
|
64
|
+
source, an existing `.k` source file, or a `.ko`/`.klib` object. Reads UTF-8
|
|
65
|
+
source from stdin when input is omitted. Output paths can be specified as a
|
|
66
|
+
positional argument or explicitly with `-o, --output`.
|
|
65
67
|
Without `--expect`, `k-llvm-run` prints the result value as compact JSON.
|
|
66
68
|
`k-llvm-build` emits a native executable that reads and writes the binary
|
|
67
69
|
k pattern+value envelope used by `codecs/k-parse.mjs` and `codecs/k-print.mjs`.
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import { argv, exit, stdin } from "node:process";
|
|
4
|
+
import {
|
|
5
|
+
compileProgramInputToObject,
|
|
6
|
+
parseCompileOptions,
|
|
7
|
+
resolveProgramInput
|
|
8
|
+
} from "../src/cli.mjs";
|
|
6
9
|
import { compileObjectToExecutable } from "../src/executable.mjs";
|
|
7
10
|
|
|
8
11
|
function usage(stream = console.error) {
|
|
9
12
|
const prog = argv[1] || "k-llvm-build.mjs";
|
|
10
|
-
stream(`Usage: node ${prog} [options]
|
|
11
|
-
stream("Compile
|
|
13
|
+
stream(`Usage: node ${prog} [options] [source-snippet | input-file [output-exe]]`);
|
|
14
|
+
stream("Compile k source, .ko, or .klib input into a native executable.");
|
|
15
|
+
stream("");
|
|
16
|
+
stream("Arguments:");
|
|
17
|
+
stream(" source-snippet Inline k source, in the same style as k.mjs.");
|
|
18
|
+
stream(" input-file Source .k, .ko, or .klib file. Reads UTF-8 source from stdin when omitted.");
|
|
19
|
+
stream(" output-exe Output executable path.");
|
|
12
20
|
stream("");
|
|
13
21
|
stream("The executable reads a binary k pattern+value envelope from stdin and");
|
|
14
22
|
stream("writes a binary k pattern+value envelope to stdout.");
|
|
@@ -16,18 +24,11 @@ function usage(stream = console.error) {
|
|
|
16
24
|
stream("stdout is encoded with the compiled output pattern.");
|
|
17
25
|
stream("");
|
|
18
26
|
stream("Options:");
|
|
19
|
-
stream(" --
|
|
20
|
-
stream(" --
|
|
21
|
-
stream("
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
function readMaybeFile(textOrPath) {
|
|
25
|
-
return fs.existsSync(textOrPath) ? fs.readFileSync(textOrPath, "utf8") : textOrPath;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function readPattern(inputPattern) {
|
|
29
|
-
if (inputPattern == null) return null;
|
|
30
|
-
return JSON.parse(readMaybeFile(inputPattern));
|
|
27
|
+
stream(" -o, --output path Specify output file path explicitly.");
|
|
28
|
+
stream(" --lib file Load one .klib dependency before compiling.");
|
|
29
|
+
stream(" --export spec Export a library alias into source scope. May be repeated.");
|
|
30
|
+
stream(" spec is 'name' or 'libname:localname'.");
|
|
31
|
+
stream(" -h, --help Show this help.");
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
try {
|
|
@@ -37,33 +38,34 @@ try {
|
|
|
37
38
|
exit(0);
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
while (args.length > 0
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
inputPattern = args.shift();
|
|
49
|
-
if (!inputPattern) throw new Error("--input-pattern requires JSON or a file path");
|
|
41
|
+
let explicitOutput = null;
|
|
42
|
+
const remainingArgs = [];
|
|
43
|
+
while (args.length > 0) {
|
|
44
|
+
const arg = args[0];
|
|
45
|
+
if (arg === "-o" || arg === "--output") {
|
|
46
|
+
args.shift();
|
|
47
|
+
explicitOutput = args.shift();
|
|
48
|
+
if (!explicitOutput) throw new Error("-o/--output requires a file argument");
|
|
50
49
|
} else {
|
|
51
|
-
|
|
50
|
+
remainingArgs.push(args.shift());
|
|
52
51
|
}
|
|
53
52
|
}
|
|
54
53
|
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
const { libraries, exportSpecs } = parseCompileOptions(remainingArgs);
|
|
55
|
+
const input = resolveProgramInput(remainingArgs, { allowStdinSource: true });
|
|
56
|
+
const positionalOutput = remainingArgs.shift();
|
|
57
|
+
if (remainingArgs.length > 0) throw new Error("Too many arguments");
|
|
58
|
+
|
|
59
|
+
const outputPath = explicitOutput || positionalOutput || null;
|
|
60
|
+
if (outputPath == null) throw new Error("Output executable path is required (pass output-exe or -o/--output)");
|
|
61
61
|
|
|
62
|
-
const object =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
const object = await compileProgramInputToObject(input, {
|
|
63
|
+
libraries,
|
|
64
|
+
exportSpecs,
|
|
65
|
+
stdin
|
|
66
66
|
});
|
|
67
|
+
|
|
68
|
+
compileObjectToExecutable(object, outputPath);
|
|
67
69
|
} catch (error) {
|
|
68
70
|
console.error(error.stack || error.message || String(error));
|
|
69
71
|
usage();
|
|
@@ -2,29 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import { argv, exit, stdin, stdout } from "node:process";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
compileProgramInputToObject,
|
|
7
|
+
parseCompileOptions,
|
|
8
|
+
resolveProgramInput
|
|
9
|
+
} from "../src/cli.mjs";
|
|
10
|
+
import { compileObjectToLLVM } from "../src/llvm.mjs";
|
|
11
|
+
import { inputPatternForObjectRelation } from "../src/executable.mjs";
|
|
6
12
|
|
|
7
13
|
function usage(stream = console.error) {
|
|
8
14
|
const prog = argv[1] || "k-llvm-compile.mjs";
|
|
9
|
-
stream(`Usage: node ${prog} [options]
|
|
15
|
+
stream(`Usage: node ${prog} [options] [source-snippet | input-file [output.ll]]`);
|
|
10
16
|
stream("Compile a k .ko/.klib object into prototype LLVM IR.");
|
|
11
17
|
stream("");
|
|
12
18
|
stream("Arguments:");
|
|
13
|
-
stream("
|
|
19
|
+
stream(" source-snippet Inline k source, in the same style as k.mjs.");
|
|
20
|
+
stream(" input-file Source .k, .ko, or .klib file. Reads UTF-8 source from stdin when omitted.");
|
|
14
21
|
stream(" output.ll Output LLVM IR path. Writes to stdout when omitted.");
|
|
15
22
|
stream("");
|
|
16
23
|
stream("Options:");
|
|
17
|
-
stream(" --
|
|
18
|
-
stream(" --
|
|
19
|
-
stream("
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
async function readStdinBytes() {
|
|
23
|
-
const chunks = [];
|
|
24
|
-
for await (const chunk of stdin) {
|
|
25
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
26
|
-
}
|
|
27
|
-
return Buffer.concat(chunks);
|
|
24
|
+
stream(" -o, --output path Specify output file path explicitly.");
|
|
25
|
+
stream(" --lib file Load one .klib dependency before compiling.");
|
|
26
|
+
stream(" --export spec Export a library alias into source scope. May be repeated.");
|
|
27
|
+
stream(" spec is 'name' or 'libname:localname'.");
|
|
28
|
+
stream(" -h, --help Show this help.");
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
try {
|
|
@@ -34,32 +35,41 @@ try {
|
|
|
34
35
|
exit(0);
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
let
|
|
38
|
-
|
|
39
|
-
while (args.length > 0
|
|
40
|
-
const
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
inputPattern = args.shift();
|
|
46
|
-
if (!inputPattern) throw new Error("--input-pattern requires JSON or a file path");
|
|
38
|
+
let explicitOutput = null;
|
|
39
|
+
const remainingArgs = [];
|
|
40
|
+
while (args.length > 0) {
|
|
41
|
+
const arg = args[0];
|
|
42
|
+
if (arg === "-o" || arg === "--output") {
|
|
43
|
+
args.shift();
|
|
44
|
+
explicitOutput = args.shift();
|
|
45
|
+
if (!explicitOutput) throw new Error("-o/--output requires a file argument");
|
|
47
46
|
} else {
|
|
48
|
-
|
|
47
|
+
remainingArgs.push(args.shift());
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
|
-
if (inputPattern == null) throw new Error("--input-pattern is required");
|
|
52
50
|
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
|
|
51
|
+
const { libraries, exportSpecs } = parseCompileOptions(remainingArgs);
|
|
52
|
+
const input = resolveProgramInput(remainingArgs, { allowStdinSource: true });
|
|
53
|
+
const positionalOutput = remainingArgs.shift();
|
|
54
|
+
if (remainingArgs.length > 0) throw new Error("Too many arguments");
|
|
55
|
+
|
|
56
|
+
const outputPath = explicitOutput || positionalOutput || null;
|
|
57
|
+
|
|
58
|
+
const object = await compileProgramInputToObject(input, {
|
|
59
|
+
libraries,
|
|
60
|
+
exportSpecs,
|
|
61
|
+
stdin
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const { llvm } = compileObjectToLLVM(object, {
|
|
65
|
+
relation: object.main,
|
|
66
|
+
inputPattern: inputPatternForObjectRelation(object, object.main)
|
|
67
|
+
});
|
|
56
68
|
|
|
57
|
-
const input = inputPath == null ? await readStdinBytes() : fs.readFileSync(inputPath);
|
|
58
|
-
const { llvm } = compileBufferToLLVM(input, { relation, inputPattern });
|
|
59
69
|
if (outputPath == null) {
|
|
60
70
|
stdout.write(llvm);
|
|
61
71
|
} else {
|
|
62
|
-
fs.writeFileSync(outputPath, llvm);
|
|
72
|
+
fs.writeFileSync(outputPath, llvm, "utf8");
|
|
63
73
|
}
|
|
64
74
|
} catch (error) {
|
|
65
75
|
console.error(error.stack || error.message || String(error));
|