@fraczak/k 6.0.2 → 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.
@@ -0,0 +1,458 @@
1
+ # KIR: k Intermediate Representation, Retyping, and Conformance
2
+
3
+ The document defines an object IR and conformance platform for LLVM and
4
+ WebAssembly backends.
5
+
6
+ ## Goals
7
+
8
+ - Define a portable polymorphic object IR.
9
+ - Define retyping for concrete input envelope patterns.
10
+ - Define conformance fixtures for interpreter, object execution,
11
+ retyped execution, and future backends.
12
+ - Keep `.ko` and `.klib` inspectable.
13
+ - Record type-derivation convergence per relation.
14
+
15
+ ## Out of Scope
16
+
17
+ - LLVM backend design.
18
+ - WebAssembly backend design.
19
+ - New language syntax.
20
+ - Replacing the current JavaScript evaluator.
21
+
22
+ ## Execution Layers
23
+
24
+ ### KIR-P: Polymorphic IR
25
+
26
+ KIR-P is the portable representation of a k relation. It keeps the current
27
+ pattern-carrying execution model.
28
+
29
+ KIR-P must:
30
+
31
+ - run any valid k program;
32
+ - preserve filters and pattern operations;
33
+ - store relation input and output patterns;
34
+ - be the canonical `.ko` / `.klib` relation format;
35
+ - be the reference for retyping and backend tests.
36
+
37
+ Alternative:
38
+
39
+ - Store source and re-run type derivation on load. This gives smaller objects,
40
+ but makes object behavior depend on the compiler version. Do not use this for
41
+ KIR.
42
+
43
+ ### KIR-R: Retyped IR
44
+
45
+ KIR-R is produced from `KIR-P + input envelope pattern`.
46
+
47
+ KIR-R must:
48
+
49
+ - be equivalent to typing the entry expression `?P __main__`;
50
+ - derive the output pattern for that invocation;
51
+ - validate filters and pattern constraints before value execution;
52
+ - preserve the same value-level partial function semantics;
53
+ - support multiple pattern contexts for the same helper relation;
54
+ - be cacheable by relation hash and input pattern hash.
55
+
56
+ Alternative:
57
+
58
+ - Re-run full source compilation for each input pattern. This is acceptable for
59
+ the first prototype, but the public API should still be
60
+ `retype(rel, inputPattern)`.
61
+
62
+ ### KIR-M: Backend IR
63
+
64
+ KIR-M is produced from KIR-R after call-site pattern contexts, layout, and ABI
65
+ decisions are fixed.
66
+
67
+ KIR-M should:
68
+
69
+ - use static product field offsets;
70
+ - use static union tag dispatch;
71
+ - represent partial failure explicitly;
72
+ - avoid envelope propagation only where call-site pattern contexts prove it safe;
73
+ - require converged type derivation for every compiled relation;
74
+ - target LLVM, Wasm, C, or another backend.
75
+
76
+ Alternative:
77
+
78
+ - Compile KIR-P directly. This is useful for a correctness experiment, but it
79
+ recreates the polymorphic interpreter and is not the final performance path.
80
+
81
+ ## Object IR
82
+
83
+ ### Step 1: Define KIR-P
84
+
85
+ Add `DOCS/KIR_V1.md`.
86
+
87
+ Define:
88
+
89
+ - top-level object fields: `format`, `codes`, `rels`, `relAlias`,
90
+ `compileStats`, `meta`, and `main`;
91
+ - canonical code table;
92
+ - polymorphic relation table;
93
+ - relation aliases;
94
+ - metadata;
95
+ - per-relation type-derivation status;
96
+ - optional origin source range;
97
+ - `.ko` main relation;
98
+ - `.klib` null main.
99
+
100
+ Current storage rules to preserve:
101
+
102
+ - `.klib` is plain UTF-8 JSON with no binary header;
103
+ - `.ko` is a `KOBJ\n` binary container around the JSON payload;
104
+ - no payload version field is stored;
105
+ - relation `typeDerivation` stores only `status`;
106
+ - code entries do not carry `typeDerivation`;
107
+ - relation bodies do not store generated input/output boundary filters;
108
+ - source ranges live only in metadata origin entries;
109
+ - origin entries do not have `kind`; the metadata entry has `type`.
110
+
111
+ Implementation:
112
+
113
+ - Add `kir.mjs`.
114
+ - Add a converter from current object payloads to KIR-P.
115
+ - Keep current object storage until KIR-P is validated.
116
+
117
+ Alternative:
118
+
119
+ - Change the stored object JSON immediately. This is less code, but risks
120
+ mixing backend contracts with current JS evaluator internals.
121
+
122
+ ### Step 1a: Record Type-Derivation Status
123
+
124
+ Each relation definition should carry:
125
+
126
+ ```json
127
+ {
128
+ "typeDerivation": {
129
+ "status": "converged"
130
+ }
131
+ }
132
+ ```
133
+
134
+ Rules:
135
+
136
+ - valid statuses are `converged`, `not-converged`, and `unknown`;
137
+ - LLVM and Wasm compilation require `converged`;
138
+ - codes/types do not carry type-derivation status;
139
+ - `.ko` and `.klib` may still store non-converged relations;
140
+ - object execution may still use the JS evaluator for non-converged relations.
141
+
142
+ Alternative:
143
+
144
+ - Store one object-level `backendEligible` flag. This hides which relation
145
+ blocks backend compilation and is not enough for libraries.
146
+
147
+ ### Step 2: Normalize Opcodes
148
+
149
+ KIR-P should use a closed opcode set:
150
+
151
+ ```json
152
+ { "op": "identity" }
153
+ { "op": "empty" }
154
+ { "op": "dot", "label": "x" }
155
+ { "op": "div", "tag": "some" }
156
+ { "op": "vid", "tag": "some" }
157
+ { "op": "code", "code": "@..." }
158
+ { "op": "filter", "filter": {} }
159
+ { "op": "ref", "ref": "@..." }
160
+ { "op": "comp", "items": [] }
161
+ { "op": "union", "items": [] }
162
+ { "op": "product", "fields": [{ "label": "x", "expr": {} }] }
163
+ ```
164
+
165
+ Alternative:
166
+
167
+ - Keep current AST field names. This is faster now, but backend code should not
168
+ depend on parser-shaped fields.
169
+
170
+ ### Step 3: Normalize Codes
171
+
172
+ Represent codes as canonical product or union nodes:
173
+
174
+ ```json
175
+ {
176
+ "@hash": {
177
+ "kind": "product",
178
+ "fields": [{ "label": "x", "code": "@..." }],
179
+ "canonical": "$C0={...};"
180
+ }
181
+ }
182
+ ```
183
+
184
+ Rules:
185
+
186
+ - Sort labels and tags canonically.
187
+ - Store references as canonical hashes.
188
+ - Validate that each hash matches its canonical form.
189
+
190
+ Alternative:
191
+
192
+ - Omit `canonical` and recompute it. This reduces payload size. Keeping it helps
193
+ debugging and validation during the POC.
194
+
195
+ ### Step 4: Normalize Pattern Graphs
196
+
197
+ Do not expose `TypePatternGraph` internals as the backend contract.
198
+
199
+ Use:
200
+
201
+ ```json
202
+ {
203
+ "root": 0,
204
+ "nodes": [
205
+ {
206
+ "id": 0,
207
+ "kind": "open-product",
208
+ "edges": [{ "label": "x", "target": 1 }]
209
+ }
210
+ ]
211
+ }
212
+ ```
213
+
214
+ Rules:
215
+
216
+ - Valid kinds: `any`, `open-product`, `closed-product`, `open-union`,
217
+ `closed-union`, `type`.
218
+ - Type nodes carry a code hash.
219
+ - Edge targets must exist.
220
+ - Edge order must be canonical.
221
+
222
+ Alternative:
223
+
224
+ - Store union-find state as debug metadata. Do not use it as backend input.
225
+
226
+ ## Retyping
227
+
228
+ ### Step 5: Add `retype(rel, inputPattern)`
229
+
230
+ Input:
231
+
232
+ - KIR-P relation;
233
+ - concrete canonical input pattern;
234
+ - code table;
235
+ - relation table.
236
+
237
+ Output:
238
+
239
+ - KIR-R relation;
240
+ - output pattern;
241
+ - call-site pattern summary.
242
+
243
+ Algorithm:
244
+
245
+ 1. Type the entry as if the program were `?inputPattern __main__`.
246
+ 2. Re-run pattern derivation over the reachable relation graph.
247
+ 3. Preserve value-level partial operations.
248
+ 4. Record the derived output pattern.
249
+ 5. Record call-site pattern contexts for helper calls.
250
+
251
+ Alternative:
252
+
253
+ - Implement this inside `run.mjs` first. This may be useful for bootstrapping,
254
+ but the final API should be separate from the evaluator.
255
+
256
+ ### Step 6: Execution After Retyping
257
+
258
+ Safe baseline:
259
+
260
+ - keep current envelope-carrying execution;
261
+ - use KIR-R only to derive the top-level output pattern;
262
+ - treat filters as already validated by retyping.
263
+
264
+ Optimized mode:
265
+
266
+ - remove envelope propagation only when every call site has a known stable
267
+ pattern context;
268
+ - keep value-level partiality for `.field`, `/tag`, merge, and composition;
269
+ - attach the derived output pattern after execution.
270
+
271
+ Alternative:
272
+
273
+ - Never remove envelopes in the JS evaluator. This is simplest and remains the
274
+ reference path. Envelope-free execution can be left to KIR-M.
275
+
276
+ ### Step 7: Call-Site Retyping
277
+
278
+ One relation may be called under multiple patterns:
279
+
280
+ ```text
281
+ f@P1
282
+ f@P2
283
+ ```
284
+
285
+ KIR-R should model these as separate instances:
286
+
287
+ ```text
288
+ relation hash + input pattern hash
289
+ ```
290
+
291
+ Recursive definitions require fixed-point iteration over these instances.
292
+
293
+ Alternative:
294
+
295
+ - Use one annotation per relation. This is easier, but too coarse for precise
296
+ output patterns and unsafe for envelope-free execution.
297
+
298
+ ### Step 8: Cache Retyping Results
299
+
300
+ Cache key:
301
+
302
+ ```text
303
+ relation-hash + input-pattern-hash
304
+ ```
305
+
306
+ Cache value:
307
+
308
+ - KIR-R relation;
309
+ - output pattern;
310
+ - call-site pattern summary;
311
+ - optional backend artifact.
312
+
313
+ Alternative:
314
+
315
+ - Cache by pattern JSON first. Replace with pattern hashes once pattern hashing
316
+ is stable.
317
+
318
+ ## Conformance
319
+
320
+ ### Step 9: Fixture Format
321
+
322
+ Use one directory per case:
323
+
324
+ ```text
325
+ conformance/projection-field/
326
+ case.json
327
+ program.k
328
+ input.kv
329
+ expected.kv
330
+ ```
331
+
332
+ Example:
333
+
334
+ ```json
335
+ {
336
+ "name": "project field",
337
+ "program": "program.k",
338
+ "input": "input.kv",
339
+ "expected": "expected.kv",
340
+ "modes": ["source", "object", "retyped"],
341
+ "tags": ["runtime", "projection"]
342
+ }
343
+ ```
344
+
345
+ Alternative:
346
+
347
+ - Store all fixtures in one JSON file. This is compact but harder to debug.
348
+
349
+ ### Step 10: Runner
350
+
351
+ Add `conformance/run.mjs`.
352
+
353
+ Modes:
354
+
355
+ - `source`: compile source and run the JS evaluator;
356
+ - `object`: compile `.ko`, load it, and run object evaluation;
357
+ - `retyped`: retype using the input wire pattern and run the retyped evaluator;
358
+ - future `wasm` / `llvm`: run backend artifacts.
359
+
360
+ Comparison:
361
+
362
+ - Parse `input.kv` through `k-parse`.
363
+ - Run one mode.
364
+ - Print through `k-print`.
365
+ - Compare normalized textual output.
366
+
367
+ Alternative:
368
+
369
+ - Compare JS values directly. This is faster, but fixtures should not depend on
370
+ JS object representation.
371
+
372
+ ### Step 11: Initial Fixtures
373
+
374
+ Runtime:
375
+
376
+ - identity;
377
+ - product projection;
378
+ - union projection;
379
+ - variant construction;
380
+ - composition;
381
+ - merge fallback;
382
+ - product construction.
383
+
384
+ Typing and patterns:
385
+
386
+ - `$type` filter;
387
+ - open product filter;
388
+ - open union filter;
389
+ - recursive list/tree filter;
390
+ - incompatible filter error.
391
+
392
+ Objects and libraries:
393
+
394
+ - compile `.klib`;
395
+ - compile `.ko` with `--lib`;
396
+ - load aliases from metadata;
397
+ - `:load --no-alias`;
398
+ - reload `extract-aliases` output.
399
+
400
+ Codecs:
401
+
402
+ - unit;
403
+ - nested product;
404
+ - nested variant;
405
+ - Unicode labels;
406
+ - explicit pattern vs derived witness pattern.
407
+
408
+ Retyping:
409
+
410
+ - output pattern derived from `?P __main__`;
411
+ - helper called under two different patterns;
412
+ - recursive helper retyping convergence;
413
+ - retyping cache reuse.
414
+
415
+ Backend eligibility:
416
+
417
+ - converged relation compiles to KIR-M;
418
+ - non-converged relation is rejected by LLVM/Wasm compiler;
419
+ - `.klib` with mixed relations reports the exact rejected aliases.
420
+
421
+ Alternative:
422
+
423
+ - Start with fuzzing. Do this later. First fixtures should be deterministic and
424
+ readable.
425
+
426
+ ## Tooling Ideas
427
+
428
+ - `k-inspect-object`: print object sections, KIR-P, aliases, metadata, and
429
+ pattern summaries.
430
+ - `k-validate-object`: validate `.ko` and `.klib` schemas and references.
431
+ - `k-retype-object`: precompute KIR-R for one relation and input pattern.
432
+ - Retyping heat counters in the JS runtime.
433
+ - Pattern-hash backend artifact cache.
434
+ - Optional binary executable object payload after KIR stabilizes.
435
+ - Minimal C backend before LLVM.
436
+ - Wasm KIR-R interpreter before native LLVM.
437
+
438
+ ## Implementation Order
439
+
440
+ 1. Write `DOCS/KIR_V1.md`.
441
+ 2. Treat current `.ko` / `.klib` storage as the initial KIR-P input format.
442
+ 3. Add `kir.mjs` to export KIR-P from current objects.
443
+ 4. Add `objects/inspect.mjs --kir`.
444
+ 5. Add `objects/validate.mjs`.
445
+ 6. Add conformance fixture format and runner.
446
+ 7. Add entry retyping for `?P __main__`.
447
+ 8. Add a KIR-R JS evaluator or retyped execution wrapper.
448
+ 9. Compare KIR-R execution against `run.mjs`.
449
+ 10. Add call-site retyping for helper relations.
450
+ 11. Add retyping cache.
451
+ 12. Reject non-converged relations in LLVM/Wasm compilation.
452
+ 13. Prototype a small C or Wasm backend for KIR-R.
453
+
454
+ Rule:
455
+
456
+ - KIR-P is the portable semantic contract.
457
+ - KIR-R is the retyping contract.
458
+ - KIR-M is backend material.
@@ -29,6 +29,10 @@ $ pattern-node = <
29
29
  $ pattern = < {} nil, { pattern-node car, pattern cdr } cons >;
