@fraczak/k 6.7.0 → 6.9.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 +10 -0
- package/DOCS/CODECS.md +80 -181
- package/DOCS/CODEC_ARCHITECTURE.md +194 -0
- package/DOCS/REPL.md +49 -60
- package/Examples/arithmetics.k +1 -0
- package/Examples/poly.k +46 -0
- package/TODO.md +112 -0
- package/browser/repl-browser.mjs +112 -733
- package/browser/shims/process.mjs +7 -0
- package/browser/tree-view.mjs +5 -2
- package/browser/vfs-data.mjs +14 -12
- package/codecs/README.md +7 -0
- package/codecs/ieee.mjs +50 -75
- package/codecs/int.mjs +83 -62
- package/codecs/json-codec.mjs +5 -77
- package/codecs/json.mjs +12 -56
- package/codecs/k-parse.mjs +3 -19
- package/codecs/runtime/codec-sdk.mjs +94 -0
- package/codecs/runtime/pattern-k.mjs +45 -0
- package/codecs/string-codec.mjs +48 -74
- package/codecs/unit.mjs +13 -61
- package/codecs/utf16.mjs +13 -56
- package/codecs/utf8.mjs +11 -55
- package/package.json +1 -1
- package/patterns/from-k.mjs +2 -22
- package/repl-codecs.mjs +78 -184
- package/repl.mjs +168 -226
- package/scripts/build-repl-html.mjs +273 -424
- package/scripts/run-tests.mjs +1 -0
- package/tests/test-codecs.mjs +186 -0
- package/tests/test-poly.mjs +44 -0
- package/tests/test-repl-html.mjs +190 -53
- package/tests/test-repl.mjs +150 -114
- package/tests/test-structural-values.mjs +17 -0
- package/tests/test-tree-view.mjs +3 -0
- package/codecs/example-pipeline.mjs +0 -163
- package/codecs/runtime/ieee-pattern.mjs +0 -30
- package/codecs/runtime/test-codec.mjs +0 -89
- package/codecs/runtime/typeFromValue.mjs +0 -34
|
@@ -12,7 +12,40 @@ const workspaceRoot = path.resolve(projectRoot, "..");
|
|
|
12
12
|
|
|
13
13
|
console.log("=== Building Self-Contained K REPL HTML ===");
|
|
14
14
|
|
|
15
|
-
// 1.
|
|
15
|
+
// 1. Node shims plugin for esbuild
|
|
16
|
+
const nodeShimsPlugin = {
|
|
17
|
+
name: "node-shims",
|
|
18
|
+
setup(build) {
|
|
19
|
+
const shims = {
|
|
20
|
+
"fs": path.join(projectRoot, "browser/shims/fs.mjs"),
|
|
21
|
+
"node:fs": path.join(projectRoot, "browser/shims/fs.mjs"),
|
|
22
|
+
"path": path.join(projectRoot, "browser/shims/path.mjs"),
|
|
23
|
+
"node:path": path.join(projectRoot, "browser/shims/path.mjs"),
|
|
24
|
+
"crypto": path.join(projectRoot, "browser/shims/crypto.mjs"),
|
|
25
|
+
"node:crypto": path.join(projectRoot, "browser/shims/crypto.mjs"),
|
|
26
|
+
"buffer": path.join(projectRoot, "browser/shims/buffer.mjs"),
|
|
27
|
+
"node:buffer": path.join(projectRoot, "browser/shims/buffer.mjs"),
|
|
28
|
+
"os": path.join(projectRoot, "browser/shims/os.mjs"),
|
|
29
|
+
"node:os": path.join(projectRoot, "browser/shims/os.mjs"),
|
|
30
|
+
"process": path.join(projectRoot, "browser/shims/process.mjs"),
|
|
31
|
+
"node:process": path.join(projectRoot, "browser/shims/process.mjs"),
|
|
32
|
+
"readline": path.join(projectRoot, "browser/shims/readline.mjs"),
|
|
33
|
+
"node:readline": path.join(projectRoot, "browser/shims/readline.mjs"),
|
|
34
|
+
"url": path.join(projectRoot, "browser/shims/url.mjs"),
|
|
35
|
+
"node:url": path.join(projectRoot, "browser/shims/url.mjs"),
|
|
36
|
+
"assert": path.join(projectRoot, "browser/shims/assert.mjs"),
|
|
37
|
+
"node:assert": path.join(projectRoot, "browser/shims/assert.mjs"),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
build.onResolve({ filter: /^(node:)?(fs|path|crypto|buffer|os|process|readline|url|assert)$/ }, (args) => {
|
|
41
|
+
if (shims[args.path]) {
|
|
42
|
+
return { path: shims[args.path] };
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// 2. Scan and generate browser/vfs-data.mjs
|
|
16
49
|
console.log("1. Generating VFS data...");
|
|
17
50
|
const vfsFiles = {};
|
|
18
51
|
|
|
@@ -28,8 +61,8 @@ if (fs.existsSync(coreKPath)) {
|
|
|
28
61
|
vfsFiles["core.k"] = fs.readFileSync(coreKPath, "utf8");
|
|
29
62
|
}
|
|
30
63
|
|
|
31
|
-
// Add verified k-code files: arithmetics.k, ieee.k
|
|
32
|
-
const verifiedExamples = ["arithmetics.k", "ieee.k"];
|
|
64
|
+
// Add verified k-code files: arithmetics.k, ieee.k, poly.k
|
|
65
|
+
const verifiedExamples = ["arithmetics.k", "ieee.k", "poly.k"];
|
|
33
66
|
const examplesDir = path.join(projectRoot, "Examples");
|
|
34
67
|
for (const filename of verifiedExamples) {
|
|
35
68
|
const fullPath = path.join(examplesDir, filename);
|
|
@@ -40,15 +73,48 @@ for (const filename of verifiedExamples) {
|
|
|
40
73
|
}
|
|
41
74
|
}
|
|
42
75
|
|
|
43
|
-
//
|
|
76
|
+
// Bundle verified codecs for browser VFS as 100% self-contained ES modules
|
|
44
77
|
const verifiedCodecs = ["json.mjs", "utf8.mjs", "int.mjs", "unit.mjs", "ieee.mjs"];
|
|
45
78
|
const codecsDir = path.join(projectRoot, "codecs");
|
|
79
|
+
|
|
80
|
+
const browserCodecSdkShim = `
|
|
81
|
+
export { Value, isProduct, isVariant, withPattern } from "../../Value.mjs";
|
|
82
|
+
export function runCodecCLI() {}
|
|
83
|
+
export function encodeToWire() {}
|
|
84
|
+
export function decodeWire() {}
|
|
85
|
+
export function patternFromFilter(script, options) {
|
|
86
|
+
if (typeof globalThis !== "undefined" && typeof globalThis.patternFromFilter === "function") {
|
|
87
|
+
return globalThis.patternFromFilter(script, options);
|
|
88
|
+
}
|
|
89
|
+
throw new Error("patternFromFilter is not available in browser environment");
|
|
90
|
+
}
|
|
91
|
+
`;
|
|
92
|
+
|
|
46
93
|
for (const filename of verifiedCodecs) {
|
|
47
94
|
const fullPath = path.join(codecsDir, filename);
|
|
48
95
|
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
96
|
+
const buildRes = await esbuild.build({
|
|
97
|
+
entryPoints: [fullPath],
|
|
98
|
+
bundle: true,
|
|
99
|
+
format: "esm",
|
|
100
|
+
write: false,
|
|
101
|
+
plugins: [{
|
|
102
|
+
name: "codec-sdk-shim",
|
|
103
|
+
setup(build) {
|
|
104
|
+
build.onResolve({ filter: /(codec-sdk|pattern-k)\.mjs$/ }, (args) => ({
|
|
105
|
+
path: args.path,
|
|
106
|
+
namespace: "codec-sdk-shim"
|
|
107
|
+
}));
|
|
108
|
+
build.onLoad({ filter: /.*/, namespace: "codec-sdk-shim" }, () => ({
|
|
109
|
+
contents: browserCodecSdkShim,
|
|
110
|
+
resolveDir: path.join(codecsDir, "runtime")
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
}]
|
|
114
|
+
});
|
|
115
|
+
const bundledContent = buildRes.outputFiles[0].text;
|
|
116
|
+
vfsFiles[filename] = bundledContent;
|
|
117
|
+
vfsFiles[`codecs/${filename}`] = bundledContent;
|
|
52
118
|
}
|
|
53
119
|
}
|
|
54
120
|
|
|
@@ -59,39 +125,6 @@ const vfsDataPath = path.join(projectRoot, "browser/vfs-data.mjs");
|
|
|
59
125
|
fs.writeFileSync(vfsDataPath, vfsDataContent, "utf8");
|
|
60
126
|
console.log(` Generated ${vfsDataPath} with ${Object.keys(vfsFiles).length} files.`);
|
|
61
127
|
|
|
62
|
-
// 2. Node shims plugin for esbuild
|
|
63
|
-
const nodeShimsPlugin = {
|
|
64
|
-
name: "node-shims",
|
|
65
|
-
setup(build) {
|
|
66
|
-
const shims = {
|
|
67
|
-
"fs": path.join(projectRoot, "browser/shims/fs.mjs"),
|
|
68
|
-
"node:fs": path.join(projectRoot, "browser/shims/fs.mjs"),
|
|
69
|
-
"path": path.join(projectRoot, "browser/shims/path.mjs"),
|
|
70
|
-
"node:path": path.join(projectRoot, "browser/shims/path.mjs"),
|
|
71
|
-
"crypto": path.join(projectRoot, "browser/shims/crypto.mjs"),
|
|
72
|
-
"node:crypto": path.join(projectRoot, "browser/shims/crypto.mjs"),
|
|
73
|
-
"buffer": path.join(projectRoot, "browser/shims/buffer.mjs"),
|
|
74
|
-
"node:buffer": path.join(projectRoot, "browser/shims/buffer.mjs"),
|
|
75
|
-
"os": path.join(projectRoot, "browser/shims/os.mjs"),
|
|
76
|
-
"node:os": path.join(projectRoot, "browser/shims/os.mjs"),
|
|
77
|
-
"process": path.join(projectRoot, "browser/shims/process.mjs"),
|
|
78
|
-
"node:process": path.join(projectRoot, "browser/shims/process.mjs"),
|
|
79
|
-
"readline": path.join(projectRoot, "browser/shims/readline.mjs"),
|
|
80
|
-
"node:readline": path.join(projectRoot, "browser/shims/readline.mjs"),
|
|
81
|
-
"url": path.join(projectRoot, "browser/shims/url.mjs"),
|
|
82
|
-
"node:url": path.join(projectRoot, "browser/shims/url.mjs"),
|
|
83
|
-
"assert": path.join(projectRoot, "browser/shims/assert.mjs"),
|
|
84
|
-
"node:assert": path.join(projectRoot, "browser/shims/assert.mjs"),
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
build.onResolve({ filter: /^(node:)?(fs|path|crypto|buffer|os|process|readline|url|assert)$/ }, (args) => {
|
|
88
|
-
if (shims[args.path]) {
|
|
89
|
-
return { path: shims[args.path] };
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
128
|
// 3. Bundle browser/repl-browser.mjs
|
|
96
129
|
console.log("2. Bundling with esbuild...");
|
|
97
130
|
const entryPoint = path.join(projectRoot, "browser/repl-browser.mjs");
|
|
@@ -173,21 +206,24 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
173
206
|
|
|
174
207
|
/* Header */
|
|
175
208
|
.navbar {
|
|
176
|
-
height: 48px;
|
|
209
|
+
min-height: 48px;
|
|
210
|
+
height: auto;
|
|
177
211
|
background: var(--bg-surface);
|
|
178
212
|
border-bottom: 1px solid var(--border-color);
|
|
179
213
|
display: flex;
|
|
180
214
|
align-items: center;
|
|
181
215
|
justify-content: space-between;
|
|
182
|
-
padding:
|
|
216
|
+
padding: 6px 16px;
|
|
183
217
|
flex-shrink: 0;
|
|
184
|
-
|
|
218
|
+
flex-wrap: wrap;
|
|
219
|
+
gap: 8px 12px;
|
|
185
220
|
}
|
|
186
221
|
|
|
187
222
|
.nav-left {
|
|
188
223
|
display: flex;
|
|
189
224
|
align-items: center;
|
|
190
225
|
gap: 12px;
|
|
226
|
+
flex-shrink: 0;
|
|
191
227
|
}
|
|
192
228
|
|
|
193
229
|
.brand {
|
|
@@ -199,12 +235,6 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
199
235
|
user-select: none;
|
|
200
236
|
}
|
|
201
237
|
|
|
202
|
-
.brand-lambda {
|
|
203
|
-
color: var(--color-prompt);
|
|
204
|
-
font-size: 20px;
|
|
205
|
-
line-height: 1;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
238
|
.brand-name {
|
|
209
239
|
letter-spacing: 0.5px;
|
|
210
240
|
}
|
|
@@ -253,8 +283,11 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
253
283
|
.nav-right {
|
|
254
284
|
display: flex;
|
|
255
285
|
align-items: center;
|
|
256
|
-
gap: 8px;
|
|
257
|
-
flex-wrap:
|
|
286
|
+
gap: 6px 8px;
|
|
287
|
+
flex-wrap: wrap;
|
|
288
|
+
justify-content: flex-end;
|
|
289
|
+
flex: 1 1 auto;
|
|
290
|
+
min-width: 0;
|
|
258
291
|
}
|
|
259
292
|
|
|
260
293
|
.control-group {
|
|
@@ -320,7 +353,8 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
320
353
|
|
|
321
354
|
/* Terminal */
|
|
322
355
|
.terminal-main {
|
|
323
|
-
flex: 1;
|
|
356
|
+
flex: 1 1 auto;
|
|
357
|
+
min-height: 0;
|
|
324
358
|
display: flex;
|
|
325
359
|
flex-direction: column;
|
|
326
360
|
overflow: hidden;
|
|
@@ -758,7 +792,7 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
758
792
|
|
|
759
793
|
/* Welcome banner */
|
|
760
794
|
.welcome-banner {
|
|
761
|
-
padding: 16px;
|
|
795
|
+
padding: 12px 16px;
|
|
762
796
|
background: var(--bg-surface);
|
|
763
797
|
border: 1px solid var(--border-color);
|
|
764
798
|
border-radius: 8px;
|
|
@@ -766,10 +800,10 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
766
800
|
}
|
|
767
801
|
|
|
768
802
|
.welcome-title {
|
|
769
|
-
font-size:
|
|
803
|
+
font-size: 16px;
|
|
770
804
|
font-weight: 700;
|
|
771
805
|
color: var(--color-prompt);
|
|
772
|
-
margin-bottom:
|
|
806
|
+
margin-bottom: 0;
|
|
773
807
|
}
|
|
774
808
|
|
|
775
809
|
.welcome-desc {
|
|
@@ -990,6 +1024,17 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
990
1024
|
font-size: 13px;
|
|
991
1025
|
}
|
|
992
1026
|
|
|
1027
|
+
.help-table th {
|
|
1028
|
+
text-align: left;
|
|
1029
|
+
padding: 6px 10px;
|
|
1030
|
+
font-size: 11px;
|
|
1031
|
+
font-weight: 600;
|
|
1032
|
+
color: var(--text-muted);
|
|
1033
|
+
text-transform: uppercase;
|
|
1034
|
+
letter-spacing: 0.5px;
|
|
1035
|
+
border-bottom: 1px solid var(--border-color);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
993
1038
|
.help-table td {
|
|
994
1039
|
padding: 6px 10px;
|
|
995
1040
|
border-bottom: 1px solid rgba(48, 54, 61, 0.4);
|
|
@@ -1001,6 +1046,27 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1001
1046
|
color: var(--color-cyan);
|
|
1002
1047
|
}
|
|
1003
1048
|
|
|
1049
|
+
.help-bridge-box {
|
|
1050
|
+
background: rgba(88, 166, 255, 0.08);
|
|
1051
|
+
border: 1px solid rgba(88, 166, 255, 0.25);
|
|
1052
|
+
border-left: 3px solid var(--color-prompt);
|
|
1053
|
+
border-radius: 4px;
|
|
1054
|
+
padding: 10px 14px;
|
|
1055
|
+
margin: 12px 0 16px 0;
|
|
1056
|
+
font-size: 12px;
|
|
1057
|
+
line-height: 1.5;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
.help-category-title {
|
|
1061
|
+
font-size: 13px;
|
|
1062
|
+
font-weight: 600;
|
|
1063
|
+
color: var(--text-main);
|
|
1064
|
+
margin: 16px 0 6px 0;
|
|
1065
|
+
display: flex;
|
|
1066
|
+
align-items: center;
|
|
1067
|
+
gap: 6px;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1004
1070
|
.help-section ul {
|
|
1005
1071
|
padding-left: 24px;
|
|
1006
1072
|
font-size: 13px;
|
|
@@ -1312,6 +1378,12 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1312
1378
|
border-color: rgba(210, 153, 34, 0.3);
|
|
1313
1379
|
}
|
|
1314
1380
|
|
|
1381
|
+
.badge-type.parameterized {
|
|
1382
|
+
background: rgba(187, 128, 179, 0.15);
|
|
1383
|
+
color: var(--color-purple);
|
|
1384
|
+
border-color: rgba(187, 128, 179, 0.3);
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1315
1387
|
.codecs-table-container {
|
|
1316
1388
|
background: var(--bg-base);
|
|
1317
1389
|
border: 1px solid var(--border-color);
|
|
@@ -1492,122 +1564,31 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1492
1564
|
min-height: 20px;
|
|
1493
1565
|
}
|
|
1494
1566
|
|
|
1495
|
-
/* Input Popup Modal */
|
|
1496
|
-
.input-popup-dialog {
|
|
1497
|
-
max-width: 580px;
|
|
1498
|
-
width: 90%;
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
|
-
.input-popup-body {
|
|
1502
|
-
padding: 16px 20px;
|
|
1503
|
-
display: flex;
|
|
1504
|
-
flex-direction: column;
|
|
1505
|
-
gap: 12px;
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
.input-popup-banner {
|
|
1509
|
-
background: var(--bg-base);
|
|
1510
|
-
border: 1px solid var(--border-color);
|
|
1511
|
-
border-radius: 6px;
|
|
1512
|
-
padding: 10px 14px;
|
|
1513
|
-
font-size: 12px;
|
|
1514
|
-
color: var(--text-main);
|
|
1515
|
-
display: flex;
|
|
1516
|
-
align-items: center;
|
|
1517
|
-
gap: 8px;
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
.input-popup-form-row {
|
|
1521
|
-
display: flex;
|
|
1522
|
-
gap: 12px;
|
|
1523
|
-
flex-wrap: wrap;
|
|
1524
|
-
}
|
|
1525
|
-
|
|
1526
|
-
.input-popup-field {
|
|
1527
|
-
display: flex;
|
|
1528
|
-
flex-direction: column;
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
|
-
.input-popup-textarea {
|
|
1532
|
-
width: 100%;
|
|
1533
|
-
background: #090d12;
|
|
1534
|
-
color: var(--text-main);
|
|
1535
|
-
border: 1px solid var(--border-color);
|
|
1536
|
-
border-radius: 6px;
|
|
1537
|
-
padding: 10px 12px;
|
|
1538
|
-
font-family: var(--font-mono);
|
|
1539
|
-
font-size: 13px;
|
|
1540
|
-
line-height: 1.4;
|
|
1541
|
-
resize: vertical;
|
|
1542
|
-
min-height: 90px;
|
|
1543
|
-
max-height: 280px;
|
|
1544
|
-
}
|
|
1545
|
-
|
|
1546
|
-
.input-popup-textarea:focus {
|
|
1547
|
-
border-color: var(--border-focus);
|
|
1548
|
-
box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.2);
|
|
1549
|
-
outline: none;
|
|
1550
|
-
}
|
|
1551
|
-
|
|
1552
|
-
.input-popup-samples {
|
|
1553
|
-
display: flex;
|
|
1554
|
-
align-items: center;
|
|
1555
|
-
gap: 8px;
|
|
1556
|
-
font-size: 11px;
|
|
1557
|
-
color: var(--text-muted);
|
|
1558
|
-
flex-wrap: wrap;
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
.samples-list {
|
|
1562
|
-
display: flex;
|
|
1563
|
-
gap: 6px;
|
|
1564
|
-
flex-wrap: wrap;
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
.sample-pill {
|
|
1568
|
-
background: var(--bg-subtle);
|
|
1569
|
-
border: 1px solid var(--border-color);
|
|
1570
|
-
color: var(--color-prompt);
|
|
1571
|
-
padding: 2px 8px;
|
|
1572
|
-
border-radius: 12px;
|
|
1573
|
-
cursor: pointer;
|
|
1574
|
-
font-family: var(--font-mono);
|
|
1575
|
-
font-size: 11px;
|
|
1576
|
-
transition: all 0.15s;
|
|
1577
|
-
}
|
|
1578
|
-
|
|
1579
|
-
.sample-pill:hover {
|
|
1580
|
-
background: rgba(88, 166, 255, 0.2);
|
|
1581
|
-
border-color: var(--border-focus);
|
|
1582
|
-
}
|
|
1583
|
-
|
|
1584
|
-
.input-popup-status {
|
|
1585
|
-
font-size: 12px;
|
|
1586
|
-
min-height: 22px;
|
|
1587
|
-
border-radius: 4px;
|
|
1588
|
-
padding: 4px 8px;
|
|
1589
|
-
background: rgba(22, 27, 34, 0.5);
|
|
1590
|
-
}
|
|
1591
|
-
|
|
1592
|
-
.input-popup-actions {
|
|
1593
|
-
display: flex;
|
|
1594
|
-
justify-content: flex-end;
|
|
1595
|
-
gap: 8px;
|
|
1596
|
-
border-top: 1px solid var(--border-color);
|
|
1597
|
-
padding-top: 12px;
|
|
1598
|
-
}
|
|
1599
1567
|
|
|
1600
1568
|
/* Responsive */
|
|
1601
1569
|
@media (max-width: 768px) {
|
|
1602
1570
|
.navbar {
|
|
1603
|
-
height: auto;
|
|
1604
|
-
flex-direction: column;
|
|
1605
1571
|
padding: 8px 12px;
|
|
1606
|
-
|
|
1572
|
+
gap: 8px;
|
|
1573
|
+
}
|
|
1574
|
+
.nav-left {
|
|
1575
|
+
width: 100%;
|
|
1576
|
+
justify-content: space-between;
|
|
1607
1577
|
}
|
|
1608
1578
|
.nav-right {
|
|
1609
|
-
|
|
1610
|
-
|
|
1579
|
+
width: 100%;
|
|
1580
|
+
justify-content: flex-start;
|
|
1581
|
+
overflow-x: visible;
|
|
1582
|
+
flex-wrap: wrap;
|
|
1583
|
+
gap: 6px;
|
|
1584
|
+
}
|
|
1585
|
+
.control-group {
|
|
1586
|
+
flex: 1 1 180px;
|
|
1587
|
+
}
|
|
1588
|
+
.control-group select {
|
|
1589
|
+
flex: 1 1 auto;
|
|
1590
|
+
max-width: 100%;
|
|
1591
|
+
min-width: 120px;
|
|
1611
1592
|
}
|
|
1612
1593
|
.vfs-body {
|
|
1613
1594
|
flex-direction: column;
|
|
@@ -1627,7 +1608,6 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1627
1608
|
<header class="navbar">
|
|
1628
1609
|
<div class="nav-left">
|
|
1629
1610
|
<div class="brand">
|
|
1630
|
-
<span class="brand-lambda">λ</span>
|
|
1631
1611
|
<span class="brand-name">k repl</span>
|
|
1632
1612
|
<span class="engine-badge">wasm-in-process</span>
|
|
1633
1613
|
</div>
|
|
@@ -1646,27 +1626,28 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1646
1626
|
<option value="core.k">core.k</option>
|
|
1647
1627
|
<option value="arithmetics.k">arithmetics.k</option>
|
|
1648
1628
|
<option value="ieee.k">ieee.k</option>
|
|
1629
|
+
<option value="poly.k">poly.k</option>
|
|
1649
1630
|
</optgroup>
|
|
1650
1631
|
<optgroup label="Quick Expressions">
|
|
1651
|
-
<option value="expr:
|
|
1652
|
-
<option value="expr:
|
|
1632
|
+
<option value="expr:{} | ok">{} | ok</option>
|
|
1633
|
+
<option value="expr:()">()</option>
|
|
1634
|
+
<option value="expr:$ bool = < {} true, {} false >; not = $ bool < / true | false, {} | true > $ bool; {} | true not">not (boolean relation with fallback)</option>
|
|
1635
|
+
<option value="expr:{10 x, 5 y} plus">{10 x, 5 y} plus (bits)</option>
|
|
1653
1636
|
<option value="expr:1 succ">1 succ</option>
|
|
1654
|
-
<option value="expr:
|
|
1655
|
-
<option value="expr::
|
|
1656
|
-
<option value="expr::
|
|
1657
|
-
<option value="expr::codes">:codes</option>
|
|
1658
|
-
<option value="expr::rels">:rels</option>
|
|
1659
|
-
<option value="expr::val">:val</option>
|
|
1637
|
+
<option value="expr:{10 int x, 5 int y} plus">{10 int x, 5 int y} plus (int)</option>
|
|
1638
|
+
<option value="expr::codes">:codes (list types)</option>
|
|
1639
|
+
<option value="expr::rels">:rels (list relations)</option>
|
|
1660
1640
|
</optgroup>
|
|
1661
|
-
<optgroup label="Codecs &
|
|
1641
|
+
<optgroup label="Codecs & Format Adapters">
|
|
1662
1642
|
<option value="expr::codecs">:codecs</option>
|
|
1663
|
-
<option value="expr::input">:input (
|
|
1664
|
-
<option value="expr::codec load int">:codec load int</option>
|
|
1665
|
-
<option value="expr
|
|
1666
|
-
<option value="expr::codec load
|
|
1667
|
-
<option value="expr::codec load
|
|
1668
|
-
<option value="expr::codec load
|
|
1669
|
-
<option value="expr::
|
|
1643
|
+
<option value="expr::input">:input (interactive dialog)</option>
|
|
1644
|
+
<option value="expr::codec load int.mjs">:codec load int.mjs</option>
|
|
1645
|
+
<option value="expr::codec load utf8.mjs">:codec load utf8.mjs</option>
|
|
1646
|
+
<option value="expr::codec load json.mjs">:codec load json.mjs</option>
|
|
1647
|
+
<option value="expr::codec load ieee.mjs">:codec load ieee.mjs</option>
|
|
1648
|
+
<option value="expr::codec load unit.mjs">:codec load unit.mjs</option>
|
|
1649
|
+
<option value="expr::input json.mjs {"a":12,"b":"hello"}">:input json.mjs {"a":12,"b":"hello"}</option>
|
|
1650
|
+
<option value="expr::input int.mjs [0,1,2]">:input int.mjs [0,1,2]</option>
|
|
1670
1651
|
</optgroup>
|
|
1671
1652
|
</select>
|
|
1672
1653
|
<button id="btn-load-example" class="btn btn-primary">Load</button>
|
|
@@ -1684,15 +1665,10 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1684
1665
|
<!-- Codecs Subsystem -->
|
|
1685
1666
|
<button id="btn-codecs" class="btn btn-secondary" title="Codecs & Custom Serializers (:codecs)">⚙ Codecs <span id="codecs-count-badge" class="badge-count">0</span></button>
|
|
1686
1667
|
|
|
1687
|
-
<!-- Codec Input Popup -->
|
|
1688
|
-
<button id="btn-input-popup" class="btn btn-secondary" title="Open Codec Input Popup (:input)">📥 Input</button>
|
|
1689
1668
|
|
|
1690
1669
|
<!-- Clear -->
|
|
1691
1670
|
<button id="btn-clear" class="btn btn-secondary" title="Clear terminal screen (Ctrl+L)">⌫ Clear</button>
|
|
1692
1671
|
|
|
1693
|
-
<!-- Reset -->
|
|
1694
|
-
<button id="btn-reset" class="btn btn-secondary" title="Reset REPL state (:reset)">↺ Reset</button>
|
|
1695
|
-
|
|
1696
1672
|
<!-- Export -->
|
|
1697
1673
|
<button id="btn-export" class="btn btn-secondary" title="Export session to .klib">💾 Save .klib</button>
|
|
1698
1674
|
|
|
@@ -1757,245 +1733,25 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
1757
1733
|
<div class="modal-dialog codecs-dialog">
|
|
1758
1734
|
<div class="modal-header">
|
|
1759
1735
|
<div style="display: flex; align-items: center; gap: 10px;">
|
|
1760
|
-
<h3>Codecs
|
|
1736
|
+
<h3>Enabled Codecs</h3>
|
|
1761
1737
|
<span class="engine-badge">:codecs subsystem</span>
|
|
1762
1738
|
</div>
|
|
1763
1739
|
<button id="btn-close-codecs" class="btn-close">×</button>
|
|
1764
1740
|
</div>
|
|
1765
1741
|
<div class="modal-body codecs-body">
|
|
1766
|
-
<!-- Section 1: Standard Built-in Codecs -->
|
|
1767
1742
|
<div class="codecs-section">
|
|
1768
1743
|
<div class="codecs-section-header">
|
|
1769
|
-
<h4>
|
|
1770
|
-
<span class="section-subtitle">
|
|
1744
|
+
<h4>Active Codecs in Current Session</h4>
|
|
1745
|
+
<span class="section-subtitle">Codecs format evaluation results and parse input for <code>:input <codec.mjs> [text]</code>. Codecs can only be loaded through <code>:codec load <file.mjs></code> in the REPL or through the <b>Files</b> explorer.</span>
|
|
1771
1746
|
</div>
|
|
1772
|
-
<div class="codec-grid">
|
|
1773
|
-
<!--
|
|
1774
|
-
<div class="codec-card" id="card-codec-int">
|
|
1775
|
-
<div class="codec-card-top">
|
|
1776
|
-
<div class="codec-card-title">
|
|
1777
|
-
<span class="codec-icon">🔢</span>
|
|
1778
|
-
<span class="codec-name">int</span>
|
|
1779
|
-
<span id="codec-badge-int" class="codec-status-badge">Inactive</span>
|
|
1780
|
-
</div>
|
|
1781
|
-
<div class="codec-types">Target: <span class="badge-type">$int</span></div>
|
|
1782
|
-
<div class="codec-desc">Arbitrary-precision signed integers serialized to/from sign-magnitude bit sequences.</div>
|
|
1783
|
-
</div>
|
|
1784
|
-
<div class="codec-card-footer">
|
|
1785
|
-
<div class="codec-caps">
|
|
1786
|
-
<span class="cap-badge print">Serializer</span>
|
|
1787
|
-
<span class="cap-badge parse">Deserializer</span>
|
|
1788
|
-
</div>
|
|
1789
|
-
<button id="btn-toggle-codec-int" class="btn btn-sm btn-primary">Load</button>
|
|
1790
|
-
</div>
|
|
1791
|
-
</div>
|
|
1792
|
-
|
|
1793
|
-
<!-- utf8 card -->
|
|
1794
|
-
<div class="codec-card" id="card-codec-utf8">
|
|
1795
|
-
<div class="codec-card-top">
|
|
1796
|
-
<div class="codec-card-title">
|
|
1797
|
-
<span class="codec-icon">🔤</span>
|
|
1798
|
-
<span class="codec-name">utf8</span>
|
|
1799
|
-
<span id="codec-badge-utf8" class="codec-status-badge">Inactive</span>
|
|
1800
|
-
</div>
|
|
1801
|
-
<div class="codec-types">Target: <span class="badge-type">$list $byte</span></div>
|
|
1802
|
-
<div class="codec-desc">UTF-8 strings serialized to/from linked lists of 8-bit bytes ($byte).</div>
|
|
1803
|
-
</div>
|
|
1804
|
-
<div class="codec-card-footer">
|
|
1805
|
-
<div class="codec-caps">
|
|
1806
|
-
<span class="cap-badge print">Serializer</span>
|
|
1807
|
-
<span class="cap-badge parse">Deserializer</span>
|
|
1808
|
-
</div>
|
|
1809
|
-
<button id="btn-toggle-codec-utf8" class="btn btn-sm btn-primary">Load</button>
|
|
1810
|
-
</div>
|
|
1811
|
-
</div>
|
|
1812
|
-
|
|
1813
|
-
<!-- json card -->
|
|
1814
|
-
<div class="codec-card" id="card-codec-json">
|
|
1815
|
-
<div class="codec-card-top">
|
|
1816
|
-
<div class="codec-card-title">
|
|
1817
|
-
<span class="codec-icon">📋</span>
|
|
1818
|
-
<span class="codec-name">json</span>
|
|
1819
|
-
<span id="codec-badge-json" class="codec-status-badge">Inactive</span>
|
|
1820
|
-
</div>
|
|
1821
|
-
<div class="codec-types">Target: <span class="badge-type universal">Universal (*)</span></div>
|
|
1822
|
-
<div class="codec-desc">Arbitrary algebraic products and variants mapped to standard JSON objects and values.</div>
|
|
1823
|
-
</div>
|
|
1824
|
-
<div class="codec-card-footer">
|
|
1825
|
-
<div class="codec-caps">
|
|
1826
|
-
<span class="cap-badge print">Serializer</span>
|
|
1827
|
-
<span class="cap-badge parse">Deserializer</span>
|
|
1828
|
-
</div>
|
|
1829
|
-
<button id="btn-toggle-codec-json" class="btn btn-sm btn-primary">Load</button>
|
|
1830
|
-
</div>
|
|
1831
|
-
</div>
|
|
1832
|
-
|
|
1833
|
-
<!-- ieee card -->
|
|
1834
|
-
<div class="codec-card" id="card-codec-ieee">
|
|
1835
|
-
<div class="codec-card-top">
|
|
1836
|
-
<div class="codec-card-title">
|
|
1837
|
-
<span class="codec-icon">🧮</span>
|
|
1838
|
-
<span class="codec-name">ieee</span>
|
|
1839
|
-
<span id="codec-badge-ieee" class="codec-status-badge">Inactive</span>
|
|
1840
|
-
</div>
|
|
1841
|
-
<div class="codec-types">Target: <span class="badge-type">$float</span></div>
|
|
1842
|
-
<div class="codec-desc">IEEE 754 floating point numbers serialized to sign, exponent, and mantissa fields.</div>
|
|
1843
|
-
</div>
|
|
1844
|
-
<div class="codec-card-footer">
|
|
1845
|
-
<div class="codec-caps">
|
|
1846
|
-
<span class="cap-badge print">Serializer</span>
|
|
1847
|
-
<span class="cap-badge parse">Deserializer</span>
|
|
1848
|
-
</div>
|
|
1849
|
-
<button id="btn-toggle-codec-ieee" class="btn btn-sm btn-primary">Load</button>
|
|
1850
|
-
</div>
|
|
1851
|
-
</div>
|
|
1852
|
-
</div>
|
|
1853
|
-
</div>
|
|
1854
|
-
|
|
1855
|
-
<!-- Section 2: Active Registered Codecs -->
|
|
1856
|
-
<div class="codecs-section">
|
|
1857
|
-
<div class="codecs-section-header">
|
|
1858
|
-
<h4>Active Registered Codecs in Current Session</h4>
|
|
1859
|
-
<span class="section-subtitle">Active codecs intercept evaluation formatting and :input commands</span>
|
|
1860
|
-
</div>
|
|
1861
|
-
<div class="codecs-table-container">
|
|
1862
|
-
<table class="codec-table">
|
|
1863
|
-
<thead>
|
|
1864
|
-
<tr>
|
|
1865
|
-
<th>Codec Name</th>
|
|
1866
|
-
<th>Target Type Binding</th>
|
|
1867
|
-
<th>Capabilities</th>
|
|
1868
|
-
<th>Source</th>
|
|
1869
|
-
<th>Action</th>
|
|
1870
|
-
</tr>
|
|
1871
|
-
</thead>
|
|
1872
|
-
<tbody id="active-codecs-tbody">
|
|
1873
|
-
<!-- dynamically populated by renderCodecsModal() -->
|
|
1874
|
-
</tbody>
|
|
1875
|
-
</table>
|
|
1876
|
-
</div>
|
|
1877
|
-
</div>
|
|
1878
|
-
|
|
1879
|
-
<!-- Section 3: Custom Codec Studio -->
|
|
1880
|
-
<div class="codecs-section">
|
|
1881
|
-
<div class="codecs-section-header">
|
|
1882
|
-
<h4>Custom Serializer & Deserializer Studio</h4>
|
|
1883
|
-
<span class="section-subtitle">Create and test custom domain formats (e.g. Yes/No booleans, Hex, Currency, Dates)</span>
|
|
1884
|
-
</div>
|
|
1885
|
-
|
|
1886
|
-
<div class="codec-studio-box">
|
|
1887
|
-
<div class="studio-top-bar">
|
|
1888
|
-
<div class="studio-field">
|
|
1889
|
-
<label for="codec-preset-select">Preset Template:</label>
|
|
1890
|
-
<select id="codec-preset-select">
|
|
1891
|
-
<option value="yn">Yes / No ($bool)</option>
|
|
1892
|
-
<option value="hex">Hexadecimal 0x... ($int)</option>
|
|
1893
|
-
<option value="currency">Currency $XX.YY ($int cents)</option>
|
|
1894
|
-
<option value="blank">Blank / Custom</option>
|
|
1895
|
-
</select>
|
|
1896
|
-
</div>
|
|
1897
|
-
|
|
1898
|
-
<div class="studio-field">
|
|
1899
|
-
<label for="codec-custom-name">Codec Name:</label>
|
|
1900
|
-
<input type="text" id="codec-custom-name" placeholder="e.g. yn" value="yn">
|
|
1901
|
-
</div>
|
|
1902
|
-
|
|
1903
|
-
<div class="studio-field" style="flex: 1;">
|
|
1904
|
-
<label for="codec-custom-type">Target Type:</label>
|
|
1905
|
-
<select id="codec-custom-type">
|
|
1906
|
-
<!-- populated dynamically from state.typeAliases -->
|
|
1907
|
-
</select>
|
|
1908
|
-
</div>
|
|
1909
|
-
</div>
|
|
1910
|
-
|
|
1911
|
-
<div class="studio-editors-grid">
|
|
1912
|
-
<div class="studio-editor-pane">
|
|
1913
|
-
<div class="pane-title">
|
|
1914
|
-
<span class="cap-badge parse">Deserializer (parse)</span>
|
|
1915
|
-
<span class="pane-hint"><code>(text, context) => Value</code></span>
|
|
1916
|
-
</div>
|
|
1917
|
-
<textarea id="codec-custom-parse" class="codec-code-area" spellcheck="false" rows="7"></textarea>
|
|
1918
|
-
</div>
|
|
1919
|
-
|
|
1920
|
-
<div class="studio-editor-pane">
|
|
1921
|
-
<div class="pane-title">
|
|
1922
|
-
<span class="cap-badge print">Serializer (print)</span>
|
|
1923
|
-
<span class="pane-hint"><code>(value, context) => string</code></span>
|
|
1924
|
-
</div>
|
|
1925
|
-
<textarea id="codec-custom-print" class="codec-code-area" spellcheck="false" rows="7"></textarea>
|
|
1926
|
-
</div>
|
|
1927
|
-
</div>
|
|
1928
|
-
|
|
1929
|
-
<div class="studio-test-bar">
|
|
1930
|
-
<div class="studio-test-input-wrap">
|
|
1931
|
-
<label for="codec-test-input">Test Input:</label>
|
|
1932
|
-
<input type="text" id="codec-test-input" placeholder="e.g. yes or 0xFF or $42.50" value="yes">
|
|
1933
|
-
</div>
|
|
1934
|
-
<button id="btn-test-parse" class="btn btn-secondary btn-sm" title="Test parse function against test input">🧪 Test Parse</button>
|
|
1935
|
-
<button id="btn-test-print" class="btn btn-secondary btn-sm" title="Test print function against current REPL value (:val)">🖨 Test Print</button>
|
|
1936
|
-
<button id="btn-register-codec" class="btn btn-primary btn-sm" title="Register codec in active REPL state">✓ Register in REPL</button>
|
|
1937
|
-
<button id="btn-save-codec-vfs" class="btn btn-secondary btn-sm" title="Export as standalone .mjs file to VFS">💾 Save to VFS</button>
|
|
1938
|
-
</div>
|
|
1939
|
-
|
|
1940
|
-
<div id="codec-studio-status" class="studio-status-box"></div>
|
|
1747
|
+
<div id="enabled-codecs-grid" class="codec-grid">
|
|
1748
|
+
<!-- dynamically populated: cards for only enabled/loaded codecs -->
|
|
1941
1749
|
</div>
|
|
1942
1750
|
</div>
|
|
1943
1751
|
</div>
|
|
1944
1752
|
</div>
|
|
1945
1753
|
</div>
|
|
1946
1754
|
|
|
1947
|
-
<!-- Input Popup Modal -->
|
|
1948
|
-
<div id="input-popup-modal" class="modal">
|
|
1949
|
-
<div class="modal-dialog input-popup-dialog">
|
|
1950
|
-
<div class="modal-header">
|
|
1951
|
-
<div style="display: flex; align-items: center; gap: 10px;">
|
|
1952
|
-
<h3>📥 Codec Input</h3>
|
|
1953
|
-
<span class="engine-badge">:input directive</span>
|
|
1954
|
-
</div>
|
|
1955
|
-
<button id="btn-close-input-popup" class="btn-close">×</button>
|
|
1956
|
-
</div>
|
|
1957
|
-
<div class="modal-body input-popup-body">
|
|
1958
|
-
<div id="input-popup-banner" class="input-popup-banner">
|
|
1959
|
-
<span id="input-popup-hint">Enter input string to deserialize into a K algebraic value:</span>
|
|
1960
|
-
</div>
|
|
1961
|
-
|
|
1962
|
-
<div class="input-popup-form-row">
|
|
1963
|
-
<div class="studio-field" style="flex: 1;">
|
|
1964
|
-
<label for="input-popup-type">Target Type:</label>
|
|
1965
|
-
<select id="input-popup-type">
|
|
1966
|
-
<!-- populated dynamically -->
|
|
1967
|
-
</select>
|
|
1968
|
-
</div>
|
|
1969
|
-
<div class="studio-field" style="flex: 1;">
|
|
1970
|
-
<label for="input-popup-codec">Deserializer Codec:</label>
|
|
1971
|
-
<select id="input-popup-codec">
|
|
1972
|
-
<!-- populated dynamically -->
|
|
1973
|
-
</select>
|
|
1974
|
-
</div>
|
|
1975
|
-
</div>
|
|
1976
|
-
|
|
1977
|
-
<div class="input-popup-field">
|
|
1978
|
-
<div class="pane-title" style="margin-bottom: 6px;">
|
|
1979
|
-
<label for="input-popup-text" style="font-size: 11px; color: var(--text-muted); font-weight: 500;">Input String / Payload:</label>
|
|
1980
|
-
<span class="pane-hint">Enter: submit • Shift+Enter: newline</span>
|
|
1981
|
-
</div>
|
|
1982
|
-
<textarea id="input-popup-text" class="input-popup-textarea" rows="4" spellcheck="false" placeholder="Type or paste input string (e.g. 42, yes, hello, {...})..."></textarea>
|
|
1983
|
-
</div>
|
|
1984
|
-
|
|
1985
|
-
<div id="input-popup-samples" class="input-popup-samples">
|
|
1986
|
-
<span class="samples-label">Quick samples:</span>
|
|
1987
|
-
<div id="input-samples-list" class="samples-list"></div>
|
|
1988
|
-
</div>
|
|
1989
|
-
|
|
1990
|
-
<div id="input-popup-status" class="input-popup-status"></div>
|
|
1991
|
-
|
|
1992
|
-
<div class="input-popup-actions">
|
|
1993
|
-
<button id="btn-cancel-input" class="btn btn-secondary">Cancel</button>
|
|
1994
|
-
<button id="btn-submit-input" class="btn btn-primary">✓ Submit to REPL</button>
|
|
1995
|
-
</div>
|
|
1996
|
-
</div>
|
|
1997
|
-
</div>
|
|
1998
|
-
</div>
|
|
1999
1755
|
|
|
2000
1756
|
<!-- Help Modal -->
|
|
2001
1757
|
<div id="help-modal" class="modal">
|
|
@@ -2005,22 +1761,112 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
2005
1761
|
<button id="btn-close-help" class="btn-close">×</button>
|
|
2006
1762
|
</div>
|
|
2007
1763
|
<div class="modal-body help-body">
|
|
1764
|
+
<div class="help-section">
|
|
1765
|
+
<h4>Language Overview</h4>
|
|
1766
|
+
<p style="margin-bottom: 8px; color: var(--text-muted); line-height: 1.45;">
|
|
1767
|
+
<b>k</b> is a concise language of <b>types</b> and <b>relations</b> (functions) over tree-like (JSON-like) documents. Every expression denotes a relation that transforms an input document into an output document.
|
|
1768
|
+
</p>
|
|
1769
|
+
<p style="margin-bottom: 10px; color: var(--text-muted); line-height: 1.45;">
|
|
1770
|
+
<b>Content-Addressed:</b> Functions and types are identified by their canonical content hash (<code>@...</code>) derived directly from their structure. Local names are just temporary aliases used for recursion and readability.
|
|
1771
|
+
</p>
|
|
1772
|
+
|
|
1773
|
+
<div class="help-category-title">1. Definitions (Local Aliases)</div>
|
|
1774
|
+
<p style="margin-bottom: 6px; color: var(--text-muted); font-size: 12px;">Definitions introduce local aliases for recursion and convenience (terminated by <code>;</code>):</p>
|
|
1775
|
+
<table class="help-table">
|
|
1776
|
+
<thead>
|
|
1777
|
+
<tr><th style="width: 38%;">Syntax</th><th>Description & Example</th></tr>
|
|
1778
|
+
</thead>
|
|
1779
|
+
<tbody>
|
|
1780
|
+
<tr>
|
|
1781
|
+
<td><code>name = relExpr;</code></td>
|
|
1782
|
+
<td><b>Relation Alias:</b> Defines a local alias for a relation expression.<br><i>e.g.</i> <code>swap = { . y x, . x y };</code></td>
|
|
1783
|
+
</tr>
|
|
1784
|
+
<tr>
|
|
1785
|
+
<td><code>$ name = typeExpr;</code></td>
|
|
1786
|
+
<td><b>Type Alias:</b> Defines a local alias for a type schema.<br><i>e.g.</i> <code>$ bool = < {} true, {} false >;</code></td>
|
|
1787
|
+
</tr>
|
|
1788
|
+
</tbody>
|
|
1789
|
+
</table>
|
|
1790
|
+
|
|
1791
|
+
<div class="help-category-title">2. Type Expressions (<code>typeExpr</code>)</div>
|
|
1792
|
+
<p style="margin-bottom: 6px; color: var(--text-muted); font-size: 12px;">Schemas describing tree-like documents:</p>
|
|
1793
|
+
<table class="help-table">
|
|
1794
|
+
<thead>
|
|
1795
|
+
<tr><th style="width: 45%;">Syntax</th><th>Description</th></tr>
|
|
1796
|
+
</thead>
|
|
1797
|
+
<tbody>
|
|
1798
|
+
<tr>
|
|
1799
|
+
<td><code>{ Type_1 label_1, ..., Type_k label_k }</code></td>
|
|
1800
|
+
<td><b>Product Type:</b> Labeled record of arity <i>k</i> (e.g. <code>{float64 x, string n}</code>; special case: <code>{}</code> is the 0-ary product)</td>
|
|
1801
|
+
</tr>
|
|
1802
|
+
<tr>
|
|
1803
|
+
<td><code>< Type_1 tag_1, ..., Type_k tag_k ></code></td>
|
|
1804
|
+
<td><b>Union Type:</b> Tagged sum of <i>k</i> variants (e.g. <code><int ok, string err></code>)</td>
|
|
1805
|
+
</tr>
|
|
1806
|
+
<tr>
|
|
1807
|
+
<td><code>name</code> / <code>@hash</code></td>
|
|
1808
|
+
<td><b>Type Reference:</b> References a type by local alias or canonical content hash</td>
|
|
1809
|
+
</tr>
|
|
1810
|
+
</tbody>
|
|
1811
|
+
</table>
|
|
1812
|
+
|
|
1813
|
+
<div class="help-category-title">3. Relation Expressions (<code>relExpr</code>)</div>
|
|
1814
|
+
<p style="margin-bottom: 6px; color: var(--text-muted); font-size: 12px;">Functions transforming an input document to an output document:</p>
|
|
1815
|
+
<table class="help-table">
|
|
1816
|
+
<thead>
|
|
1817
|
+
<tr><th style="width: 45%;">Syntax</th><th>Description</th></tr>
|
|
1818
|
+
</thead>
|
|
1819
|
+
<tbody>
|
|
1820
|
+
<tr>
|
|
1821
|
+
<td><code>{ rel_1 label_1, ..., rel_k label_k }</code></td>
|
|
1822
|
+
<td><b>Product:</b> Evaluates <i>k</i> relations into record fields (special case: <code>{}</code> evaluates 0 relations, producing empty record <code>{}</code>)</td>
|
|
1823
|
+
</tr>
|
|
1824
|
+
<tr>
|
|
1825
|
+
<td><code>< rel_1, ..., rel_k ></code></td>
|
|
1826
|
+
<td><b>Union (Choice):</b> Evaluates relations in order of arity <i>k</i> (tries <code>rel_1</code>; if it fails, tries <code>rel_2</code>, ..., <code>rel_k</code>)</td>
|
|
1827
|
+
</tr>
|
|
1828
|
+
<tr>
|
|
1829
|
+
<td><code>( rel_1 ... rel_k )</code></td>
|
|
1830
|
+
<td><b>Composition:</b> Sequentially composes <i>k</i> relations (special case: <code>()</code> is the 0-ary composition, denoting identity; parentheses may be omitted when non-empty: <code>f g</code>)</td>
|
|
1831
|
+
</tr>
|
|
1832
|
+
<tr>
|
|
1833
|
+
<td><code>. label</code></td>
|
|
1834
|
+
<td><b>Field Projection:</b> Extracts field <code>label</code> from a record</td>
|
|
1835
|
+
</tr>
|
|
1836
|
+
<tr>
|
|
1837
|
+
<td><code>/ tag</code></td>
|
|
1838
|
+
<td><b>Variant Branch:</b> Extracts payload of variant <code>tag</code> (fails if tag differs)</td>
|
|
1839
|
+
</tr>
|
|
1840
|
+
<tr>
|
|
1841
|
+
<td><code>| tag</code></td>
|
|
1842
|
+
<td><b>Variant Constructor:</b> Wraps document into variant <code>tag</code></td>
|
|
1843
|
+
</tr>
|
|
1844
|
+
<tr>
|
|
1845
|
+
<td><code>$ typeExpr</code></td>
|
|
1846
|
+
<td><b>Type Constraint:</b> Asserts input matches <code>typeExpr</code> (compile-time Type Error on mismatch)</td>
|
|
1847
|
+
</tr>
|
|
1848
|
+
<tr>
|
|
1849
|
+
<td><code>name</code> / <code>@hash</code></td>
|
|
1850
|
+
<td><b>Relation Reference:</b> Calls a relation by local alias or canonical content hash</td>
|
|
1851
|
+
</tr>
|
|
1852
|
+
</tbody>
|
|
1853
|
+
</table>
|
|
1854
|
+
</div>
|
|
1855
|
+
|
|
2008
1856
|
<div class="help-section">
|
|
2009
1857
|
<h4>REPL Commands</h4>
|
|
2010
1858
|
<table class="help-table">
|
|
2011
1859
|
<tr><td><code>:load <file></code></td><td>Load a <code>.k</code> source or <code>.klib</code> library into current state</td></tr>
|
|
2012
1860
|
<tr><td><code>:t <name></code></td><td>Display the derived type of relation <code><name></code></td></tr>
|
|
2013
1861
|
<tr><td><code>:d <name></code></td><td>Display definition of relation <code><name></code></td></tr>
|
|
2014
|
-
<tr><td><code>:type <name></code></td><td>
|
|
2015
|
-
<tr><td><code>:
|
|
2016
|
-
<tr><td><code>:codes</code></td><td>List all type aliases</td></tr>
|
|
1862
|
+
<tr><td><code>:type <name></code></td><td>Display definition of type <code><name></code></td></tr>
|
|
1863
|
+
<tr><td><code>:codes</code></td><td>List all type aliases and canonical hashes</td></tr>
|
|
2017
1864
|
<tr><td><code>:rels</code></td><td>List all relation aliases</td></tr>
|
|
2018
|
-
<tr><td><code>:codecs</code></td><td>List all loaded codecs
|
|
2019
|
-
<tr><td><code>:codec load <
|
|
2020
|
-
<tr><td><code>:codec
|
|
2021
|
-
<tr><td><code>:
|
|
2022
|
-
<tr><td><code>:
|
|
2023
|
-
<tr><td><code>:val</code></td><td>Print current accumulator value</td></tr>
|
|
1865
|
+
<tr><td><code>:codecs</code></td><td>List all loaded format codecs</td></tr>
|
|
1866
|
+
<tr><td><code>:codec load <file.mjs></code></td><td>Load a codec from file (or load through Files)</td></tr>
|
|
1867
|
+
<tr><td><code>:codec unload <file.mjs></code></td><td>Unload a loaded codec</td></tr>
|
|
1868
|
+
<tr><td><code>:input <codec.mjs> [text]</code></td><td>Parse input using specified codec (opens dialog if text omitted)</td></tr>
|
|
1869
|
+
<tr><td><code>:time <expr></code></td><td>Evaluate <code><expr></code> and report execution time</td></tr>
|
|
2024
1870
|
<tr><td><code>:klib <file></code></td><td>Export current state as a <code>.klib</code> binary file</td></tr>
|
|
2025
1871
|
<tr><td><code>:reset</code></td><td>Clear state and reset to initial environment</td></tr>
|
|
2026
1872
|
<tr><td><code>:help</code></td><td>Show command reference</td></tr>
|
|
@@ -2031,10 +1877,13 @@ const htmlContent = `<!DOCTYPE html>
|
|
|
2031
1877
|
<h4>Expressions & Snippets</h4>
|
|
2032
1878
|
<p style="margin-bottom: 8px; color: var(--text-muted);">Any raw K expression entered at the prompt is compiled and evaluated on top of the current state using WebAssembly.</p>
|
|
2033
1879
|
<ul>
|
|
2034
|
-
<li><code>
|
|
2035
|
-
<li><code>
|
|
2036
|
-
<li><code>
|
|
2037
|
-
<li><code>$
|
|
1880
|
+
<li><code>{} | ok</code> — Constant relation producing variant <code>ok</code> with empty document payload <code>{}</code></li>
|
|
1881
|
+
<li><code>not = < / true | false, / false | true >;</code> — Polymorphic negation via branch projections and ordered choice</li>
|
|
1882
|
+
<li><code>{} | true not</code> — Compose constant relation <code>{} | true</code> with <code>not</code> (evaluates to <code>{} | false</code>)</li>
|
|
1883
|
+
<li><code>$ bool = < {} true, {} false >;</code> — Define a boolean union type schema</li>
|
|
1884
|
+
<li><code>not = $ bool < / true | false, {} | true > $ bool;</code> — Typed boolean negation: guarded by <code>$ bool</code>, defaulting to <code>{} | true</code></li>
|
|
1885
|
+
<li><code>swap = { . y x, . x y };</code> — Define a product field-swapping relation</li>
|
|
1886
|
+
<li><code>{ {} | ok x, {} | nil y } swap</code> — Construct a product and pass it through <code>swap</code></li>
|
|
2038
1887
|
</ul>
|
|
2039
1888
|
</div>
|
|
2040
1889
|
|