@fraczak/k 6.0.1 → 6.0.2

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 (38) hide show
  1. package/AGENTS.md +35 -0
  2. package/CHANGELOG.md +48 -0
  3. package/CLAUDE.md +64 -0
  4. package/DOCS/BIG_PICTURE.md +4 -8
  5. package/DOCS/BINARY_CODEC_STATUS_AND_TODO.md +74 -0
  6. package/DOCS/CONVERGENCE.md +92 -0
  7. package/DOCS/DIVERGENCE_DETECTION.md +24 -0
  8. package/DOCS/Makefile +99 -0
  9. package/DOCS/OBJECT_FILE_AND_PATTERN.md +217 -0
  10. package/DOCS/PATTERNS.md +114 -0
  11. package/DOCS/PATTERNS_AND_TYPED_VALUES.md +665 -0
  12. package/DOCS/REPL.md +125 -125
  13. package/DOCS/TEXTUAL_VALUES.md +108 -0
  14. package/DOCS/TYPE_DERIVATION.md +230 -0
  15. package/DOCS/book/06-values-in-memory.md +1085 -0
  16. package/DOCS/book/07-the-partial-function-abi.md +143 -0
  17. package/DOCS/book/08-operational-semantics-and-execution.md +201 -0
  18. package/DOCS/book/09-compiler-architecture.md +160 -0
  19. package/DOCS/book/10-from-ast-to-intermediate-representation.md +167 -0
  20. package/DOCS/book/14-canonical-serialization.md +176 -0
  21. package/DOCS/book/appendix-b-incorporating-external-predefined-types-and-functions.md +155 -0
  22. package/DOCS/book/overview.txt +68 -0
  23. package/README.md +71 -27
  24. package/codecs/README.md +8 -0
  25. package/codecs/pandoc.css +71 -0
  26. package/codecs/runtime/test-codec.mjs +89 -0
  27. package/package.json +2 -2
  28. package/{codecs/k-pattern.mjs → patterns/from-k.mjs} +3 -3
  29. package/repl2.mjs +259 -50
  30. package/scripts/generate-dependency-graph.mjs +121 -0
  31. package/test-repl2.mjs +55 -8
  32. package/DOCS/book-combined.html +0 -3798
  33. package/DOCS/book-combined.md +0 -3745
  34. package/DOCS/book-combined.pdf +0 -0
  35. package/DOCS/book-combined.tex +0 -5682
  36. package/DOCS/book.html +0 -65
  37. package/DOCS/book.pdf +0 -0
  38. package/DOCS/book.tex +0 -150
