@fraczak/k 5.1.2 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/Code-derivation-tests/blowup.mjs +3 -3
  2. package/Code-derivation-tests/bnat.mjs +2 -2
  3. package/Code-derivation-tests/codec-witness-pattern.mjs +50 -0
  4. package/Code-derivation-tests/convergence-strategy.mjs +24 -0
  5. package/Code-derivation-tests/dot.mjs +12 -9
  6. package/Code-derivation-tests/filter-syntax.mjs +21 -0
  7. package/Code-derivation-tests/loop.mjs +8 -2
  8. package/Code-derivation-tests/nat.mjs +1 -1
  9. package/Code-derivation-tests/not-not.mjs +3 -3
  10. package/Code-derivation-tests/pattern-envelope.mjs +68 -0
  11. package/Code-derivation-tests/rlz.mjs +2 -2
  12. package/{BIG_PICTURE.md → DOCS/BIG_PICTURE.md} +103 -50
  13. package/DOCS/REPL.md +191 -0
  14. package/DOCS/book/01-introduction.md +51 -0
  15. package/DOCS/book/02-syntax-and-values.md +111 -0
  16. package/DOCS/book/03-types-as-finite-automata.md +156 -0
  17. package/DOCS/book/04-partial-functions-and-composition.md +146 -0
  18. package/DOCS/book/05-typing-filters-and-normalization.md +111 -0
  19. package/DOCS/book.md +54 -0
  20. package/README.md +204 -508
  21. package/TypeGraph.mjs +43 -0
  22. package/TypePatternGraph.mjs +251 -0
  23. package/Value.mjs +192 -0
  24. package/augmentation.mjs +198 -0
  25. package/codecs/BINARY_FORMAT.md +53 -0
  26. package/codecs/POLYMORPHIC_BINARY_FORMAT.md +303 -0
  27. package/codecs/README.md +215 -0
  28. package/codecs/example-pipeline.mjs +149 -0
  29. package/codecs/ieee.mjs +140 -0
  30. package/codecs/int.mjs +104 -0
  31. package/codecs/json-codec.mjs +215 -0
  32. package/codecs/json.mjs +40 -0
  33. package/codecs/k-parse.mjs +90 -0
  34. package/codecs/k-pattern.mjs +75 -0
  35. package/codecs/k-print.mjs +46 -0
  36. package/codecs/runtime/codec.mjs +768 -0
  37. package/codecs/runtime/ieee-pattern.mjs +30 -0
  38. package/codecs/runtime/pattern-json.mjs +96 -0
  39. package/codecs/runtime/prefix-codec.mjs +425 -0
  40. package/codecs/runtime/show-value.mjs +68 -0
  41. package/codecs/runtime/typeFromValue.mjs +34 -0
  42. package/codecs/runtime/unicode-string.mjs +220 -0
  43. package/codecs/show.mjs +41 -0
  44. package/codecs/string-codec.mjs +80 -0
  45. package/codecs/unit.mjs +51 -0
  46. package/codecs/utf16.mjs +66 -0
  47. package/codecs/utf8.mjs +37 -0
  48. package/codes.mjs +146 -44
  49. package/compiler.mjs +111 -0
  50. package/convergence.mjs +197 -0
  51. package/core.k +197 -0
  52. package/export.mjs +22 -32
  53. package/hash.mjs +29 -31
  54. package/index.mjs +41 -15
  55. package/k-vscode/.vscode/launch.json +14 -0
  56. package/k-vscode/README.md +65 -0
  57. package/k-vscode/language-configuration.json +42 -0
  58. package/k-vscode/package.json +57 -0
  59. package/k-vscode/snippets/k.json +92 -0
  60. package/k-vscode/syntaxes/k.tmLanguage.json +243 -0
  61. package/k.mjs +56 -54
  62. package/object.mjs +517 -0
  63. package/objects/README.md +38 -0
  64. package/objects/compile-lib.mjs +42 -0
  65. package/objects/compile.mjs +42 -0
  66. package/objects/decompile.mjs +32 -0
  67. package/package.json +18 -8
  68. package/parser.jison +27 -46
  69. package/parser.mjs +68 -100
  70. package/pretty.mjs +21 -40
  71. package/repl2.mjs +652 -0
  72. package/run.mjs +264 -231
  73. package/symbol-table.mjs +3 -17
  74. package/test-fingerprint.mjs +7 -7
  75. package/test-hash-fuzz.mjs +107 -0
  76. package/test-hash-normalization.mjs +134 -0
  77. package/test-k-object.mjs +74 -0
  78. package/test-repl2.mjs +95 -0
  79. package/test.mjs +45 -70
  80. package/tests.sh +10 -1
  81. package/typing.mjs +129 -676
  82. package/unification.mjs +157 -0
  83. package/valueIO.mjs +54 -0
  84. package/valueParser.jison +143 -0
  85. package/valueParser.mjs +713 -0
  86. package/Code-derivation-tests/built-in.mjs +0 -19
  87. package/Code-derivation-tests/vector.mjs +0 -19
  88. package/Filters/bug.k +0 -3
  89. package/Filters/composing.k +0 -15
  90. package/Filters/filter.k +0 -9
  91. package/TODO.md +0 -53
  92. package/TYPING.md +0 -365
  93. package/k-repl.cast +0 -1913
  94. package/k.cast +0 -618
  95. package/my-objects.json +0 -6
  96. package/patterns.mjs +0 -543
  97. package/repl.mjs +0 -213
  98. package/test-filters.mjs +0 -45
  99. package/typing-test.mjs +0 -40
