@fraczak/k 6.1.1 → 6.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/.codex +0 -0
  2. package/Code-derivation-tests/pattern-envelope.mjs +26 -0
  3. package/DOCS/BIG_PICTURE.md +10 -10
  4. package/DOCS/DIVERGENCE_DETECTION.md +1 -1
  5. package/DOCS/REPL.md +33 -0
  6. package/DOCS/TYPE_DERIVATION.md +12 -12
  7. package/DOCS/a.html +398 -0
  8. package/DOCS/book/01-introduction.md +2 -2
  9. package/DOCS/book/02-syntax-and-values.md +8 -8
  10. package/DOCS/book/03-types-as-finite-automata.md +2 -2
  11. package/DOCS/book/04-partial-functions-and-composition.md +2 -2
  12. package/DOCS/book/05-typing-filters-and-normalization.md +3 -3
  13. package/DOCS/book/06-values-in-memory.md +3 -3
  14. package/DOCS/book/07-the-partial-function-abi.md +1 -1
  15. package/DOCS/book/08-operational-semantics-and-execution.md +1 -1
  16. package/DOCS/book/09-compiler-architecture.md +2 -2
  17. package/DOCS/book/appendix-b-incorporating-external-predefined-types-and-functions.md +1 -0
  18. package/DOCS/dependency-graph.html +140 -0
  19. package/DOCS/dependency-graph.md +144 -0
  20. package/NAT.k~ +452 -0
  21. package/README.md +7 -8
  22. package/UU/ta.k +1 -0
  23. package/UU/ta.k~ +0 -0
  24. package/UU/tb.k +0 -0
  25. package/UU/tc.k +0 -0
  26. package/a.k +138 -0
  27. package/a.klib +1 -0
  28. package/codecs/BINARY_FORMAT.html +471 -0
  29. package/codecs/BINARY_FORMAT.md +1 -1
  30. package/codecs/POLYMORPHIC_BINARY_FORMAT.html +355 -0
  31. package/codecs/POLYMORPHIC_BINARY_FORMAT.md +1 -1
  32. package/codecs/ieee.mjs +19 -4
  33. package/codecs/int.mjs +11 -4
  34. package/codecs/json.mjs +7 -4
  35. package/codecs/k-parse.mjs +7 -4
  36. package/codecs/k-print.mjs +7 -4
  37. package/codecs/runtime/cli-entry.mjs +13 -0
  38. package/codecs/show.mjs +7 -4
  39. package/codecs/unit.mjs +23 -8
  40. package/codecs/utf16.mjs +27 -5
  41. package/codecs/utf8.mjs +27 -5
  42. package/codes.mjs +14 -33
  43. package/core.json +1 -0
  44. package/core.klib +1 -0
  45. package/core.klib~ +0 -0
  46. package/export.mjs +3 -3
  47. package/ieee.klib +1 -0
  48. package/k-vscode/package-lock.json +4176 -0
  49. package/kkk.k +197 -0
  50. package/kkk.klib +0 -0
  51. package/kkk.klib~ +0 -0
  52. package/nak.klib +1 -0
  53. package/nak2.klib +1 -0
  54. package/nat.k +10 -0
  55. package/nat2.k +9 -0
  56. package/object.mjs +20 -7
  57. package/p.json +5475 -0
  58. package/package.json +3 -2
  59. package/repl-codecs.mjs +173 -0
  60. package/repl.mjs +215 -5
  61. package/run.mjs +16 -2
  62. package/scripts/benchmark-idempotency.mjs +72 -0
  63. package/test-ieee-arithmetic.mjs +93 -0
  64. package/test-k-object.mjs +19 -0
  65. package/test-repl.mjs +60 -1
  66. package/tests.sh +10 -1
  67. package/type_registry/registry.mjs~ +105 -0
  68. package/type_registry/typeParser.jison~ +132 -0
  69. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  70. package/.idea/copilot.data.migration.agent.xml +0 -6
  71. package/.idea/copilot.data.migration.ask.xml +0 -6
  72. package/.idea/copilot.data.migration.ask2agent.xml +0 -6
  73. package/.idea/copilot.data.migration.edit.xml +0 -6
  74. package/.idea/k.iml +0 -9
  75. package/.idea/misc.xml +0 -6
  76. package/.idea/modules.xml +0 -8
  77. package/.idea/vcs.xml +0 -6
  78. package/k_compiler/runtime.c +0 -205
  79. package/k_compiler/runtime.h +0 -34
