@fraczak/k 6.0.1 → 6.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 (38) hide show
  1. package/AGENTS.md +35 -0
  2. package/CHANGELOG.md +48 -0
  3. package/CLAUDE.md +64 -0
  4. package/DOCS/BIG_PICTURE.md +4 -8
  5. package/DOCS/BINARY_CODEC_STATUS_AND_TODO.md +74 -0
  6. package/DOCS/CONVERGENCE.md +92 -0
  7. package/DOCS/DIVERGENCE_DETECTION.md +24 -0
  8. package/DOCS/Makefile +99 -0
  9. package/DOCS/OBJECT_FILE_AND_PATTERN.md +217 -0
  10. package/DOCS/PATTERNS.md +114 -0
  11. package/DOCS/PATTERNS_AND_TYPED_VALUES.md +665 -0
  12. package/DOCS/REPL.md +125 -125
  13. package/DOCS/TEXTUAL_VALUES.md +108 -0
  14. package/DOCS/TYPE_DERIVATION.md +230 -0
  15. package/DOCS/book/06-values-in-memory.md +1085 -0
  16. package/DOCS/book/07-the-partial-function-abi.md +143 -0
  17. package/DOCS/book/08-operational-semantics-and-execution.md +201 -0
  18. package/DOCS/book/09-compiler-architecture.md +160 -0
  19. package/DOCS/book/10-from-ast-to-intermediate-representation.md +167 -0
  20. package/DOCS/book/14-canonical-serialization.md +176 -0
  21. package/DOCS/book/appendix-b-incorporating-external-predefined-types-and-functions.md +155 -0
  22. package/DOCS/book/overview.txt +68 -0
  23. package/README.md +71 -27
  24. package/codecs/README.md +8 -0
  25. package/codecs/pandoc.css +71 -0
  26. package/codecs/runtime/test-codec.mjs +89 -0
  27. package/package.json +2 -2
  28. package/{codecs/k-pattern.mjs → patterns/from-k.mjs} +3 -3
  29. package/repl2.mjs +259 -50
  30. package/scripts/generate-dependency-graph.mjs +121 -0
  31. package/test-repl2.mjs +55 -8
  32. package/DOCS/book-combined.html +0 -3798
  33. package/DOCS/book-combined.md +0 -3745
  34. package/DOCS/book-combined.pdf +0 -0
  35. package/DOCS/book-combined.tex +0 -5682
  36. package/DOCS/book.html +0 -65
  37. package/DOCS/book.pdf +0 -0
  38. package/DOCS/book.tex +0 -150
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { execSync } from "node:child_process";
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ const root = path.resolve(__dirname, "..");
11
+ const outPath = path.join(root, "DOCS", "dependency-graph.md");
12
+
13
+ function getTrackedMjsFiles() {
14
+ const raw = execSync("git ls-files '*.mjs'", {
15
+ cwd: root,
16
+ encoding: "utf8"
17
+ });
18
+
19
+ const all = raw
20
+ .split("\n")
21
+ .map((s) => s.trim())
22
+ .filter(Boolean);
23
+
24
+ return all.filter((relPath) => {
25
+ if (relPath.startsWith("codecs/")) return true;
26
+ if (relPath.includes("/")) return false;
27
+ if (relPath.startsWith("test")) return false;
28
+ if (relPath.includes("-test")) return false;
29
+ return true;
30
+ });
31
+ }
32
+
33
+ function parseLocalImports(absPath) {
34
+ const source = fs.readFileSync(absPath, "utf8");
35
+ const regex = /^\s*import\s+[^;]*?from\s+["']([^"']+)["'];?\s*$/gm;
36
+ const imports = [];
37
+ let match;
38
+ while ((match = regex.exec(source)) !== null) {
39
+ const specifier = match[1];
40
+ if (specifier.startsWith("./") || specifier.startsWith("../")) {
41
+ imports.push(specifier);
42
+ }
43
+ }
44
+ return imports;
45
+ }
46
+
47
+ function toNodeId(relPath) {
48
+ return relPath.replace(/[^a-zA-Z0-9]/g, "_");
49
+ }
50
+
51
+ function makeBar(sizeKb) {
52
+ const units = Math.max(1, Math.min(20, Math.round(sizeKb)));
53
+ return "█".repeat(units);
54
+ }
55
+
56
+ function renderGraph(files, sizesKb, edges) {
57
+ const lines = [];
58
+ lines.push("# Project Dependency Graph");
59
+ lines.push("");
60
+ lines.push("_Auto-generated by scripts/generate-dependency-graph.mjs._");
61
+ lines.push("");
62
+ lines.push("```mermaid");
63
+ lines.push("graph TD");
64
+ lines.push(" classDef default fill:#fff,stroke:#333,stroke-width:2px,color:#000;");
65
+ lines.push("");
66
+
67
+ for (const relPath of files) {
68
+ const id = toNodeId(relPath);
69
+ const sizeKb = sizesKb[relPath];
70
+ const bar = makeBar(sizeKb);
71
+ lines.push(` ${id}[\"${relPath} (${sizeKb.toFixed(1)} KB)<br/>${bar}\"]`);
72
+ }
73
+
74
+ if (edges.length > 0) {
75
+ lines.push("");
76
+ }
77
+
78
+ for (const { src, dst } of edges) {
79
+ lines.push(` ${toNodeId(src)} --> ${toNodeId(dst)}`);
80
+ }
81
+
82
+ lines.push("```");
83
+ lines.push("");
84
+ return lines.join("\n");
85
+ }
86
+
87
+ function main() {
88
+ const files = getTrackedMjsFiles().sort();
89
+ const fileSet = new Set(files);
90
+
91
+ const sizesKb = {};
92
+ for (const relPath of files) {
93
+ const absPath = path.join(root, relPath);
94
+ const bytes = fs.statSync(absPath).size;
95
+ sizesKb[relPath] = bytes / 1024;
96
+ }
97
+
98
+ const edgeKeys = new Set();
99
+ const edges = [];
100
+ for (const relPath of files) {
101
+ const absPath = path.join(root, relPath);
102
+ const imports = parseLocalImports(absPath);
103
+
104
+ for (const specifier of imports) {
105
+ const resolved = path.normalize(path.join(path.dirname(relPath), specifier));
106
+ if (!resolved.endsWith(".mjs")) continue;
107
+ if (!fileSet.has(resolved)) continue;
108
+ const key = `${relPath}->${resolved}`;
109
+ if (edgeKeys.has(key)) continue;
110
+ edgeKeys.add(key);
111
+ edges.push({ src: relPath, dst: resolved });
112
+ }
113
+ }
114
+
115
+ const graph = renderGraph(files, sizesKb, edges);
116
+ fs.writeFileSync(outPath, graph, "utf8");
117
+ console.log(`Wrote ${path.relative(root, outPath)}`);
118
+ console.log(`Nodes: ${files.length}, Edges: ${edges.length}`);
119
+ }
120
+
121
+ main();
package/test-repl2.mjs CHANGED
@@ -4,7 +4,18 @@ import os from "node:os";
4
4
  import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
 