30
30
  ```
31
31
 
32
+ This does not mean `core.k` is pre-loaded into ordinary program execution. The
33
+ special role of `core.k` here is that the wire codec relies on the canonical
34
+ `$pattern` definition from that file.
35
+
32
36
  In this schema:
33
37
 
34
38
  - the first pattern-list element is node `0`, the root,
@@ -78,29 +82,53 @@ type still needs design work because the concrete input value is typed by the
78
82
  decoded pattern. The important boundary is that object files should carry
79
83
  ordinary k values and patterns, not a JSON codec object.
80
84
 
81
- Later versions can add relation IR, constant tables, symbol dictionaries,
82
- relocation/linking records, optimization metadata, and optional indexes.
85
+ The format can add relation IR, constant tables, symbol dictionaries,
86
+ relocation/linking records, optimization metadata, and optional indexes as the
87
+ implementation changes.
83
88
 
84
- ## Executable Object Container v1
89
+ ## Object And Library Containers
85
90
 
86
- The current executable object format is a small binary container:
91
+ The current executable `.ko` format is a small binary container:
87
92
 
88
93
  ```text
89
- "KOBJ" 0x00 0x01 0x0a
94
+ "KOBJ" 0x0a
90
95
  uint32-be payload-byte-length
91
96
  utf8-json-payload
