@fraczak/k 7.0.0 → 7.0.2

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.
Files changed (63) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/DOCS/BIG_PICTURE.md +5 -5
  3. package/DOCS/FILE_FORMATS.md +5 -5
  4. package/DOCS/OBJECT_FILE_AND_PATTERN.md +9 -9
  5. package/DOCS/PATTERNS.md +3 -3
  6. package/DOCS/PROFILING_AND_TRACING.md +60 -72
  7. package/DOCS/REPL.md +3 -3
  8. package/DOCS/book/03-types-as-finite-automata.md +4 -4
  9. package/DOCS/book/06-values-in-memory.md +9 -9
  10. package/DOCS/book/08-operational-semantics-and-execution.md +1 -1
  11. package/DOCS/book/09-compiler-architecture.md +2 -2
  12. package/DOCS/book/10-from-ast-to-intermediate-representation.md +2 -2
  13. package/DOCS/book/14-canonical-serialization.md +1 -1
  14. package/Examples/arithmetics.k +2 -2
  15. package/Examples/bnat.k +1 -1
  16. package/Examples/karatsuba-mult.k +2 -2
  17. package/README.md +3 -8
  18. package/backend-api.mjs +9 -1
  19. package/backends/llvm/runtime/krt.c +33 -0
  20. package/backends/llvm/runtime/krt.h +1 -0
  21. package/backends/llvm/scripts/run-tests.mjs +5 -0
  22. package/backends/llvm/src/executable.mjs +4 -4
  23. package/backends/llvm/src/kvm2llvm.mjs +42 -19
  24. package/backends/llvm/src/llvm.mjs +30 -36
  25. package/backends/llvm/tests/integration.sh +2 -2
  26. package/backends/llvm/tests/perf-support.mjs +1 -55
  27. package/backends/llvm/tests/test-llvm.mjs +3 -3
  28. package/backends/llvm/tests/test-open-product-misalignment.mjs +140 -0
  29. package/backends/wasm/demo_ieee.mjs +2 -3
  30. package/backends/wasm/runtime.wat +157 -5
  31. package/backends/wasm/src/kvm2wasm.mjs +57 -34
  32. package/backends/wasm/src/wasm.mjs +40 -18
  33. package/backends/wasm/tests/perf-support.mjs +4 -4
  34. package/backends/wasm/tests/test-wasm.mjs +13 -14
  35. package/browser/vfs-data.mjs +6 -6
  36. package/core.k +8 -8
  37. package/harness/format.mjs +2 -2
  38. package/harness/registry.mjs +0 -2
  39. package/kir.mjs +299 -17
  40. package/package.json +1 -5
  41. package/scripts/benchmark-idempotency.mjs +12 -8
  42. package/scripts/benchmark.mjs +5 -9
  43. package/scripts/build-repl-html.mjs +2 -2
  44. package/scripts/perf-ieee.mjs +17 -118
  45. package/scripts/perf-int.mjs +313 -318
  46. package/scripts/perf-multiplication.mjs +10 -20
  47. package/scripts/perf-poly.mjs +29 -183
  48. package/tests/code-derivation/pattern-envelope.mjs +4 -4
  49. package/tests/test-kvm-polymorphic.mjs +2 -2
  50. package/tests/test-repl-html.mjs +15 -0
  51. package/tests/test-repl.mjs +10 -0
  52. package/backends/arm64/README.md +0 -103
  53. package/backends/arm64/bin/k-arm64-compile.mjs +0 -93
  54. package/backends/arm64/bin/k-arm64-run.mjs +0 -58
  55. package/backends/arm64/bin/k-arm64.mjs +0 -88
  56. package/backends/arm64/scripts/run-tests.mjs +0 -57
  57. package/backends/arm64/src/arm64.mjs +0 -229
  58. package/backends/arm64/src/cli.mjs +0 -155
  59. package/backends/arm64/src/kvm2arm64.mjs +0 -906
  60. package/backends/arm64/src/runtime.c +0 -744
  61. package/backends/arm64/tests/integration.sh +0 -112
  62. package/backends/arm64/tests/test-arm64.mjs +0 -240
  63. package/harness/adapters/arm64.mjs +0 -105
package/core.k CHANGED
@@ -1,17 +1,17 @@
1
1
  -- core.k — the k standard core library
2
2
  --
3
3
  -- Defines:
4
- -- 1. bits — canonical binary number / bit-path relation
5
- -- 2. string — unicode strings relation (used for labels)
6
- -- 3. pattern — pattern graph relation
4
+ -- 1. bits? — canonical binary number / bit-path relation
5
+ -- 2. string? — unicode strings relation (used for labels)
6
+ -- 3. pattern? — pattern graph relation
7
7
 
8
8
  ---------------------------------------------------------------
9
9
  -- §1. Bits
10
10
  ---------------------------------------------------------------
11
11
 
12
- bit = ?< {} 0, {} 1 >;
12
+ bit? = ?< {} 0, {} 1 >;
13
13
 
14
- bits = ?< {} _, bits 0, bits 1 > = bits;
14
+ bits? = ?< {} _, bits? 0, bits? 1 > = bits?;
15
15
 
16
16
  _ = {}|_;
17
17
 
@@ -22,7 +22,7 @@ _ = {}|_;
22
22
  -- §2. Unicode and String
23
23
  ---------------------------------------------------------------
24
24
 
25
- string = ? <
25
+ string? = ? <
26
26
  {} nil,
27
27
  {
28
28
  <
@@ -82,7 +82,7 @@ string = ? <
82
82
  -- to decode any value, first decode a pattern under that constant,
83
83
  -- then decode the value under the pattern just obtained.
84
84
 
85
- pattern = ? <
85
+ pattern? = ? <
86
86
  {} nil,
87
87
  {
88
88
  <
@@ -150,4 +150,4 @@ pattern = ? <
150
150
  } cons
151
151
  > = Pattern;
152
152
 
153
- pattern
153
+ pattern?
@@ -1,6 +1,6 @@
1
1
  import { PHASES, formatUs } from "./trace.mjs";
2
2
 
3
- export function formatPhaseTable(phaseResults, backendIds = ["arm64", "llvm", "wasm", "kvm"]) {
3
+ export function formatPhaseTable(phaseResults, backendIds = ["llvm", "wasm", "kvm"]) {
4
4
  const lines = [];
5
5
 
6
6
  for (const item of phaseResults) {
@@ -25,7 +25,7 @@ export function formatPhaseTable(phaseResults, backendIds = ["arm64", "llvm", "w
25
25
  return lines.join("\n");
26
26
  }
27
27
 
28
- export function formatProfileTable(profileResults, backendIds = ["arm64", "wasm", "kvm"]) {
28
+ export function formatProfileTable(profileResults, backendIds = ["wasm", "kvm"]) {
29
29
  const lines = [];
30
30
 
31
31
  for (const item of profileResults) {
@@ -1,7 +1,6 @@
1
1
  import { NativeAdapter } from "./adapters/native.mjs";
2
2
  import { KVMAdapter } from "./adapters/kvm.mjs";
3
3
  import { WasmAdapter } from "./adapters/wasm.mjs";
4
- import { ARM64Adapter } from "./adapters/arm64.mjs";
5
4
  import { LLVMAdapter } from "./adapters/llvm.mjs";
6
5
 
7
6
  export function createRegistry(config = {}) {
@@ -16,7 +15,6 @@ export function createRegistry(config = {}) {
16
15
  register("kvm", () => new KVMAdapter(config.state));
17
16
  register("wasm", () => new WasmAdapter(config.wasm || {}));
18
17
  register("wasm-in-process", () => new WasmAdapter({ id: "wasm-in-process", mode: "in-process", ...(config.wasm || {}) }));
19
- register("arm64", () => new ARM64Adapter(config.arm64 || {}));
20
18
  register("llvm", () => new LLVMAdapter(config.llvm || {}));
21
19
 
22
20
  return {
package/kir.mjs CHANGED
@@ -8,6 +8,7 @@ import { compileObject, decodeObject, hydrateObject } from "./object.mjs";
8
8
  import { exportPatternGraph } from "./codecs/runtime/codec.mjs";
9
9
  import { patternToPropertyList } from "./codecs/runtime/pattern-json.mjs";
10
10
  import { propertyListToFilter } from "./codecs/runtime/show-value.mjs";
11
+ import { TypePatternGraph } from "./TypePatternGraph.mjs";
11
12
 
12
13
  const KIR_FORMAT = "k-ir";
13
14
  const KIR_VERSION = 1;
@@ -240,6 +241,11 @@ function resolveRelation(object, relationName = null) {
240
241
  const alias = object.relAlias?.[name];
241
242
  if (alias && object.rels?.[alias]) return { name: alias, rel: object.rels[alias] };
242
243
  if (alias && object.rels?.[name]) return { name, rel: object.rels[name] };
244
+ if (alias) {
245
+ for (const [k, rel] of Object.entries(object.rels || {})) {
246
+ if (object.relAlias?.[k] === alias) return { name: k, rel };
247
+ }
248
+ }
243
249
 
244
250
  throw new Error(`Relation '${name}' not found`);
245
251
  }
@@ -264,7 +270,274 @@ function relationLibraryWithTarget(object, targetRel) {
264
270
  };
265
271
  }
266
272
 
267
- function relationPatternPropertyList(rel, index) {
273
+ function addPropertyListToPatternGraph(graph, propertyList) {
274
+ const kindToPattern = {
275
+ any: "(...)",
276
+ "open-product": "{...}",
277
+ "open-union": "<...>",
278
+ "closed-product": "{}",
279
+ "closed-union": "<>"
280
+ };
281
+ const nodes = propertyList.map(([kind]) =>
282
+ graph.addNewNode({ pattern: kindToPattern[kind] })
283
+ );
284
+
285
+ propertyList.forEach(([, edges], nodeIndex) => {
286
+ for (const [label, target] of edges) {
287
+ graph.edges[nodes[nodeIndex]][label] = [nodes[target]];
288
+ }
289
+ });
290
+
291
+ return nodes[0];
292
+ }
293
+
294
+ function cloneRelation(rel) {
295
+ const clonedGraph = new TypePatternGraph(
296
+ rel.typePatternGraph.registerCodeDef,
297
+ rel.typePatternGraph.findCode
298
+ );
299
+ clonedGraph.patterns.nodes = JSON.parse(JSON.stringify(rel.typePatternGraph.patterns.nodes));
300
+ clonedGraph.patterns.parent = [...rel.typePatternGraph.patterns.parent];
301
+ clonedGraph.edges = JSON.parse(JSON.stringify(rel.typePatternGraph.edges));
302
+ clonedGraph.codeId = { ...rel.typePatternGraph.codeId };
303
+
304
+ return {
305
+ ...rel,
306
+ def: JSON.parse(JSON.stringify(rel.def)),
307
+ typePatternGraph: clonedGraph,
308
+ typeDerivation: { ...(rel.typeDerivation || {}) }
309
+ };
310
+ }
311
+
312
+ function findCallSites(exp) {
313
+ const calls = [];
314
+ function visit(node) {
315
+ if (!node) return;
316
+ if (node.op === "ref") calls.push(node);
317
+ if (node.comp) node.comp.forEach(visit);
318
+ if (node.items) node.items.forEach(visit);
319
+ if (node.union) node.union.forEach(visit);
320
+ if (node.product) node.product.forEach((item) => visit(item.exp));
321
+ if (node.fields) node.fields.forEach((item) => visit(item.expr));
322
+ }
323
+ visit(exp);
324
+ return calls;
325
+ }
326
+
327
+ function findRelation(rels, relAlias, name) {
328
+ if (!name) return null;
329
+ if (rels[name]) return { name, rel: rels[name] };
330
+ const alias = relAlias?.[name];
331
+ if (alias && rels[alias]) return { name: alias, rel: rels[alias] };
332
+ if (alias) {
333
+ for (const [k, rel] of Object.entries(rels)) {
334
+ if (relAlias?.[k] === alias) return { name: k, rel };
335
+ }
336
+ }
337
+ return null;
338
+ }
339
+
340
+ function findDots(exp, res = []) {
341
+ if (!exp || typeof exp !== "object") return res;
342
+ if (exp.op === "dot") res.push(exp);
343
+ if (Array.isArray(exp.comp)) exp.comp.forEach((c) => findDots(c, res));
344
+ if (Array.isArray(exp.items)) exp.items.forEach((c) => findDots(c, res));
345
+ if (Array.isArray(exp.union)) exp.union.forEach((c) => findDots(c, res));
346
+ if (Array.isArray(exp.product)) {
347
+ exp.product.forEach((c) => findDots(c?.exp || c?.expr, res));
348
+ }
349
+ if (Array.isArray(exp.fields)) {
350
+ exp.fields.forEach((c) => findDots(c?.expr || c?.exp, res));
351
+ }
352
+ return res;
353
+ }
354
+
355
+ function getDotIndex(rel, dotExp) {
356
+ const label = dotExp.dot || dotExp.label;
357
+ if (!label) return -1;
358
+ const propList = expPatternPropertyList(rel, dotExp, 0);
359
+ if (Array.isArray(propList?.[0]?.[1])) {
360
+ return propList[0][1].findIndex(([l]) => l === label);
361
+ }
362
+ return -1;
363
+ }
364
+
365
+ function relationLayoutSignature(rel) {
366
+ const inPropList = relationPatternPropertyList(rel, 0);
367
+ if (!Array.isArray(inPropList)) return "";
368
+
369
+ const dots = findDots(rel.def);
370
+ const dotIndices = dots.map((d) => {
371
+ const lbl = d.dot || d.label || "";
372
+ return `${lbl}:${getDotIndex(rel, d)}`;
373
+ });
374
+
375
+ const productShapes = [];
376
+ for (const [kind, edges] of inPropList) {
377
+ if (kind === "open-product" || kind === "closed-product") {
378
+ const fieldNames = edges.map(([l]) => l).sort().join(",");
379
+ if (fieldNames.length > 0) productShapes.push(fieldNames);
380
+ }
381
+ }
382
+
383
+ return dotIndices.join(",") + "|" + productShapes.sort().join(";");
384
+ }
385
+
386
+ function productShapeSignature(propList) {
387
+ if (!Array.isArray(propList)) return "";
388
+ const shapes = [];
389
+ for (const [kind, edges] of propList) {
390
+ if (kind === "open-product" || kind === "closed-product") {
391
+ const fieldNames = edges.map(([l]) => l).sort().join(",");
392
+ if (fieldNames.length > 0) shapes.push(fieldNames);
393
+ }
394
+ }
395
+ return shapes.sort().join(";");
396
+ }
397
+
398
+ export function specializeObjectRelations(object, entryRelationName = null, inputPattern = null) {
399
+ if (object?.format !== "k-object") {
400
+ throw new Error("specializeObjectRelations requires a k object");
401
+ }
402
+
403
+ const baseRels = Object.fromEntries(
404
+ Object.entries(object.rels || {}).map(([name, rel]) => [name, cloneRelation(rel)])
405
+ );
406
+ for (const [aliasName, hash] of Object.entries(object.relAlias || {})) {
407
+ if (!baseRels[aliasName]) {
408
+ const match = Object.entries(baseRels).find(([k]) => object.relAlias?.[k] === hash);
409
+ if (match) baseRels[aliasName] = match[1];
410
+ }
411
+ }
412
+
413
+ const entry = findRelation(
414
+ baseRels,
415
+ object.relAlias,
416
+ entryRelationName || object.main || "__main__"
417
+ );
418
+ if (!entry) return object;
419
+
420
+ const specializedRels = new Map();
421
+ const specializedCounts = new Map();
422
+ const newRels = {};
423
+ const inProgress = new Map();
424
+ let entryCandidate = null;
425
+
426
+ function specializeRelation(relName, argPropList) {
427
+ const target = findRelation(baseRels, object.relAlias, relName);
428
+ if (!target) return relName;
429
+
430
+ const baseInSig = relationLayoutSignature(target.rel);
431
+ const shapeSig = productShapeSignature(argPropList);
432
+ const specKey = target.name + "::" + shapeSig;
433
+
434
+ if (specializedRels.has(specKey)) {
435
+ return specializedRels.get(specKey);
436
+ }
437
+ if (inProgress.has(specKey)) {
438
+ return inProgress.get(specKey);
439
+ }
440
+
441
+ const count = (specializedCounts.get(target.name) || 0) + 1;
442
+ const specName = `${target.name}$${count}`;
443
+ inProgress.set(specKey, specName);
444
+
445
+ const candidateRel = cloneRelation(target.rel);
446
+ if (!candidateRel.typeDerivation) candidateRel.typeDerivation = {};
447
+ if (!candidateRel.typeDerivation.status) {
448
+ candidateRel.typeDerivation.status = target.rel?.typeDerivation?.status || "converged";
449
+ }
450
+
451
+ if (Array.isArray(argPropList) && argPropList.length > 0) {
452
+ const tInRoot = addPropertyListToPatternGraph(candidateRel.typePatternGraph, argPropList);
453
+ try {
454
+ candidateRel.typePatternGraph.unify("specialize", candidateRel.def.patterns[0], tInRoot);
455
+ } catch {
456
+ // Unification failure: keep target unspecialized
457
+ }
458
+ }
459
+
460
+ if (relName === entry.name && (!entryCandidate || Array.isArray(argPropList))) {
461
+ entryCandidate = candidateRel;
462
+ }
463
+
464
+ let anyCallChanged = false;
465
+ const calls = findCallSites(candidateRel.def);
466
+ for (const call of calls) {
467
+ const argPatternId = call.patterns?.[0];
468
+ if (argPatternId != null) {
469
+ const argRoot = candidateRel.typePatternGraph.find(argPatternId);
470
+ const childArgPropList = patternToPropertyList(
471
+ exportPatternGraph(candidateRel.typePatternGraph, argRoot)
472
+ );
473
+ const childSpecName = specializeRelation(call.ref, childArgPropList);
474
+ if (childSpecName !== call.ref) {
475
+ call.ref = childSpecName;
476
+ anyCallChanged = true;
477
+ }
478
+
479
+ const childRel = newRels[childSpecName] || baseRels[childSpecName];
480
+ if (childRel) {
481
+ const outPatternId = childRel.def.patterns?.[1];
482
+ const retPatternId = call.patterns?.[1];
483
+ if (outPatternId != null && retPatternId != null) {
484
+ const outRoot = childRel.typePatternGraph.find(outPatternId);
485
+ const retPropList = patternToPropertyList(
486
+ exportPatternGraph(childRel.typePatternGraph, outRoot)
487
+ );
488
+ const rRetRoot = addPropertyListToPatternGraph(candidateRel.typePatternGraph, retPropList);
489
+ try {
490
+ candidateRel.typePatternGraph.unify("specialize", retPatternId, rRetRoot);
491
+ } catch {
492
+ // Keep existing call return pattern on unification error
493
+ }
494
+ }
495
+ }
496
+ }
497
+ }
498
+
499
+ inProgress.delete(specKey);
500
+
501
+ const newInSig = relationLayoutSignature(candidateRel);
502
+ const isDifferent = (newInSig !== baseInSig) || anyCallChanged;
503
+
504
+ if (!isDifferent) {
505
+ specializedRels.set(specKey, target.name);
506
+ return target.name;
507
+ }
508
+
509
+ specializedCounts.set(target.name, count);
510
+ specializedRels.set(specKey, specName);
511
+ newRels[specName] = candidateRel;
512
+ return specName;
513
+ }
514
+
515
+ const entrySpecName = specializeRelation(entry.name, inputPattern);
516
+ if (entrySpecName !== entry.name && newRels[entrySpecName]) {
517
+ newRels[entry.name] = newRels[entrySpecName];
518
+ } else if (entryCandidate) {
519
+ newRels[entry.name] = entryCandidate;
520
+ } else if (!newRels[entry.name]) {
521
+ newRels[entry.name] = baseRels[entry.name];
522
+ }
523
+
524
+ const resultRels = {
525
+ ...baseRels,
526
+ ...newRels
527
+ };
528
+ const resultRelAlias = { ...(object.relAlias || {}) };
529
+ for (const name of Object.keys(newRels)) {
530
+ if (!resultRelAlias[name]) resultRelAlias[name] = name;
531
+ }
532
+
533
+ return {
534
+ ...object,
535
+ rels: resultRels,
536
+ relAlias: resultRelAlias
537
+ };
538
+ }
539
+
540
+ export function relationPatternPropertyList(rel, index) {
268
541
  return expPatternPropertyList(rel, rel.def, index);
269
542
  }
270
543
 
@@ -284,28 +557,35 @@ export function retypeObjectRelationForBackend(object, relationName, inputPatter
284
557
  }
285
558
 
286
559
  const target = resolveRelation(object, relationName);
287
- const source = `?${propertyListToFilter(inputPattern)} __kir_target__`;
288
- const retypedObject = hydrateObject(compileObject(source, {
289
- source: options.source || "<kir-retype>",
290
- libraries: [relationLibraryWithTarget(object, target.rel)]
291
- }));
292
- const kir = objectToKIRP(retypedObject);
293
- const entryName = retypedObject.main || "__main__";
294
- const retypedRel = retypedObject.rels[entryName];
295
- const entryInputPattern = relationPatternPropertyList(retypedRel, 0);
560
+ const specializedObject = specializeObjectRelations(object, target.name, inputPattern);
561
+ const specializedRel = resolveRelation(specializedObject, target.name);
562
+ const kir = objectToKIRP(specializedObject);
296
563
 
297
564
  return {
298
- relation: relationName || object.main,
299
- retypedObject,
565
+ relation: target.name,
566
+ retypedObject: specializedObject,
300
567
  kir,
301
- entryName,
302
- inputPattern: entryInputPattern,
303
- outputPattern: relationPatternPropertyList(retypedRel, 1)
568
+ entryName: target.name,
569
+ inputPattern: relationPatternPropertyList(specializedRel.rel, 0),
570
+ outputPattern: relationPatternPropertyList(specializedRel.rel, 1)
304
571
  };
305
572
  }
306
573
 
307
574
  export function retypeObjectRelation(object, relationName, inputPattern, options = {}) {
308
- return retypeObjectRelationForBackend(object, relationName, inputPattern, options).kir;
575
+ if (object?.format !== "k-object") {
576
+ throw new Error("KIR retyping requires a k object");
577
+ }
578
+ if (!Array.isArray(inputPattern)) {
579
+ throw new Error("KIR retyping requires an input pattern property list");
580
+ }
581
+
582
+ const target = resolveRelation(object, relationName);
583
+ const source = `?${propertyListToFilter(inputPattern)} __kir_target__`;
584
+ const retypedObject = hydrateObject(compileObject(source, {
585
+ source: options.source || "<kir-retype>",
586
+ libraries: [relationLibraryWithTarget(object, target.rel)]
587
+ }));
588
+ return objectToKIRP(retypedObject);
309
589
  }
310
590
 
311
591
  export { KIR_FORMAT, KIR_VERSION };
@@ -314,8 +594,10 @@ export default {
314
594
  KIR_FORMAT,
315
595
  KIR_VERSION,
316
596
  objectToKIRP,
597
+ relationPatternPropertyList,
317
598
  retypeObjectRelation,
318
- retypeObjectRelationForBackend
599
+ retypeObjectRelationForBackend,
600
+ specializeObjectRelations
319
601
  };
320
602
 
321
603
  function helpText() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fraczak/k",
3
- "version": "7.0.0",
3
+ "version": "7.0.2",
4
4
  "description": "k — a language for content-addressable schemas and data transformations over algebraic data types (products and tagged unions); includes runtime, contract derivation, REPL, and codec toolchain",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -16,7 +16,6 @@
16
16
  "test:backends": "node backends/llvm/scripts/run-tests.mjs && node backends/wasm/scripts/run-tests.mjs",
17
17
  "test:llvm": "node backends/llvm/scripts/run-tests.mjs",
18
18
  "test:wasm": "node backends/wasm/scripts/run-tests.mjs",
19
- "test:arm64": "node backends/arm64/scripts/run-tests.mjs",
20
19
  "conformance": "node conformance/run.mjs",
21
20
  "benchmark": "node scripts/benchmark.mjs",
22
21
  "benchmark:html": "node scripts/render-benchmark.mjs",
@@ -49,9 +48,6 @@
49
48
  "k-llvm-compile": "backends/llvm/bin/k-llvm-compile.mjs",
50
49
  "k-llvm-jit": "backends/llvm/bin/k-llvm-jit.mjs",
51
50
  "k-llvm-run": "backends/llvm/bin/k-llvm-run.mjs",
52
- "k-arm64": "backends/arm64/bin/k-arm64.mjs",
53
- "k-arm64-compile": "backends/arm64/bin/k-arm64-compile.mjs",
54
- "k-arm64-run": "backends/arm64/bin/k-arm64-run.mjs",
55
51
  "k-wasm": "backends/wasm/bin/k-wasm.mjs",
56
52
  "k-wasm-compile": "backends/wasm/bin/k-wasm-compile.mjs",
57
53
  "k-wasm-run": "backends/wasm/bin/k-wasm-run.mjs",
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { spawnSync } from "node:child_process";
4
- import { mkdtempSync, statSync } from "node:fs";
4
+ import { mkdtempSync, rmSync, statSync } from "node:fs";
5
5
  import { tmpdir } from "node:os";
6
6
  import { join } from "node:path";
7
7
  import { performance } from "node:perf_hooks";
@@ -80,13 +80,17 @@ for (const example of benchmarkExamples) {
80
80
 
81
81
  for (let i = 0; i < iterations; i++) {
82
82
  const out = mkdtempSync(join(tmpdir(), `k-idempotency-bench-${example.replaceAll("/", "_")}-`));
83
- const t0 = performance.now();
84
- run(["objects/compile.mjs", example, join(out, "1.klib")]);
85
- run(["objects/decompile.mjs", join(out, "1.klib"), join(out, "1.k")]);
86
- run(["objects/compile.mjs", join(out, "1.k"), join(out, "2.klib")]);
87
- run(["objects/decompile.mjs", join(out, "2.klib"), join(out, "2.k")]);
88
- times.push(performance.now() - t0);
89
- size = statSync(join(out, "1.klib")).size;
83
+ try {
84
+ const t0 = performance.now();
85
+ run(["objects/compile.mjs", example, join(out, "1.klib")]);
86
+ run(["objects/decompile.mjs", join(out, "1.klib"), join(out, "1.k")]);
87
+ run(["objects/compile.mjs", join(out, "1.k"), join(out, "2.klib")]);
88
+ run(["objects/decompile.mjs", join(out, "2.klib"), join(out, "2.k")]);
89
+ times.push(performance.now() - t0);
90
+ size = statSync(join(out, "1.klib")).size;
91
+ } finally {
92
+ rmSync(out, { recursive: true, force: true });
93
+ }
90
94
  }
91
95
 
92
96
  console.log([
@@ -21,13 +21,12 @@ import {
21
21
  retypeObjectRelationForBackend,
22
22
  patternToPropertyList,
23
23
  propertyListToPattern,
24
- parseFloat64,
25
24
  run,
26
25
  run_converged,
27
- valueForCode,
28
26
  Value
29
27
  } from "../backend-api.mjs";
30
28
  import { parse as parseIntValue } from "../codecs/int.mjs";
29
+ import { parse as parseFloatValue } from "../codecs/ieee.mjs";
31
30
  import {
32
31
  compileObjectBuffer as compileBackendObjectBuffer,
33
32
  decodeObject as decodeBackendObject
@@ -460,13 +459,10 @@ async function prepareState(suite) {
460
459
  }
461
460
 
462
461
  function ieeeInput(testCase, state) {
463
- const float64Hash = state.typeAliases.float64;
464
- const floatPairHash = state.typeAliases.float_pair;
465
- const float64 = text => valueForCode(parseFloat64(text), float64Hash, codes.find);
466
- return valueForCode(Value.product({
467
- x: float64(testCase.input.x),
468
- y: float64(testCase.input.y)
469
- }), floatPairHash, codes.find);
462
+ return Value.product({
463
+ x: parseFloatValue(testCase.input.x),
464
+ y: parseFloatValue(testCase.input.y)
465
+ });
470
466
  }
471
467
 
472
468
  function arithmeticInput(testCase) {
@@ -1888,8 +1888,8 @@ const htmlContent = `<!DOCTYPE html>
1888
1888
  <li><code>{} | ok</code> &mdash; Constant relation producing variant <code>ok</code> with empty document payload <code>{}</code></li>
1889
1889
  <li><code>not = &lt; / true | false, / false | true &gt;;</code> &mdash; Polymorphic negation via branch projections and ordered choice</li>
1890
1890
  <li><code>{} | true not</code> &mdash; Compose constant relation <code>{} | true</code> with <code>not</code> (evaluates to <code>{} | false</code>)</li>
1891
- <li><code>bool = ?&lt; {} true, {} false &gt;;</code> &mdash; Define a boolean pattern filter relation</li>
1892
- <li><code>not = bool ?X &lt; / true | false, {} | true &gt; ?X;</code> &mdash; Filtered boolean negation: guarded by <code>bool</code>, defaulting to <code>{} | true</code></li>
1891
+ <li><code>bool? = ?&lt; {} true, {} false &gt;;</code> &mdash; Define a boolean pattern filter relation</li>
1892
+ <li><code>not = bool? ?X &lt; / true | false, {} | true &gt; ?X;</code> &mdash; Filtered boolean negation: guarded by <code>bool?</code>, defaulting to <code>{} | true</code></li>
1893
1893
  <li><code>swap = { . y x, . x y };</code> &mdash; Define a product field-swapping relation</li>
1894
1894
  <li><code>{ {} | ok x, {} | nil y } swap</code> &mdash; Construct a product and pass it through <code>swap</code></li>
1895
1895
  </ul>