@fraczak/k 6.8.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.
@@ -160,6 +160,9 @@ export function parse(text) {
160
160
  }
161
161
 
162
162
  export function print(value) {
163
+ if (!value || (value.tag !== "true" && value.tag !== "false")) {
164
+ throw new Error("expected true or false");
165
+ }
163
166
  return value.tag;
164
167
  }
165
168
  `);
@@ -172,58 +175,52 @@ assert(completions.includes(":codec list"));
172
175
  completions = completeInput(`:codec load ${tmpDir}/bool`, codecState)[0];
173
176
  assert(completions.includes(`:codec load ${codecPath}`));
174
177
  output = await evaluateInput(`:codec load ${codecPath}`, codecState);
175
- assert.equal(output[0], `loaded codec yn for ${boolHash}`);
178
+ assert.equal(output[0], `loaded codec bool-codec.mjs`);
176
179
  output = await evaluateInput(":codec list", codecState);
177
- assert.match(output[0], new RegExp(`^yn ${boolHash.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`));
178
- completions = completeInput(":input bo", codecState)[0];
179
- assert(completions.includes(":input bool"));
180
- completions = completeInput(":input bool y", codecState)[0];
181
- assert(completions.includes(":input bool yn"));
182
- output = await evaluateInput(":input bool yn", codecState);
183
- assert.equal(output[0], `input ${boolHash} using yn: enter value text`);
180
+ assert.match(output[0], /^bool-codec\.mjs/);
181
+ completions = completeInput(":input", codecState)[0];
182
+ assert(completions.includes(":input"));
183
+ completions = completeInput(":input ", codecState)[0];
184
+ assert(completions.includes(":input bool-codec.mjs"));
185
+ completions = completeInput(":input b", codecState)[0];
186
+ assert(completions.includes(":input bool-codec.mjs"));
187
+ output = await evaluateInput(":input bool-codec.mjs", codecState);
188
+ assert.equal(promptForState(codecState), "bool-codec.mjs> ");
184
189
  output = await evaluateInput("true", codecState);
185
190
  assert.match(output[0], /\{\}\|true \?</);
186
- assert.match(output[0], /yn: true/);
191
+ assert.match(output[0], /bool-codec\.mjs: true/);
187
192
  output = await evaluateInput("{} | false", codecState);
188
- assert.doesNotMatch(output[0], /yn: false/);
193
+ assert.match(output[0], /bool-codec\.mjs: false/);
194
+ output = await evaluateInput("{}", codecState);
195
+ assert.doesNotMatch(output[0], /bool-codec\.mjs:/);
189
196
 
190
197
  const utf8State = createState();
191
198
  output = await evaluateInput(":load core.k", utf8State);
192
199
  assert.equal(output[0], "loaded core.k");
193
200
  output = await evaluateInput(":codec load ./codecs/utf8.mjs", utf8State);
194
- assert.equal(output[0], `loaded codec utf8 for ${utf8State.typeAliases.string}`);
195
- output = await evaluateInput(":input string utf8", utf8State);
196
- assert.equal(output[0], `input ${utf8State.typeAliases.string} using utf8: enter value text`);
197
- output = await evaluateInput("hello", utf8State);
198
- assert.match(output[0], /utf8: hello/);
201
+ assert.equal(output[0], `loaded codec utf8.mjs`);
202
+ output = await evaluateInput(":input utf8.mjs hello", utf8State);
203
+ assert.match(output[0], /utf8\.mjs: hello/);
199
204
 
200
205
  const jsonState = createState();
201
- output = await evaluateInput("$ bool = < {} true, {} false >;", jsonState);
202
206
  output = await evaluateInput(":codec load ./codecs/json.mjs", jsonState);
203
- assert.match(output[0], /^loaded codec json for all types/);
207
+ assert.match(output[0], /^loaded codec json\.mjs/);
204
208
  output = await evaluateInput(":codec list", jsonState);
205
- assert.match(output[0], /^json all /);
206
- completions = completeInput(":input bool j", jsonState)[0];
207
- assert(completions.includes(":input bool json"));
208
- output = await evaluateInput(":input bool", jsonState);
209
- assert.equal(output[0], `input ${jsonState.typeAliases.bool}: enter value text`);
210
- assert.equal(promptForState(jsonState), "json> ");
209
+ assert.match(output[0], /^json\.mjs/);
210
+ completions = completeInput(":input j", jsonState)[0];
211
+ assert(completions.includes(":input json.mjs"));
212
+ output = await evaluateInput(":input json.mjs", jsonState);
213
+ assert.equal(promptForState(jsonState), "json.mjs> ");
211
214
  output = await evaluateInput("true", jsonState);
212
215
  assert.match(output[0], /\{\}\|true \?</);
213
- assert.match(output[0], /json: true/);
216
+ assert.match(output[0], /json\.mjs: true/);
214
217
  assert.equal(promptForState(jsonState), "> ");
215
- output = await evaluateInput(":input <{}true,{}false>", jsonState);
216
- assert.equal(output[0], `input ${jsonState.typeAliases.bool}: enter value text`);
217
- assert.equal(promptForState(jsonState), "json> ");
218
- output = await evaluateInput("false", jsonState);
218
+ output = await evaluateInput(":input json.mjs false", jsonState);
219
219
  assert.match(output[0], /\{\}\|false \?</);
220
- assert.match(output[0], /json: false/);
220
+ assert.match(output[0], /json\.mjs: false/);
221
221
  assert.equal(promptForState(jsonState), "> ");
222
- output = await evaluateInput(":input {bool left, bool right} json", jsonState);
223
- assert.match(output[0], /^input @[^ ]+ using json: enter value text$/);
224
- assert.equal(promptForState(jsonState), "json> ");
225
- output = await evaluateInput('{"left":true,"right":false}', jsonState);
226
- assert.match(output[0], /json: \{"left":true,"right":false\}/);
222
+ output = await evaluateInput(':input json.mjs {"left":true,"right":false}', jsonState);
223
+ assert.match(output[0], /json\.mjs: \{"left":true,"right":false\}/);
227
224
  assert.equal(promptForState(jsonState), "> ");
228
225
 
229
226
  const replPath = fileURLToPath(new URL("../repl.mjs", import.meta.url));
@@ -302,41 +299,45 @@ assert.match(output[0], /^\{\}\|_\|0\|1\|0\|1/);
302
299
  output = await evaluateInput("{10 int x, 5 int y} plus", arithState);
303
300
  assert.match(output[0], /^\{\}\|_\|1\|1\|1\|1\|\+/);
304
301
 
305
- // Verify built-in codecs, :codecs, and :codec unload
302
+ // Verify codecs loading, listing, and unloading
306
303
  const codecTestState = createState();
307
304
  output = await evaluateInput(":codecs", codecTestState);
308
305
  assert.equal(output[0], "(none)");
309
306
 
310
- output = await evaluateInput(":codec load int", codecTestState);
311
- assert.match(output[0], /^loaded codec int for @/);
307
+ output = await evaluateInput(":codec load ./codecs/int.mjs", codecTestState);
308
+ assert.match(output[0], /^loaded codec int\.mjs/);
312
309
 
313
310
  output = await evaluateInput(":codecs", codecTestState);
314
- assert.match(output[0], /^int @/);
311
+ assert.match(output[0], /^int\.mjs/);
315
312
 
316
313
  completions = completeInput(":codec un", codecTestState)[0];
317
314
  assert(completions.includes(":codec unload"));
318
315
  completions = completeInput(":codec unload ", codecTestState)[0];
319
- assert(completions.includes(":codec unload int"));
320
- completions = completeInput(":codec load i", codecTestState)[0];
321
- assert(completions.includes(":codec load int"));
316
+ assert(completions.includes(":codec unload int.mjs"));
317
+ completions = completeInput(":codec load ./codecs/i", codecTestState)[0];
318
+ assert(completions.includes(":codec load ./codecs/int.mjs"));
322
319
 
323
- output = await evaluateInput(":codec unload int", codecTestState);
324
- assert.equal(output[0], "unloaded codec int");
320
+ output = await evaluateInput(":codec unload int.mjs", codecTestState);
321
+ assert.equal(output[0], "unloaded codec int.mjs");
325
322
  output = await evaluateInput(":codecs", codecTestState);
326
323
  assert.equal(output[0], "(none)");
327
324
 
328
325
  output = await evaluateInput("$ bool = < {} true, {} false >;", codecTestState);
329
326
  registerCodec(codecTestState, {
330
- name: "yn",
331
- codes: [codecTestState.typeAliases.bool],
332
- universal: false,
327
+ name: "yn.mjs",
333
328
  parse: (text) => Value.variant(text.trim() === "yes" ? "true" : "false", Value.product({})),
334
- print: (v) => v.tag === "true" ? "YES" : "NO"
335
- }, "<test>");
336
-
337
- output = await evaluateInput(":input bool yn", codecTestState);
329
+ print: (v) => {
330
+ if (v.tag !== "true" && v.tag !== "false") throw new Error("not a bool");
331
+ return v.tag === "true" ? "YES" : "NO";
332
+ }
333
+ }, "yn.mjs");
334
+
335
+ output = await evaluateInput(":input yn.mjs", codecTestState);
336
+ assert.equal(promptForState(codecTestState), "yn.mjs> ");
338
337
  output = await evaluateInput("yes", codecTestState);
339
- assert.match(output[0], /yn: YES/);
338
+ assert.match(output[0], /yn\.mjs: YES/);
339
+ output = await evaluateInput(":input yn.mjs no", codecTestState);
340
+ assert.match(output[0], /yn\.mjs: NO/);
340
341
 
341
342
  // Projection on product with variant field (avoids filter variable collisions)
342
343
  const projState = createState();
@@ -351,103 +352,88 @@ assert.match(output[0], /^\{\{\}\|a a, \{\} y\}/);
351
352
  output = await evaluateInput(".a", projState2);
352
353
  assert.match(output[0], /^\{\}\|a/);
353
354
 
354
- // Auto-loading dependencies and bidirectional type aliasing tests
355
- const autoLoadState = createState();
356
- output = await evaluateInput(":codec load int", autoLoadState);
357
- assert.match(output[0], /auto-loaded (?:Examples\/)?arithmetics\.k/);
358
- assert.ok(autoLoadState.typeAliases.int, "int type alias should be registered");
359
- output = await evaluateInput(":input int", autoLoadState);
360
- output = await evaluateInput("123", autoLoadState);
361
- assert.match(output[0], /int: 123/);
355
+ // Explicit loading of dependencies and codec testing (no auto-loading)
356
+ const intState = createState();
357
+ await evaluateInput(":load Examples/arithmetics.k", intState);
358
+ output = await evaluateInput(":codec load ./codecs/int.mjs", intState);
359
+ assert.match(output[0], /^loaded codec int\.mjs/);
360
+ output = await evaluateInput(":input int.mjs", intState);
361
+ output = await evaluateInput("123", intState);
362
+ assert.match(output[0], /int\.mjs: 123/);
363
+ output = await evaluateInput(":input int.mjs", intState);
364
+ output = await evaluateInput("[0,1,2]", intState);
365
+ assert.match(output[0], /int\.mjs: \[0,1,2\]/);
362
366
 
363
367
  const utf8AutoState = createState();
364
- output = await evaluateInput(":codec load utf8", utf8AutoState);
365
- assert.match(output[0], /auto-loaded core\.k/);
366
- assert.ok(utf8AutoState.typeAliases.utf8, "utf8 type alias should be registered");
367
- assert.ok(utf8AutoState.typeAliases.string, "string type alias should be registered");
368
- assert.equal(utf8AutoState.typeAliases.utf8, utf8AutoState.typeAliases.string);
369
- output = await evaluateInput(":input utf8", utf8AutoState);
368
+ await evaluateInput(":load core.k", utf8AutoState);
369
+ output = await evaluateInput(":codec load ./codecs/utf8.mjs", utf8AutoState);
370
+ assert.match(output[0], /^loaded codec utf8\.mjs/);
371
+ output = await evaluateInput(":input utf8.mjs", utf8AutoState);
370
372
  output = await evaluateInput("test utf8", utf8AutoState);
371
- assert.match(output[0], /utf8: test utf8/);
373
+ assert.match(output[0], /utf8\.mjs: test utf8/);
372
374
 
373
375
  const ieeeAutoState = createState();
374
- output = await evaluateInput(":codec load ieee", ieeeAutoState);
375
- assert.match(output[0], /auto-loaded (?:Examples\/)?ieee\.k/);
376
+ await evaluateInput(":load Examples/ieee.k", ieeeAutoState);
377
+ output = await evaluateInput(":codec load ./codecs/ieee.mjs", ieeeAutoState);
378
+ assert.match(output[0], /^loaded codec ieee\.mjs/);
376
379
  assert.ok(ieeeAutoState.typeAliases.ieee, "ieee type alias should be registered");
377
- assert.ok(ieeeAutoState.typeAliases.float64, "float64 type alias should be registered");
378
- assert.equal(ieeeAutoState.typeAliases.ieee, ieeeAutoState.typeAliases.float64);
379
380
 
380
381
  const jsonInputState = createState();
381
382
  await evaluateInput(":load core.k", jsonInputState);
382
- await evaluateInput(":load ieee.k", jsonInputState);
383
- await evaluateInput(":codec load json", jsonInputState);
384
- output = await evaluateInput(":input {string a, float64 n}", jsonInputState);
385
- assert.match(output[0], /enter value text/);
386
- output = await evaluateInput('{"a":"Woj","n":123}', jsonInputState);
387
- assert.match(output[0], /json: \{"a":"Woj","n":123\}/);
388
-
389
- // Verify pattern expressions and standalone codec input
390
- const patternInputState = createState();
391
- await evaluateInput(":codec load json", patternInputState);
392
-
393
- // 1. Explicit pattern expression: ? {string a, float64 n} json
394
- output = await evaluateInput(":input ? {string a, float64 n} json", patternInputState);
395
- assert.match(output[0], /input \? \{string a, float64 n\} using json: enter value text/);
396
- output = await evaluateInput('{"a":"Woj","n":123}', patternInputState);
397
- assert.match(output[0], /json: \{"a":"Woj","n":123\}/);
398
-
399
- // 2. Wildcard pattern expression: ? (...) json
400
- output = await evaluateInput(":input ? (...) json", patternInputState);
401
- assert.match(output[0], /enter value text/);
402
- output = await evaluateInput('{"anything": [1, 2, 3]}', patternInputState);
403
- assert.match(output[0], /json: \{"anything":\[1,2,3\]\}/);
404
-
405
- // 3. Standalone codec input: :input json (no predefined type or pattern required)
406
- output = await evaluateInput(":input json", patternInputState);
407
- assert.match(output[0], /input json: enter value text/);
408
- output = await evaluateInput('{"hello":"world"}', patternInputState);
409
- assert.match(output[0], /json: \{"hello":"world"\}/);
410
-
411
- // 4. Pattern mismatch detection
412
- output = await evaluateInput(":input ? {string a, float64 n} json", patternInputState);
413
- await assert.rejects(
414
- () => evaluateInput('{"wrong_key": 999}', patternInputState),
415
- /Closed product pattern does not match value fields/
416
- );
417
-
418
- // 5. Bare :input defaults to :input (...) with auto-loaded json codec
383
+ await evaluateInput(":load Examples/ieee.k", jsonInputState);
384
+ await evaluateInput(":codec load ./codecs/json.mjs", jsonInputState);
385
+ output = await evaluateInput(':input json.mjs {"a":"Woj","n":123}', jsonInputState);
386
+ assert.match(output[0], /json\.mjs: \{"a":"Woj","n":123\}/);
387
+
388
+ // Verify standalone codec input, one-line and interactive modes, and multi-codec printing
389
+ const multiCodecState = createState();
390
+ await evaluateInput(":codec load ./codecs/json.mjs", multiCodecState);
391
+ await evaluateInput(":codec load ./codecs/utf8.mjs", multiCodecState);
392
+ await evaluateInput(":codec load ./codecs/int.mjs", multiCodecState);
393
+
394
+ // 1. One-line JSON input: :input json.mjs {"hello":"world"}
395
+ output = await evaluateInput(':input json.mjs {"hello":"world"}', multiCodecState);
396
+ assert.match(output[0], /json\.mjs: \{"hello":"world"\}/);
397
+
398
+ // 2. Interactive JSON input: :input json.mjs then {"anything": [1, 2, 3]}
399
+ output = await evaluateInput(":input json.mjs", multiCodecState);
400
+ assert.equal(promptForState(multiCodecState), "json.mjs> ");
401
+ output = await evaluateInput('{"anything": [1, 2, 3]}', multiCodecState);
402
+ assert.match(output[0], /json\.mjs: \{"anything":\[1,2,3\]\}/);
403
+ assert.equal(promptForState(multiCodecState), "> ");
404
+
405
+ // 3. Integer scalar and list input
406
+ output = await evaluateInput(":input int.mjs 42", multiCodecState);
407
+ assert.match(output[0], /int\.mjs: 42/);
408
+
409
+ output = await evaluateInput(":input int.mjs [0,1,2]", multiCodecState);
410
+ assert.match(output[0], /int\.mjs: \[0,1,2\]/);
411
+
412
+ // 4. Bare :input displays usage and loaded codecs
419
413
  const bareInputState = createState();
420
- assert.equal(promptForState(bareInputState), "> ");
421
414
  output = await evaluateInput(":input", bareInputState);
422
- assert.deepEqual(output, ["input (...): enter value text"]);
423
- assert.equal(promptForState(bareInputState), "json> ");
424
- output = await evaluateInput('{"test": 123}', bareInputState);
425
- assert.match(output[0], /json: \{"test":123\}/);
426
- assert.equal(promptForState(bareInputState), "> ");
427
-
428
- // 6. Pattern as type prefixed by dollar
429
- const dollarPatternState = createState();
430
- await evaluateInput(":load arithmetics.k", dollarPatternState);
431
- output = await evaluateInput(":input $ int", dollarPatternState);
432
- assert.deepEqual(output, ["input $ int: enter value text"]);
433
- assert.equal(promptForState(dollarPatternState), "int> ");
434
- output = await evaluateInput("42", dollarPatternState);
435
- assert.match(output[0], /int: 42/);
436
-
437
- await evaluateInput("$ bool = <{} true, {} false>;", dollarPatternState);
438
- output = await evaluateInput(":input $ bool json", dollarPatternState);
439
- assert.deepEqual(output, ["input $ bool using json: enter value text"]);
440
- assert.equal(promptForState(dollarPatternState), "json> ");
441
- output = await evaluateInput("true", dollarPatternState);
442
- assert.match(output[0], /json: true/);
415
+ assert.match(output[0], /^Usage: :input <codec\.mjs> \[text\]/);
416
+ assert.match(output[1], /Loaded codecs:/);
417
+
418
+ // 5. Codec with leading dollar sign is accepted
419
+ output = await evaluateInput(":input $ int.mjs 42", multiCodecState);
420
+ assert.match(output[0], /int\.mjs: 42/);
421
+ output = await evaluateInput(":input $int.mjs 100", multiCodecState);
422
+ assert.match(output[0], /int\.mjs: 100/);
423
+
424
+ // 6. Unknown codec throws descriptive error
425
+ await assert.rejects(
426
+ () => evaluateInput(":input nonexistent 123", multiCodecState),
427
+ /Codec 'nonexistent' is not loaded/
428
+ );
443
429
 
444
430
  const unitState = createState();
445
- output = await evaluateInput(":codec load unit", unitState);
446
- assert.match(output[0], /loaded codec unit/);
447
- output = await evaluateInput(":input unit", unitState);
448
- assert.match(output[0], /enter value text/);
431
+ output = await evaluateInput(":codec load ./codecs/unit.mjs", unitState);
432
+ assert.match(output[0], /^loaded codec unit\.mjs/);
433
+ output = await evaluateInput(":input unit.mjs", unitState);
434
+ assert.equal(promptForState(unitState), "unit.mjs> ");
449
435
  output = await evaluateInput("{}", unitState);
450
- assert.match(output[0], /unit: \{\}/);
436
+ assert.match(output[0], /unit\.mjs: \{\}/);
451
437
 
452
438
  const polyAutoState = createState();
453
439
  output = await evaluateInput(":load Examples/poly.k", polyAutoState);
@@ -25,3 +25,20 @@ assert.equal(valueToK(foreignTwo), "{}|_|0|1|+");
25
25
 
26
26
  const decoded = decodeWire(encodeToWire(foreignTwo, INT_PATTERN)).value;
27
27
  assert.equal(printInt(decoded), "2");
28
+
29
+ const { INT_LIST_PATTERN, parse: parseIntCodec } = await import("../codecs/int.mjs");
30
+ const { valueWithEnvelopeToK } = await import("../codecs/runtime/show-value.mjs");
31
+
32
+ const parsedList = parseIntCodec("[0,1,2]");
33
+ const listWire = encodeToWire(parsedList, INT_LIST_PATTERN);
34
+ const decodedList = decodeWire(listWire).value;
35
+ assert.equal(
36
+ valueWithEnvelopeToK(decodedList),
37
+ "{{}|_|0|+ car, {{}|_|1|+ car, {{}|_|0|1|+ car, {}|nil cdr}|cons cdr}|cons cdr}|cons ?<{<<X1 0, X1 1, {}=X2 _>=X1 +, X1 -> car, X0 cdr} cons, X2 nil>=X0"
38
+ );
39
+ assert.equal(printInt(decodedList), "[0,1,2]");
40
+
41
+ const emptyList = parseIntCodec("[]");
42
+ const emptyWire = encodeToWire(emptyList, INT_LIST_PATTERN);
43
+ const decodedEmpty = decodeWire(emptyWire).value;
44
+ assert.equal(printInt(decodedEmpty), "[]");
@@ -172,6 +172,7 @@ assert.strictEqual(patTree.open, true, "Root pattern node must be open");
172
172
  assert(patTree.textContent.includes("recursive"), "Recursive cycle must be detected and marked 'recursive'");
173
173
 
174
174
  // 5. Test createOutputEntryElement
175
+ variantVal.pattern = recursivePattern;
175
176
  const entryEl = createOutputEntryElement({
176
177
  value: variantVal,
177
178
  rawText: "{}|_|1|0|1|+ ?<<X0 0, X0 1, {} _>=X0 +, X0 ->\nint: 11",
@@ -180,6 +181,8 @@ const entryEl = createOutputEntryElement({
180
181
 
181
182
  assert(entryEl.querySelector(".k-tree-view"), "Tree view container must exist");
182
183
  assert(entryEl.querySelector(".k-raw-view"), "Raw view container must exist");
184
+ assert.strictEqual(entryEl.querySelector(".k-tree-value-section")?.open, false, "Value section must be collapsed by default");
185
+ assert.strictEqual(entryEl.querySelector(".k-tree-pat-section")?.open, false, "Pattern section must be collapsed by default");
183
186
  assert(entryEl.textContent.includes("int: 11"), "Codec output must be visible in container");
184
187
 
185
188
  console.log("OK - All tree view unit tests passed.");
@@ -1,163 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Example: Demonstrating the codec pipeline
4
- *
5
- * Shows how to:
6
- * 1. Define types with canonical names
7
- * 2. Create values
8
- * 3. Encode to binary
9
- * 4. Pass through "compiled program" (identity)
10
- * 5. Decode from binary
11
- * 6. Print result
12
- */
13
-
14
- import { deriveClosedPattern } from './runtime/codec.mjs';
15
- import { encodeToWire, decodeWire } from './runtime/prefix-codec.mjs';
16
- import { patternToPropertyList } from './runtime/pattern-json.mjs';
17
- import { Value, isVariant } from '../Value.mjs';
18
- import hash from '../hash.mjs';
19
- import { argv, exit } from 'node:process';
20
-
21
- function usage() {
22
- console.log(`Usage: ${argv[1]}`);
23
- console.log(" Run a self-contained demonstration of the codec pipeline.");
24
- console.log("");
25
- console.log("Options:");
26
- console.log(" -h, --help Show this help.");
27
- }
28
-
29
- if (argv.slice(2).includes("-h") || argv.slice(2).includes("--help")) {
30
- usage();
31
- exit(0);
32
- }
33
-
34
- console.log('=== K Codec Pipeline Example ===\n');
35
-
36
- // ============================================================================
37
- // Step 1: Define types (normally from compiler)
38
- // ============================================================================
39
-
40
- const types = {};
41
-
42
- // Unit: {}
43
- const unitDef = { code: 'product', product: {} };
44
- const unitName = hash('$C0={};');
45
- types[unitName] = unitDef;
46
-
47
- // Bool: <{} false, {} true>
48
- const boolDef = {
49
- code: 'union',
50
- union: { false: unitName, true: unitName }
51
- };
52
- const boolName = hash(`$C0=<${unitName}"false",${unitName}"true">;`);
53
- types[boolName] = boolDef;
54
-
55
- // Maybe: <{} nothing, Bool something>
56
- const maybeDef = {
57
- code: 'union',
58
- union: { nothing: unitName, something: boolName }
59
- };
60
- const maybeName = hash(
61
- `$C0=<${unitName}"nothing",${boolName}"something">;`
62
- );
63
- types[maybeName] = maybeDef;
64
-
65
- console.log('Types defined:');
66
- console.log(' unit:', unitName);
67
- console.log(' bool:', boolName);
68
- console.log(' maybe:', maybeName);
69
- console.log();
70
-
71
- // ============================================================================
72
- // Step 2: Type resolver
73
- // ============================================================================
74
-
75
- function resolveType(typeName) {
76
- const def = types[typeName];
77
- if (!def) {
78
- throw new Error(`Unknown type: ${typeName}`);
79
- }
80
- return def;
81
- }
82
-
83
- // ============================================================================
84
- // Step 3: Create input value: Maybe Bool = something(true)
85
- // ============================================================================
86
-
87
- const inputValue = Value.variant(
88
- 'something',
89
- Value.variant('true', Value.product({}))
90
- );
91
-
92
- console.log('Input value:', inputValue.toString());
93
- console.log();
94
-
95
- const maybePattern = patternToPropertyList(
96
- deriveClosedPattern(maybeName, maybeDef, resolveType)
97
- );
98
-
99
- // ============================================================================
100
- // Step 4: Parse (TEXT → BINARY)
101
- // ============================================================================
102
-
103
- console.log('--- PARSE (text → binary) ---');
104
- const binaryInput = encodeToWire(inputValue, maybePattern);
105
- console.log('Binary size:', binaryInput.length, 'bytes');
106
- console.log(' Bytes:', binaryInput.toString('hex'));
107
- console.log();
108
-
109
- // ============================================================================
110
- // Step 5: Compiled k-program (BINARY → BINARY)
111
- // ============================================================================
112
-
113
- console.log('--- COMPILED PROGRAM (binary → binary) ---');
114
-
115
- // Simulate a compiled k-program: decode → transform → encode
116
- const { value: programInput } = decodeWire(binaryInput);
117
-
118
- console.log('Program sees value:', programInput.toString());
119
-
120
- // Example transformation: NOT operation (flip bool inside Maybe)
121
- let programOutput;
122
- if (isVariant(programInput) && programInput.tag === 'something') {
123
- const innerBool = programInput.value;
124
- if (isVariant(innerBool)) {
125
- const flipped = Value.variant(
126
- innerBool.tag === 'true' ? 'false' : 'true',
127
- innerBool.value
128
- );
129
- programOutput = Value.variant('something', flipped);
130
- }
131
- } else {
132
- programOutput = programInput; // nothing → nothing
133
- }
134
-
135
- console.log('Program output value:', programOutput.toString());
136
-
137
- // Encode output
138
- const binaryOutput = encodeToWire(programOutput, maybePattern);
139
-
140
- console.log('Binary output size:', binaryOutput.length, 'bytes');
141
- console.log(' Bytes:', binaryOutput.toString('hex'));
142
- console.log();
143
-
144
- // ============================================================================
145
- // Step 6: Print (BINARY → TEXT)
146
- // ============================================================================
147
-
148
- console.log('--- PRINT (binary → text) ---');
149
- const { value: finalValue } = decodeWire(binaryOutput);
150
-
151
- console.log('Output value:', finalValue.toString());
152
- console.log();
153
-
154
- // ============================================================================
155
- // Summary
156
- // ============================================================================
157
-
158
- console.log('=== Pipeline Summary ===');
159
- console.log('Input: ', inputValue.toString(), '(true inside Maybe)');
160
- console.log('Transform: NOT operation on inner bool');
161
- console.log('Output: ', finalValue.toString(), '(false inside Maybe)');
162
- console.log();
163
- console.log('Binary representations are canonical and type-safe!');
@@ -1,30 +0,0 @@
1
- import fs from "node:fs";
2
- import { parse as parseScript } from "../../parser.mjs";
3
- import codes from "../../codes.mjs";
4
- import { deriveClosedPattern } from "./codec.mjs";
5
- import { patternToPropertyList } from "./pattern-json.mjs";
6
-
7
- const IEEE_SCRIPT = fs.readFileSync(new URL("../../Examples/ieee.k", import.meta.url), "utf8");
8
-
9
- function loadFloat64Pattern() {
10
- const { defs } = parseScript(IEEE_SCRIPT);
11
- const { codes: finalizedCodes, representatives } = codes.finalize(defs.codes);
12
- const typeName = representatives.float64 || "float64";
13
- const typeInfo = finalizedCodes[typeName];
14
- if (!typeInfo) {
15
- throw new Error("Could not resolve float64 type from Examples/ieee.k");
16
- }
17
- const resolveType = (name) => {
18
- const type = finalizedCodes[name];
19
- if (!type) {
20
- throw new Error(`Unknown IEEE helper type '${name}'`);
21
- }
22
- return type;
23
- };
24
- return patternToPropertyList(deriveClosedPattern(typeName, typeInfo, resolveType));
25
- }
26
-
27
- const FLOAT64_PATTERN = loadFloat64Pattern();
28
-
29
- export { FLOAT64_PATTERN, loadFloat64Pattern };
30
- export default { FLOAT64_PATTERN, loadFloat64Pattern };