92
97
  ```
93
98
 
99
+ Library files (`.klib`) are plain UTF-8 JSON with no binary header.
100
+
101
+ Both containers use the same JSON payload shape. Executable `.ko` files set
102
+ `main` to the entry relation name. Library `.klib` files set `main` to `null`.
103
+ There is no payload version field.
104
+
94
105
  The payload stores:
95
106
 
96
107
  - the normalized code repository needed by the object,
97
- - the compiled relation IR,
108
+ - the compiled relation IR without generated boundary filters,
98
109
  - each relation's type-pattern graph state,
110
+ - each relation's `typeDerivation.status`,
111
+ - relation aliases in `relAlias`,
112
+ - compiler convergence details in top-level `compileStats`,
113
+ - metadata, including aliases and origin source locations,
99
114
  - the main relation name.
100
115
 
116
+ Relation `def` values do not store source `start` / `end` markers. Source
117
+ locations live on `meta[hash].origins[]` entries. Each metadata entry has
118
+ `type: "code"` or `type: "rel"`. Origin entries hold `source`, `name`,
119
+ `compiledAt`, and optional `start` / `end`; origin entries do not have `kind`.
120
+
121
+ Relation `def` values also do not store the generated input/output filters.
122
+ Those filters are derived from `def.patterns` and `typePatternGraph` when
123
+ printing or enforcing relation boundaries.
124
+
125
+ Codes/types do not carry `typeDerivation`. Type derivation is a relation
126
+ property, and the persisted `typeDerivation` object currently contains only
127
+ `status`.
128
+
101
129
  Loading an object hydrates the type-pattern graphs back into runtime
102
- `TypePatternGraph` instances and executes them through `run.mjs`. This avoids
103
- source parsing and type derivation on the execution path.
130
+ `TypePatternGraph` instances and executes relation boundaries through
131
+ `run.mjs`. This avoids source parsing and type derivation on the execution path.
104
132
 
105
133
  Object execution through `k.mjs`:
106
134
 
@@ -116,10 +144,12 @@ Standalone helpers live in `objects/`:
116
144
 
117
145
  ```sh
