@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,111 @@
|
|
|
1
|
+
# Chapter 2 — Syntax and Values
|
|
2
|
+
|
|
3
|
+
## **2.1 Language fragments**
|
|
4
|
+
|
|
5
|
+
The `k` language has only one kind of program element: a **definition**.
|
|
6
|
+
A program is a sequence of definitions of two kinds:
|
|
7
|
+
|
|
8
|
+
```k-lang
|
|
9
|
+
$ type_name = ...type_expression... ;
|
|
10
|
+
function_name = ...expression... ;
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The definitions are followed in the file by the *main expression*; it represents the partial function defined by the program as a whole.
|
|
14
|
+
|
|
15
|
+
There is no syntax for values.
|
|
16
|
+
Every syntactic form in an expression describes a **function** -- possibly a constant function that always returns the same value.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## **2.2 Types**
|
|
21
|
+
|
|
22
|
+
A type describes the possible **tree shapes** of values.
|
|
23
|
+
Types are formed from two constructors:
|
|
24
|
+
|
|
25
|
+
1. **Product** – written `{ T₁ l₁, T₂ l₂, … }`
|
|
26
|
+
represents records with fixed labeled fields.
|
|
27
|
+
|
|
28
|
+
2. **Union** – written `< T₁ l₁, T₂ l₂, … >`
|
|
29
|
+
represents a choice between labeled alternatives.
|
|
30
|
+
|
|
31
|
+
Both are finite and fully explicit.
|
|
32
|
+
Every type denotes a finite tree automaton whose accepted trees are the possible values of that type.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## **2.3 Special and limiting cases**
|
|
37
|
+
|
|
38
|
+
1. **Empty product**
|
|
39
|
+
`{}` has no fields.
|
|
40
|
+
It represents the type that admits exactly one value, called *unit*.
|
|
41
|
+
There is nothing exceptional about the type and its value; it is simply the degenerate case of a product with zero fields.
|
|
42
|
+
|
|
43
|
+
2. **Empty union**
|
|
44
|
+
`<>` has no variants.
|
|
45
|
+
It represents a type with no possible values.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## **2.4 Projections**
|
|
50
|
+
|
|
51
|
+
**Dot** notation, e.g.,
|
|
52
|
+
|
|
53
|
+
```k
|
|
54
|
+
. field_name
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
is used for extracting the value of a field from a record (product type value).
|
|
58
|
+
**Div** notation, e.g.,
|
|
59
|
+
|
|
60
|
+
```k
|
|
61
|
+
/ variant_name
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
is used for asserting a particular variant of a union and extracting its value.
|
|
65
|
+
Product type `{ T₁ l₁, T₂ l₂, … , Tₙ lₙ }` naturally defines `n` partial functions: `.l₁, .l₂, … , .lₙ`,
|
|
66
|
+
and union type `< T₁ l₁, T₂ l₂, … , Tₙ lₙ >` naturally defines `n` partial functions `/l₁, /l₂, … , /lₙ`.
|
|
67
|
+
Those partial functions are called **projections** and they constitute the basis for the definition
|
|
68
|
+
of all other partial functions in the `k` language.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## **2.5 Functions**
|
|
73
|
+
|
|
74
|
+
Expressions combine partial functions using the following operators:
|
|
75
|
+
|
|
76
|
+
1. **Composition** `(f₁ f₂ …)` — sequential application.
|
|
77
|
+
2. **Union** `< f₁, f₂, … >` — try each in order, first defined wins.
|
|
78
|
+
3. **Product (parallel)** `{ f₁ l₁, f₂ l₂, … }` — apply all to the same input, succeed only if all succeed.
|
|
79
|
+
4. **Variant construction** `| tag` — lift the input as a variant `tag` of a union type.
|
|
80
|
+
|
|
81
|
+
Parentheses around a composition may be omitted except for the empty composition `()` — the identity function.
|
|
82
|
+
Empty product, `{ }`, defines a constant function (ignoring its input) returning *unit*.
|
|
83
|
+
|
|
84
|
+
It is important to notice that after the three markers: `dot (.)`, `div (/)`, or `pipe (|)`, there must be a constant label literal. For that reason, it is possible and advised not to leave any blanks after the marker, e.g.:
|
|
85
|
+
|
|
86
|
+
```k-lang
|
|
87
|
+
.field /'a-tag' |"strange and long tag name ✅"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## **2.6 Example**
|
|
93
|
+
|
|
94
|
+
```k-lang
|
|
95
|
+
$ bool = < {} true, {} false >;
|
|
96
|
+
true = {} |true $ bool;
|
|
97
|
+
false = {} |false $ bool;
|
|
98
|
+
neg = $ bool < /true false, /false true >;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This defines a "two-variant" union type and three functions: two constants and one transformation exchanging the variants.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## **2.7 Summary**
|
|
106
|
+
|
|
107
|
+
* All types describe tree shapes.
|
|
108
|
+
* As type expression, `{}` is the empty product type (with one value, called *unit*).
|
|
109
|
+
* Functions, not values, are the only expressions in `k`.
|
|
110
|
+
|
|
111
|
+
---
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Chapter 3 — Types as Finite Automata
|
|
2
|
+
|
|
3
|
+
## **3.1 Motivation**
|
|
4
|
+
|
|
5
|
+
A type in `k` describes a set of finite labeled trees, which can be recognized by a finite tree automaton (FTA). Equivalently, a type definition can be seen as a Context-Free Grammar (CFG), where the values of the type are the derivation trees of the grammar.
|
|
6
|
+
|
|
7
|
+
For example, the recursive type definition of a `list`:
|
|
8
|
+
|
|
9
|
+
```k-lang
|
|
10
|
+
$ bool = < {} true, {} false >;
|
|
11
|
+
$ list = < {} nil, { bool head, list tail } cons >;
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
corresponds to the following 4-rule grammar:
|
|
15
|
+
|
|
16
|
+
```bnf
|
|
17
|
+
1: <bool> ::= {} |true
|
|
18
|
+
2: <bool> ::= {} |false
|
|
19
|
+
3: <list> ::= {} |nil
|
|
20
|
+
4: <list> ::= { <bool> head, <list> tail } |cons
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
A value of type `list` is a derivation tree of this grammar. For instance, a list containing a single boolean value `true` can be represented by the following derivation:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
<list>
|
|
27
|
+
-- (rule 4) --> { <bool> head, <list> tail } |cons
|
|
28
|
+
| |
|
|
29
|
+
| -- (rule 3) --> {} |nil
|
|
30
|
+
|
|
|
31
|
+
-- (rule 1) --> {} |true
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
This derivation tree corresponds to the value generated by constant function: `{ {} |true head, {} |nil tail } |cons`.
|
|
35
|
+
|
|
36
|
+
Representing types as automata (or CFGs) provides each type with a well-defined structure, independent of the names used in the source code. This allows for canonical normal forms and for comparing types for equality by structure alone.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## **3.2 States and Transitions**
|
|
41
|
+
|
|
42
|
+
Each type definition introduces one or more *states* in the automaton. A union or a product definition corresponds to a state, and the variants or fields correspond to transitions to other states.
|
|
43
|
+
|
|
44
|
+
For example, consider the `$bool` type:
|
|
45
|
+
|
|
46
|
+
```k-lang
|
|
47
|
+
$ bool = < {} true, {} false >;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
This definition translates to an automaton with two states:
|
|
51
|
+
|
|
52
|
+
- A root state, let's call it `C0`, representing the `$bool` type itself (a union).
|
|
53
|
+
- A state `C1` representing the empty product `{}`.
|
|
54
|
+
|
|
55
|
+
From the root state `C0`, there are two transitions:
|
|
56
|
+
|
|
57
|
+
- A transition labeled `true` to state `C1`.
|
|
58
|
+
- A transition labeled `false` to state `C1`.
|
|
59
|
+
|
|
60
|
+
`C0` is the root state of the type, and `C1` is a leaf state, representing an empty value.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## **3.3 Canonical Form**
|
|
65
|
+
|
|
66
|
+
Different type expressions can describe the same automaton. For example:
|
|
67
|
+
|
|
68
|
+
```k-lang
|
|
69
|
+
$ bool = < {} false, {} true >;
|
|
70
|
+
$ pair = { bool x, bool y };
|
|
71
|
+
$ pair2 = { < {} true, {} false > x, bool y };
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The types `pair` and `pair2` are structurally equivalent because `$bool` is defined as `< {} true, {} false >`, making the definition of `x` in `pair2` identical to the standalone `$bool` type used in `pair`. Canonicalization is the process of removing these superficial differences by erasing local names and renumbering states to produce a single stable representation for each unique type structure.
|
|
75
|
+
|
|
76
|
+
The canonical form is generated by traversing the type's graph structure starting from its root state. The process ensures a unique representation by following a consistent ordering:
|
|
77
|
+
|
|
78
|
+
1. **Start at the Root**: Assign the number `C0` to the root state of the type.
|
|
79
|
+
2. **Explore Neighbors**: Visit all states reachable from `C0`. Sort the transitions alphabetically by their labels (field or variant names) and assign consecutive numbers (`C1`, `C2`, ...) to the destination states in that order.
|
|
80
|
+
3. **Iterate**: Move to the next state in the numbered sequence (`C1`, then `C2`, etc.) and repeat the process for any of its neighbors that have not yet been numbered.
|
|
81
|
+
4. **Complete**: Continue until all reachable states have been assigned a unique number.
|
|
82
|
+
|
|
83
|
+
This traversal produces a unique and deterministic numbering for any finite directed graph, ensuring that any two structurally identical types will have the exact same canonical representation.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## **3.4 Examples**
|
|
88
|
+
|
|
89
|
+
For a type representing binary natural numbers:
|
|
90
|
+
|
|
91
|
+
```k-lang
|
|
92
|
+
$ bnat = < bnat 0, bnat 1, {} _ >;
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
the canonical form is:
|
|
96
|
+
|
|
97
|
+
```k-lang
|
|
98
|
+
$C0 = < C0 "0", C0 "1", C1 "_" >;
|
|
99
|
+
$C1 = {};
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The automaton has two states. `C0` is a recursive state that recognizes sequences of "0"s and "1"s, while `C1` is the terminal state, marked by the "_" transition.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## **3.5 Normalization Process**
|
|
107
|
+
|
|
108
|
+
When compiling a program, the following steps are taken to normalize types:
|
|
109
|
+
|
|
110
|
+
1. **Collect**: Gather all type definitions from the program.
|
|
111
|
+
2. **Expand**: Recursively replace all named types with their underlying definitions until only products and unions remain.
|
|
112
|
+
3. **Deduplicate**: Eliminate duplicate type structures by comparing them structurally.
|
|
113
|
+
4. **Canonicalize**: Assign stable state numbers to the unique types to produce their canonical text representation.
|
|
114
|
+
|
|
115
|
+
This process is deterministic, ensuring that the same type structure always produces the exact same canonical form.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## **3.6 Hash-Based Naming**
|
|
120
|
+
|
|
121
|
+
To create a globally unique and stable identifier for each type, the compiler computes a hash of its canonical representation. This hash becomes the official, unambiguous name of the type.
|
|
122
|
+
|
|
123
|
+
For example:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
Canonical Form: $C0=<C0"0",C0"1",C1"_">;$C1={}
|
|
127
|
+
↓
|
|
128
|
+
Hash
|
|
129
|
+
↓
|
|
130
|
+
Identifier: @VtPHxGf5GNMzzyVFxtv7gegFfJRYapBGtCeyV56bs5Zb
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Program objects can then refer to types by their hash-based identifiers (prefixed with `@`) without ambiguity.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## **3.7 Interpretation**
|
|
138
|
+
|
|
139
|
+
The canonical representation of a type can be interpreted as:
|
|
140
|
+
|
|
141
|
+
- A finite set of states, `C0…Cn`.
|
|
142
|
+
- Each state is either a product (a record with named fields) or a union (a set of variants).
|
|
143
|
+
- Transitions between states are labeled with strings (field or variant names).
|
|
144
|
+
|
|
145
|
+
Every value of a given type is a finite tree that is accepted by this automaton.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## **3.8 Summary**
|
|
150
|
+
|
|
151
|
+
- Types in `k` denote sets of finite, labeled trees.
|
|
152
|
+
- Every type can be expressed as a finite tree automaton or a context-free grammar.
|
|
153
|
+
- The canonical form eliminates naming differences, providing a single representation for structurally identical types.
|
|
154
|
+
- Hash-based naming gives each unique type a stable and globally unique identifier.
|
|
155
|
+
|
|
156
|
+
---
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Chapter 4 — Partial Functions and Composition
|
|
2
|
+
|
|
3
|
+
## **4.1 Partial functions**
|
|
4
|
+
|
|
5
|
+
A **partial function** is a mapping that may be undefined for some inputs.
|
|
6
|
+
In `k`, every expression denotes such a function.
|
|
7
|
+
If a function is undefined for a given input, the evaluation process halts at that point, producing no result.
|
|
8
|
+
|
|
9
|
+
There is no notion of error or exception.
|
|
10
|
+
Undefined means simply “no output”.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## **4.2 Composition**
|
|
15
|
+
|
|
16
|
+
Composition combines two or more partial functions sequentially.
|
|
17
|
+
If `f` and `g` are functions, `(f g)` means “apply `f`, then apply `g` to the result”.
|
|
18
|
+
|
|
19
|
+
A composition `(f g)` is defined on a value `x` if and only if:
|
|
20
|
+
|
|
21
|
+
* `f` is defined on `x`, and
|
|
22
|
+
* `g` is defined on the result of `f(x)`.
|
|
23
|
+
|
|
24
|
+
Otherwise, the composition is undefined.
|
|
25
|
+
|
|
26
|
+
Composition is **associative**:
|
|
27
|
+
|
|
28
|
+
```math
|
|
29
|
+
(f (g h)) ≡ ((f g) h)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Therefore, parentheses are unnecessary, except for the special case of the **empty composition**, written `()`, which is the identity function:
|
|
33
|
+
|
|
34
|
+
```math
|
|
35
|
+
() x = x () = x
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## **4.3 Product composition**
|
|
41
|
+
|
|
42
|
+
Product composition creates a function that applies several subfunctions in parallel to the same input and gathers their results into a product value.
|
|
43
|
+
|
|
44
|
+
Syntax:
|
|
45
|
+
|
|
46
|
+
```math
|
|
47
|
+
{ f₁ l₁, f₂ l₂, …, fₙ lₙ }
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
This expression is defined on an input value if all component functions are defined on that input.
|
|
51
|
+
Its result is a product with fields labeled `l₁ … lₙ`, each containing the result of the corresponding function.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## **4.4 Union composition**
|
|
56
|
+
|
|
57
|
+
Union composition represents concurrent evaluation with fallback:
|
|
58
|
+
|
|
59
|
+
```k-lang
|
|
60
|
+
< f₁, f₂, …, fₙ >
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The result is defined for an input `x` if at least one subfunction is defined.
|
|
64
|
+
Evaluation proceeds left to right; the first defined result is used.
|
|
65
|
+
If none are defined, the result is undefined.
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
|
|
69
|
+
```k-lang
|
|
70
|
+
< /x, /y >
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
extracts variant `x` if present; otherwise `y` if present.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## **4.5 Constants**
|
|
78
|
+
|
|
79
|
+
A constant function is one that always returns the same value, regardless of its input.
|
|
80
|
+
Since `k` lacks a direct syntax for literal values, constants are created using functions that produce them.
|
|
81
|
+
|
|
82
|
+
For example, we can define functions that return `true` and `false`:
|
|
83
|
+
|
|
84
|
+
```k-lang
|
|
85
|
+
$ bool = < {} true, {} false >;
|
|
86
|
+
true_bool = {} |true $bool ;
|
|
87
|
+
false_bool = {} |false $bool ;
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Here, `true_bool` and `false_bool` are constant functions. They are also **total functions**, meaning they are defined for all inputs. Each function ignores its input and produces a fixed boolean value.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## **4.6 Projection and Variant Value constructor**
|
|
95
|
+
|
|
96
|
+
Projection selects a field or a variant from a product or union.
|
|
97
|
+
It is written with a leading dot `.` or a leading slash `/`, respectively:
|
|
98
|
+
|
|
99
|
+
```k-lang
|
|
100
|
+
.x // Selects field 'x' from a product: { T x, ... }
|
|
101
|
+
/x // Extracts the value from a union variant 'x': < T x, ... >
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If the input is a product, `.x` returns the value of field `x`. If the input is a union, `/x` returns the value of variant `x`. In all other cases, the projection is undefined.
|
|
105
|
+
|
|
106
|
+
Variant value constructors for a given union type `T = <T₁ tag₁, T₂ tag₂, … >` are written as `|tag₁`, `|tag₂`, ….
|
|
107
|
+
|
|
108
|
+
```k-lang
|
|
109
|
+
|tag₁ // lift a value of type T₁ into a value of type T
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Projections and variant constructors are the most basic partial functions.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## **4.7 Derived combinations**
|
|
117
|
+
|
|
118
|
+
Complex functions are built by nesting compositions.
|
|
119
|
+
For example:
|
|
120
|
+
|
|
121
|
+
```k-lang
|
|
122
|
+
{ .x field1, .y |tag field2 }
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## **4.8 Identity and emptiness**
|
|
128
|
+
|
|
129
|
+
The empty composition `()` is the identity function.
|
|
130
|
+
The empty union `<>` is the always-undefined function.
|
|
131
|
+
The empty product `{}` is the constant function returning the unit value.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## **4.9 Summary**
|
|
136
|
+
|
|
137
|
+
* In `k`, all expressions denote **partial functions**.
|
|
138
|
+
* An undefined result simply means “no output,” not an error.
|
|
139
|
+
* **Composition** `(f g)` applies functions sequentially and is associative, so parentheses are often optional.
|
|
140
|
+
* The empty composition `()` is the **identity function**.
|
|
141
|
+
* **Product composition** `{...}` runs functions in parallel and gathers their results.
|
|
142
|
+
* **Union composition** `<...>` tries functions in order, returning the first successful result.
|
|
143
|
+
* **Projections** (`.x`, `/x`) are fundamental building blocks for accessing data structures.
|
|
144
|
+
* **Variant constructor** (`|tag`) allows lifting a value into a variant type value.
|
|
145
|
+
|
|
146
|
+
---
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Chapter 5 — Typing, Filters, and Normalization
|
|
2
|
+
|
|
3
|
+
## **5.1 Types as functions**
|
|
4
|
+
|
|
5
|
+
A type expression in `k` can appear wherever a function is expected.
|
|
6
|
+
When used this way, it is prefixed by `$`.
|
|
7
|
+
It then behaves as a partial **identity** function that is defined only for values of that type.
|
|
8
|
+
For example, `$ bool` is a partial identity: it returns its argument unchanged when the argument is of type `bool`, and it is undefined otherwise.
|
|
9
|
+
|
|
10
|
+
This convention eliminates any special syntax for annotating sub-expressions with types.
|
|
11
|
+
An expression may be *restricted* to a type simply by composing it with the corresponding type expression.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## **5.2 Filters**
|
|
16
|
+
|
|
17
|
+
A **filter** is a syntactic form that denotes a *class of types* — a set of types that share a common structure.
|
|
18
|
+
|
|
19
|
+
Filter expressions are introduced by `?` and can be:
|
|
20
|
+
|
|
21
|
+
- **Type expressions** — `? $bool`, `? $< {} x, bool y >`
|
|
22
|
+
- **Product filters** — `? { Filter1 field1, Filter2 field2 }`
|
|
23
|
+
- **Union filters** — `? < Filter1 tag1, Filter2 tag2 >`
|
|
24
|
+
- **Any-type filter** — `? ( ... )`
|
|
25
|
+
- **Filter variables** — `? X` (metavariables representing unknown types)
|
|
26
|
+
- **Filter bindings** — `? < X f, (...) = Y g, ... > = X`
|
|
27
|
+
|
|
28
|
+
Filters may contain `...` to indicate that additional fields or tags are allowed:
|
|
29
|
+
`? { Filter1 field1, ... }` matches any product with at least `field1`.
|
|
30
|
+
|
|
31
|
+
The filter `? (...)` matches any type.
|
|
32
|
+
The filter `? {...}` matches any product type.
|
|
33
|
+
The filter `? <...>` matches any union type.
|
|
34
|
+
There is no closed unknown filter: use `?{}` for the empty product or `?<>` for the empty union.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## **5.3 Examples of filters**
|
|
39
|
+
|
|
40
|
+
- `?(...)` — represents any type.
|
|
41
|
+
- `?< (...) f, (...) g >` — represents all union types having exactly two variants `f` and `g`.
|
|
42
|
+
- `?{ X f, X g }` — represents all product types with two fields `f` and `g`, both of the same type.
|
|
43
|
+
|
|
44
|
+
A filter constrains where a partial function is defined; it does not affect the operational behavior of the function once defined.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## **5.4 Recursive filters**
|
|
49
|
+
|
|
50
|
+
Filters may be recursive.
|
|
51
|
+
They can describe families of recursive types by defining a metavariable in terms of a filter that references it.
|
|
52
|
+
|
|
53
|
+
Example (list definition):
|
|
54
|
+
|
|
55
|
+
```k-lang
|
|
56
|
+
?< {} nil, {X car, Y cdr} cons > = Y
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This filter states that `Y` is a union type with two variants: `nil` and `cons`.
|
|
60
|
+
|
|
61
|
+
- The `nil` variant holds an empty product `{}`.
|
|
62
|
+
- The `cons` variant is a product with two fields: `car` of some type `X`, and `cdr` of type `Y` itself.
|
|
63
|
+
|
|
64
|
+
This recursive structure defines a linked list where each element has a `car` (the value) and a `cdr` (the rest of the list).
|
|
65
|
+
It thus denotes lists of elements of type `X`.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## **5.5 Type variables and scope**
|
|
70
|
+
|
|
71
|
+
A type variable (an identifier, typically starting with an uppercase letter) introduced in a filter is visible within the enclosing function definition.
|
|
72
|
+
For example:
|
|
73
|
+
|
|
74
|
+
```k-lang
|
|
75
|
+
car = ?< {} nil, {X car, Y cdr} cons > = Y /cons .car ?X;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Here:
|
|
79
|
+
|
|
80
|
+
- `X` and `Y` are type variables.
|
|
81
|
+
- The filter `?<{}nil,{X car,Y cdr}cons>=Y` constrains the function `car` to be defined only on types that match the recursive list structure.
|
|
82
|
+
- The expression `/cons` selects the `cons` variant of the union.
|
|
83
|
+
- The expression `.car` accesses the `car` field of a `cons` variant.
|
|
84
|
+
- The final filter `?X` asserts that the result of the field access is of type `X`, the type of the list's elements.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## **5.6 Type inference and normalization**
|
|
89
|
+
|
|
90
|
+
Every `k` program can be analyzed to assign an input and an output filter to every sub-expression. This process is called type inference abd normalization.
|
|
91
|
+
|
|
92
|
+
Type inference and normalization proceeds as follows:
|
|
93
|
+
|
|
94
|
+
1. Build a graph of all type references appearing explicitly and implicitly in the program.
|
|
95
|
+
2. Annotate each expression node with a pair of (input filter, output filter).
|
|
96
|
+
3. Replace filters that match a single, concrete type with that type expression, adding any newly-discovered types to the graph.
|
|
97
|
+
4. Repeat until a fixed point is reached and no more changes occur.
|
|
98
|
+
5. Compute canonical forms for all newly introduced types.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## **5.7 Summary**
|
|
103
|
+
|
|
104
|
+
- Type expressions act as identity functions defined on values of that type.
|
|
105
|
+
- Filters describe sets of types and can constrain where a function is defined.
|
|
106
|
+
- Filters may be products, unions, or the unconstrained any-type form, and can be recursive.
|
|
107
|
+
- Variables in filters have definition-level scope.
|
|
108
|
+
- Normalization computes explicit input/output filters for every expression.
|
|
109
|
+
- Filters are used in the normalization and type checking process. They are ignored at runtime.
|
|
110
|
+
|
|
111
|
+
---
|