@@ -0,0 +1,53 @@
1
+ # Binary Packaging Notes
2
+
3
+ This document no longer defines the active codec semantics.
4
+
5
+ The active format is the self-hosted pattern-plus-prefix-tree stream described
6
+ in [`POLYMORPHIC_BINARY_FORMAT.md`](./POLYMORPHIC_BINARY_FORMAT.md):
7
+
8
+ ```text
9
+ encode($pattern_value : $pattern) encode(value : decoded_pattern)
10
+ ```
11
+
12
+ ## Purpose Of This File
13
+
14
+ This file records constraints for any future optimized container layered above
15
+ the canonical stream.
16
+
17
+ The design sequence is:
18
+
19
+ 1. define the abstract pattern graph,
20
+ 2. define prefix-free value-tree encoding relative to that graph,
21
+ 3. encode the pattern itself as a k `$pattern` value,
22
+ 4. optionally add higher-level indexes or compression as separate layers.
23
+
24
+ ## Expected Container Shape
25
+
26
+ The canonical stream contains:
27
+
28
+ ```text
29
+ encoded-$pattern + value-bitstream
30
+ ```
31
+
32
+ where:
33
+
34
+ - `encoded-$pattern` is the k value representation defined in `core.k`,
35
+ - the value bitstream is exactly the same prefix-free payload described by the
36
+ semantic codec.
37
+
38
+ ## Non-Goals
39
+
40
+ This future binary package should not redefine the semantic codec.
41
+
42
+ In particular, it should not introduce as part of the base semantics:
43
+
44
+ - byte-oriented node tables,
45
+ - mandatory DAG encoding,
46
+ - transport-driven structural compromises.
47
+
48
+ Those are explicitly outside the target architecture of the rewrite.
49
+
50
+ ## Current Format
51
+
52
+ The working concrete format is the canonical stream above. JSON property-list
53
+ patterns are debug notation only, not a transport container.
@@ -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.
@@ -0,0 +1,215 @@
1
+ # K Codecs
2
+
3
+ This directory is being rewritten around a new codec design:
4
+
5
+ ```text
6
+ abstract pattern graph + prefix-free tree encoding
7
+ ```
8
+
9
+ The default concrete format is now the binary encoding of a `$pattern` value,
10
+ using the `$pattern` type from [`../core.k`](../core.k), immediately followed by
11
+ the binary encoding of the value under that decoded pattern.
12
+
13
+ There is no separate JSON container format.
14
+
15
+ ## Objectives
16
+
17
+ The rewrite is guided by two hard requirements:
18
+
19
+ 1. compactness close to the structural lower bound,
20
+ 2. efficient `k` projections, especially `.field` and `/tag`.
21
+
22
+ The current target architecture is the pattern graph plus prefix-free value-tree
23
+ stream described here and in
24
+ [`POLYMORPHIC_BINARY_FORMAT.md`](./POLYMORPHIC_BINARY_FORMAT.md).
25
+
26
+ ## Core Idea
27
+
28
+ The semantic object serialized by the new codec is:
29
+
30
+ ```text
31
+ (P, v)
32
+ ```
33
+
34
+ where:
35
+
36
+ - `P` is an abstract rooted pattern graph,
37
+ - `v` is a value tree compatible with `P`.
38
+
39
+ The same pair is now the in-memory runtime model as well. Decoding a stream
40
+ attaches `P` to the resulting `Value` as `value.pattern`; evaluation propagates
41
+ that pattern through projections and constructors; encoding a `Value` uses its
42
+ carried pattern unless an explicit pattern is supplied.
43
+
44
+ The base value encoding is:
45
+
46
+ - tree-based, not DAG-based,
47
+ - prefix-free,
48
+ - interpreted relative to the pattern graph,
49
+ - free of repeated field names and tag names in the value payload.
50
+
51
+ The base codec does **not** perform DAG compression. If sharing is desired, it
52
+ should happen as a higher-level transform, not inside the primitive value
53
+ format.
54
+
55
+ ## Wire Format
56
+
57
+ The default transport format is:
58
+
59
+ ```text
60
+ encode($pattern_value : $pattern) encode(value : decoded_pattern)
61
+ ```
62
+
63
+ `$pattern_value` is a normal k value whose shape is defined in `core.k`. After
64
+ that value is decoded, it becomes the pattern used to decode the remaining
65
+ value payload.
66
+
67
+ The runtime boundary is therefore:
68
+
69
+ ```text
70
+ binary pattern+value stream <-> Value(pattern, tree)
71
+ ```
72
+
73
+ `k.mjs` is only the command-line adapter for that boundary. The operational
74
+ runtime sees and preserves the pattern on the `Value` itself.
75
+
76
+ ## Pattern Graph Representation
77
+
78
+ For documentation and tests, a pattern graph may be shown as a property-list
79
+ style vector of nodes:
80
+
81
+ ```text
82
+ [kind, edges]
83
+ ```
84
+
85
+ where:
86
+
87
+ - `kind` is one of:
88
+ - `"any"`
89
+ - `"open-product"`
90
+ - `"open-union"`
91
+ - `"closed-product"`
92
+ - `"closed-union"`
93
+ - `edges` is a list of:
94
+ - `[label, target_node_id]`
95
+
96
+ Example:
97
+
98
+ ```json
99
+ [
100
+ ["closed-union", [["nil", 1], ["cons", 2]]],
101
+ ["closed-product", []],
102
+ ["closed-product", [["car", 3], ["cdr", 0]]],
103
+ ["closed-union", [["_", 1], ["0", 3], ["1", 3]]]
104
+ ]
105
+ ```
106
+
107
+ Canonical rules:
108
+
109
+ - root node is node `0`,
110
+ - node list order is canonical graph-discovery order,
111
+ - edges are sorted by label,
112
+ - edge labels are unique within a node,
113
+ - `"any"` must have no outgoing edges.
114
+
115
+ This JSON-like graph is only a readable notation. The wire representation is
116
+ the ordinary k `$pattern` value from `core.k`.
117
+
118
+ ## Witness-Derived Patterns
119
+
120
+ When `k-parse` is used without an explicit input pattern or type, the wire
121
+ pattern is derived from the parsed value tree.
122
+
123
+ - An empty textual node is a closed product: `{}`.
124
+ - A textual node with multiple children is a closed product.
125
+ - A textual node with one child is interpreted as an open union by default.
126
+ - An explicit product input pattern may force such a node to be treated as a
127
+ singleton product instead.
128
+
129
+ For example, parsing:
130
+
131
+ ```text
132
+ {a:{b:x,c:{}}}
133
+ ```
134
+
135
+ without an input pattern derives:
136
+
137
+ ```json
138
+ [
139
+ ["open-union", [["a", 1]]],
140
+ ["closed-product", [["b", 2], ["c", 3]]],
141
+ ["open-union", [["x", 3]]],
142
+ ["closed-product", []]
143
+ ]
144
+ ```
145
+
146
+ During this construction, finite closed pattern subtrees are hash-consed from
147
+ the leaves upward. The starting closed leaf is `["closed-product", []]`. Two
148
+ closed nodes collapse only when they have the same closed kind, the same labels,
149
+ and the same already-collapsed child targets. Open nodes keep their identity,
150
+ and recursive closed nodes are not collapsed by this witness-tree rule.
151
+
152
+ This is canonicalization of the pattern graph carried in the wire stream. It is
153
+ not DAG compression of the value payload.
154
+
155
+ ## Prefix-Free Value Encoding
156
+
157
+ The value payload is a bitstream interpreted relative to the pattern graph.
158
+
159
+ Base rules:
160
+
161
+ - closed or open product:
162
+ - encode child values in canonical edge order,
163
+ - closed or open union:
164
+ - encode the selected tag position,
165
+ - then encode the selected payload,
166
+ - `any`:
167
+ - not directly value-carrying in the base format.
168
+
169
+ The initial concrete union encoding rule is:
170
+
171
+ ```text
172
+ width = ceil(log2(cardinality))
173
+ emit tag ordinal in width bits
174
+ ```
175
+
176
+ This is the simplest canonical prefix-free choice encoding. It is not the final
177
+ word on compression, but it gives a regular and compact base encoding that can
178
+ later be refined without changing the abstract pattern/value model.
179
+
180
+ ## Projections
181
+
182
+ The base tree encoding is chosen so that:
183
+
184
+ - `/tag` only needs to read the union choice at the current node,
185
+ - `.field` follows canonical product order and may later be accelerated by
186
+ higher-level indexes if necessary.
187
+
188
+ In the materialized runtime, projections also project the carried pattern:
189
+ `.field` returns the subpattern at that product field, and `/tag` returns the
190
+ subpattern at that union tag. If no carried subpattern is available, later
191
+ encoding can still derive a witness pattern from the result tree.
192
+
193
+ The primitive codec stays minimal. Projection indexes, framing, or sharing
194
+ schemes are explicitly separate concerns.
195
+
196
+ ## Design Boundary
197
+
198
+ The new codec work is split into layers:
199
+
200
+ 1. abstract pattern graph semantics,
201
+ 2. prefix-free value-tree semantics relative to that graph,
202
+ 3. self-hosted `k` representation of the pattern graph,
203
+ 4. optional higher-level optimizations.
204
+
205
+ ## Files
206
+
207
+ - [`POLYMORPHIC_BINARY_FORMAT.md`](./POLYMORPHIC_BINARY_FORMAT.md):
208
+ main design document for the new pattern-plus-prefix-tree codec.
209
+ - [`BINARY_FORMAT.md`](./BINARY_FORMAT.md):
210
+ notes on future binary packaging of the same abstract semantics.
211
+
212
+ ## Status
213
+
214
+ The active command-line pipeline emits and consumes the self-hosted binary
215
+ pattern+value stream.
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Example: Demonstrating the codec pipeline
4
+ *
5
+ * Shows how to:
6
+ * 1. Define types with canonical names
7
+ * 2. Create values
8
+ * 3. Encode to binary
9
+ * 4. Pass through "compiled program" (identity)
10
+ * 5. Decode from binary
11
+ * 6. Print result
12
+ */
13
+
14
+ import { deriveClosedPattern } from './runtime/codec.mjs';
15
+ import { encodeToWire, decodeWire } from './runtime/prefix-codec.mjs';
16
+ import { patternToPropertyList } from './runtime/pattern-json.mjs';
17
+ import { Product, Variant } from '../Value.mjs';
18
+ import hash from '../hash.mjs';
19
+
20
+ console.log('=== K Codec Pipeline Example ===\n');
21
+
22
+ // ============================================================================
23
+ // Step 1: Define types (normally from compiler)
24
+ // ============================================================================
25
+
26
+ const types = {};
27
+
28
+ // Unit: {}
29
+ const unitDef = { code: 'product', product: {} };
30
+ const unitName = hash('$C0={};');
31
+ types[unitName] = unitDef;
32
+
33
+ // Bool: <{} false, {} true>
34
+ const boolDef = {
35
+ code: 'union',
36
+ union: { false: unitName, true: unitName }
37
+ };
38
+ const boolName = hash(`$C0=<${unitName}"false",${unitName}"true">;`);
39
+ types[boolName] = boolDef;
40
+
41
+ // Maybe: <{} nothing, Bool something>
42
+ const maybeDef = {
43
+ code: 'union',
44
+ union: { nothing: unitName, something: boolName }
45
+ };
46
+ const maybeName = hash(
47
+ `$C0=<${unitName}"nothing",${boolName}"something">;`
48
+ );
49
+ types[maybeName] = maybeDef;
50
+
51
+ console.log('Types defined:');
52
+ console.log(' unit:', unitName);
53
+ console.log(' bool:', boolName);
54
+ console.log(' maybe:', maybeName);
55
+ console.log();
56
+
57
+ // ============================================================================
58
+ // Step 2: Type resolver
59
+ // ============================================================================
60
+
61
+ function resolveType(typeName) {
62
+ const def = types[typeName];
63
+ if (!def) {
64
+ throw new Error(`Unknown type: ${typeName}`);
65
+ }
66
+ return def;
67
+ }
68
+
69
+ // ============================================================================
70
+ // Step 3: Create input value: Maybe Bool = something(true)
71
+ // ============================================================================
72
+
73
+ const inputValue = new Variant(
74
+ 'something',
75
+ new Variant('true', new Product({}))
76
+ );
77
+
78
+ console.log('Input value:', inputValue.toString());
79
+ console.log();
80
+
81
+ const maybePattern = patternToPropertyList(
82
+ deriveClosedPattern(maybeName, maybeDef, resolveType)
83
+ );
84
+
85
+ // ============================================================================
86
+ // Step 4: Parse (TEXT → BINARY)
87
+ // ============================================================================
88
+
89
+ console.log('--- PARSE (text → binary) ---');
90
+ const binaryInput = encodeToWire(inputValue, maybePattern);
91
+ console.log('Binary size:', binaryInput.length, 'bytes');
92
+ console.log(' Bytes:', binaryInput.toString('hex'));
93
+ console.log();
94
+
95
+ // ============================================================================
96
+ // Step 5: Compiled k-program (BINARY → BINARY)
97
+ // ============================================================================
98
+
99
+ console.log('--- COMPILED PROGRAM (binary → binary) ---');
100
+
101
+ // Simulate a compiled k-program: decode → transform → encode
102
+ const { value: programInput } = decodeWire(binaryInput);
103
+
104
+ console.log('Program sees value:', programInput.toString());
105
+
106
+ // Example transformation: NOT operation (flip bool inside Maybe)
107
+ let programOutput;
108
+ if (programInput instanceof Variant && programInput.tag === 'something') {
109
+ const innerBool = programInput.value;
110
+ if (innerBool instanceof Variant) {
111
+ const flipped = new Variant(
112
+ innerBool.tag === 'true' ? 'false' : 'true',
113
+ innerBool.value
114
+ );
115
+ programOutput = new Variant('something', flipped);
116
+ }
117
+ } else {
118
+ programOutput = programInput; // nothing → nothing
119
+ }
120
+
121
+ console.log('Program output value:', programOutput.toString());
122
+
123
+ // Encode output
124
+ const binaryOutput = encodeToWire(programOutput, maybePattern);
125
+
126
+ console.log('Binary output size:', binaryOutput.length, 'bytes');
127
+ console.log(' Bytes:', binaryOutput.toString('hex'));
128
+ console.log();
129
+
130
+ // ============================================================================
131
+ // Step 6: Print (BINARY → TEXT)
132
+ // ============================================================================
133
+
134
+ console.log('--- PRINT (binary → text) ---');
135
+ const { value: finalValue } = decodeWire(binaryOutput);
136
+
137
+ console.log('Output value:', finalValue.toString());
138
+ console.log();
139
+
140
+ // ============================================================================
141
+ // Summary
142
+ // ============================================================================
143
+
144
+ console.log('=== Pipeline Summary ===');
145
+ console.log('Input: ', inputValue.toString(), '(true inside Maybe)');
146
+ console.log('Transform: NOT operation on inner bool');
147
+ console.log('Output: ', finalValue.toString(), '(false inside Maybe)');
148
+ console.log();
149
+ console.log('Binary representations are canonical and type-safe!');