@fraczak/k 6.0.3 → 6.0.4

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/object.mjs CHANGED
@@ -1,11 +1,10 @@
1
1
  import { annotate } from "./index.mjs";
2
- import run from "./run.mjs";
2
+ import run, { run_rel, run_converged } from "./run.mjs";
3
3
  import codes from "./codes.mjs";
4
4
  import { TypePatternGraph } from "./TypePatternGraph.mjs";
5
5
  import { patterns2filters, prettyRel } from "./pretty.mjs";
6
6
 
7
- const MAGIC = Buffer.from([0x4b, 0x4f, 0x42, 0x4a, 0x00, 0x01, 0x0a]);
8
- const LIB_MAGIC = Buffer.from([0x4b, 0x4c, 0x49, 0x42, 0x00, 0x01, 0x0a]);
7
+ const OBJECT_MAGIC = Buffer.from("KOBJ\n");
9
8
 
10
9
  function serializeTypePatternGraph(typePatternGraph) {
11
10
  return {
@@ -27,9 +26,11 @@ function hydrateTypePatternGraph(serialized) {
27
26
  return graph;
28
27
  }
29
28
 
30
- function serializeRelation(rel) {
29
+ function serializeRelation(rel, typeDerivation = rel.typeDerivation) {
30
+ const def = stripDebugFieldsFromExp(stripRelationBoundaryFilters(rel.def, rel.typePatternGraph));
31
31
  return {
32
- ...rel,
32
+ def,
33
+ ...(typeDerivation ? { typeDerivation } : {}),
33
34
  typePatternGraph: serializeTypePatternGraph(rel.typePatternGraph)
34
35
  };
35
36
  }
@@ -42,9 +43,13 @@ function hydrateRelation(rel) {
42
43
  }
43
44
 
44
45
  function serializeAnnotated(annotated) {
46
+ const typeDerivations = buildRelTypeDerivations(annotated.rels, annotated.compileStats);
45
47
  return {
46
48
  rels: Object.fromEntries(
47
- Object.entries(annotated.rels).map(([name, rel]) => [name, serializeRelation(rel)])
49
+ Object.entries(annotated.rels).map(([name, rel]) => [
50
+ name,
51
+ serializeRelation(rel, typeDerivations[name])
52
+ ])
48
53
  ),
49
54
  representatives: annotated.representatives,
50
55
  relAlias: annotated.relAlias,
@@ -52,15 +57,6 @@ function serializeAnnotated(annotated) {
52
57
  };
53
58
  }
54
59
 
55
- function hydrateAnnotated(serialized) {
56
- return {
57
- ...serialized,
58
- rels: Object.fromEntries(
59
- Object.entries(serialized.rels).map(([name, rel]) => [name, hydrateRelation(rel)])
60
- )
61
- };
62
- }
63
-
64
60
  const NAME_RE = /^[a-zA-Z0-9_+-][a-zA-Z0-9_?!+-]*$/;
65
61
 
66
62
  function isSourceName(name) {
@@ -86,6 +82,207 @@ function addOrigin(meta, hash, type, origin) {
86
82
  meta[hash].origins.push(origin);
87
83
  }
88
84
 
85
+ const TYPE_DERIVATION_STATUSES = new Set(["converged", "not-converged", "unknown"]);
86
+
87
+ function validTypeDerivationStatus(status) {
88
+ return TYPE_DERIVATION_STATUSES.has(status) ? status : "unknown";
89
+ }
90
+
91
+ function compileStatsByRelName(compileStats = {}) {
92
+ const byName = {};
93
+ for (const scc of compileStats.sccs || []) {
94
+ for (const member of scc.members || []) {
95
+ byName[member] = scc;
96
+ }
97
+ }
98
+ return byName;
99
+ }
100
+
101
+ function samePatternId(typePatternGraph, left, right) {
102
+ return typePatternGraph.find(left) === typePatternGraph.find(right);
103
+ }
104
+
105
+ function isBoundaryFilter(exp, typePatternGraph, patternId) {
106
+ return exp?.op === "filter" &&
107
+ exp.patterns?.length === 2 &&
108
+ samePatternId(typePatternGraph, exp.patterns[0], patternId) &&
109
+ samePatternId(typePatternGraph, exp.patterns[1], patternId);
110
+ }
111
+
112
+ function stripRelationBoundaryFilters(exp, typePatternGraph = null) {
113
+ if (!exp) return exp;
114
+ if (typePatternGraph == null) {
115
+ return exp;
116
+ }
117
+ const [inputPattern, outputPattern] = exp.patterns || [];
118
+ if (inputPattern == null || outputPattern == null) return exp;
119
+
120
+ if (isBoundaryFilter(exp, typePatternGraph, inputPattern) && samePatternId(typePatternGraph, inputPattern, outputPattern)) {
121
+ return {
122
+ op: "identity",
123
+ patterns: [...exp.patterns],
124
+ ...(exp.start ? { start: exp.start } : {}),
125
+ ...(exp.end ? { end: exp.end } : {})
126
+ };
127
+ }
128
+
129
+ if (exp.op !== "comp") return exp;
130
+ let parts = exp.comp || [];
131
+ if (parts.length > 0 && isBoundaryFilter(parts[0], typePatternGraph, inputPattern)) {
132
+ parts = parts.slice(1);
133
+ }
134
+ if (parts.length > 0 && isBoundaryFilter(parts[parts.length - 1], typePatternGraph, outputPattern)) {
135
+ parts = parts.slice(0, -1);
136
+ }
137
+ if (parts.length === (exp.comp || []).length) return exp;
138
+ if (parts.length === 0) {
139
+ return {
140
+ op: "identity",
141
+ patterns: [...exp.patterns],
142
+ ...(exp.start ? { start: exp.start } : {}),
143
+ ...(exp.end ? { end: exp.end } : {})
144
+ };
145
+ }
146
+ if (parts.length === 1) return { ...parts[0], patterns: [...exp.patterns] };
147
+ return { ...exp, comp: parts };
148
+ }
149
+
150
+ function stripDebugFieldsFromFilter(filter) {
151
+ if (!filter) return filter;
152
+ const { start, end, fields, ...rest } = filter;
153
+ if (!fields) return rest;
154
+ return {
155
+ ...rest,
156
+ fields: Object.fromEntries(
157
+ Object.entries(fields).map(([label, child]) => [label, stripDebugFieldsFromFilter(child)])
158
+ )
159
+ };
160
+ }
161
+
162
+ function stripDebugFieldsFromExp(exp) {
163
+ if (!exp) return exp;
164
+ const { start, end, ...rest } = exp;
165
+ switch (rest.op) {
166
+ case "filter":
167
+ return { ...rest, filter: stripDebugFieldsFromFilter(rest.filter) };
168
+ case "comp":
169
+ return { ...rest, comp: rest.comp.map(stripDebugFieldsFromExp) };
170
+ case "union":
171
+ return { ...rest, union: rest.union.map(stripDebugFieldsFromExp) };
172
+ case "product":
173
+ return {
174
+ ...rest,
175
+ product: rest.product.map(({ label, exp: child }) => ({
176
+ label,
177
+ exp: stripDebugFieldsFromExp(child)
178
+ }))
179
+ };
180
+ default:
181
+ return rest;
182
+ }
183
+ }
184
+
185
+ function stripDebugFieldsFromCode(code) {
186
+ if (!code) return code;
187
+ const { start, end, ...rest } = code;
188
+ return rest;
189
+ }
190
+
191
+ function stripDebugFieldsFromCodes(codeTable) {
192
+ return Object.fromEntries(
193
+ Object.entries(codeTable || {}).map(([hash, code]) => [hash, stripDebugFieldsFromCode(code)])
194
+ );
195
+ }
196
+
197
+ function firstFilterSourceRange(filter) {
198
+ if (!filter) return null;
199
+ if (filter.start || filter.end) {
200
+ return {
201
+ ...(filter.start ? { start: filter.start } : {}),
202
+ ...(filter.end ? { end: filter.end } : {})
203
+ };
204
+ }
205
+ for (const child of Object.values(filter.fields || {})) {
206
+ const range = firstFilterSourceRange(child);
207
+ if (range) return range;
208
+ }
209
+ return null;
210
+ }
211
+
212
+ function firstExpSourceRange(exp) {
213
+ if (!exp) return null;
214
+ if (exp.start || exp.end) {
215
+ return {
216
+ ...(exp.start ? { start: exp.start } : {}),
217
+ ...(exp.end ? { end: exp.end } : {})
218
+ };
219
+ }
220
+ switch (exp.op) {
221
+ case "filter":
222
+ return firstFilterSourceRange(exp.filter);
223
+ case "comp":
224
+ for (const child of exp.comp) {
225
+ const range = firstExpSourceRange(child);
226
+ if (range) return range;
227
+ }
228
+ return null;
229
+ case "union":
230
+ for (const child of exp.union) {
231
+ const range = firstExpSourceRange(child);
232
+ if (range) return range;
233
+ }
234
+ return null;
235
+ case "product":
236
+ for (const { exp: child } of exp.product) {
237
+ const range = firstExpSourceRange(child);
238
+ if (range) return range;
239
+ }
240
+ return null;
241
+ default:
242
+ return null;
243
+ }
244
+ }
245
+
246
+ function originFromSourceNode(source, name, compiledAt, node) {
247
+ return {
248
+ source,
249
+ name,
250
+ compiledAt,
251
+ ...(node?.start ? { start: node.start } : {}),
252
+ ...(node?.end ? { end: node.end } : {})
253
+ };
254
+ }
255
+
256
+ function relationOrigin(source, name, compiledAt, rel) {
257
+ const printableDef = stripRelationBoundaryFilters(rel.def, rel.typePatternGraph);
258
+ const range = firstExpSourceRange(printableDef);
259
+ return {
260
+ source,
261
+ name,
262
+ compiledAt,
263
+ ...(range?.start ? { start: range.start } : {}),
264
+ ...(range?.end ? { end: range.end } : {})
265
+ };
266
+ }
267
+
268
+ function buildRelTypeDerivation(rel, sccStats) {
269
+ const existing = rel?.typeDerivation || {};
270
+ const status = sccStats
271
+ ? (sccStats.converged ? "converged" : "not-converged")
272
+ : validTypeDerivationStatus(existing.status);
273
+ return { status };
274
+ }
275
+
276
+ function buildRelTypeDerivations(rels, compileStats) {
277
+ const statsByName = compileStatsByRelName(compileStats);
278
+ return Object.fromEntries(
279
+ Object.entries(rels || {}).map(([name, rel]) => [
280
+ name,
281
+ buildRelTypeDerivation(rel, statsByName[name])
282
+ ])
283
+ );
284
+ }
285
+
89
286
  function mergeMetaEntries(...metas) {
90
287
  const merged = {};
91
288
  for (const meta of metas) {
@@ -94,11 +291,7 @@ function mergeMetaEntries(...metas) {
94
291
  if (type !== "code" && type !== "rel") continue;
95
292
  for (const origin of entry.origins || []) {
96
293
  if (!origin?.name) continue;
97
- addOrigin(merged, hash, type, {
98
- ...(origin.source == null ? {} : { source: origin.source }),
99
- name: origin.name,
100
- ...(origin.compiledAt == null ? {} : { compiledAt: origin.compiledAt })
101
- });
294
+ addOrigin(merged, hash, type, { ...origin });
102
295
  }
103
296
  }
104
297
  }
@@ -113,13 +306,20 @@ function buildMeta(annotated, source) {
113
306
 
114
307
  for (const [name, hash] of Object.entries(representatives)) {
115
308
  if (!isSourceName(name)) continue;
116
- addOrigin(meta, hash, "code", { source, name, compiledAt: now });
309
+ addOrigin(meta, hash, "code", originFromSourceNode(
310
+ source,
311
+ name,
312
+ now,
313
+ annotated.sourceDefs?.codes?.[name]
314
+ ));
117
315
  }
118
316
 
119
317
  for (const [name, hash] of Object.entries(relAlias)) {
120
- if (name === "__main__") continue;
121
- if (!isSourceName(name)) continue;
122
- addOrigin(meta, hash, "rel", { source, name, compiledAt: now });
318
+ const rel = annotated.rels?.[name];
319
+ if (!rel) continue;
320
+ if (name === "__main__" || isSourceName(name)) {
321
+ addOrigin(meta, hash, "rel", relationOrigin(source, name, now, rel));
322
+ }
123
323
  }
124
324
  return meta;
125
325
  }
@@ -196,7 +396,7 @@ function collectReachable(mainName, rels, allCodes) {
196
396
  const rel = rels[relName];
197
397
  if (rel.typePatternGraph) {
198
398
  const codeId = rel.typePatternGraph.codeId || (rel.typePatternGraph.codeId);
199
- if (codeId) Object.values(codeId).forEach(walkCode);
399
+ if (codeId) Object.keys(codeId).forEach(walkCode);
200
400
  }
201
401
  }
202
402
 
@@ -205,7 +405,7 @@ function collectReachable(mainName, rels, allCodes) {
205
405
 
206
406
  function compileObject(script, options = {}) {
207
407
  const annotated = annotate(script, options);
208
- const allCodes = codes.dump();
408
+ const allCodes = stripDebugFieldsFromCodes(codes.dump());
209
409
  const serialized = serializeAnnotated(annotated);
210
410
  const meta = mergeMetaEntries(
211
411
  importedLibraryMeta(options.libraries),
@@ -220,13 +420,15 @@ function compileObject(script, options = {}) {
220
420
  const prunedRels = Object.fromEntries(
221
421
  Object.entries(serialized.rels).filter(([name]) => reachableRels.has(name))
222
422
  );
423
+ const reachableRelHashes = new Set(
424
+ [...reachableRels].map((name) => serialized.relAlias?.[name] || name)
425
+ );
223
426
  const prunedMeta = Object.fromEntries(
224
- Object.entries(meta).filter(([h]) => reachableRels.has(h) || reachableCodes.has(h))
427
+ Object.entries(meta).filter(([h]) => reachableRels.has(h) || reachableRelHashes.has(h) || reachableCodes.has(h))
225
428
  );
226
429
 
227
430
  return {
228
431
  format: "k-object",
229
- version: 2,
230
432
  codes: prunedCodes,
231
433
  rels: prunedRels,
232
434
  relAlias: serialized.relAlias,
@@ -260,6 +462,7 @@ function rewriteRefsToCanonical(exp, relAlias) {
260
462
 
261
463
  function compileLibrary(script, options = {}) {
262
464
  const annotated = annotateLibrary(script, options);
465
+ const allCodes = stripDebugFieldsFromCodes(codes.dump());
263
466
  const serialized = serializeAnnotated(annotated);
264
467
  const meta = mergeMetaEntries(
265
468
  importedLibraryMeta(options.libraries),
@@ -278,15 +481,21 @@ function compileLibrary(script, options = {}) {
278
481
  def: rewriteRefsToCanonical(rel.def, relAlias)
279
482
  };
280
483
  }
484
+ const libraryMetaHashes = new Set([
485
+ ...Object.keys(allCodes),
486
+ ...Object.keys(libRels)
487
+ ]);
488
+ const libMeta = Object.fromEntries(
489
+ Object.entries(meta).filter(([hash]) => libraryMetaHashes.has(hash))
490
+ );
281
491
 
282
492
  return {
283
493
  format: "k-object",
284
- version: 2,
285
- codes: codes.dump(),
494
+ codes: allCodes,
286
495
  rels: libRels,
287
496
  relAlias: serialized.relAlias,
288
497
  compileStats: serialized.compileStats,
289
- meta,
498
+ meta: libMeta,
290
499
  main: null
291
500
  };
292
501
  }
@@ -295,15 +504,6 @@ function hydrateObject(object) {
295
504
  if (object?.format !== "k-object") {
296
505
  throw new Error("Unsupported k object file");
297
506
  }
298
- // v1 compat: defs wrapper
299
- if (object.version === 1) {
300
- codes.load(object.codes);
301
- return {
302
- ...object,
303
- defs: hydrateAnnotated(object.defs)
304
- };
305
- }
306
- // v2: flat rels
307
507
  codes.load(object.codes);
308
508
  const hydratedRels = Object.fromEntries(
309
509
  Object.entries(object.rels).map(([name, rel]) => [name, hydrateRelation(rel)])
@@ -320,25 +520,23 @@ function loadLibrary(object) {
320
520
  }
321
521
 
322
522
  function isHydratedObject(object) {
323
- // v2 format
324
523
  if (object?.rels) {
325
524
  const firstRel = Object.values(object.rels)[0];
326
525
  return firstRel?.typePatternGraph instanceof TypePatternGraph;
327
526
  }
328
- // v1 format
329
- return object?.defs?.rels?.[object.main]?.typePatternGraph instanceof TypePatternGraph;
527
+ return false;
330
528
  }
331
529
 
332
530
  function encodeObject(object) {
333
- const magic = object.main == null ? LIB_MAGIC : MAGIC;
531
+ if (object.main == null) return encodeLibrary(object);
334
532
  const payload = Buffer.from(JSON.stringify(object), "utf8");
335
533
  if (payload.length > 0xffffffff) {
336
534
  throw new Error("k object payload is too large");
337
535
  }
338
536
 
339
- const header = Buffer.alloc(magic.length + 4);
340
- magic.copy(header, 0);
341
- header.writeUInt32BE(payload.length, magic.length);
537
+ const header = Buffer.alloc(OBJECT_MAGIC.length + 4);
538
+ OBJECT_MAGIC.copy(header, 0);
539
+ header.writeUInt32BE(payload.length, OBJECT_MAGIC.length);
342
540
  return Buffer.concat([header, payload]);
343
541
  }
344
542
 
@@ -346,15 +544,16 @@ function decodeObject(buffer) {
346
544
  if (!Buffer.isBuffer(buffer)) {
347
545
  throw new Error("k object input must be a Buffer");
348
546
  }
349
- const isObj = buffer.length >= MAGIC.length && buffer.subarray(0, MAGIC.length).equals(MAGIC);
350
- const isLib = buffer.length >= LIB_MAGIC.length && buffer.subarray(0, LIB_MAGIC.length).equals(LIB_MAGIC);
351
- if (!isObj && !isLib) {
547
+ const trimmed = buffer.toString("utf8").trimStart();
548
+ if (trimmed.startsWith("{")) {
549
+ return hydrateObject(JSON.parse(trimmed));
550
+ }
551
+ if (buffer.length < OBJECT_MAGIC.length || !buffer.subarray(0, OBJECT_MAGIC.length).equals(OBJECT_MAGIC)) {
352
552
  throw new Error("Invalid k object file header");
353
553
  }
354
554
 
355
- const magic = isLib ? LIB_MAGIC : MAGIC;
356
- const length = buffer.readUInt32BE(magic.length);
357
- const payloadStart = magic.length + 4;
555
+ const length = buffer.readUInt32BE(OBJECT_MAGIC.length);
556
+ const payloadStart = OBJECT_MAGIC.length + 4;
358
557
  const payloadEnd = payloadStart + length;
359
558
  if (payloadEnd !== buffer.length) {
360
559
  throw new Error("Invalid k object file length");
@@ -364,7 +563,7 @@ function decodeObject(buffer) {
364
563
  }
365
564
 
366
565
  function encodeLibrary(object) {
367
- return encodeObject(object);
566
+ return Buffer.from(JSON.stringify(object), "utf8");
368
567
  }
369
568
 
370
569
  function decodeLibrary(buffer) {
@@ -380,20 +579,19 @@ function compileObjectBuffer(script, options = {}) {
380
579
  }
381
580
 
382
581
  function compileLibraryBuffer(script, options = {}) {
383
- return encodeObject(compileLibrary(script, options));
582
+ return encodeLibrary(compileLibrary(script, options));
384
583
  }
385
584
 
386
585
  function getRels(hydrated) {
387
- // v2: flat rels; v1: defs.rels
388
- return hydrated.rels || hydrated.defs?.rels;
586
+ return hydrated.rels;
389
587
  }
390
588
 
391
589
  function runObject(object, value) {
392
590
  const hydrated = isHydratedObject(object) ? object : hydrateObject(object);
393
591
  const rels = getRels(hydrated);
394
- run.defs = hydrated.defs || { rels };
592
+ run.defs = { rels };
395
593
  const mainRel = rels[hydrated.main];
396
- return run(codes.find, mainRel.def, value, mainRel.typePatternGraph);
594
+ return run_rel(codes.find, mainRel, value, hydrated.main);
397
595
  }
398
596
 
399
597
  function objectToFunction(object) {
@@ -401,6 +599,29 @@ function objectToFunction(object) {
401
599
  return (value) => runObject(hydrated, value);
402
600
  }
403
601
 
602
+ function assertRelConverged(rel, name) {
603
+ const status = rel?.typeDerivation?.status || "unknown";
604
+ if (status !== "converged") {
605
+ throw new Error(`Cannot run '${name}' without envelopes: type derivation is ${status}`);
606
+ }
607
+ }
608
+
609
+ function runConvergedObject(object, value) {
610
+ const hydrated = isHydratedObject(object) ? object : hydrateObject(object);
611
+ const rels = getRels(hydrated);
612
+ const mainRel = rels[hydrated.main];
613
+ assertRelConverged(mainRel, hydrated.main);
614
+ run_converged.defs = { rels };
615
+ return run_converged(codes.find, mainRel.def, value, mainRel.typePatternGraph, {
616
+ requireConverged: true
617
+ });
618
+ }
619
+
620
+ function objectToConvergedFunction(object) {
621
+ const hydrated = isHydratedObject(object) ? object : hydrateObject(object);
622
+ return (value) => runConvergedObject(hydrated, value);
623
+ }
624
+
404
625
  function hashAlias(hash) {
405
626
  return hash.startsWith("@") ? hash.slice(1) : hash;
406
627
  }
@@ -486,10 +707,23 @@ function boundaryFilterSource(typePatternGraph, patternId, aliases) {
486
707
  return prettyRel({ op: "filter", filter: rewriteCodesInFilter(filter, aliases) });
487
708
  }
488
709
 
710
+ function prettyRelation(rel, aliases = {}, relAliases = {}) {
711
+ const body = rewriteRefsInExp(
712
+ stripRelationBoundaryFilters(stripDebugFieldsFromExp(rel.def), rel.typePatternGraph),
713
+ aliases,
714
+ relAliases
715
+ );
716
+ return [
717
+ boundaryFilterSource(rel.typePatternGraph, rel.def.patterns[0], aliases),
718
+ prettyRel(body),
719
+ boundaryFilterSource(rel.typePatternGraph, rel.def.patterns[1], aliases)
720
+ ].join(" ");
721
+ }
722
+
489
723
  function decompileObject(object) {
490
724
  const hydrated = isHydratedObject(object) ? object : hydrateObject(object);
491
725
  const rels = getRels(hydrated);
492
- const relAliases = hydrated.defs?.relAlias || hydrated.relAlias || {};
726
+ const relAliases = hydrated.relAlias || {};
493
727
  const aliases = shortestUniqueAliases([
494
728
  ...Object.keys(hydrated.codes),
495
729
  ...Object.values(relAliases)
@@ -505,9 +739,9 @@ function decompileObject(object) {
505
739
  const relName = relAliases[name] || name;
506
740
  if (emittedRelAliases.has(relName)) return null;
507
741
  emittedRelAliases.add(relName);
508
- return `${aliases[relName] || relName} = ${prettyRel(rewriteRefsInExp(rel.def, aliases, relAliases))};`;
742
+ return `${aliases[relName] || relName} = ${prettyRelation(rel, aliases, relAliases)};`;
509
743
  };
510
- const compileStats = hydrated.defs?.compileStats || hydrated.compileStats;
744
+ const compileStats = hydrated.compileStats;
511
745
  const sccs = compileStats?.sccs || [];
512
746
  const relGroups = sccs.map(({ members }) =>
513
747
  members.map(relDefForName).filter((line) => line != null)
@@ -592,6 +826,7 @@ function extractAliasesFromObject(object) {
592
826
  if (type !== "code" && type !== "rel") continue;
593
827
  const typeOrder = type === "code" ? 0 : 1;
594
828
  for (const origin of entry.origins || []) {
829
+ if (origin?.name === "__main__") continue;
595
830
  if (!origin?.name || !isSourceName(origin.name)) continue;
596
831
  entries.push({
597
832
  type,
@@ -644,7 +879,10 @@ export {
644
879
  hydrateObject,
645
880
  loadLibrary,
646
881
  runObject,
882
+ runConvergedObject,
647
883
  objectToFunction,
884
+ objectToConvergedFunction,
885
+ prettyRelation,
648
886
  decompileObject,
649
887
  decompileObjectBuffer,
650
888
  extractAliasesFromObject,
@@ -663,7 +901,10 @@ export default {
663
901
  hydrateObject,
664
902
  loadLibrary,
665
903
  runObject,
904
+ runConvergedObject,
666
905
  objectToFunction,
906
+ objectToConvergedFunction,
907
+ prettyRelation,
667
908
  decompileObject,
668
909
  decompileObjectBuffer,
669
910
  extractAliasesFromObject,
package/objects/README.md CHANGED
@@ -8,6 +8,7 @@ CLI tools for compiling and inspecting k object files (`.ko`) and library files
8
8
 
9
9
  Compiles a `.k` source file into an executable object file (`.ko`).
10
10
  The output contains only the codes and relations reachable from `main`.
11
+ Each stored relation includes `typeDerivation.status` for backend eligibility.
11
12
 
12
13
  ```bash
13
14
  ./objects/compile.mjs [--lib lib-file]... [k-file [object-file]]
@@ -16,8 +17,12 @@ The output contains only the codes and relations reachable from `main`.
16
17
  ### compile-lib.mjs
17
18
 
18
19
  Compiles a `.k` source file into a library file (`.klib`).
19
- The output contains all codes and relations defined in the source (no main entry point).
20
+ The output is plain JSON with no binary header. It contains the library closure
21
+ formed from loaded `--lib` dependencies plus the compiled source definitions,
22
+ with `main: null`.
20
23
  Use `--lib` to build on top of existing libraries.
24
+ Each stored relation includes `typeDerivation.status`; libraries may contain a
25
+ mix of converged and non-converged relations.
21
26
 
22
27
  ```bash
23
28
  ./objects/compile-lib.mjs [--lib lib-file]... [k-file [lib-file]]
@@ -41,6 +46,18 @@ alias name and `compiledAt`.
41
46
  ./objects/extract-aliases.mjs [object-file [k-file]]
42
47
  ```
43
48
 
49
+ ## Current Format Notes
50
+
51
+ - `.klib` files are plain UTF-8 JSON, not binary containers.
52
+ - `.ko` files use the `KOBJ\n` binary header followed by a JSON payload.
53
+ - There is no object payload version field in either format.
54
+ - `typeDerivation` belongs only to relations and currently stores only
55
+ `status`.
56
+ - Source `start` / `end` ranges live on `meta[hash].origins[]` entries.
57
+ - Origin entries do not have `kind`; the metadata entry has `type: "code"` or
58
+ `type: "rel"`.
59
+ - Stored relation bodies do not include generated input/output boundary filters.
60
+
44
61
  ## Further reading
45
62
 
46
63
  - [DOCS/OBJECT_FILE_AND_PATTERN.md](../DOCS/OBJECT_FILE_AND_PATTERN.md) — object file format and pattern encoding
@@ -6,13 +6,14 @@ import { compileLibraryBuffer, decodeObject, loadLibrary } from "../object.mjs";
6
6
 
7
7
  function helpText() {
8
8
  return [
9
- "Compile a k source file into a .klib library object.",
9
+ "Compile a k source file into a plain-JSON .klib library object.",
10
+ "The library records type-derivation convergence for each stored relation.",
10
11
  "",
11
12
  `Usage: ${argv[1]} [ --lib lib-file ]... [ k-file [ lib-file ] ]`,
12
13
  "",
13
14
  "Arguments:",
14
15
  " k-file Source .k file to compile. Reads UTF-8 source from stdin when omitted.",
15
- " lib-file Output .klib path. Writes binary library data to stdout when omitted.",
16
+ " lib-file Output .klib path. Writes plain JSON library data to stdout when omitted.",
16
17
  "",
17
18
  "Options:",
18
19
  " --lib file Load a .klib dependency before compiling. May be repeated.",
@@ -7,6 +7,7 @@ import { compileObjectBuffer, decodeObject, loadLibrary } from "../object.mjs";
7
7
  function helpText() {
8
8
  return [
9
9
  "Compile a k source file into an executable .ko object.",
10
+ "The object records type-derivation convergence for each stored relation.",
10
11
  "",
11
12
  `Usage: ${argv[1]} [ --lib lib-file ]... [ k-file [ object-file ] ]`,
12
13
  "",
@@ -11,7 +11,7 @@ function helpText() {
11
11
  `Usage: ${argv[1]} [ object-file [ k-file ] ]`,
12
12
  "",
13
13
  "Arguments:",
14
- " object-file Input .ko or .klib path. Reads binary object data from stdin when omitted.",
14
+ " object-file Input .ko or .klib path. Reads object data from stdin when omitted.",
15
15
  " k-file Output .k path. Writes source to stdout when omitted.",
16
16
  "",
17
17
  "Options:",
@@ -15,7 +15,7 @@ function helpText() {
15
15
  "out so only the latest one remains active.",
16
16
  "",
17
17
  "Arguments:",
18
- " object-file Input .ko or .klib path. Reads binary object data from stdin when omitted.",
18
+ " object-file Input .ko or .klib path. Reads object data from stdin when omitted.",
19
19
  " k-file Output .k path. Writes source to stdout when omitted.",
20
20
  "",
21
21
  "Options:",