118
146
  ./objects/compile.mjs path/to/program.k path/to/program.ko
147
+ ./objects/compile-lib.mjs path/to/library.k path/to/library.klib
119
148
  ./objects/decompile.mjs path/to/program.ko path/to/program.decompiled.k
149
+ ./objects/extract-aliases.mjs path/to/library.klib path/to/aliases.k
120
150
  ```
121
151
 
122
- With no arguments, both helpers read from stdin and write to stdout:
152
+ With no arguments, the helpers read from stdin and write to stdout:
123
153
 
124
154
  ```sh
125
155
  cat path/to/program.k | ./objects/compile.mjs > path/to/program.ko
@@ -149,8 +179,8 @@ compile it with:
149
179
  The first bytes of `id.ko` are the binary container header:
150
180
 
151
181
  ```text
152
- 4b 4f 42 4a 00 01 0a 00 00 03 0b ...
153
- K O B J \0 v1 \n payload-length
182
+ 4b 4f 42 4a 0a 00 00 03 0b ...
183
+ K O B J \n payload-length
154
184
  ```
155
185
 
156
186
  After the header, the payload is UTF-8 JSON. Pretty-printed and shortened, the
@@ -159,59 +189,119 @@ payload has this shape:
159
189
  ```json
160
190
  {
161
191
  "format": "k-object",
162
- "version": 1,
163
- "codes": {
164
- "@NiDZqYggx3VZ6b8quBZKTfkgJztWctkesuX4CrhTxM5c": {
165
- "code": "product",
166
- "product": {},
167
- "def": "$C0={};"
192
+ "codes": {},
193
+ "main": "__main__",
194
+ "rels": {
195
+ "__main__": {
196
+ "def": { "op": "identity", "patterns": [0, 0] },
197
+ "typeDerivation": {
198
+ "status": "converged"
199
+ },
200
+ "typePatternGraph": {
201
+ "patterns": {
202
+ "nodes": [{ "pattern": "(...)", "fields": [] }],
203
+ "parent": []
204
+ },
205
+ "edges": [{}],
206
+ "codeId": {}
207
+ }
168
208
  }
169
209
  },
170
- "main": "__main__",
171
- "defs": {
172
- "rels": {
173
- "__main__": {
174
- "def": {
175
- "op": "filter",
176
- "filter": { "type": null, "open": true, "fields": {}, "name": "X0" },
177
- "patterns": [0, 0],
210
+ "relAlias": { "__main__": "@QfyLpmn56wuppuGvrrUJz8LKtgaXfbMtad7RnzBcFk2S" },
211
+ "compileStats": { "sccs": [...], "sccCount": 1 },
212
+ "meta": {
213
+ "@QfyLpmn56wuppuGvrrUJz8LKtgaXfbMtad7RnzBcFk2S": {
214
+ "type": "rel",
215
+ "origins": [
216
+ {
217
+ "source": "id.k",
218
+ "name": "__main__",
219
+ "compiledAt": "2026-05-20T00:00:00.000Z",
178
220
  "start": { "line": 1, "column": 1 },
179
221
  "end": { "line": 1, "column": 3 }
180
- },
181
- "typePatternGraph": {
182
- "patterns": {
183
- "nodes": [{ "pattern": "(...)", "fields": [] }],
184
- "parent": []
185
- },
186
- "edges": [{}],
187
- "codeId": {}
188
222
  }
189
- }
190
- },
191
- "representatives": {},
192
- "relAlias": { "__main__": "..." },
193
- "compileStats": { "sccs": [...], "sccCount": 1 }
223
+ ]
224
+ }
194
225
  }
195
226
  }
196
227
  ```