7
- import { completeInput, createState, evaluateInput, isMainEntrypoint } from "./repl2.mjs";
7
+ import {
8
+ aliasNames,
9
+ analyzeAcceptedSnippet,
10
+ analyzeRawSnippet,
11
+ completeInput,
12
+ createState,
13
+ evaluateInput,
14
+ explicitSnippetTerminated,
15
+ isMainEntrypoint,
16
+ lineHasExplicitContinuation,
17
+ lineTerminatesSnippet
18
+ } from "./repl2.mjs";
8
19
  import { decodeObject, objectToFunction } from "./object.mjs";
9
20
  import { Product } from "./Value.mjs";
10
21
 
@@ -41,12 +52,38 @@ assert(completions.some((line) => line.endsWith(state.typeAliases.nat)));
41
52
  completions = completeInput(`(${canonicalPartial}`, state)[0];
42
53
  assert(completions.includes(`(${state.typeAliases.nat}`));
43
54
 
55
+ completions = completeInput(":run su", state)[0];
56
+ assert(completions.includes(":run succ"));
57
+
58
+ completions = completeInput("$na", state)[0];
59
+ assert(completions.includes("$nat"));
60
+
61
+ assert.deepEqual(aliasNames(state), ["nat", "succ"]);
62
+ assert.equal(lineTerminatesSnippet(";"), true);
63
+ assert.equal(lineTerminatesSnippet(" ; "), true);
64
+ assert.equal(lineTerminatesSnippet(" ; -- comment"), false);
65
+ assert.equal(lineTerminatesSnippet("succ"), false);
66
+ assert.equal(explicitSnippetTerminated("$ bool = <{} true, {} false>;"), true);
67
+ assert.equal(lineHasExplicitContinuation("succ \\"), true);
68
+ assert.equal(analyzeRawSnippet("$ bool = <{} true, {} false>").kind, "incomplete");
69
+ assert.equal(analyzeAcceptedSnippet("$ bool = <{} true, {} false>;", true).kind, "definitionsOnly");
70
+ assert.equal(analyzeRawSnippet("a =").kind, "incomplete");
71
+ assert.equal(analyzeRawSnippet("{} | succ").kind, "withMain");
72
+
73
+ const offsetState = createState();
74
+ await evaluateInput(":type ab = <{} 1, {} 2>", offsetState);
75
+ await evaluateInput(":type bool = <{} true, {} false>", offsetState);
76
+ await assert.rejects(
77
+ () => evaluateInput("$ab", offsetState),
78
+ /Type Error in 'filter' \(lines 1:1\.\.\.1:4\)/
79
+ );
80
+
44
81
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "k-repl2-"));
45
82
  const libPath = path.join(tmpDir, "session.klib");