@@ -0,0 +1,176 @@
1
+ # Chapter 14 — Canonical Serialization
2
+
3
+ ## **14.1 Purpose**
4
+
5
+ Serialization is the process of converting a value in memory into a compact sequence of bits or bytes that can be stored or transmitted.
6
+ For the k language, serialization serves an additional goal: it defines a **canonical representation** of each value that is unique and independent of the machine on which it was produced.
7
+
8
+ A canonical encoding allows values to be compared, hashed, or stored in a registry in a reproducible way.
9
+ Two values that are structurally identical will always produce the same bit sequence.
10
+
11
+ ---
12
+
13
+ ## **14.2 Canonical type information**
14
+
15
+ Serialization always depends on structural information. In the monomorphic case
16
+ this is the **canonical form of the type**. In the polymorphic codec this is a
17
+ pattern graph carried with the value.
18
+ A type in canonical form is a finite tree automaton (Chapter 3) that describes the structure of all its values.
19
+ Because this form is unique, every possible value of the type can be encoded deterministically.
20
+
21
+ Before any value is serialized, the compiler or runtime must know:
22
+
23
+ * the list of states (C0, C1, …),
24
+ * for each state, whether it is a product or a union,
25
+ * the number of possible transitions, and
26
+ * for unions, the order of their variants.
27
+
28
+ This information acts as the grammar from which all bit sequences are derived.
29
+ For a pattern-framed value, the same role is played by the decoded leading
30
+ pattern; singleton patterns are exactly the monomorphic type case.
31
+
32
+ ---
33
+
34
+ ## **14.3 Encoding principle**
35
+
36
+ Each node in a value tree corresponds to one of the type’s states.
37
+
38
+ * **Product node** – emits no bits; the encoder simply serializes each child in canonical field order.
39
+ * **Union node** – emits a small binary code that identifies which variant is used, then serializes its single child.
40
+ * **Unit node** (empty product) – emits nothing; it has no children.
41
+ * **Empty union** – cannot be encoded because it has no possible values.
42
+
43
+ Thus, the sequence of bits records exactly which union branches were taken while descending the tree.
44
+
45
+ ---
46
+
47
+ ## **14.4 Fixed-length codes per state**
48
+
49
+ For simplicity, each union state uses fixed-length binary codes of equal size.
50
+
51
+ If a union has *m* variants, then
52
+
53
+ ```
54
+ k = ceil(log2(m))
55
+ ```
56
+
57
+ bits are needed.
58
+ Each variant is numbered in canonical order from 0 to m − 1 and represented by the binary form of its index.
59
+
60
+ Products and units use k = 0 and emit no bits.
61
+
62
+ This rule allows the decoder to know, from the type alone, how many bits to read at each step.
63
+
64
+ ---
65
+
66
+ ## **14.5 Example: natural numbers**
67
+
68
+ For the type
69
+
70
+ ```
71
+ $bnat = < bnat 0, bnat 1, {} _ >;
72
+ ```
73
+
74
+ the canonical form has three transitions from state C0.
75
+ Therefore, `k = ceil(log2(3)) = 2` bits are required per union node.
76
+
77
+ Assigning codes in order:
78
+
79
+ | Rule | Code |
80
+ | -------------- | ---- |
81
+ | C0 → {C0 "0"} | `00` |
82
+ | C0 → {C0 "1"} | `01` |
83
+ | C0 → {C1 "_" } | `10` |
84
+
85
+ The value `{ {{ {} _ } 1 } 0 }` is encoded by concatenating the codes of the transitions chosen during a leftmost derivation:
86
+
87
+ ```
88
+ 00 → first C0
89
+ 01 → next C0
90
+ 10 → final C0
91
+ ```
92
+
93
+ Resulting bit sequence: `000110`.
94
+
95
+ ---
96
+
97
+ ## **14.6 Decoding**
98
+
99
+ Decoding is deterministic and mirrors the encoding process:
100
+
101
+ 1. Start at the root state (C0).
102
+ 2. If the current state is a union, read k bits to choose a rule.
103
+ 3. Create the corresponding node, then recursively decode its child or children.
104
+ 4. For products, decode all children in order; for units, stop.
105
+
106
+ The decoder stops when the entire tree has been reconstructed and all bits have been consumed.
107
+
108
+ Because every union code is of fixed length, the decoding process requires no backtracking and can be implemented as a simple loop.
109
+
110
+ ---
111
+
112
+ ## **14.7 Folding repeated subtrees**
113
+
114
+ Many values contain repeated substructures.
115
+ To avoid serializing the same tree several times, identical subtrees can be *folded* into a **directed acyclic graph (DAG)** before encoding.
116
+
117
+ Each unique node is assigned an identifier.
118
+ When the encoder encounters a repeated node, it emits a reference to its identifier instead of encoding it again.
119
+
120
+ During decoding, the identifier is resolved to the corresponding subtree, reconstructing the shared structure.
121
+
122
+ Folding is optional; it saves space without changing the logical value.
123
+
124
+ ---
125
+
126
+ ## **14.8 Stream format**
127
+
128
+ A minimal canonical bitstream consists of:
129
+
130
+ 1. **Header** – type hash (e.g., 8 bytes) identifying the canonical type.
131
+ 2. **Node count** – integer *N* if DAG encoding is used.
132
+ 3. **Encoded data** – concatenation of all fixed-length union codes and, if folded, node references.
133
+
134
+ If two systems share the same canonical type table, the bitstream alone is enough to reconstruct the original value.
135
+
136
+ ---
137
+
138
+ ## **14.9 Implementation sketch**
139
+
140
+ A compact encoder can be written as follows:
141
+
142
+ ```
143
+ procedure encode(node):
144
+ if node.arity == 0:
145
+ return
146
+ if node.arity == 1:
147
+ write_bits(code_for(node.state, node.tag))
148
+ encode(node.child[0])
149
+ else:
150
+ for each child in node.children:
151
+ encode(child)
152
+ ```
153
+
154
+ The corresponding decoder reverses the process.
155
+ Both procedures require only the canonical type tables and simple bit operations.
156
+
157
+ ---
158
+
159
+ ## **14.10 Determinism and equality**
160
+
161
+ Because encoding is fully determined by the canonical type and field order, two equal values always produce identical bit sequences.
162
+ Conversely, decoding the same bit sequence always yields the same tree.
163
+
164
+ This property allows equality comparison by direct byte comparison of serialized forms, without traversing the trees in memory.
165
+
166
+ ---
167
+
168
+ ## **14.11 Summary**
169
+
170
+ * Every type’s canonical automaton defines a unique bit-level grammar for its values.
171
+ * Products emit no bits; unions emit fixed-length variant codes.
172
+ * The number of bits required for each state depends only on the number of variants in that state.
173
+ * Optional DAG folding eliminates repeated subtrees.
174
+ * The resulting bitstream is compact, deterministic, and machine-independent.
175
+
176
+ ---
@@ -0,0 +1,155 @@
1
+ # Appendix B — Incorporating External Predefined Types and Functions
2
+ ## **B.1 Purpose**
3
+
4
+ The k language is intentionally minimal.
5
+ Nevertheless, real systems often need to interact with data types and operations defined outside of k—for example, numeric values, text, or platform-specific constants.
6
+ This appendix explains how external predefined types and functions can be introduced into a k compiler without changing the language itself.
7
+
8
+ ---
9
+
10
+ ## **B.2 External types**
11
+
12
+ An **external type** is a canonical type that is *not* expressed through k's own product-and-union syntax but is known to the compiler through registration.
13
+
14
+ Each external type has:
15
+
16
+ | Field | Description |
17
+ | --------------------- | ---------------------------------------------------------------------------- |
18
+ | **Name** | symbolic name (e.g., `$int`, `$string`) |
19
+ | **Hash** | unique stable identifier, just like canonical types |
20
+ | **Runtime kind** | how the value is stored in memory (pointer, immediate integer, etc.) |
21
+ | **Adapter functions** | conversion between the external representation and the standard `KNode` tree |
22
+
23
+ Example registry entry:
24
+
25
+ ```json
26
+ {
27
+ "hash": "E001",
28
+ "kind": "type",
29
+ "external": true,
30
+ "name": "$int",
31
+ "runtime_kind": "primitive_i64"
32
+ }
33
+ ```
34
+
35
+ The compiler treats such a type as an atomic node, represented internally as a single `KNode` with `arity = 0` but tagged as *external*.
36
+
37
+ ---
38
+
39
+ ## **B.3 External constructors**
40
+
41
+ External types may provide special constructors or constants.
42
+ For example, `$int` might include predefined constant functions:
43
+
44
+ ```
45
+ zero = {} $int;
46
+ one = {} $int;
47
+ ```
48
+
49
+ At compile time these appear as constant functions returning fixed external nodes provided by the runtime.
50
+
51
+ ---
52
+
53
+ ## **B.4 External functions**
54
+
55
+ External functions are partial functions implemented outside of k but declared inside a k program.
56
+ They have known input and output types, possibly external.
57
+
58
+ Declaration syntax:
59
+
60
+ ```
61
+ extern add : $int $int → $int;
62
+ extern less : $int $int → $bool;
63
+ ```
64
+
65
+ At compile time the compiler records the signature and associates it with a runtime symbol name such as `k_ext_add`.
66
+
67
+ When generating code, each external call becomes a standard function call following the ABI:
68
+
69
+ ```llvm
70
+ declare %KOpt @k_ext_add(%KVal %a, %KVal %b)
71
+ ```
72
+
73
+ The runtime library provides these implementations in a native language (C, C++, Rust, etc.).
74
+
75
+ ---
76
+
77
+ ## **B.5 Integration with canonical types**
78
+
79
+ External types are integrated into the canonical system as *leaf states*.
80
+ They can appear as components in products or unions just like built-in ones.
81
+
82
+ Example:
83
+
84
+ ```
85
+ $point = { $int x, $int y };
86
+ ```
87
+
88
+ Canonical form:
89
+
90
+ ```
91
+ $C0 = { C1 "x", C1 "y" };
92
+ $C1 = external $int;
93
+ ```
94
+
95
+ This allows normal serialization and type comparison; the external leaf is treated as opaque but identified by its hash.
96
+
97
+ ---
98
+
99
+ ## **B.6 Serialization and external values**
100
+
101
+ During serialization, an external node is encoded by:
102
+
103
+ 1. Its type hash (to indicate which external kind it represents).
104
+ 2. A binary blob produced by a runtime-supplied encoder for that type.
105
+
106
+ Deserialization reverses the process using the corresponding decoder.
107
+ All external codecs must be deterministic and version-stable to preserve canonical equality.
108
+
109
+ ---
110
+
111
+ ## **B.7 Example**
112
+
113
+ Suppose we introduce `$int` and external function `add`:
114
+
115
+ ```
116
+ $pair_int = { $int a, $int b };
117
+ sum = { .a x, .b y } (add x y);
118
+ ```
119
+
120
+ The compiler generates code that:
121
+
122
+ * projects fields `.a` and `.b`,
123
+ * passes them as `KVal` pointers to `@k_ext_add`,
124
+ * and returns the result as a new `$int` node.
125
+
126
+ All logic outside arithmetic remains standard k code.
127
+
128
+ ---
129
+
130
+ ## **B.8 Practical implementation**
131
+
132
+ In a Python prototype:
133
+
134
+ ```python
135
+ EXTERNAL_TYPES = {
136
+ "$int": {"hash": "E001", "kind": "external", "runtime_kind": "primitive_i64"}
137
+ }
138
+
139
+ EXTERNAL_FUNCS = {
140
+ "add": {"inputs": ["$int", "$int"], "output": "$int", "symbol": "k_ext_add"},
141
+ "less": {"inputs": ["$int", "$int"], "output": "$bool", "symbol": "k_ext_less"}
142
+ }
143
+ ```
144
+
145
+ During code generation, when a call refers to an external function, the compiler emits a call to the symbol given in the table.
146
+
147
+ ---
148
+
149
+ ## **B.9 Summary**
150
+
151
+ * External predefined types extend k without altering its core semantics.
152
+ * They are registered with hashes and treated as atomic nodes.
153
+ * External functions follow the same calling convention as normal ones.
154
+ * Serialization of external values uses type-specific codecs.
155
+ * This mechanism allows integration of native computations (numbers, strings, system data) while preserving the purity and determinism of the k language.
@@ -0,0 +1,68 @@
1
+ Numbers are an extremely smart encoding.
2
+ Kernel/core can describe that encoding — and many others.
3
+
4
+ Most programming languages take numbers as a starting point. Integers, booleans, characters, and strings appear as given, primitive entities, and computation is then defined in terms of control flow operating over those primitives.
5
+
6
+ Kernel/core deliberately inverts this perspective.
7
+
8
+ Kernel/core starts from the observation that numbers are not fundamental objects of computation. They are encodings: highly successful, extremely smart encodings, but encodings nonetheless. What is truly fundamental is the ability to describe structured values and to define relations between them.
9
+
10
+ Kernel/core is a language built around this idea.
11
+
12
+ Kernel/core is based on exactly two concepts: encoding and relation.
13
+
14
+ Encoding describes how values are represented. Relation describes how values are transformed.
15
+
16
+ Everything else found in conventional programming languages—control flow, loops, exceptions, built-in types, higher-order functions—is intentionally absent. Not because kernel/core is low-level, but because those constructs are derivable, incidental, or encoding-specific.
17
+
18
+ Kernel/core is a high-level language precisely because it is minimal.
19
+
20
+ An encoding describes the shape of values. Encodings are algebraic data types built from two constructors: products and unions.
21
+
22
+ Encodings are explicit, first-class, and user-defined. Kernel/core has no built-in integers, booleans, strings, or characters. If such values are needed, they are described as encodings within the language itself.
23
+
24
+ This has several consequences. Every value has a precise, inspectable structure. Serialization and deserialization are intrinsic, not an afterthought. Different encodings of the same concept, such as unary, binary, or decimal numbers, coexist naturally.
25
+
26
+ Numbers, in particular, appear not as primitives but as one possible encoding among many.
27
+
28
+ A kernel/core program defines a relation: a partial, first-order function from encoded values to encoded values.
29
+
30
+ Relations are partial: they may be undefined for some inputs. They are first-order: relations do not take other relations as values. They are pure: there is no implicit state and no hidden effects.
31
+
32
+ Kernel/core deliberately avoids if, while, throw, and similar constructs. Instead, relations are combined using three forms of composition.
33
+
34
+ Sequential composition chains transformations. Parallel composition executes multiple relations independently on the same input and produces a product value. Concurrent composition defines ordered alternatives, where the first defined result is selected.
35
+
36
+ Control flow emerges from partiality and composition, not from dedicated syntax.
37
+
38
+ Kernel/core bootstraps computation without primitives by relying on projections induced by encodings.
39
+
40
+ Every product or union encoding introduces canonical projection relations. These projections are the only predefined relations in the language. All other behavior is built by composition.
41
+
42
+ There are no built-in constants in the traditional sense. Even constants are relations: partial functions that ignore their input and return a fixed encoded value.
43
+
44
+ This makes the language uniform: everything is a relation.
45
+
46
+ Kernel/core supports polymorphic relations through patterns.
47
+
48
+ A pattern is a relaxed encoding specification: a filter that constrains only part of a value’s structure. Patterns allow relations to be defined over classes of encodings, not just single concrete ones.
49
+
50
+ For example, a relation may require any product type with at least a given field of a given encoding, without fixing the rest of the structure.
51
+
52
+ This form of polymorphism is structural, explicit, and decidable. It does not rely on subtyping hierarchies, inheritance, or ad-hoc overloading.
53
+
54
+ Kernel/core is not a scripting language, not an object-oriented language, not a numeric language, and not a control-flow language.
55
+
56
+ Kernel/core is a language for describing encodings, a language for defining relations over structured data, a foundation for serialization, transformation, and compilation, and a minimal core on top of which richer systems can be built.
57
+
58
+ Kernel/core does not claim that numbers are wrong.
59
+
60
+ On the contrary: numbers are one of the most successful encodings ever invented.
61
+
62
+ Kernel/core simply makes that fact explicit.
63
+
64
+ By separating what computation is from how values are encoded, kernel/core offers a different foundation for programming—one where arithmetic becomes a special case, not the starting point.
65
+
66
+ Numbers are an extremely smart encoding.
67
+
68
+ Kernel/core is the language that lets you describe that encoding — and any other one you can imagine.
package/README.md CHANGED
@@ -28,12 +28,12 @@ k-repl # start the interactive REPL (or: node repl2.mjs)
28
28
  | Binary | Source | Purpose |
