@fraczak/k 7.0.1 → 7.1.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/CHANGELOG.md +78 -0
- package/DOCS/BIG_PICTURE.md +5 -5
- package/DOCS/FILE_FORMATS.md +241 -18
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +9 -9
- package/DOCS/PATTERNS.md +3 -3
- package/DOCS/POLYMORPHIC_IR.md +104 -0
- package/DOCS/PROFILING_AND_TRACING.md +60 -72
- package/DOCS/REPL.md +3 -3
- package/DOCS/book/03-types-as-finite-automata.md +4 -4
- package/DOCS/book/06-values-in-memory.md +9 -9
- package/DOCS/book/08-operational-semantics-and-execution.md +1 -1
- package/DOCS/book/09-compiler-architecture.md +2 -2
- package/DOCS/book/10-from-ast-to-intermediate-representation.md +2 -2
- package/DOCS/book/14-canonical-serialization.md +1 -1
- package/Examples/arithmetics.k +2 -2
- package/Examples/bnat.k +1 -1
- package/Examples/karatsuba-mult.k +2 -2
- package/JOURNAL.md +288 -0
- package/README.md +13 -10
- package/access-table.mjs +343 -0
- package/backend-api.mjs +18 -0
- package/backends/llvm/README.md +20 -21
- package/backends/llvm/bin/k-llvm-build.mjs +105 -32
- package/backends/llvm/bin/k-llvm-compile.mjs +63 -24
- package/backends/llvm/bin/k-llvm.mjs +292 -0
- package/backends/llvm/runtime/krt.c +41 -0
- package/backends/llvm/runtime/krt.h +2 -0
- package/backends/llvm/src/cli.mjs +95 -17
- package/backends/llvm/src/executable.mjs +132 -15
- package/backends/llvm/src/kvm2llvm.mjs +50 -23
- package/backends/llvm/src/llvm.mjs +133 -20
- package/backends/llvm/tests/integration.sh +11 -11
- package/backends/llvm/{bin → tests}/k-llvm-run.mjs +48 -22
- package/backends/llvm/tests/perf-support.mjs +25 -58
- package/backends/llvm/tests/test-llvm.mjs +25 -4
- package/backends/wasm/bin/k-wasm-compile.mjs +46 -20
- package/backends/wasm/bin/k-wasm-run.mjs +61 -20
- package/backends/wasm/bin/k-wasm.mjs +47 -13
- package/backends/wasm/src/cli.mjs +141 -19
- package/backends/wasm/src/wasm.mjs +132 -24
- package/backends/wasm/tests/test-wasm.mjs +5 -5
- package/browser/repl-browser.mjs +16 -5
- package/browser/vfs-data.mjs +5 -5
- package/codecs/k-parse.mjs +29 -8
- package/codecs/k-print.mjs +22 -6
- package/codecs/runtime/codec-sdk.mjs +8 -4
- package/codecs/show.mjs +20 -6
- package/core.k +8 -8
- package/harness/format.mjs +2 -2
- package/harness/registry.mjs +0 -2
- package/k.mjs +56 -16
- package/kir.mjs +200 -75
- package/kvm.mjs +49 -12
- package/objects/compile.mjs +37 -23
- package/objects/decompile.mjs +40 -10
- package/objects/extract-aliases.mjs +44 -14
- package/objects/inspect.mjs +19 -14
- package/objects/validate.mjs +18 -11
- package/package.json +10 -7
- package/pkir.mjs +772 -0
- package/repl.mjs +36 -18
- package/scripts/benchmark-idempotency.mjs +12 -8
- package/scripts/benchmark.mjs +5 -9
- package/scripts/build-repl-html.mjs +16 -4
- package/scripts/perf-ieee.mjs +253 -103
- package/scripts/perf-int.mjs +585 -297
- package/scripts/perf-multiplication.mjs +66 -25
- package/scripts/perf-poly.mjs +292 -164
- package/scripts/run-tests.mjs +3 -0
- package/tests/code-derivation/pattern-envelope.mjs +4 -4
- package/tests/test-access-table.mjs +213 -0
- package/tests/test-kvm-polymorphic.mjs +2 -2
- package/tests/test-pkir.mjs +530 -0
- package/tests/test-polymorphic-tdd.mjs +196 -0
- package/tests/test-repl-html.mjs +15 -2
- package/tests/test-repl.mjs +30 -1
- package/backends/arm64/README.md +0 -103
- package/backends/arm64/bin/k-arm64-compile.mjs +0 -93
- package/backends/arm64/bin/k-arm64-run.mjs +0 -58
- package/backends/arm64/bin/k-arm64.mjs +0 -88
- package/backends/arm64/scripts/run-tests.mjs +0 -57
- package/backends/arm64/src/arm64.mjs +0 -229
- package/backends/arm64/src/cli.mjs +0 -155
- package/backends/arm64/src/kvm2arm64.mjs +0 -906
- package/backends/arm64/src/runtime.c +0 -744
- package/backends/arm64/tests/integration.sh +0 -112
- package/backends/arm64/tests/test-arm64.mjs +0 -240
- package/backends/llvm/bin/k-llvm-jit.mjs +0 -160
- package/harness/adapters/arm64.mjs +0 -105
|
@@ -1,26 +1,112 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
compileLibrary,
|
|
6
|
+
decodeObject,
|
|
7
|
+
loadLibrary
|
|
8
|
+
} from "@fraczak/k/backend-api.mjs";
|
|
5
9
|
import {
|
|
6
10
|
compileWasmArtifact,
|
|
7
11
|
compileWasmArtifactFromKVM,
|
|
8
|
-
compileWasmArtifactFromObject
|
|
12
|
+
compileWasmArtifactFromObject,
|
|
13
|
+
compileWasmArtifactFromPKIR
|
|
9
14
|
} from "./wasm.mjs";
|
|
10
15
|
|
|
11
16
|
function readAll(stream) {
|
|
12
17
|
return new Promise((resolve, reject) => {
|
|
13
18
|
const chunks = [];
|
|
14
|
-
stream.on("data", (chunk) =>
|
|
19
|
+
stream.on("data", (chunk) => {
|
|
20
|
+
chunks.push(
|
|
21
|
+
Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
|
|
22
|
+
);
|
|
23
|
+
});
|
|
15
24
|
stream.on("end", () => resolve(Buffer.concat(chunks)));
|
|
16
25
|
stream.on("error", reject);
|
|
17
26
|
});
|
|
18
27
|
}
|
|
19
28
|
|
|
29
|
+
export function buildExportPreamble(exports = [], libraries = []) {
|
|
30
|
+
if (exports.length === 0) return "";
|
|
31
|
+
const aliasMap = {};
|
|
32
|
+
for (const lib of libraries) {
|
|
33
|
+
for (const [name, hash] of Object.entries(lib.relAlias || {})) {
|
|
34
|
+
if (name !== "__main__") aliasMap[name] = hash;
|
|
35
|
+
}
|
|
36
|
+
for (const [hash, entry] of Object.entries(lib.meta || {})) {
|
|
37
|
+
if (entry?.type !== "rel") continue;
|
|
38
|
+
for (const origin of entry?.origins || []) {
|
|
39
|
+
if (origin?.name && origin.name !== "__main__") {
|
|
40
|
+
aliasMap[origin.name] = hash;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const lines = [];
|
|
46
|
+
for (const spec of exports) {
|
|
47
|
+
const [libName, localName] = spec.includes(":")
|
|
48
|
+
? spec.split(":", 2)
|
|
49
|
+
: [spec, spec];
|
|
50
|
+
const hash = aliasMap[libName];
|
|
51
|
+
if (!hash) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`--export: '${libName}' not found in loaded libraries`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
const body = hash.startsWith("@") ? hash.slice(1) : hash;
|
|
57
|
+
lines.push(`${localName} = @${body};`);
|
|
58
|
+
}
|
|
59
|
+
return lines.join("\n") + "\n";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function loadLibraryFromPath(libPath) {
|
|
63
|
+
const ext = path.extname(libPath).toLowerCase();
|
|
64
|
+
if (ext === ".klib" || ext === ".ko") {
|
|
65
|
+
return loadLibrary(decodeObject(fs.readFileSync(libPath)));
|
|
66
|
+
}
|
|
67
|
+
if (ext === ".k") {
|
|
68
|
+
let depLibs = [];
|
|
69
|
+
const baseName = path.basename(libPath);
|
|
70
|
+
if (baseName === "poly.k") {
|
|
71
|
+
const dir = path.dirname(libPath);
|
|
72
|
+
const arithPath = path.join(dir, "arithmetics.k");
|
|
73
|
+
if (fs.existsSync(arithPath)) {
|
|
74
|
+
const arithLib = loadLibrary(
|
|
75
|
+
compileLibrary(fs.readFileSync(arithPath, "utf8"), {
|
|
76
|
+
source: arithPath
|
|
77
|
+
})
|
|
78
|
+
);
|
|
79
|
+
depLibs.push(arithLib);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const rawSource = fs.readFileSync(libPath, "utf8");
|
|
83
|
+
if (depLibs.length > 0) {
|
|
84
|
+
const neededExports = [
|
|
85
|
+
"0", "int", "inc", "dec", "nat", "zero_int?", "neg?", "GT"
|
|
86
|
+
];
|
|
87
|
+
const preamble = buildExportPreamble(neededExports, depLibs);
|
|
88
|
+
const compiled = compileLibrary(preamble + rawSource, {
|
|
89
|
+
source: libPath,
|
|
90
|
+
libraries: depLibs
|
|
91
|
+
});
|
|
92
|
+
const mergedLib = loadLibrary(compiled);
|
|
93
|
+
for (const dep of depLibs) {
|
|
94
|
+
for (const [k, v] of Object.entries(dep.relAlias || {})) {
|
|
95
|
+
if (!mergedLib.relAlias[k]) mergedLib.relAlias[k] = v;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return mergedLib;
|
|
99
|
+
}
|
|
100
|
+
return loadLibrary(compileLibrary(rawSource, { source: libPath }));
|
|
101
|
+
}
|
|
102
|
+
throw new Error(`Unsupported library extension: ${ext}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
20
105
|
function parseCompileOptions(args) {
|
|
21
106
|
const libraries = [];
|
|
22
107
|
const exportSpecs = [];
|
|
23
108
|
let loadedLibrary = false;
|
|
109
|
+
let usePKIR = false;
|
|
24
110
|
|
|
25
111
|
while (args.length > 0) {
|
|
26
112
|
if (args[0] === "--") {
|
|
@@ -28,25 +114,34 @@ function parseCompileOptions(args) {
|
|
|
28
114
|
break;
|
|
29
115
|
}
|
|
30
116
|
if (args[0] === "--lib") {
|
|
31
|
-
if (loadedLibrary)
|
|
117
|
+
if (loadedLibrary) {
|
|
118
|
+
throw new Error("--lib may only be specified once");
|
|
119
|
+
}
|
|
32
120
|
args.shift();
|
|
33
121
|
const libPath = args.shift();
|
|
34
122
|
if (!libPath) throw new Error("--lib requires a file argument");
|
|
35
|
-
libraries.push(
|
|
123
|
+
libraries.push(loadLibraryFromPath(libPath));
|
|
36
124
|
loadedLibrary = true;
|
|
37
125
|
} else if (args[0] === "--export") {
|
|
38
126
|
args.shift();
|
|
39
127
|
const spec = args.shift();
|
|
40
|
-
if (!spec)
|
|
128
|
+
if (!spec) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
"--export requires a spec argument (name or libname:localname)"
|
|
131
|
+
);
|
|
132
|
+
}
|
|
41
133
|
exportSpecs.push(spec);
|
|
134
|
+
} else if (args[0] === "--pkir") {
|
|
135
|
+
args.shift();
|
|
136
|
+
usePKIR = true;
|
|
42
137
|
} else if (args[0].startsWith("--")) {
|
|
43
|
-
|
|
138
|
+
break;
|
|
44
139
|
} else {
|
|
45
140
|
break;
|
|
46
141
|
}
|
|
47
142
|
}
|
|
48
143
|
|
|
49
|
-
return { libraries, exportSpecs };
|
|
144
|
+
return { libraries, exportSpecs, usePKIR };
|
|
50
145
|
}
|
|
51
146
|
|
|
52
147
|
function fileInputType(filePath) {
|
|
@@ -54,6 +149,7 @@ function fileInputType(filePath) {
|
|
|
54
149
|
if (ext === ".ko") return "ko";
|
|
55
150
|
if (ext === ".kvm") return "kvm";
|
|
56
151
|
if (ext === ".klib") return "klib";
|
|
152
|
+
if (ext === ".pkir") return "pkir";
|
|
57
153
|
return "source-file";
|
|
58
154
|
}
|
|
59
155
|
|
|
@@ -68,38 +164,55 @@ function resolveProgramInput(args, { allowStdinSource = false } = {}) {
|
|
|
68
164
|
if (fs.existsSync(inputArg)) {
|
|
69
165
|
const kind = fileInputType(inputArg);
|
|
70
166
|
if (kind === "klib") {
|
|
71
|
-
throw new Error(
|
|
167
|
+
throw new Error(
|
|
168
|
+
"Cannot compile a .klib library to WebAssembly without a main " +
|
|
169
|
+
"relation; load it with --lib."
|
|
170
|
+
);
|
|
72
171
|
}
|
|
73
172
|
return { kind, path: inputArg, sourceName: inputArg };
|
|
74
173
|
}
|
|
75
174
|
|
|
76
|
-
if ([".k", ".ko", ".kvm", ".klib", ".wasm"].includes(ext)) {
|
|
175
|
+
if ([".k", ".ko", ".kvm", ".klib", ".wasm", ".pkir"].includes(ext)) {
|
|
77
176
|
throw new Error(`Input file not found: ${inputArg}`);
|
|
78
177
|
}
|
|
79
178
|
|
|
80
|
-
return {
|
|
179
|
+
return {
|
|
180
|
+
kind: "inline-source",
|
|
181
|
+
source: inputArg,
|
|
182
|
+
sourceName: "<inline>"
|
|
183
|
+
};
|
|
81
184
|
}
|
|
82
185
|
|
|
83
186
|
async function compileProgramInput(
|
|
84
187
|
input,
|
|
85
|
-
{
|
|
188
|
+
{
|
|
189
|
+
libraries = [],
|
|
190
|
+
exportSpecs = [],
|
|
191
|
+
stdin = null,
|
|
192
|
+
inputEnvelopePattern = null,
|
|
193
|
+
usePKIR = false
|
|
194
|
+
} = {}
|
|
86
195
|
) {
|
|
87
196
|
if (input.kind === "inline-source") {
|
|
88
197
|
return compileWasmArtifact(input.source, {
|
|
89
198
|
libraries,
|
|
90
199
|
exports: exportSpecs,
|
|
91
200
|
source: input.sourceName,
|
|
92
|
-
inputEnvelopePattern
|
|
201
|
+
inputEnvelopePattern,
|
|
202
|
+
usePKIR
|
|
93
203
|
});
|
|
94
204
|
}
|
|
95
205
|
|
|
96
206
|
if (input.kind === "stdin-source") {
|
|
97
|
-
if (!stdin)
|
|
207
|
+
if (!stdin) {
|
|
208
|
+
throw new Error("stdin source requested without a stdin stream");
|
|
209
|
+
}
|
|
98
210
|
return compileWasmArtifact((await readAll(stdin)).toString("utf8"), {
|
|
99
211
|
libraries,
|
|
100
212
|
exports: exportSpecs,
|
|
101
213
|
source: input.sourceName,
|
|
102
|
-
inputEnvelopePattern
|
|
214
|
+
inputEnvelopePattern,
|
|
215
|
+
usePKIR
|
|
103
216
|
});
|
|
104
217
|
}
|
|
105
218
|
|
|
@@ -108,18 +221,27 @@ async function compileProgramInput(
|
|
|
108
221
|
libraries,
|
|
109
222
|
exports: exportSpecs,
|
|
110
223
|
source: input.sourceName,
|
|
111
|
-
inputEnvelopePattern
|
|
224
|
+
inputEnvelopePattern,
|
|
225
|
+
usePKIR
|
|
112
226
|
});
|
|
113
227
|
}
|
|
114
228
|
|
|
115
229
|
if (input.kind === "ko") {
|
|
116
|
-
|
|
117
|
-
|
|
230
|
+
const obj = decodeObject(fs.readFileSync(input.path));
|
|
231
|
+
return compileWasmArtifactFromObject(obj, {
|
|
232
|
+
inputEnvelopePattern,
|
|
233
|
+
usePKIR
|
|
118
234
|
});
|
|
119
235
|
}
|
|
120
236
|
|
|
237
|
+
if (input.kind === "pkir") {
|
|
238
|
+
const pkir = JSON.parse(fs.readFileSync(input.path, "utf8"));
|
|
239
|
+
return compileWasmArtifactFromPKIR(pkir);
|
|
240
|
+
}
|
|
241
|
+
|
|
121
242
|
if (input.kind === "kvm") {
|
|
122
|
-
|
|
243
|
+
const kvm = JSON.parse(fs.readFileSync(input.path, "utf8"));
|
|
244
|
+
return compileWasmArtifactFromKVM(kvm);
|
|
123
245
|
}
|
|
124
246
|
|
|
125
247
|
throw new Error(`Unsupported input kind: ${input.kind}`);
|
|
@@ -14,7 +14,9 @@ import {
|
|
|
14
14
|
propertyListToPattern,
|
|
15
15
|
Value,
|
|
16
16
|
specializeKVM,
|
|
17
|
-
specializeObjectRelations
|
|
17
|
+
specializeObjectRelations,
|
|
18
|
+
compileRelationToPKIR,
|
|
19
|
+
lowerPKIRToKVM
|
|
18
20
|
} from "@fraczak/k/backend-api.mjs";
|
|
19
21
|
import { intersectPropertyListPatterns } from "@fraczak/k/codecs/runtime/codec.mjs";
|
|
20
22
|
import { propertyListToFilter } from "@fraczak/k/codecs/runtime/show-value.mjs";
|
|
@@ -283,7 +285,7 @@ function cloneKVMFunction(kvmFunc) {
|
|
|
283
285
|
};
|
|
284
286
|
}
|
|
285
287
|
|
|
286
|
-
function compileModule(mainRelName, defs) {
|
|
288
|
+
function compileModule(mainRelName, defs, { usePKIR = false } = {}) {
|
|
287
289
|
const compiled = new Set();
|
|
288
290
|
const queue = [mainRelName];
|
|
289
291
|
const wats = [];
|
|
@@ -299,8 +301,14 @@ function compileModule(mainRelName, defs) {
|
|
|
299
301
|
throw new Error(`Relation ${name} not found`);
|
|
300
302
|
}
|
|
301
303
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
+
let kvmFunc;
|
|
305
|
+
if (usePKIR) {
|
|
306
|
+
const pkir = compileRelationToPKIR(relDef, name);
|
|
307
|
+
kvmFunc = lowerPKIRToKVM(pkir);
|
|
308
|
+
} else {
|
|
309
|
+
kvmFunc = lowerToKVM(relDef, name);
|
|
310
|
+
kvmFunc.typePatternGraph = relDef.typePatternGraph;
|
|
311
|
+
}
|
|
304
312
|
scanCalls(kvmFunc.body, compiled, queue);
|
|
305
313
|
|
|
306
314
|
kvmFunc.name = nameMap.get(name) || cleanName(name);
|
|
@@ -439,7 +447,8 @@ function relTypeStatus(defs, name) {
|
|
|
439
447
|
const rel = defs.rels?.[name];
|
|
440
448
|
const explicit = rel?.typeDerivation?.status;
|
|
441
449
|
if (explicit) return explicit;
|
|
442
|
-
const
|
|
450
|
+
const stats = compileStatsByRelName(defs.compileStats);
|
|
451
|
+
const scc = stats.get(name) || (name.includes("$") ? stats.get(name.split("$")[0]) : null);
|
|
443
452
|
if (scc) return scc.converged ? "converged" : "not-converged";
|
|
444
453
|
return "unknown";
|
|
445
454
|
}
|
|
@@ -501,7 +510,7 @@ function buildExportPreamble(exportSpecs, libraries) {
|
|
|
501
510
|
async function compileWasmArtifactFromDefs(
|
|
502
511
|
defs,
|
|
503
512
|
mainRelName = "__main__",
|
|
504
|
-
{ typingMode = "generic" } = {}
|
|
513
|
+
{ typingMode = "generic", usePKIR = false } = {}
|
|
505
514
|
) {
|
|
506
515
|
resetTagIds();
|
|
507
516
|
const mainRel = defs.rels[mainRelName];
|
|
@@ -509,7 +518,11 @@ async function compileWasmArtifactFromDefs(
|
|
|
509
518
|
throw new Error(`No main relation (${mainRelName}) defined in script`);
|
|
510
519
|
}
|
|
511
520
|
|
|
512
|
-
const { wat: moduleWatBody, relationNames, entryName } = compileModule(
|
|
521
|
+
const { wat: moduleWatBody, relationNames, entryName } = compileModule(
|
|
522
|
+
mainRelName,
|
|
523
|
+
defs,
|
|
524
|
+
{ usePKIR }
|
|
525
|
+
);
|
|
513
526
|
assertRelationsConverged(defs, relationNames);
|
|
514
527
|
const fullWat = runtimeWat.trim().slice(0, -1) + "\n" + moduleWatBody + "\n)";
|
|
515
528
|
const graph = mainRel.typePatternGraph;
|
|
@@ -522,7 +535,12 @@ async function compileWasmArtifactFromDefs(
|
|
|
522
535
|
entry: entryName || cleanName(mainRelName),
|
|
523
536
|
inputPattern,
|
|
524
537
|
outputPattern,
|
|
525
|
-
typing: classifyTyping(
|
|
538
|
+
typing: classifyTyping(
|
|
539
|
+
inputPattern,
|
|
540
|
+
outputPattern,
|
|
541
|
+
relTypeStatus(defs, mainRelName),
|
|
542
|
+
typingMode
|
|
543
|
+
),
|
|
526
544
|
tags: getTagEntries()
|
|
527
545
|
};
|
|
528
546
|
return appendCustomSection(await compileWat(fullWat), METADATA_SECTION, JSON.stringify(metadata));
|
|
@@ -597,12 +615,17 @@ async function compileWasmArtifactFromKVM(kvmInput, options = {}) {
|
|
|
597
615
|
return appendCustomSection(await compileWat(fullWat), METADATA_SECTION, JSON.stringify(metadata));
|
|
598
616
|
}
|
|
599
617
|
|
|
600
|
-
async function compileWasmArtifactFromObject(
|
|
618
|
+
async function compileWasmArtifactFromObject(
|
|
619
|
+
object,
|
|
620
|
+
{ entry = null, inputEnvelopePattern = null, usePKIR = false } = {}
|
|
621
|
+
) {
|
|
601
622
|
if (!object?.rels) {
|
|
602
623
|
throw new Error("Expected .ko input to contain k object relations");
|
|
603
624
|
}
|
|
604
625
|
if (object.main == null) {
|
|
605
|
-
throw new Error(
|
|
626
|
+
throw new Error(
|
|
627
|
+
"Cannot compile a .klib library to WebAssembly without a main relation"
|
|
628
|
+
);
|
|
606
629
|
}
|
|
607
630
|
const mainRelName = entry || object.main || "__main__";
|
|
608
631
|
let defs = { rels: object.rels, compileStats: object.compileStats };
|
|
@@ -610,43 +633,126 @@ async function compileWasmArtifactFromObject(object, { entry = null, inputEnvelo
|
|
|
610
633
|
|
|
611
634
|
if (inputEnvelopePattern) {
|
|
612
635
|
const mainRel = object.rels[mainRelName];
|
|
613
|
-
if (!mainRel)
|
|
614
|
-
|
|
615
|
-
|
|
636
|
+
if (!mainRel) {
|
|
637
|
+
throw new Error(`No main relation (${mainRelName}) defined in object`);
|
|
638
|
+
}
|
|
639
|
+
const inputPattern = getPatternPropertyList(
|
|
640
|
+
mainRel.typePatternGraph,
|
|
641
|
+
mainRel.def.patterns[0]
|
|
642
|
+
);
|
|
643
|
+
const outputPattern = getPatternPropertyList(
|
|
644
|
+
mainRel.typePatternGraph,
|
|
645
|
+
mainRel.def.patterns[1]
|
|
646
|
+
);
|
|
616
647
|
const typing = classifyTyping(inputPattern, outputPattern);
|
|
617
648
|
if (typing.program === "polymorphic") {
|
|
618
|
-
const specialized = specializeObjectRelations(
|
|
619
|
-
|
|
649
|
+
const specialized = specializeObjectRelations(
|
|
650
|
+
object,
|
|
651
|
+
mainRelName,
|
|
652
|
+
inputEnvelopePattern
|
|
653
|
+
);
|
|
654
|
+
defs = {
|
|
655
|
+
rels: specialized.rels,
|
|
656
|
+
relAlias: specialized.relAlias,
|
|
657
|
+
compileStats: specialized.compileStats
|
|
658
|
+
};
|
|
620
659
|
typingMode = "specialized";
|
|
621
660
|
}
|
|
622
661
|
}
|
|
623
662
|
|
|
624
|
-
return compileWasmArtifactFromDefs(defs, mainRelName, {
|
|
663
|
+
return compileWasmArtifactFromDefs(defs, mainRelName, {
|
|
664
|
+
typingMode,
|
|
665
|
+
usePKIR
|
|
666
|
+
});
|
|
625
667
|
}
|
|
626
668
|
|
|
627
669
|
async function compileWasmArtifact(
|
|
628
670
|
source,
|
|
629
|
-
{
|
|
671
|
+
{
|
|
672
|
+
libraries = [],
|
|
673
|
+
exports = [],
|
|
674
|
+
source: sourceName = null,
|
|
675
|
+
inputEnvelopePattern = null,
|
|
676
|
+
usePKIR = false
|
|
677
|
+
} = {}
|
|
630
678
|
) {
|
|
631
679
|
const preamble = buildExportPreamble(exports, libraries);
|
|
632
680
|
const fullSource = preamble + source;
|
|
633
|
-
const options = {
|
|
681
|
+
const options = {
|
|
682
|
+
libraries,
|
|
683
|
+
...(sourceName ? { source: sourceName } : {})
|
|
684
|
+
};
|
|
634
685
|
let defs = annotate(fullSource, options);
|
|
635
686
|
|
|
636
687
|
let typingMode = "generic";
|
|
637
688
|
if (inputEnvelopePattern) {
|
|
638
689
|
const mainRel = defs.rels.__main__;
|
|
639
|
-
const inputPattern = getPatternPropertyList(
|
|
640
|
-
|
|
690
|
+
const inputPattern = getPatternPropertyList(
|
|
691
|
+
mainRel.typePatternGraph,
|
|
692
|
+
mainRel.def.patterns[0]
|
|
693
|
+
);
|
|
694
|
+
const outputPattern = getPatternPropertyList(
|
|
695
|
+
mainRel.typePatternGraph,
|
|
696
|
+
mainRel.def.patterns[1]
|
|
697
|
+
);
|
|
641
698
|
if (classifyTyping(inputPattern, outputPattern).program === "polymorphic") {
|
|
642
|
-
const obj = {
|
|
643
|
-
|
|
644
|
-
|
|
699
|
+
const obj = {
|
|
700
|
+
format: "k-object",
|
|
701
|
+
rels: defs.rels,
|
|
702
|
+
relAlias: defs.relAlias,
|
|
703
|
+
compileStats: defs.compileStats,
|
|
704
|
+
main: "__main__"
|
|
705
|
+
};
|
|
706
|
+
const specialized = specializeObjectRelations(
|
|
707
|
+
obj,
|
|
708
|
+
"__main__",
|
|
709
|
+
inputEnvelopePattern
|
|
710
|
+
);
|
|
711
|
+
defs = {
|
|
712
|
+
rels: specialized.rels,
|
|
713
|
+
relAlias: specialized.relAlias,
|
|
714
|
+
compileStats: specialized.compileStats
|
|
715
|
+
};
|
|
645
716
|
typingMode = "specialized";
|
|
646
717
|
}
|
|
647
718
|
}
|
|
648
719
|
|
|
649
|
-
return compileWasmArtifactFromDefs(defs, "__main__", {
|
|
720
|
+
return compileWasmArtifactFromDefs(defs, "__main__", {
|
|
721
|
+
typingMode,
|
|
722
|
+
usePKIR
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
async function compileWasmArtifactFromPKIR(pkirInput, options = {}) {
|
|
727
|
+
let kvmProgram;
|
|
728
|
+
let entry = options.entry || "__main__";
|
|
729
|
+
if (pkirInput && typeof pkirInput === "object") {
|
|
730
|
+
if (pkirInput.format === "pk-ir" && pkirInput.functions) {
|
|
731
|
+
entry = pkirInput.entry || entry;
|
|
732
|
+
kvmProgram = {};
|
|
733
|
+
for (const [name, f] of Object.entries(pkirInput.functions)) {
|
|
734
|
+
kvmProgram[name] = lowerPKIRToKVM(f);
|
|
735
|
+
}
|
|
736
|
+
} else if (pkirInput.instructions) {
|
|
737
|
+
const kvm = lowerPKIRToKVM(pkirInput);
|
|
738
|
+
entry = kvm.name || entry;
|
|
739
|
+
kvmProgram = { [entry]: kvm };
|
|
740
|
+
} else if (pkirInput.functions) {
|
|
741
|
+
entry = pkirInput.entry || entry;
|
|
742
|
+
kvmProgram = {};
|
|
743
|
+
for (const [name, f] of Object.entries(pkirInput.functions)) {
|
|
744
|
+
kvmProgram[name] = lowerPKIRToKVM(f);
|
|
745
|
+
}
|
|
746
|
+
} else {
|
|
747
|
+
throw new Error("Invalid PKIR input for WebAssembly compilation");
|
|
748
|
+
}
|
|
749
|
+
} else {
|
|
750
|
+
throw new Error("Expected PKIR input object");
|
|
751
|
+
}
|
|
752
|
+
return compileWasmArtifactFromKVM(
|
|
753
|
+
{ format: "k-vm", layer: "KVM", entry, functions: kvmProgram },
|
|
754
|
+
options
|
|
755
|
+
);
|
|
650
756
|
}
|
|
651
757
|
|
|
652
758
|
function createTagRegistry(entries) {
|
|
@@ -1049,6 +1155,7 @@ export {
|
|
|
1049
1155
|
appendCustomSection,
|
|
1050
1156
|
compileWasmArtifactFromKVM,
|
|
1051
1157
|
compileWasmArtifactFromObject,
|
|
1158
|
+
compileWasmArtifactFromPKIR,
|
|
1052
1159
|
compileWasmArtifact,
|
|
1053
1160
|
instantiateWasmArtifact,
|
|
1054
1161
|
metadataFromModule,
|
|
@@ -1066,6 +1173,7 @@ export default {
|
|
|
1066
1173
|
appendCustomSection,
|
|
1067
1174
|
compileWasmArtifactFromKVM,
|
|
1068
1175
|
compileWasmArtifactFromObject,
|
|
1176
|
+
compileWasmArtifactFromPKIR,
|
|
1069
1177
|
compileWasmArtifact,
|
|
1070
1178
|
metadataFromModule,
|
|
1071
1179
|
readArenaValue,
|
|
@@ -443,11 +443,11 @@ console.log("==> Running End-to-End Peano Addition & Serialization Tests");
|
|
|
443
443
|
const runtimeWat = fs.readFileSync("runtime.wat", "utf8");
|
|
444
444
|
|
|
445
445
|
const script = `
|
|
446
|
-
nat = ?< {} 0, nat +1 >;
|
|
447
|
-
0 = {} | 0 nat
|
|
448
|
-
inc = | +1 nat
|
|
449
|
-
dec = nat / +1;
|
|
450
|
-
add = ?{ nat x, nat y } = X <
|
|
446
|
+
nat? = ?< {} 0, nat? +1 >;
|
|
447
|
+
0 = {} | 0 nat?;
|
|
448
|
+
inc = | +1 nat?;
|
|
449
|
+
dec = nat? / +1;
|
|
450
|
+
add = ?{ nat? x, nat? y } = X <
|
|
451
451
|
{ . x dec x, . y inc y } ?X add,
|
|
452
452
|
. y
|
|
453
453
|
>;
|
package/browser/repl-browser.mjs
CHANGED
|
@@ -311,13 +311,17 @@ export async function executeCommand(input) {
|
|
|
311
311
|
function updateEngineUI() {
|
|
312
312
|
const badge = document.getElementById("engine-badge");
|
|
313
313
|
if (!badge) return;
|
|
314
|
-
badge.
|
|
315
|
-
badge.title = `Engine: ${state.engine} (click to toggle wasm/js)`;
|
|
314
|
+
badge.classList.remove("js-mode", "pkir-mode");
|
|
316
315
|
if (state.engine === "js") {
|
|
316
|
+
badge.textContent = "js-in-process";
|
|
317
317
|
badge.classList.add("js-mode");
|
|
318
|
+
} else if (state.engine === "pkir") {
|
|
319
|
+
badge.textContent = "pkir-wasm";
|
|
320
|
+
badge.classList.add("pkir-mode");
|
|
318
321
|
} else {
|
|
319
|
-
badge.
|
|
322
|
+
badge.textContent = "wasm-in-process";
|
|
320
323
|
}
|
|
324
|
+
badge.title = `Engine: ${state.engine} (click to toggle wasm/pkir/js)`;
|
|
321
325
|
}
|
|
322
326
|
|
|
323
327
|
function adjustInputHeight() {
|
|
@@ -979,11 +983,18 @@ export function initRepl() {
|
|
|
979
983
|
}
|
|
980
984
|
});
|
|
981
985
|
|
|
982
|
-
// Engine Badge toggle (wasm
|
|
986
|
+
// Engine Badge toggle (wasm -> pkir -> js -> wasm)
|
|
983
987
|
const engineBadge = document.getElementById("engine-badge");
|
|
984
988
|
if (engineBadge) {
|
|
985
989
|
engineBadge.onclick = () => {
|
|
986
|
-
|
|
990
|
+
let nextEngine;
|
|
991
|
+
if (state.engine === "wasm") {
|
|
992
|
+
nextEngine = "pkir";
|
|
993
|
+
} else if (state.engine === "pkir") {
|
|
994
|
+
nextEngine = "js";
|
|
995
|
+
} else {
|
|
996
|
+
nextEngine = "wasm";
|
|
997
|
+
}
|
|
987
998
|
executeCommand(`:engine ${nextEngine}`);
|
|
988
999
|
};
|
|
989
1000
|
}
|