@fraczak/k 5.1.2 → 6.0.1
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/.codex +0 -0
- package/Code-derivation-tests/blowup.mjs +3 -3
- package/Code-derivation-tests/bnat.mjs +2 -2
- package/Code-derivation-tests/codec-witness-pattern.mjs +50 -0
- package/Code-derivation-tests/convergence-strategy.mjs +24 -0
- package/Code-derivation-tests/dot.mjs +12 -9
- package/Code-derivation-tests/filter-syntax.mjs +21 -0
- package/Code-derivation-tests/loop.mjs +8 -2
- package/Code-derivation-tests/nat.mjs +1 -1
- package/Code-derivation-tests/not-not.mjs +3 -3
- package/Code-derivation-tests/pattern-envelope.mjs +68 -0
- package/Code-derivation-tests/rlz.mjs +2 -2
- package/{BIG_PICTURE.md → DOCS/BIG_PICTURE.md} +103 -50
- package/DOCS/REPL.md +191 -0
- package/DOCS/a.html +398 -0
- package/DOCS/book/01-introduction.md +51 -0
- package/DOCS/book/02-syntax-and-values.md +111 -0
- package/DOCS/book/03-types-as-finite-automata.md +156 -0
- package/DOCS/book/04-partial-functions-and-composition.md +146 -0
- package/DOCS/book/05-typing-filters-and-normalization.md +111 -0
- package/DOCS/book-combined.html +3798 -0
- package/DOCS/book-combined.md +3745 -0
- package/DOCS/book-combined.pdf +0 -0
- package/DOCS/book-combined.tex +5682 -0
- package/DOCS/book.html +65 -0
- package/DOCS/book.md +54 -0
- package/DOCS/book.pdf +0 -0
- package/DOCS/book.tex +150 -0
- package/NAT.k~ +452 -0
- package/README.md +204 -508
- package/TypeGraph.mjs +43 -0
- package/TypePatternGraph.mjs +251 -0
- package/Value.mjs +192 -0
- package/augmentation.mjs +198 -0
- package/codecs/BINARY_FORMAT.html +471 -0
- package/codecs/BINARY_FORMAT.md +53 -0
- package/codecs/POLYMORPHIC_BINARY_FORMAT.html +355 -0
- package/codecs/POLYMORPHIC_BINARY_FORMAT.md +303 -0
- package/codecs/README.md +215 -0
- package/codecs/example-pipeline.mjs +149 -0
- package/codecs/ieee.mjs +140 -0
- package/codecs/int.mjs +104 -0
- package/codecs/json-codec.mjs +215 -0
- package/codecs/json.mjs +40 -0
- package/codecs/k-parse.mjs +90 -0
- package/codecs/k-pattern.mjs +75 -0
- package/codecs/k-print.mjs +46 -0
- package/codecs/runtime/codec.mjs +768 -0
- package/codecs/runtime/ieee-pattern.mjs +30 -0
- package/codecs/runtime/pattern-json.mjs +96 -0
- package/codecs/runtime/prefix-codec.mjs +425 -0
- package/codecs/runtime/show-value.mjs +68 -0
- package/codecs/runtime/typeFromValue.mjs +34 -0
- package/codecs/runtime/unicode-string.mjs +220 -0
- package/codecs/show.mjs +41 -0
- package/codecs/string-codec.mjs +80 -0
- package/codecs/unit.mjs +51 -0
- package/codecs/utf16.mjs +66 -0
- package/codecs/utf8.mjs +37 -0
- package/codes.mjs +146 -44
- package/compiler.mjs +111 -0
- package/convergence.mjs +197 -0
- package/core.k +197 -0
- package/export.mjs +22 -32
- package/hash.mjs +29 -31
- package/ieee.klib +0 -0
- package/index.mjs +41 -15
- package/k-vscode/.vscode/launch.json +14 -0
- package/k-vscode/README.md +65 -0
- package/k-vscode/language-configuration.json +42 -0
- package/k-vscode/package-lock.json +4176 -0
- package/k-vscode/package.json +57 -0
- package/k-vscode/snippets/k.json +92 -0
- package/k-vscode/syntaxes/k.tmLanguage.json +243 -0
- package/k.mjs +56 -54
- package/object.mjs +517 -0
- package/objects/README.md +38 -0
- package/objects/compile-lib.mjs +42 -0
- package/objects/compile.mjs +42 -0
- package/objects/decompile.mjs +32 -0
- package/package.json +13 -6
- package/parser.jison +27 -46
- package/parser.mjs +68 -100
- package/pretty.mjs +21 -40
- package/repl2.mjs +662 -0
- package/run.mjs +264 -231
- package/symbol-table.mjs +3 -17
- package/test-fingerprint.mjs +7 -7
- package/test-hash-fuzz.mjs +107 -0
- package/test-hash-normalization.mjs +134 -0
- package/test-k-object.mjs +74 -0
- package/test-repl2.mjs +106 -0
- package/test.mjs +45 -70
- package/tests.sh +10 -1
- package/type_registry/registry.mjs~ +105 -0
- package/type_registry/typeParser.jison~ +132 -0
- package/typing.mjs +129 -676
- package/unification.mjs +157 -0
- package/valueIO.mjs +54 -0
- package/valueParser.jison +143 -0
- package/valueParser.mjs +713 -0
- package/Code-derivation-tests/built-in.mjs +0 -19
- package/Code-derivation-tests/vector.mjs +0 -19
- package/Filters/bug.k +0 -3
- package/Filters/composing.k +0 -15
- package/Filters/filter.k +0 -9
- package/TODO.md +0 -53
- package/TYPING.md +0 -365
- package/k-repl.cast +0 -1913
- package/k.cast +0 -618
- package/my-objects.json +0 -6
- package/patterns.mjs +0 -543
- package/repl.mjs +0 -213
- package/test-filters.mjs +0 -45
- package/typing-test.mjs +0 -40
|
@@ -0,0 +1,355 @@
|
|
|
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>POLYMORPHIC_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
|
+
</style>
|
|
25
|
+
<link rel="stylesheet" href="pandoc.css" />
|
|
26
|
+
</head>
|
|
27
|
+
<body>
|
|
28
|
+
<h1 id="k-polymorphic-binary-format">K Polymorphic Binary Format</h1>
|
|
29
|
+
<h2 id="purpose">Purpose</h2>
|
|
30
|
+
<p>This document defines a binary format for polymorphic values in
|
|
31
|
+
<code>k</code>.</p>
|
|
32
|
+
<p>The semantic object to be serialized is:</p>
|
|
33
|
+
<pre class="text"><code>(P, v)</code></pre>
|
|
34
|
+
<p>where:</p>
|
|
35
|
+
<ul>
|
|
36
|
+
<li><code>P</code> is a normalized pattern graph,</li>
|
|
37
|
+
<li><code>v</code> is a typed value compatible with <code>P</code>.</li>
|
|
38
|
+
</ul>
|
|
39
|
+
<p>The binary format is designed so that:</p>
|
|
40
|
+
<ul>
|
|
41
|
+
<li>the pattern carries all field and tag names,</li>
|
|
42
|
+
<li>the value payload carries no explicit labels or tags,</li>
|
|
43
|
+
<li>the value payload is friendly to <code>.label</code> and
|
|
44
|
+
<code>/tag</code>,</li>
|
|
45
|
+
<li>closed typed values appear as the singleton-pattern special
|
|
46
|
+
case.</li>
|
|
47
|
+
</ul>
|
|
48
|
+
<h2 id="design-principles">Design Principles</h2>
|
|
49
|
+
<h3 id="pattern-is-the-structural-authority">1. Pattern is the
|
|
50
|
+
structural authority</h3>
|
|
51
|
+
<p>The pattern section is the authoritative description of the structure
|
|
52
|
+
expected by the value section.</p>
|
|
53
|
+
<p>It determines:</p>
|
|
54
|
+
<ul>
|
|
55
|
+
<li>whether a node is product or union,</li>
|
|
56
|
+
<li>whether it is open or closed,</li>
|
|
57
|
+
<li>which fields or tags are present explicitly,</li>
|
|
58
|
+
<li>which subpositions point to the same pattern node,</li>
|
|
59
|
+
<li>which leaves are exact types.</li>
|
|
60
|
+
</ul>
|
|
61
|
+
<h3 id="value-is-interpreted-relative-to-the-pattern">2. Value is
|
|
62
|
+
interpreted relative to the pattern</h3>
|
|
63
|
+
<p>The value payload is not self-describing. It is decoded relative to
|
|
64
|
+
the pattern graph.</p>
|
|
65
|
+
<p>This is why the payload does not need to repeat field names or tag
|
|
66
|
+
names.</p>
|
|
67
|
+
<h3 id="is-not-value-carrying">3. <code>(...)</code> is not
|
|
68
|
+
value-carrying</h3>
|
|
69
|
+
<p>The leaf pattern <code>(...)</code> is allowed in the pattern
|
|
70
|
+
language, but it is <strong>not</strong> allowed to carry serialized
|
|
71
|
+
value content in version 1 of this format.</p>
|
|
72
|
+
<p>This restriction keeps explicit labels out of the value payload.
|
|
73
|
+
Otherwise the missing structure would have to be reintroduced locally in
|
|
74
|
+
the value itself.</p>
|
|
75
|
+
<h3 id="value-dag-is-only-an-optimization">4. Value DAG is only an
|
|
76
|
+
optimization</h3>
|
|
77
|
+
<p>Semantically, the value is a tree. On the wire, it may be encoded as
|
|
78
|
+
a DAG by collapsing equal occurrences relative to the pattern.</p>
|
|
79
|
+
<h2 id="high-level-structure">High-Level Structure</h2>
|
|
80
|
+
<p>The package layout is:</p>
|
|
81
|
+
<pre class="text"><code>| magic | format_version | flags | symbol_table | pattern_section | value_section |</code></pre>
|
|
82
|
+
<p>There is no separate <code>type_section</code>.</p>
|
|
83
|
+
<h2 id="primitive-encodings">Primitive Encodings</h2>
|
|
84
|
+
<h3 id="integers">Integers</h3>
|
|
85
|
+
<ul>
|
|
86
|
+
<li>fixed-width integers are unsigned and big-endian,</li>
|
|
87
|
+
<li>variable-width integers use unsigned LEB128 and are written
|
|
88
|
+
<code>uvarint</code>.</li>
|
|
89
|
+
</ul>
|
|
90
|
+
<h3 id="symbols">Symbols</h3>
|
|
91
|
+
<p>A symbol is a UTF-8 string used as:</p>
|
|
92
|
+
<ul>
|
|
93
|
+
<li>a field name,</li>
|
|
94
|
+
<li>a tag name,</li>
|
|
95
|
+
<li>an exact type identifier when such identifiers are serialized as
|
|
96
|
+
strings.</li>
|
|
97
|
+
</ul>
|
|
98
|
+
<p>Symbols are interned in a symbol table and referred to by symbol
|
|
99
|
+
ID.</p>
|
|
100
|
+
<h2 id="header">Header</h2>
|
|
101
|
+
<pre class="text"><code>| magic:4 bytes | format_version:u8 | flags:u8 |</code></pre>
|
|
102
|
+
<p>Current values:</p>
|
|
103
|
+
<ul>
|
|
104
|
+
<li><code>magic = "KPV2"</code></li>
|
|
105
|
+
<li><code>format_version = 1</code></li>
|
|
106
|
+
</ul>
|
|
107
|
+
<p>All flag bits are reserved in version 1 and must be zero.</p>
|
|
108
|
+
<h2 id="symbol-table">Symbol Table</h2>
|
|
109
|
+
<pre class="text"><code>| symbol_count:uvarint | symbol_0 | ... | symbol_(N-1) |</code></pre>
|
|
110
|
+
<p>Each symbol is:</p>
|
|
111
|
+
<pre class="text"><code>| byte_length:uvarint | utf8_bytes... |</code></pre>
|
|
112
|
+
<h3 id="canonical-ordering">Canonical ordering</h3>
|
|
113
|
+
<p>Symbols are ordered canonically by:</p>
|
|
114
|
+
<ol type="1">
|
|
115
|
+
<li>ascending UTF-8 byte sequence,</li>
|
|
116
|
+
<li>duplicates removed.</li>
|
|
117
|
+
</ol>
|
|
118
|
+
<p>The same symbol table is used by both the pattern and the value
|
|
119
|
+
sections.</p>
|
|
120
|
+
<h2 id="pattern-section">Pattern Section</h2>
|
|
121
|
+
<p>The pattern section serializes a normalized rooted pattern graph.</p>
|
|
122
|
+
<h3 id="pattern-node-kinds">Pattern node kinds</h3>
|
|
123
|
+
<p>There are exactly five semantic node kinds:</p>
|
|
124
|
+
<ul>
|
|
125
|
+
<li><code>(...)</code></li>
|
|
126
|
+
<li><code>{...}</code></li>
|
|
127
|
+
<li><code><...></code></li>
|
|
128
|
+
<li><code>{}</code></li>
|
|
129
|
+
<li><code><></code></li>
|
|
130
|
+
</ul>
|
|
131
|
+
<p>These are constructor classes of pattern nodes, not leaf/internal
|
|
132
|
+
tags. Only <code>(...)</code> is forced to have no outgoing edges. All
|
|
133
|
+
other node kinds may have zero or more outgoing edges.</p>
|
|
134
|
+
<p>Their meanings are:</p>
|
|
135
|
+
<ul>
|
|
136
|
+
<li><p><code>(...)</code> means unconstrained type,</p></li>
|
|
137
|
+
<li><p><code>{...}</code> with edges
|
|
138
|
+
<code>l1 -> X1, ..., ln -> Xn</code> means</p>
|
|
139
|
+
<pre class="text"><code>{ X1 l1, ..., Xn ln, ... }</code></pre></li>
|
|
140
|
+
<li><p><code><...></code> with edges
|
|
141
|
+
<code>t1 -> X1, ..., tn -> Xn</code> means</p>
|
|
142
|
+
<pre class="text"><code>< X1 t1, ..., Xn tn, ... ></code></pre></li>
|
|
143
|
+
<li><p><code>{}</code> with edges
|
|
144
|
+
<code>l1 -> X1, ..., ln -> Xn</code> means</p>
|
|
145
|
+
<pre class="text"><code>{ X1 l1, ..., Xn ln }</code></pre></li>
|
|
146
|
+
<li><p><code><></code> with edges
|
|
147
|
+
<code>t1 -> X1, ..., tn -> Xn</code> means</p>
|
|
148
|
+
<pre class="text"><code>< X1 t1, ..., Xn tn ></code></pre></li>
|
|
149
|
+
</ul>
|
|
150
|
+
<p>In particular:</p>
|
|
151
|
+
<ul>
|
|
152
|
+
<li><code>{}</code> with zero edges is the unit type,</li>
|
|
153
|
+
<li><code><></code> with zero edges is the empty type,</li>
|
|
154
|
+
<li><code>{...}</code> with zero edges matches any product type,</li>
|
|
155
|
+
<li><code><...></code> with zero edges matches any union
|
|
156
|
+
type.</li>
|
|
157
|
+
</ul>
|
|
158
|
+
<h3 id="canonical-node-numbering">Canonical node numbering</h3>
|
|
159
|
+
<p>Pattern nodes are numbered by first discovery in rooted depth-first
|
|
160
|
+
traversal:</p>
|
|
161
|
+
<ol type="1">
|
|
162
|
+
<li>start at the root,</li>
|
|
163
|
+
<li>visit outgoing edges in ascending symbol ID order,</li>
|
|
164
|
+
<li>assign a new node ID on first encounter,</li>
|
|
165
|
+
<li>reuse the existing node ID on revisits.</li>
|
|
166
|
+
</ol>
|
|
167
|
+
<p>The root pattern node is always node <code>0</code>.</p>
|
|
168
|
+
<h3 id="structure">Structure</h3>
|
|
169
|
+
<pre class="text"><code>| pattern_node_count:uvarint | pattern_node_0 | ... | pattern_node_(P-1) |</code></pre>
|
|
170
|
+
<h3 id="pattern-node-record">Pattern node record</h3>
|
|
171
|
+
<p>Every pattern node record starts with:</p>
|
|
172
|
+
<pre class="text"><code>| node_kind:u8 |</code></pre>
|
|
173
|
+
<p>The codes are:</p>
|
|
174
|
+
<ul>
|
|
175
|
+
<li><code>0</code> = <code>(...)</code></li>
|
|
176
|
+
<li><code>1</code> = <code>{...}</code></li>
|
|
177
|
+
<li><code>2</code> = <code><...></code></li>
|
|
178
|
+
<li><code>3</code> = <code>{}</code></li>
|
|
179
|
+
<li><code>4</code> = <code><></code></li>
|
|
180
|
+
</ul>
|
|
181
|
+
<p>The remainder of every record is:</p>
|
|
182
|
+
<pre class="text"><code>| edge_count:uvarint | edge_0 | ... | edge_(k-1) |</code></pre>
|
|
183
|
+
<p>Each edge is:</p>
|
|
184
|
+
<pre class="text"><code>| symbol_id:uvarint | target_pattern_node:uvarint |</code></pre>
|
|
185
|
+
<p>Edges must be sorted by ascending <code>symbol_id</code> and have no
|
|
186
|
+
duplicates.</p>
|
|
187
|
+
<p>Validation rules for node kinds:</p>
|
|
188
|
+
<ul>
|
|
189
|
+
<li><code>(...)</code> must have <code>edge_count = 0</code>,</li>
|
|
190
|
+
<li>all other node kinds may have any <code>edge_count ≥ 0</code>.</li>
|
|
191
|
+
</ul>
|
|
192
|
+
<p>This document therefore starts without type hashes or exact-type
|
|
193
|
+
leaves. Closed typed values are represented simply as values whose root
|
|
194
|
+
pattern happens to be singleton.</p>
|
|
195
|
+
<h2 id="value-section">Value Section</h2>
|
|
196
|
+
<p>The value section encodes the witness value tree relative to the
|
|
197
|
+
pattern graph. On the wire, it is represented as a DAG of value
|
|
198
|
+
occurrences decorated by pattern-node identity.</p>
|
|
199
|
+
<h3 id="canonical-value-node-identity">Canonical value-node
|
|
200
|
+
identity</h3>
|
|
201
|
+
<p>The canonical key of a value node is:</p>
|
|
202
|
+
<pre class="text"><code>(pattern_node_id, node_shape)</code></pre>
|
|
203
|
+
<p>where:</p>
|
|
204
|
+
<ul>
|
|
205
|
+
<li>for product pattern nodes (<code>{...}</code> or <code>{}</code>),
|
|
206
|
+
<code>node_shape</code> is the ordered list of child node IDs,</li>
|
|
207
|
+
<li>for union pattern nodes (<code><...></code> or
|
|
208
|
+
<code><></code>), <code>node_shape</code> is
|
|
209
|
+
<code>(tag_ordinal, child_node_id)</code>,</li>
|
|
210
|
+
<li><code>(...)</code> carries no value and therefore cannot appear in
|
|
211
|
+
the value section.</li>
|
|
212
|
+
</ul>
|
|
213
|
+
<p>This is the criterion for canonical DAG sharing in the value
|
|
214
|
+
payload.</p>
|
|
215
|
+
<h3 id="encodability-restriction">Encodability restriction</h3>
|
|
216
|
+
<p>Version 1 forbids serialized values from descending into an
|
|
217
|
+
<code>any-leaf</code> pattern node.</p>
|
|
218
|
+
<p>So if evaluation of a value against a pattern would require
|
|
219
|
+
materializing a subtree at <code>(...)</code>, the value is <strong>not
|
|
220
|
+
encodable</strong> in this format.</p>
|
|
221
|
+
<h3 id="canonical-value-node-numbering">Canonical value-node
|
|
222
|
+
numbering</h3>
|
|
223
|
+
<p>Value nodes are numbered in canonical postorder:</p>
|
|
224
|
+
<ol type="1">
|
|
225
|
+
<li>children before parents,</li>
|
|
226
|
+
<li>for product nodes, children in ascending pattern-edge symbol
|
|
227
|
+
order,</li>
|
|
228
|
+
<li>for union nodes, the selected child before the parent,</li>
|
|
229
|
+
<li>a shared node is emitted only once, at the first completed postorder
|
|
230
|
+
visit.</li>
|
|
231
|
+
</ol>
|
|
232
|
+
<p>The root value node is always the last node.</p>
|
|
233
|
+
<h3 id="structure-1">Structure</h3>
|
|
234
|
+
<pre class="text"><code>| value_node_count:uvarint | value_node_0 | ... | value_node_(V-1) |</code></pre>
|
|
235
|
+
<h3 id="value-node-record">Value node record</h3>
|
|
236
|
+
<p>Each value node starts with:</p>
|
|
237
|
+
<pre class="text"><code>| pattern_node_id:uvarint | body... |</code></pre>
|
|
238
|
+
<p>The body depends on the referenced pattern node kind.</p>
|
|
239
|
+
<h4 id="product-value-node">Product value node</h4>
|
|
240
|
+
<p>If the pattern node is <code>{...}</code> or <code>{}</code> with
|
|
241
|
+
<code>k</code> outgoing edges in ascending symbol order:</p>
|
|
242
|
+
<pre class="text"><code>| child_ref_0:uvarint | child_ref_1:uvarint | ... | child_ref_(k-1):uvarint |</code></pre>
|
|
243
|
+
<p>The value carries exactly the children of the explicitly listed
|
|
244
|
+
fields. Open product patterns do not permit the value section to
|
|
245
|
+
introduce additional unlabeled fields.</p>
|
|
246
|
+
<h4 id="union-value-node">Union value node</h4>
|
|
247
|
+
<p>If the pattern node is <code><...></code> or
|
|
248
|
+
<code><></code> with <code>m</code> outgoing edges in ascending
|
|
249
|
+
symbol order:</p>
|
|
250
|
+
<pre class="text"><code>| tag_ordinal:uvarint | child_ref:uvarint |</code></pre>
|
|
251
|
+
<p><code>tag_ordinal</code> must be in <code>[0, m)</code>. Open union
|
|
252
|
+
patterns do not permit the value section to introduce additional unnamed
|
|
253
|
+
tags.</p>
|
|
254
|
+
<h4 id="value-node"><code>(...)</code> value node</h4>
|
|
255
|
+
<p>This case is forbidden in version 1.</p>
|
|
256
|
+
<h2 id="child-references">Child References</h2>
|
|
257
|
+
<p>Child references are encoded as back-distances:</p>
|
|
258
|
+
<pre class="text"><code>child_ref = current_value_node_id - 1 - child_value_node_id</code></pre>
|
|
259
|
+
<p>So:</p>
|
|
260
|
+
<ul>
|
|
261
|
+
<li><code>0</code> means the immediately preceding node,</li>
|
|
262
|
+
<li><code>1</code> means two records back,</li>
|
|
263
|
+
<li>and so on.</li>
|
|
264
|
+
</ul>
|
|
265
|
+
<p>The decoder reconstructs:</p>
|
|
266
|
+
<pre class="text"><code>child_value_node_id = current_value_node_id - 1 - child_ref</code></pre>
|
|
267
|
+
<h2 id="validation">Validation</h2>
|
|
268
|
+
<p>After decoding, a package is valid iff all of the following hold.</p>
|
|
269
|
+
<h3 id="pattern-section-1">Pattern section</h3>
|
|
270
|
+
<ul>
|
|
271
|
+
<li>all pattern node IDs referenced by edges are in range,</li>
|
|
272
|
+
<li>all edge symbol IDs are in range,</li>
|
|
273
|
+
<li>edge symbol IDs are strictly increasing within each node,</li>
|
|
274
|
+
<li><code>(...)</code> has no outgoing edges,</li>
|
|
275
|
+
<li>the root node exists.</li>
|
|
276
|
+
</ul>
|
|
277
|
+
<h3 id="value-section-1">Value section</h3>
|
|
278
|
+
<ul>
|
|
279
|
+
<li>every <code>pattern_node_id</code> is in range,</li>
|
|
280
|
+
<li>every child reference points to an earlier value node,</li>
|
|
281
|
+
<li>a product value node references a <code>{...}</code> or
|
|
282
|
+
<code>{}</code> pattern node,</li>
|
|
283
|
+
<li>a union value node references a <code><...></code> or
|
|
284
|
+
<code><></code> pattern node,</li>
|
|
285
|
+
<li>no value node references <code>(...)</code>,</li>
|
|
286
|
+
<li><code>tag_ordinal</code> is valid for the referenced union pattern
|
|
287
|
+
node,</li>
|
|
288
|
+
<li>the root value node references pattern node <code>0</code>.</li>
|
|
289
|
+
<li>no value node references <code><></code> with zero outgoing
|
|
290
|
+
edges, since the empty type has no values.</li>
|
|
291
|
+
</ul>
|
|
292
|
+
<h2 id="example">Example</h2>
|
|
293
|
+
<p>Consider:</p>
|
|
294
|
+
<pre class="k"><code>pattern: < X tag1, {} tag2, ... > = X
|
|
295
|
+
value: {}|tag2|tag1|tag1</code></pre>
|
|
296
|
+
<h3 id="symbols-1">Symbols</h3>
|
|
297
|
+
<pre class="text"><code>0 -> "tag1"
|
|
298
|
+
1 -> "tag2"</code></pre>
|
|
299
|
+
<h3 id="pattern-graph">Pattern graph</h3>
|
|
300
|
+
<pre class="text"><code>P0: <...>, edges(tag1 -> P0, tag2 -> P1)
|
|
301
|
+
P1: {}, no edges
|
|
302
|
+
root = P0</code></pre>
|
|
303
|
+
<h3 id="value-dag">Value DAG</h3>
|
|
304
|
+
<pre class="text"><code>V0: {} at P1
|
|
305
|
+
V1: V0 | tag2 at P0
|
|
306
|
+
V2: V1 | tag1 at P0
|
|
307
|
+
V3: V2 | tag1 at P0
|
|
308
|
+
root = V3</code></pre>
|
|
309
|
+
<p>This example has no repeated decorated subtrees, so the value DAG is
|
|
310
|
+
the same as the value tree.</p>
|
|
311
|
+
<h2 id="closed-value-specialization">Closed-Value Specialization</h2>
|
|
312
|
+
<p>If the root pattern is singleton, then the whole package represents
|
|
313
|
+
an ordinary closed typed value.</p>
|
|
314
|
+
<p>In that case:</p>
|
|
315
|
+
<ul>
|
|
316
|
+
<li>the pattern section still exists and makes the package
|
|
317
|
+
self-contained,</li>
|
|
318
|
+
<li>a more compact specialization may omit the pattern section and use
|
|
319
|
+
the dedicated closed-value format.</li>
|
|
320
|
+
</ul>
|
|
321
|
+
<p>So the closed-value format is a derived optimization, not the
|
|
322
|
+
semantic foundation.</p>
|
|
323
|
+
<h2 id="operational-properties">Operational Properties</h2>
|
|
324
|
+
<p>The value payload is chosen to support efficient <code>k</code>
|
|
325
|
+
navigation.</p>
|
|
326
|
+
<h3 id="label"><code>.label</code></h3>
|
|
327
|
+
<p>For a product value node:</p>
|
|
328
|
+
<ol type="1">
|
|
329
|
+
<li>inspect the referenced pattern node,</li>
|
|
330
|
+
<li>map <code>label</code> to field ordinal by the pattern edge
|
|
331
|
+
order,</li>
|
|
332
|
+
<li>jump to the corresponding child reference.</li>
|
|
333
|
+
</ol>
|
|
334
|
+
<h3 id="tag"><code>/tag</code></h3>
|
|
335
|
+
<p>For a union value node:</p>
|
|
336
|
+
<ol type="1">
|
|
337
|
+
<li>inspect the referenced pattern node,</li>
|
|
338
|
+
<li>compare the stored <code>tag_ordinal</code> with the requested tag
|
|
339
|
+
ordinal,</li>
|
|
340
|
+
<li>on success follow the child reference.</li>
|
|
341
|
+
</ol>
|
|
342
|
+
<p>So field and tag names stay in the pattern graph, not in the value
|
|
343
|
+
payload.</p>
|
|
344
|
+
<h2 id="future-extensions">Future Extensions</h2>
|
|
345
|
+
<p>Possible future extensions include:</p>
|
|
346
|
+
<ul>
|
|
347
|
+
<li>introducing exact-type leaf nodes and a pattern registry,</li>
|
|
348
|
+
<li>allowing a controlled self-describing payload under
|
|
349
|
+
<code>(...)</code>,</li>
|
|
350
|
+
<li>auxiliary indexes for faster random access,</li>
|
|
351
|
+
<li>optional textual debug envelopes,</li>
|
|
352
|
+
<li>section compression that preserves the decoded semantic object.</li>
|
|
353
|
+
</ul>
|
|
354
|
+
</body>
|
|
355
|
+
</html>
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# K Prefix-Free Pattern Codec
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
This document defines the new target semantics for binary codecs in `k`.
|
|
6
|
+
|
|
7
|
+
The object to be serialized is:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
(P, v)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
where:
|
|
14
|
+
|
|
15
|
+
- `P` is a rooted pattern graph,
|
|
16
|
+
- `v` is a value tree compatible with `P`.
|
|
17
|
+
|
|
18
|
+
This is both the transport semantics and the runtime value semantics. In the
|
|
19
|
+
current JavaScript runtime, the materialized `Value` stores the pattern as
|
|
20
|
+
`value.pattern`; the tree is still represented by `Product` and `Variant`
|
|
21
|
+
nodes.
|
|
22
|
+
|
|
23
|
+
The codec is designed around:
|
|
24
|
+
|
|
25
|
+
1. compactness,
|
|
26
|
+
2. efficient structural navigation,
|
|
27
|
+
3. a clean separation between semantic encoding and optional acceleration
|
|
28
|
+
structures.
|
|
29
|
+
|
|
30
|
+
This document defines the semantic codec and the canonical wire stream.
|
|
31
|
+
|
|
32
|
+
## Design Principles
|
|
33
|
+
|
|
34
|
+
### 1. Pattern is the structural authority
|
|
35
|
+
|
|
36
|
+
The pattern determines:
|
|
37
|
+
|
|
38
|
+
- whether a node is a product or union,
|
|
39
|
+
- whether it is open or closed,
|
|
40
|
+
- what field names or tag names exist,
|
|
41
|
+
- how recursive positions are connected.
|
|
42
|
+
|
|
43
|
+
The value payload is interpreted relative to the pattern.
|
|
44
|
+
During execution, the same pattern context is propagated with materialized
|
|
45
|
+
values, so structural operations do not have to reconstruct framing information
|
|
46
|
+
after the fact.
|
|
47
|
+
|
|
48
|
+
### 2. Values are trees in the base codec
|
|
49
|
+
|
|
50
|
+
The base codec serializes value trees, not value DAGs.
|
|
51
|
+
|
|
52
|
+
DAG compression is not part of the primitive codec. If wanted, it should happen
|
|
53
|
+
as a separate transform above the base value encoding.
|
|
54
|
+
|
|
55
|
+
### 3. Prefix-free value encoding
|
|
56
|
+
|
|
57
|
+
The value payload is a prefix-free bitstream.
|
|
58
|
+
|
|
59
|
+
Products rely on structural concatenation.
|
|
60
|
+
Unions emit a choice code, then the payload of the selected branch.
|
|
61
|
+
|
|
62
|
+
### 4. One canonical stream
|
|
63
|
+
|
|
64
|
+
The pattern graph is embedded as an ordinary k `$pattern` value. The canonical
|
|
65
|
+
stream is that encoded pattern followed by the value payload interpreted under
|
|
66
|
+
the decoded pattern.
|
|
67
|
+
|
|
68
|
+
## Pattern Graph
|
|
69
|
+
|
|
70
|
+
### Semantic node kinds
|
|
71
|
+
|
|
72
|
+
There are exactly five node kinds:
|
|
73
|
+
|
|
74
|
+
- `any`
|
|
75
|
+
- `open-product`
|
|
76
|
+
- `open-union`
|
|
77
|
+
- `closed-product`
|
|
78
|
+
- `closed-union`
|
|
79
|
+
|
|
80
|
+
Their informal meanings are:
|
|
81
|
+
|
|
82
|
+
- `any`
|
|
83
|
+
unconstrained position,
|
|
84
|
+
- `open-product`
|
|
85
|
+
explicit fields plus possibly more fields in the matched value,
|
|
86
|
+
- `open-union`
|
|
87
|
+
explicit tags plus possibly more tags in the matched value,
|
|
88
|
+
- `closed-product`
|
|
89
|
+
exactly the listed fields,
|
|
90
|
+
- `closed-union`
|
|
91
|
+
exactly the listed tags.
|
|
92
|
+
|
|
93
|
+
In the base codec, `any` is not directly value-carrying.
|
|
94
|
+
|
|
95
|
+
### Graph structure
|
|
96
|
+
|
|
97
|
+
A pattern graph node is:
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
[kind, edges]
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
where `edges` is a list of:
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
[label, target_node_id]
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The root node is node `0`.
|
|
110
|
+
|
|
111
|
+
### Canonical constraints
|
|
112
|
+
|
|
113
|
+
- node `0` is the root,
|
|
114
|
+
- node order is canonical graph-discovery order,
|
|
115
|
+
- edges are sorted by label,
|
|
116
|
+
- no duplicate labels occur within one node,
|
|
117
|
+
- `any` has no outgoing edges.
|
|
118
|
+
|
|
119
|
+
### Readable property-list notation
|
|
120
|
+
|
|
121
|
+
For documentation and tests, the abstract graph may be rendered as:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"pattern": [
|
|
126
|
+
["closed-union", [["nil", 1], ["cons", 2]]],
|
|
127
|
+
["closed-product", []],
|
|
128
|
+
["closed-product", [["car", 3], ["cdr", 0]]],
|
|
129
|
+
["closed-union", [["_", 1], ["0", 3], ["1", 3]]]
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
This syntax is only a readable notation for the abstract graph.
|
|
135
|
+
|
|
136
|
+
## Pattern Construction From A Witness Tree
|
|
137
|
+
|
|
138
|
+
When no external pattern or type is supplied, the codec tools derive a
|
|
139
|
+
pattern from the value tree itself.
|
|
140
|
+
|
|
141
|
+
- `{}` derives the closed product leaf `["closed-product", []]`.
|
|
142
|
+
- A textual tree node with multiple children derives a closed product.
|
|
143
|
+
- A textual tree node with exactly one child derives an open union.
|
|
144
|
+
- If an explicit product pattern is supplied, that pattern can disambiguate the
|
|
145
|
+
same one-child textual node as a singleton product.
|
|
146
|
+
|
|
147
|
+
Example:
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
{a:{b:x,c:{}}}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
derives:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
[
|
|
157
|
+
["open-union", [["a", 1]]],
|
|
158
|
+
["closed-product", [["b", 2], ["c", 3]]],
|
|
159
|
+
["open-union", [["x", 3]]],
|
|
160
|
+
["closed-product", []]
|
|
161
|
+
]
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The derived graph is canonicalized by a bottom-up closed-node collapse. Starting
|
|
165
|
+
from the closed empty product, two closed nodes are collapsible only when their
|
|
166
|
+
kind, labels, and already-collapsed children are identical. Open nodes are not
|
|
167
|
+
collapsed, and this rule is not value-DAG compression.
|
|
168
|
+
|
|
169
|
+
## Value Encoding
|
|
170
|
+
|
|
171
|
+
### General shape
|
|
172
|
+
|
|
173
|
+
The value encoding is defined recursively relative to the current pattern node.
|
|
174
|
+
|
|
175
|
+
#### Product node
|
|
176
|
+
|
|
177
|
+
For `open-product` or `closed-product`:
|
|
178
|
+
|
|
179
|
+
```text
|
|
180
|
+
encode(v_0) encode(v_1) ... encode(v_(n-1))
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
in canonical edge order.
|
|
184
|
+
|
|
185
|
+
There are no separators between children. The pattern determines where each
|
|
186
|
+
child begins and ends.
|
|
187
|
+
|
|
188
|
+
#### Union node
|
|
189
|
+
|
|
190
|
+
For `open-union` or `closed-union`:
|
|
191
|
+
|
|
192
|
+
```text
|
|
193
|
+
encode-choice(tag_ordinal, tag_count)
|
|
194
|
+
encode(selected_payload)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
#### Any node
|
|
198
|
+
|
|
199
|
+
`any` is not directly value-carrying in the base format.
|
|
200
|
+
|
|
201
|
+
If a value would need to descend into an `any` position, the pattern must first
|
|
202
|
+
be refined.
|
|
203
|
+
|
|
204
|
+
## Choice Encoding
|
|
205
|
+
|
|
206
|
+
The initial concrete choice encoding is fixed-width by cardinality:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
width(cardinality) = ceil(log2(cardinality))
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
A choice with:
|
|
213
|
+
|
|
214
|
+
- `cardinality = n`
|
|
215
|
+
- `ordinal in [0, n)`
|
|
216
|
+
|
|
217
|
+
is encoded as the binary representation of `ordinal` in `width(n)` bits.
|
|
218
|
+
|
|
219
|
+
Examples:
|
|
220
|
+
|
|
221
|
+
- `n = 1`: `0` bits,
|
|
222
|
+
- `n = 2`: `1` bit,
|
|
223
|
+
- `n = 3`: `2` bits,
|
|
224
|
+
- `n = 4`: `2` bits,
|
|
225
|
+
- `n = 5`: `3` bits.
|
|
226
|
+
|
|
227
|
+
This is the initial canonical rule for the rewrite. More aggressive coding
|
|
228
|
+
schemes may be considered later, but only after the abstract semantics are
|
|
229
|
+
stable.
|
|
230
|
+
|
|
231
|
+
## Operational Properties
|
|
232
|
+
|
|
233
|
+
### `/tag`
|
|
234
|
+
|
|
235
|
+
At a union node:
|
|
236
|
+
|
|
237
|
+
1. read the choice code,
|
|
238
|
+
2. compare it to the requested tag ordinal,
|
|
239
|
+
3. if it matches, continue with the selected payload.
|
|
240
|
+
|
|
241
|
+
This makes `/tag` naturally efficient.
|
|
242
|
+
|
|
243
|
+
### `.field`
|
|
244
|
+
|
|
245
|
+
At a product node, child values appear in canonical field order.
|
|
246
|
+
|
|
247
|
+
So `.field` is resolved by:
|
|
248
|
+
|
|
249
|
+
1. locating the field ordinal in the pattern,
|
|
250
|
+
2. decoding or skipping earlier children,
|
|
251
|
+
3. decoding the requested child subtree.
|
|
252
|
+
|
|
253
|
+
The base codec does not include field-offset indexes. Such indexes may be added
|
|
254
|
+
later as separate higher-level acceleration structures.
|
|
255
|
+
|
|
256
|
+
In the materialized evaluator, `.field` applies the analogous pattern operation:
|
|
257
|
+
the output `Value` carries the subpattern reached by the selected field.
|
|
258
|
+
Likewise, `/tag` carries the subpattern reached by the selected variant tag.
|
|
259
|
+
|
|
260
|
+
## Recursive Types
|
|
261
|
+
|
|
262
|
+
Recursive pattern graphs are first-class.
|
|
263
|
+
|
|
264
|
+
For example, a bit-list-like recursive type:
|
|
265
|
+
|
|
266
|
+
```text
|
|
267
|
+
["closed-union", [["_", 1], ["0", 3], ["1", 3]]]
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
is encoded as repeated union choices in a value tree, not as a byte-aligned node
|
|
271
|
+
table and not as a built-in primitive integer format.
|
|
272
|
+
|
|
273
|
+
This keeps the codec uniform: recursion is handled by the pattern graph itself.
|
|
274
|
+
|
|
275
|
+
## Canonical Wire Format
|
|
276
|
+
|
|
277
|
+
The transport format is:
|
|
278
|
+
|
|
279
|
+
```text
|
|
280
|
+
encode($pattern_value : $pattern) encode(value : decoded_pattern)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
The first segment is a normal k value of type `$pattern`, encoded under the
|
|
284
|
+
fixed singleton pattern for `$pattern` defined by `core.k`. The decoded pattern
|
|
285
|
+
is then used as the structural authority for the second segment.
|
|
286
|
+
|
|
287
|
+
Decoding the stream yields `Value(pattern, tree)`. Encoding a runtime `Value`
|
|
288
|
+
uses its carried pattern by default, or an explicit caller-supplied pattern when
|
|
289
|
+
one is provided.
|
|
290
|
+
|
|
291
|
+
## Out Of Scope For The Base Codec
|
|
292
|
+
|
|
293
|
+
The following are intentionally outside the primitive codec:
|
|
294
|
+
|
|
295
|
+
- DAG compression,
|
|
296
|
+
- subtree deduplication,
|
|
297
|
+
- projection indexes,
|
|
298
|
+
- alternate transport-specific framing,
|
|
299
|
+
- alternate binary pattern serialization,
|
|
300
|
+
- exact-type-only specializations.
|
|
301
|
+
|
|
302
|
+
These may be added later, but they are not part of the base pattern-plus-tree
|
|
303
|
+
prefix codec.
|