29
29
  |--------|--------|---------|
30
30
  | `k` | `k.mjs` | Execute a `.k` script; reads binary pattern+value stream from stdin |
31
- | `k-repl` / `k-repl2` | `repl2.mjs` | Interactive REPL |
32
- | `k-parse` | `codecs/k-parse.mjs` | Encode a JSON value to the binary pattern+value wire format |
33
- | `k-print` | `codecs/k-print.mjs` | Decode binary pattern+value stream back to JSON |
34
- | `k-pattern` | `codecs/k-pattern.mjs` | Print the pattern of a binary-encoded value |
35
- | `k-compile-object` | `objects/compile.mjs` | Compile a `.k` source to a `.kobj` object file |
36
- | `k-decompile-object` | `objects/decompile.mjs` | Decompile a `.kobj` file back to k source |
31
+ | `k-repl` / `k-repl2` | `repl2.mjs` | Interactive interpreter |
32
+ | `k-parse` | `codecs/k-parse.mjs` | Encode textual k values to the binary pattern+value wire format |
33
+ | `k-print` | `codecs/k-print.mjs` | Decode binary pattern+value stream to JSON-like textual k values |
34
+ | `k-pattern` | `patterns/from-k.mjs` | Extract the canonical root pattern from a k script |
35
+ | `k-compile-object` | `objects/compile.mjs` | Compile a `.k` source to an executable `.ko` object |
36
+ | `k-decompile-object` | `objects/decompile.mjs` | Decompile a `.ko` or `.klib` file back to k source |
37
37
 