@@ -0,0 +1,471 @@
1
+ <!DOCTYPE html>
2
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="generator" content="pandoc" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
7
+ <title>BINARY_FORMAT</title>
8
+ <style>
9
+ code{white-space: pre-wrap;}
10
+ span.smallcaps{font-variant: small-caps;}
11
+ div.columns{display: flex; gap: min(4vw, 1.5em);}
12
+ div.column{flex: auto; overflow-x: auto;}
13
+ div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
14
+ /* The extra [class] is a hack that increases specificity enough to
15
+ override a similar rule in reveal.js */
16
+ ul.task-list[class]{list-style: none;}
17
+ ul.task-list li input[type="checkbox"] {
18
+ font-size: inherit;
19
+ width: 0.8em;
20
+ margin: 0 0.8em 0.2em -1.6em;
21
+ vertical-align: middle;
22
+ }
23
+ .display.math{display: block; text-align: center; margin: 0.5rem auto;}
24
+ /* CSS for syntax highlighting */
25
+ html { -webkit-text-size-adjust: 100%; }
26
+ pre > code.sourceCode { white-space: pre; position: relative; }
27
+ pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
28
+ pre > code.sourceCode > span:empty { height: 1.2em; }
29
+ .sourceCode { overflow: visible; }
30
+ code.sourceCode > span { color: inherit; text-decoration: inherit; }
31
+ div.sourceCode { margin: 1em 0; }
32
+ pre.sourceCode { margin: 0; }
33
+ @media screen {
34
+ div.sourceCode { overflow: auto; }
35
+ }
36
+ @media print {
37
+ pre > code.sourceCode { white-space: pre-wrap; }
38
+ pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
39
+ }
40
+ pre.numberSource code
41
+ { counter-reset: source-line 0; }
42
+ pre.numberSource code > span
43
+ { position: relative; left: -4em; counter-increment: source-line; }
44
+ pre.numberSource code > span > a:first-child::before
45
+ { content: counter(source-line);
46
+ position: relative; left: -1em; text-align: right; vertical-align: baseline;
47
+ border: none; display: inline-block;
48
+ -webkit-touch-callout: none; -webkit-user-select: none;
49
+ -khtml-user-select: none; -moz-user-select: none;
50
+ -ms-user-select: none; user-select: none;
51
+ padding: 0 4px; width: 4em;
52
+ color: #aaaaaa;
53
+ }
54
+ pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
55
+ div.sourceCode
56
+ { }
57
+ @media screen {
58
+ pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
59
+ }
60
+ code span.al { color: #ff0000; font-weight: bold; } /* Alert */
61
+ code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
62
+ code span.at { color: #7d9029; } /* Attribute */
63
+ code span.bn { color: #40a070; } /* BaseN */
64
+ code span.bu { color: #008000; } /* BuiltIn */
65
+ code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
66
+ code span.ch { color: #4070a0; } /* Char */
67
+ code span.cn { color: #880000; } /* Constant */
68
+ code span.co { color: #60a0b0; font-style: italic; } /* Comment */
69
+ code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
70
+ code span.do { color: #ba2121; font-style: italic; } /* Documentation */
71
+ code span.dt { color: #902000; } /* DataType */
72
+ code span.dv { color: #40a070; } /* DecVal */
73
+ code span.er { color: #ff0000; font-weight: bold; } /* Error */
74
+ code span.ex { } /* Extension */
75
+ code span.fl { color: #40a070; } /* Float */
76
+ code span.fu { color: #06287e; } /* Function */
77
+ code span.im { color: #008000; font-weight: bold; } /* Import */
78
+ code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
79
+ code span.kw { color: #007020; font-weight: bold; } /* Keyword */
80
+ code span.op { color: #666666; } /* Operator */
81
+ code span.ot { color: #007020; } /* Other */
82
+ code span.pp { color: #bc7a00; } /* Preprocessor */
83
+ code span.sc { color: #4070a0; } /* SpecialChar */
84
+ code span.ss { color: #bb6688; } /* SpecialString */
85
+ code span.st { color: #4070a0; } /* String */
86
+ code span.va { color: #19177c; } /* Variable */
87
+ code span.vs { color: #4070a0; } /* VerbatimString */
88
+ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
89
+ </style>
90
+ <link rel="stylesheet" href="pandoc.css" />
91
+ </head>
92
+ <body>
93
+ <h1 id="k-binary-interchange-format-specification">K Binary Interchange
94
+ Format Specification</h1>
95
+ <p>This document describes the <strong>closed-value
96
+ specialization</strong> of the more general polymorphic package format
97
+ defined in <code>POLYMORPHIC_BINARY_FORMAT.md</code>.</p>
98
+ <p>Semantically, this file covers the singleton-pattern case:</p>
99
+ <pre class="text"><code>(Pat(T), (T, t))</code></pre>
100
+ <p>where the explicit pattern graph is omitted because it is uniquely
101
+ determined by the witness type <code>T</code>.</p>
102
+ <p>Equivalently, this is the codec used at an
103
+ <code>exact-type-leaf</code> boundary in the polymorphic format.</p>
104
+ <p>So this document does <strong>not</strong> define a separate semantic
105
+ object. It defines the compact binary representation of the
106
+ already-understood object:</p>
107
+ <pre class="text"><code>(Pat(T), (T, t))</code></pre>
108
+ <p>with the following optimization:</p>
109
+ <ul>
110
+ <li>the explicit pattern graph <code>Pat(T)</code> is omitted,</li>
111
+ <li>the exact root type is named directly by
112
+ <code>root_type_hash</code>,</li>
113
+ <li>the value is decoded relative to that exact type.</li>
114
+ </ul>
115
+ <h2 id="overview">Overview</h2>
116
+ <p>The binary format for k values consists of two parts:</p>
117
+ <ol type="1">
118
+ <li><strong>Type header</strong>: Identifies the canonical type of the
119
+ value</li>
120
+ <li><strong>Value payload</strong>: canonical encoding of the value’s
121
+ <strong>minimal typed DAG</strong></li>
122
+ </ol>
123
+ <p>The payload is designed to be friendly to the two primitive
124
+ <code>k</code> navigations:</p>
125
+ <ul>
126
+ <li><code>.label</code> on products</li>
127
+ <li><code>/tag</code> on unions</li>
128
+ </ul>
129
+ <p>This pushes the format away from a pure inline bitstream tree and
130
+ toward a <strong>node-table encoding</strong> of the minimal typed DAG.
131
+ The type carries labels and tag names; the payload carries only compact
132
+ structural references.</p>
133
+ <h2 id="relation-to-the-polymorphic-format">Relation To The Polymorphic
134
+ Format</h2>
135
+ <p>The general polymorphic package serializes:</p>
136
+ <pre class="text"><code>pattern_section + value_section</code></pre>
137
+ <p>where pattern nodes may include <code>exact-type-leaf</code>.</p>
138
+ <p>This file is the specialization obtained when:</p>
139
+ <ul>
140
+ <li>the root pattern is singleton,</li>
141
+ <li>the whole package can therefore be represented by one exact root
142
+ type,</li>
143
+ <li>the explicit pattern section is dropped.</li>
144
+ </ul>
145
+ <p>Operationally:</p>
146
+ <ul>
147
+ <li><code>root_type_hash</code> plays the role of the omitted singleton
148
+ root pattern,</li>
149
+ <li><code>state_id</code> values are interpreted in the canonical
150
+ automaton of that exact type,</li>
151
+ <li>the resulting closed-value payload is exactly what an
152
+ <code>exact-type-leaf</code> delegates to in the polymorphic spec.</li>
153
+ </ul>
154
+ <h2 id="format-structure">Format Structure</h2>
155
+ <pre><code>┌─────────────────┬────────────────────────────────┐
156
+ │ Type Header │ Value Payload │
157
+ │ (variable) │ (variable) │
158
+ └─────────────────┴────────────────────────────────┘</code></pre>
159
+ <h3 id="type-header">Type Header</h3>
160
+ <p>The type is identified by its <strong>canonical name</strong>
161
+ (content-addressed hash), which is a base58-encoded SHA-256 hash
162
+ prefixed with <code>@</code>.</p>
163
+ <p><strong>Format Options:</strong></p>
164
+ <p><strong>Option A: Length-prefixed ASCII</strong></p>
165
+ <pre><code>[1 byte: length N][N bytes: ASCII type hash including &#39;@&#39;]</code></pre>
166
+ <p>Example:
167
+ <code>\x2d@NiDZqYggx3VZ6b8quBZKTfkgJztWctkesuX4CrhTxM5c</code></p>
168
+ <p><strong>Option B: Fixed 32-byte hash</strong></p>
169
+ <pre><code>[32 bytes: raw SHA-256 hash]</code></pre>
170
+ <p>No ‘@’ prefix, no base58 encoding - pure binary.</p>
171
+ <p><strong>Option C: No header (rely on context)</strong></p>
172
+ <pre><code>[Value payload only]</code></pre>
173
+ <p>The decoder must know the expected type from context.</p>
174
+ <p><strong>Decision: Option B</strong> - Fixed 32-byte raw hash</p>
175
+ <ul>
176
+ <li>Predictable size (easier to parse)</li>
177
+ <li>Compact (no encoding overhead)</li>
178
+ <li>Fast to validate (direct hash comparison)</li>
179
+ </ul>
180
+ <p>In the polymorphic setting, this corresponds to omitting the explicit
181
+ singleton pattern and naming the exact root type directly.</p>
182
+ <h3 id="value-payload-canonical-serialization">Value Payload (Canonical
183
+ Serialization)</h3>
184
+ <p>The source semantic object is always a <strong>typed tree</strong>.
185
+ For compact interchange, the wire format may encode the tree through its
186
+ unique minimal DAG quotient.</p>
187
+ <p>Two subtrees are shareable only if they are equal as <strong>typed
188
+ values</strong>:</p>
189
+ <ul>
190
+ <li>they are rooted at the same canonical subtype/state,</li>
191
+ <li>they choose the same union alternative if applicable,</li>
192
+ <li>and their children are recursively equal as typed values.</li>
193
+ </ul>
194
+ <p>Equality of local payload bytes alone is not enough. In particular,
195
+ two subtrees that happen to serialize to the same bit pattern under
196
+ different types must <strong>not</strong> be merged.</p>
197
+ <p>After quotienting by typed-value equality, each DAG node is
198
+ serialized according to its canonical type state:</p>
199
+ <ol type="1">
200
+ <li><strong>Product nodes</strong> store child references in canonical
201
+ field order</li>
202
+ <li><strong>Union nodes</strong> store the chosen tag ordinal, then one
203
+ child reference</li>
204
+ <li><strong>Unit</strong> (empty product) stores no children</li>
205
+ <li><strong>Empty union</strong> cannot be encoded</li>
206
+ </ol>
207
+ <p>The wire format is determined by the minimal typed DAG itself, not by
208
+ encoder heuristics such as “share only large nodes” or “share whichever
209
+ duplicate was found first”.</p>
210
+ <p>For values with no repeated typed subtrees, the DAG degenerates to
211
+ the original tree.</p>
212
+ <p>This is the closed-type analogue of the polymorphic rule that value
213
+ sharing is computed relative to the structural authority above it. Here
214
+ that authority is the exact root type rather than an explicit pattern
215
+ graph.</p>
216
+ <h2 id="canonical-payload-layout">Canonical Payload Layout</h2>
217
+ <p>The payload after the root type hash is:</p>
218
+ <pre class="text"><code>| payload_version:u8 | node_count:uvarint | node_record_0 | ... | node_record_(N-1) |</code></pre>
219
+ <p>Conventions:</p>
220
+ <ul>
221
+ <li><code>payload_version</code> is currently <code>1</code>.</li>
222
+ <li><code>node_count</code> is the number of nodes in the minimal typed
223
+ DAG.</li>
224
+ <li>Node IDs are implicit: the first record is node <code>0</code>, the
225
+ next is node <code>1</code>, …, the last is node <code>N-1</code>.</li>
226
+ <li>The <strong>root node ID is always <code>N-1</code></strong>.</li>
227
+ </ul>
228
+ <p>The payload is therefore compact, sequentially parseable, and
229
+ canonically ordered.</p>
230
+ <h3 id="why-root-last-node">Why root = last node</h3>
231
+ <p>Node records are emitted in canonical <strong>postorder</strong>:</p>
232
+ <ol type="1">
233
+ <li>children before parents,</li>
234
+ <li>product children in canonical field order,</li>
235
+ <li>union nodes visit their single selected child,</li>
236
+ <li>a shared node is emitted only on its first completed postorder
237
+ visit.</li>
238
+ </ol>
239
+ <p>This yields:</p>
240
+ <ul>
241
+ <li>a deterministic node numbering,</li>
242
+ <li>every child ID strictly smaller than its parent ID,</li>
243
+ <li>no explicit root ID field.</li>
244
+ </ul>
245
+ <h2 id="canonical-node-identity">Canonical Node Identity</h2>
246
+ <p>The canonical typed-DAG node key is:</p>
247
+ <pre class="text"><code>(state_id, node_shape)</code></pre>
248
+ <p>where:</p>
249
+ <ul>
250
+ <li><code>state_id</code> is the canonical automaton state of the
251
+ subtree root,</li>
252
+ <li><code>node_shape</code> is:
253
+ <ul>
254
+ <li>for product states: the ordered list of child node IDs,</li>
255
+ <li>for union states: <code>(tag_ordinal, child_id)</code>.</li>
256
+ </ul></li>
257
+ </ul>
258
+ <p>Equivalently, an encoder may compute a bottom-up semantic hash
259
+ from:</p>
260
+ <pre class="text"><code>hash(state_id, tag_ordinal_or_product, hash(child_0), hash(child_1), ...)</code></pre>
261
+ <p>but the semantic rule is normative, not the hash function.</p>
262
+ <h2 id="node-record-layout">Node Record Layout</h2>
263
+ <p>Every node record starts with:</p>
264
+ <pre class="text"><code>| state_id:uvarint | body... |</code></pre>
265
+ <p>The decoder uses <code>state_id</code> together with the root type’s
266
+ canonical automaton to know whether this is a product or union state,
267
+ how many fields it has, and what child states are expected.</p>
268
+ <h3 id="product-record">Product Record</h3>
269
+ <p>If <code>state_id</code> is a product state with fields</p>
270
+ <pre class="text"><code>f0, f1, ..., f(k-1)</code></pre>
271
+ <p>in canonical field order, the record body is:</p>
272
+ <pre class="text"><code>| child_ref_0:uvarint | child_ref_1:uvarint | ... | child_ref_(k-1):uvarint |</code></pre>
273
+ <p>There are no field names in the payload. Labels come entirely from
274
+ the canonical type.</p>
275
+ <h3 id="union-record">Union Record</h3>
276
+ <p>If <code>state_id</code> is a union state with variants</p>
277
+ <pre class="text"><code>t0, t1, ..., t(m-1)</code></pre>
278
+ <p>in canonical tag order, the record body is:</p>
279
+ <pre class="text"><code>| tag_ordinal:uvarint | child_ref:uvarint |</code></pre>
280
+ <p><code>tag_ordinal</code> must be in <code>[0, m)</code>.</p>
281
+ <p>There are no tag names in the payload. Tag names come entirely from
282
+ the canonical type.</p>
283
+ <h3 id="unit-record">Unit Record</h3>
284
+ <p>If <code>state_id</code> is an empty product state <code>{}</code>,
285
+ the record body is empty.</p>
286
+ <p>Its full encoding is just:</p>
287
+ <pre class="text"><code>| state_id:uvarint |</code></pre>
288
+ <h2 id="child-references">Child References</h2>
289
+ <p>Child references are encoded as <strong>back-distances</strong>
290
+ rather than absolute node IDs.</p>
291
+ <p>For a current node with ID <code>i</code> and a child with ID
292
+ <code>j</code>, where <code>j &lt; i</code>, encode:</p>
293
+ <pre class="text"><code>child_ref = i - 1 - j</code></pre>
294
+ <p>Therefore:</p>
295
+ <ul>
296
+ <li><code>0</code> means “the immediately preceding node”,</li>
297
+ <li><code>1</code> means “two records back”,</li>
298
+ <li>and so on.</li>
299
+ </ul>
300
+ <p>The decoder reconstructs:</p>
301
+ <pre class="text"><code>j = i - 1 - child_ref</code></pre>
302
+ <p>This is compact because canonical postorder tends to place children
303
+ near their parents, especially for non-shared subtrees.</p>
304
+ <h2 id="complete-format">Complete Format</h2>
305
+ <pre class="text"><code>| root_type_hash:32 bytes | payload_version:u8 | node_count:uvarint | node records... |</code></pre>
306
+ <p>The root type hash identifies the canonical type automaton used to
307
+ interpret all <code>state_id</code> values and all product-field /
308
+ union-tag ordinals.</p>
309
+ <p>No separate pattern section is needed because the omitted pattern is
310
+ exactly the singleton pattern <code>Pat(T)</code> induced by that root
311
+ type.</p>
312
+ <h2 id="examples">Examples</h2>
313
+ <h3 id="example-1-unit-type">Example 1: Unit type <code>{}</code></h3>
314
+ <ul>
315
+ <li>Type: <code>$unit = {}</code></li>
316
+ <li>Canonical name: <code>@KL...</code> (hash computed by compiler)</li>
317
+ </ul>
318
+ <p>Binary:</p>
319
+ <pre class="text"><code>[32 bytes: root_type_hash($unit)]
320
+ [1 byte: payload_version = 1]
321
+ [uvarint: node_count = 1]
322
+ [uvarint: state_id(unit)]</code></pre>
323
+ <p>There is one node, and because it is the last node, it is also the
324
+ root.</p>
325
+ <h3 id="example-2-boolean">Example 2: Boolean</h3>
326
+ <ul>
327
+ <li>Type: <code>$bool = &lt; {} false, {} true &gt;</code></li>
328
+ <li>Value: <code>{true {}}</code></li>
329
+ </ul>
330
+ <p>Canonical form assigns ordinals: false=0, true=1</p>
331
+ <p>Binary:</p>
332
+ <pre class="text"><code>[32 bytes: root_type_hash($bool)]
333
+ [1 byte: payload_version = 1]
334
+ [uvarint: node_count = 2]
335
+
336
+ node 0:
337
+ [uvarint: state_id(unit)]
338
+
339
+ node 1:
340
+ [uvarint: state_id(bool)]
341
+ [uvarint: tag_ordinal(true) = 1]
342
+ [uvarint: child_ref = 0] // points to node 0</code></pre>
343
+ <p>There are no repeated typed subtrees here, so the minimal DAG is the
344
+ same as the tree.</p>
345
+ <h3 id="example-3-natural-number">Example 3: Natural number</h3>
346
+ <ul>
347
+ <li>Type: <code>$nat = &lt; {} zero, {nat succ} &gt;</code></li>
348
+ <li>Value: <code>{{{{} zero} succ} succ}</code> (represents 2)</li>
349
+ </ul>
350
+ <p>Variant ordinals: zero=0, succ=1</p>
351
+ <p>Binary:</p>
352
+ <pre class="text"><code>[32 bytes: root_type_hash($nat)]
353
+ [1 byte: payload_version = 1]
354
+ [uvarint: node_count = 4]
355
+
356
+ node 0:
357
+ [uvarint: state_id(unit)]
358
+
359
+ node 1:
360
+ [uvarint: state_id(nat)]
361
+ [uvarint: tag_ordinal(zero) = 0]
362
+ [uvarint: child_ref = 0] // points to node 0
363
+
364
+ node 2:
365
+ [uvarint: state_id(nat)]
366
+ [uvarint: tag_ordinal(succ) = 1]
367
+ [uvarint: child_ref = 0] // points to node 1
368
+
369
+ node 3:
370
+ [uvarint: state_id(nat)]
371
+ [uvarint: tag_ordinal(succ) = 1]
372
+ [uvarint: child_ref = 0] // points to node 2</code></pre>
373
+ <p>The root is node 3. Again, this example has no repeated typed
374
+ subtrees, so only ordinary parent-to-child back-distances are used.</p>
375
+ <h2 id="parsing-and-validation">Parsing and Validation</h2>
376
+ <p>The decoder MUST:</p>
377
+ <ol type="1">
378
+ <li>Read the 32-byte root type hash.</li>
379
+ <li>Resolve the canonical type automaton for that hash.</li>
380
+ <li>Read <code>payload_version</code> and reject unknown mandatory
381
+ versions.</li>
382
+ <li>Read <code>node_count</code>.</li>
383
+ <li>Parse records in node-ID order <code>0..N-1</code>.</li>
384
+ <li>For each record:
385
+ <ul>
386
+ <li>resolve <code>state_id</code>,</li>
387
+ <li>determine whether the state is a product or union,</li>
388
+ <li>read exactly the required number of body items,</li>
389
+ <li>verify every child reference points to an earlier node,</li>
390
+ <li>verify every child node’s state matches the edge-required child
391
+ state from the automaton,</li>
392
+ <li>verify union <code>tag_ordinal</code> is valid for the state.</li>
393
+ </ul></li>
394
+ <li>Treat node <code>N-1</code> as the root node.</li>
395
+ </ol>
396
+ <p>Malformed payloads include:</p>
397
+ <ul>
398
+ <li>unknown <code>state_id</code>,</li>
399
+ <li>child references that point outside <code>[0, i)</code>,</li>
400
+ <li>child nodes whose states do not match the type automaton,</li>
401
+ <li>invalid union tag ordinals,</li>
402
+ <li>trailing undecoded bytes,</li>
403
+ <li>impossible empty-union values.</li>
404
+ </ul>
405
+ <h2 id="operation-friendliness">Operation Friendliness</h2>
406
+ <p>This payload is chosen so that a runtime can build an offset table in
407
+ one linear scan and then execute <code>.</code> and <code>/</code>
408
+ cheaply.</p>
409
+ <h3 id="label"><code>.label</code></h3>
410
+ <p>Given a pointer <code>(node_id, state_id)</code> to a product
411
+ node:</p>
412
+ <ol type="1">
413
+ <li>Look up <code>label -&gt; field_index</code> in the canonical type
414
+ state.</li>
415
+ <li>Jump to the <code>field_index</code>-th child reference in the node
416
+ record.</li>
417
+ <li>Follow the child reference to child node <code>j</code>.</li>
418
+ <li>The child state is already determined by the type edge.</li>
419
+ </ol>
420
+ <p>No sibling scanning by label is needed.</p>
421
+ <h3 id="tag"><code>/tag</code></h3>
422
+ <p>Given a pointer <code>(node_id, state_id)</code> to a union node:</p>
423
+ <ol type="1">
424
+ <li>Read <code>tag_ordinal</code> from the node record.</li>
425
+ <li>Compare with the requested tag’s canonical ordinal.</li>
426
+ <li>On match, follow the single child reference.</li>
427
+ <li>On mismatch, fail immediately.</li>
428
+ </ol>
429
+ <p>The discriminator is therefore available before touching the child
430
+ payload.</p>
431
+ <h2 id="implementation-requirements">Implementation Requirements</h2>
432
+ <h3 id="encoder-interface">Encoder Interface</h3>
433
+ <div class="sourceCode" id="cb23"><pre
434
+ class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
435
+ <span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a><span class="co"> * Encode a k value to binary format</span></span>
436
+ <span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="co"> * </span><span class="an">@param</span><span class="co"> </span><span class="cv">{Object}</span><span class="co"> value - k value (Product/Variant from Value.mjs)</span></span>
437
+ <span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a><span class="co"> * </span><span class="an">@param</span><span class="co"> </span><span class="cv">{string}</span><span class="co"> typeName - Canonical type name (e.g., &quot;</span><span class="an">@ABC123...&quot;)</span></span>
438
+ <span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="co"> * </span><span class="an">@param</span><span class="co"> </span><span class="cv">{Object}</span><span class="co"> typeDef - Type definition from compiler</span></span>
439
+ <span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a><span class="co"> * </span><span class="an">@returns</span><span class="co"> {Buffer} Binary representation</span></span>
440
+ <span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a><span class="co"> */</span></span>
441
+ <span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span> <span class="fu">encode</span>(value<span class="op">,</span> typeName<span class="op">,</span> typeDef)<span class="op">;</span></span></code></pre></div>
442
+ <h3 id="decoder-interface">Decoder Interface</h3>
443
+ <div class="sourceCode" id="cb24"><pre
444
+ class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="co">/**</span></span>
445
+ <span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="co"> * Decode a k value from binary format</span></span>
446
+ <span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="co"> * </span><span class="an">@param</span><span class="co"> </span><span class="cv">{Buffer}</span><span class="co"> buffer - Binary data</span></span>
447
+ <span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a><span class="co"> * </span><span class="an">@returns</span><span class="co"> {Object} {typeName: string, value: Value}</span></span>
448
+ <span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="co"> */</span></span>
449
+ <span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span> <span class="fu">decode</span>(buffer)<span class="op">;</span></span></code></pre></div>
450
+ <h2 id="extension-streaming-format">Extension: Streaming Format</h2>
451
+ <p>For streaming multiple values:</p>
452
+ <pre><code>┌─────────────┬──────────┬─────────────┬──────────┬───
453
+ │ 32B hash │ payload │ 32B hash │ payload │ ...
454
+ └─────────────┴──────────┴─────────────┴──────────┴───</code></pre>
455
+ <p>Each value is independently parseable.</p>
456
+ <h2 id="notes">Notes</h2>
457
+ <ul>
458
+ <li>The payload is byte-oriented and node-oriented, not a packed
459
+ bitstream of inline tree branches.</li>
460
+ <li>This slightly increases per-node overhead relative to the most
461
+ compact tree-only encoding, but it makes the format much friendlier to
462
+ the primitive <code>k</code> operations <code>.label</code> and
463
+ <code>/tag</code>.</li>
464
+ <li>A future transport may add a non-canonical auxiliary index for
465
+ zero-scan random access to raw bytes, but the canonical payload itself
466
+ does not require one.</li>
467
+ <li>In the general polymorphic format, this payload appears as the
468
+ delegated leaf codec for <code>exact-type-leaf</code>.</li>
469
+ </ul>
470
+ </body>
471
+ </html>
@@ -9,7 +9,7 @@ in [`POLYMORPHIC_BINARY_FORMAT.md`](./POLYMORPHIC_BINARY_FORMAT.md):
9
9
  encode($pattern_value : $pattern) encode(value : decoded_pattern)
10
10
  ```
11
11
 
12
- ## Purpose Of This File
12
+ ## Purpose of This File
13
13
 
14
14
  This file records constraints for any future optimized container layered above
15
15
  the canonical stream.