46
83
  const koPath = path.join(tmpDir, "succ.ko");
47
84
  const sourcePath = path.join(tmpDir, "session.k");
48
85
  const symlinkPath = path.resolve(".test-k-repl2-link");
49
- output = await evaluateInput(`:save ${libPath}`, state);
86
+ output = await evaluateInput(`:klib ${libPath}`, state);
50
87
  assert.equal(output[0], `saved ${libPath}`);
51
88
 
52
89
  completions = completeInput(`:load ${tmpDir}/ses`, state)[0];
@@ -89,12 +126,22 @@ output = await evaluateInput("succ", reloaded);
89
126
  assert.equal(output[0], "{}|succ ?<{} succ, ...>");
90
127
 
91
128
  const shorthand = createState();
92
- output = await evaluateInput("$ nat = <{} zero, nat succ>;", shorthand);
93
- assert.match(output[0], /^\$ nat = @/);
94
- output = await evaluateInput("succ = |succ;", shorthand);
95
- assert.match(output[0], /^succ = @/);
96
- output = await evaluateInput("succ", shorthand);
97
- assert.equal(output[0], "{}|succ ?<{} succ, ...>");
129
+ output = await evaluateInput("$ nat = <{} zero, nat succ>\n; succ = |succ\n;", shorthand);
130
+ assert.deepEqual(output, []);
131
+ output = await evaluateInput(":codes", shorthand);
132
+ assert.match(output[0], /^nat = @/m);
133
+ output = await evaluateInput(":rels", shorthand);
134
+ assert.match(output[0], /^succ = @/m);
135
+ output = await evaluateInput("$ bool = <{} true, {} false>\n; not = $bool </true | false, {} | true >\n; {} | true not", shorthand);
136
+ assert.match(output[0], /^\{\}\|false \?</);
137
+ assert.match(output[0], / false/);
138
+ assert.match(output[0], / true/);
139
+ output = await evaluateInput("$ maybe = <{} none, {} some>;", shorthand);
140
+ assert.deepEqual(output, []);
141
+ output = await evaluateInput(":codes", shorthand);
142
+ assert.match(output[0], /^maybe = @/m);
143
+ output = await evaluateInput("{} | true not", shorthand);
144
+ assert.match(output[0], /^\{\}\|false \?</);
98
145
 
99
146
  await assert.rejects(
100
147
  () => evaluateInput("/type", createState()),