38
38
  ---
39
39
 
@@ -48,6 +48,9 @@ Codes are algebraic data types built from two constructors:
48
48
 
49
49
  Native k-like notation is canonical; JSON-like is supported as syntactic sugar.
50
50
 
51
+ For the JSON-like textual notation used by `k-parse` and `k-print`, see
52
+ [DOCS/TEXTUAL_VALUES.md](DOCS/TEXTUAL_VALUES.md).
53
+
51
54
  ### Defining codes (`$`)
52
55
 
53
56
  ```k
@@ -135,38 +138,60 @@ A partial function may be undefined on some inputs. Core primitives:
135
138
 
136
139
  ---
137
140
 
138
- ## REPL
141
+ ## Interpreter
139
142
 
140
143
  Start with `k-repl` (or `node repl2.mjs`). The prompt is `> `.
141
144
 
142
- ### Defining names and codes
145
+ `repl2.mjs` keeps a live `.klib`-style state in memory. You can:
143
146
 
144
- ```
145
- > $ nat = < {} zero, nat succ >;
146
- > succ = |succ;
147
- > zero = {} |zero $nat;
148
- ```
147
+ - define types and relations incrementally
148
+ - run expressions against the current value
149
+ - load `.k` or `.klib` files into the session
150
+ - export the session as `.klib`
151
+ - export an executable `.ko` from an expression in the current context
149
152
 
150
- ### REPL commands
153
+ ### Main commands
151
154
 
152
155
  | Command | Effect |
153
156
  |---------|--------|
154
- | `--C name` | Show canonical (hash-addressed) form of a code |
155
- | `--R name` | Show the type derivation (pattern graph) for a function |
156
- | `--help` | List available commands |
157
+ | `:type name = <...>` | Define a type alias |
158
+ | `:rel name = expr` | Define a relation alias |
159
+ | `:run expr` | Evaluate an expression on the current value |
160
+ | `:t name` | Show relation input/output filters |
161
+ | `:d name` | Show relation definition |
162
+ | `:C name` | Show canonical code definition |
163
+ | `:codes` / `:rels` | List type or relation aliases |
164
+ | `:load file` | Load `.k` or `.klib` |
165
+ | `:klib file` | Export current state as `.klib` |
166
+ | `:ko file expr` | Export executable `.ko` |
167
+ | `:val` | Print current value |
168
+ | `:reset` | Clear state |
169
+ | `:help` | Show command summary |
170
+
171
+ ### Raw snippets
172
+
173
+ Raw k input is also accepted. It compiles on top of the current interpreter
174
+ state.
157
175
 
158
- **Example session:**
159
-
160
- ```
161
- > $ nat = < {} zero, nat succ >;
162
- > $ pair = { nat x, nat y };
163
- > --C pair
164
- $ @wq9VvJgYt8sASQfevD23... = { @w8iSHe... x, @w8iSHe... y };
165
- > toto = .toto;
166
- > --R toto
167
- toto : ?{ X0 toto, ... } --> ?X0
176
+ ```text
177
+ > $ bool = <{} true, {} false>;
178
+ > not = $bool </true | false, {} | true>;
179
+ > {} |true not
180
+ {false: {}} ?<{} true, {} false>
168
181
  ```