197
228
 
198
229
  The `codes` field is the type repository snapshot needed by this object. The
199
- `defs.rels.__main__.def` field is the executable relation IR. The
230
+ `rels.__main__.def` field is the executable relation body. The
200
231
  `typePatternGraph` field is the compiled pattern graph used by `run.mjs` for
201
- input-envelope refinement. Loading the object reconstructs live
232
+ relation-boundary refinement. Loading the object reconstructs live
202
233
  `TypePatternGraph` instances from this JSON state and then evaluates the input
203
- value directly against the compiled IR.
234
+ value against the compiled IR.
204
235
 
205
236
  Decompiling this object produces canonical source with generated prefix names:
206
237
 
207
238
  ```k
208
239
  ----- codes -----
209
- $ NiDZ = {};
210
240
  ----- rels -----
211
- QfyL = ?X0;
241
+ QfyL = ?(...) () ?(...);
212
242
  ----- main -----
213
243
  ?(...) QfyL ?(...)
214
244
  ```
215
245
 
216
246
  In the `rels` section, relation definitions are printed in the same SCC order
217
247
  recorded during compilation. Non-empty SCC groups are separated by a blank line.
248
+
249
+ ## Small Library Example
250
+
251
+ For a definitions-only source file:
252
+
253
+ ```k
254
+ -- defs.k
255
+ $ nat = <{} zero, nat succ>;
256
+ succ = |succ;
257
+ ```
258
+
259
+ compile it with:
260
+
261
+ ```sh
262
+ ./objects/compile-lib.mjs defs.k defs.klib
263
+ ```
264
+
265
+ The output file is plain JSON and starts with `{`, not a binary prefix. Its
266
+ shape is the same object payload shape with `main: null`:
267
+
268
+ ```json
269
+ {
270
+ "format": "k-object",
271
+ "codes": {
272
+ "@...": {
273
+ "code": "union",
274
+ "union": { "zero": "@...", "succ": "@..." },
275
+ "def": "$C0=<C1\"succ\",C2\"zero\">;..."
276
+ }
277
+ },
278
+ "rels": {
279
+ "@...": {
280
+ "def": { "op": "vid", "vid": "succ", "patterns": [0, 1] },
281
+ "typeDerivation": { "status": "converged" },
282
+ "typePatternGraph": { "patterns": "...", "edges": "...", "codeId": "..." }
283
+ }
284
+ },
285
+ "relAlias": { "succ": "@..." },
286
+ "compileStats": { "sccs": [...], "sccCount": 1 },
287
+ "meta": {
288
+ "@...": {
289
+ "type": "rel",
290
+ "origins": [
291
+ {
292
+ "source": "defs.k",
293
+ "name": "succ",
294
+ "compiledAt": "2026-05-20T00:00:00.000Z",
295
+ "start": { "line": 3, "column": 8 },
296
+ "end": { "line": 3, "column": 13 }
297
+ }
298
+ ]
299
+ }
300
+ },
301
+ "main": null
302
+ }
303
+ ```
304
+
305
+ When a library is compiled with `--lib`, the output is the merged library
306
+ closure. Imported codes, relations, aliases, and metadata are preserved, and the
307
+ new source adds its own origins.