169
182
 
183
+ Definitions-only snippets extend the session silently. Snippets with a terminal
184
+ expression are evaluated immediately.
185
+
186
+ Tab completion covers:
187
+
188
+ - command names
189
+ - file paths for `:load`, `:klib`, and `:ko`
190
+ - aliases
191
+ - canonical names beginning with `@`
192
+
193
+ See [DOCS/REPL.md](DOCS/REPL.md) for the exact buffering and evaluation rules.
194
+
170
195
  ---
171
196
 
172
197
  ## Code Derivation and Patterns
@@ -269,6 +294,25 @@ echo '{"cons":{"car":{"1":{}},"cdr":{"nil":{}}}}' \
269
294
 
270
295
  See [`codecs/README.md`](codecs/README.md) for codec internals and format details.
271
296
 
297
+ For the textual boundary notation used by `k-parse` and `k-print`, see
298
+ [DOCS/TEXTUAL_VALUES.md](DOCS/TEXTUAL_VALUES.md). For canonical exported
299
+ patterns and `k-pattern`, see [DOCS/PATTERNS.md](DOCS/PATTERNS.md).
300
+
301
+ ## Object and Library Files
302
+
303
+ The object toolchain is documented in [objects/README.md](objects/README.md).
304
+
305
+ - `.klib` stores compiled library state: codes, relations, aliases, metadata
306
+ - `.ko` stores an executable object with a main expression
307
+
308
+ Typical CLI usage:
309
+
310
+ ```bash
311
+ ./objects/compile-lib.mjs Examples/ieee.k ieee.klib
312
+ ./objects/compile.mjs --lib ieee.klib Examples/nat.k nat.ko
313
+ ./objects/decompile.mjs nat.ko
314
+ ```
315
+
272
316
  ---
273
317
 
274
318
  ## Examples
package/codecs/README.md CHANGED
@@ -70,6 +70,11 @@ The runtime boundary is therefore:
70
70
  binary pattern+value stream <-> Value(pattern, tree)
71
71
  ```
72
72
 
73
+ At the command-line boundary, `k-parse` and `k-print` use a JSON-like textual
74
+ notation for k values. That notation is documented in
75
+ [`../DOCS/TEXTUAL_VALUES.md`](../DOCS/TEXTUAL_VALUES.md). It is a readable
76
+ notation for k values, not a separate JSON container format.
77
+
73
78
  `k.mjs` is only the command-line adapter for that boundary. The operational
74
79
  runtime sees and preserves the pattern on the `Value` itself.
75
80
 
@@ -115,6 +120,9 @@ Canonical rules:
115
120
  This JSON-like graph is only a readable notation. The wire representation is
116
121
  the ordinary k `$pattern` value from `core.k`.
117
122
 
123
+ For user-facing pattern export, see [`../DOCS/PATTERNS.md`](../DOCS/PATTERNS.md)
124
+ and the `k-pattern` CLI.
125
+
118
126
  ## Witness-Derived Patterns
119
127
 
120
128
  When `k-parse` is used without an explicit input pattern or type, the wire
@@ -0,0 +1,71 @@
1
+ html {
2
+ line-height: 1.5;
3
+ font-family: Georgia, "Times New Roman", serif;
4
+ color: #1f2328;
5
+ background: #ffffff;
6
+ }
7
+
8
+ body {
9
+ max-width: 980px;
10
+ margin: 2rem auto 4rem;
11
+ padding: 0 1.25rem;
12
+ }
13
+
14
+ h1, h2, h3, h4 {
15
+ line-height: 1.2;
16
+ margin-top: 1.8rem;
17
+ }
18
+
19
+ h1 {
20
+ border-bottom: 1px solid #d0d7de;
21
+ padding-bottom: 0.3rem;
22
+ }
23
+
24
+ p, li {
25
+ max-width: 78ch;
26
+ }
27
+
28
+ pre, code {
29
+ font-family: "Iosevka Term", "SFMono-Regular", Consolas, monospace;
30
+ }
31
+
32
+ code {
33
+ background: #f6f8fa;
34
+ padding: 0.1rem 0.25rem;
35
+ border-radius: 4px;
36
+ }
37
+
38
+ pre {
39
+ background: #f6f8fa;
40
+ border: 1px solid #d0d7de;
41
+ border-radius: 8px;
42
+ padding: 0.9rem 1rem;
43
+ overflow-x: auto;
44
+ }
45
+
46
+ pre code {
47
+ background: transparent;
48
+ padding: 0;
49
+ }
50
+
51
+ blockquote {
52
+ margin-left: 0;
53
+ padding-left: 1rem;
54
+ border-left: 4px solid #d0d7de;
55
+ color: #57606a;
56
+ }
57
+
58
+ table {
59
+ border-collapse: collapse;
60
+ margin: 1rem 0;
61
+ }
62
+
63
+ th, td {
64
+ border: 1px solid #d0d7de;
65
+ padding: 0.4rem 0.7rem;
66
+ vertical-align: top;
67
+ }
68
+
69
+ th {
70
+ background: #f6f8fa;
71
+ }