@fraczak/k 6.10.2 → 6.10.4
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/CHANGELOG.md +73 -0
- package/DOCS/BIG_PICTURE.md +174 -100
- package/DOCS/CODECS.md +74 -29
- package/DOCS/CODEC_ARCHITECTURE.md +87 -31
- package/DOCS/CONVERGENCE.md +42 -11
- package/DOCS/DICTIONARY.md +69 -2
- package/DOCS/FILE_FORMATS.md +420 -0
- package/DOCS/KIR_V1.md +53 -42
- package/DOCS/KVM_EXECUTION_MODEL.md +189 -147
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +35 -17
- package/DOCS/PATTERNS.md +10 -6
- package/DOCS/REPL.md +100 -60
- package/DOCS/TEXTUAL_VALUES.md +24 -19
- package/DOCS/TYPE_DERIVATION.md +68 -22
- package/Examples/karatsuba-mult.k +215 -0
- package/README.md +92 -58
- package/backends/arm64/scripts/run-tests.mjs +16 -0
- package/backends/llvm/bin/k-llvm-build.mjs +40 -14
- package/backends/llvm/bin/k-llvm-compile.mjs +29 -12
- package/backends/llvm/runtime/krt.c +10 -10
- package/backends/llvm/runtime/krt.h +6 -1
- package/backends/llvm/scripts/run-tests.mjs +16 -0
- package/backends/llvm/src/cli.mjs +1 -1
- package/backends/llvm/src/executable.mjs +36 -0
- package/backends/llvm/src/kvm2llvm.mjs +10 -4
- package/backends/llvm/tests/integration.sh +11 -0
- package/backends/llvm/tests/test-llvm.mjs +15 -1
- package/backends/wasm/scripts/run-tests.mjs +16 -0
- package/browser/vfs-data.mjs +1 -1
- package/codecs/README.md +78 -67
- package/core.k +5 -5
- package/objects/README.md +57 -37
- package/package.json +2 -1
- package/scripts/benchmark-idempotency.mjs +27 -0
- package/scripts/benchmark.mjs +51 -0
- package/scripts/build-repl-html.mjs +17 -0
- package/scripts/generate-dependency-graph.mjs +25 -1
- package/scripts/perf-ieee.mjs +75 -0
- package/scripts/perf-int.mjs +67 -0
- package/scripts/perf-multiplication.mjs +644 -0
- package/scripts/perf-poly.mjs +67 -0
- package/scripts/render-benchmark.mjs +25 -0
- package/scripts/run-tests.mjs +19 -0
- package/tests/README.md +28 -17
- package/tests/test-karatsuba.mjs +133 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,79 @@ All notable changes to this project will be documented here.
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [6.10.4] — 2026-10-06 — Karatsuba Multiplication, Multi-Backend Harness, and CLI Help
|
|
9
|
+
|
|
10
|
+
### Arithmetic & Algorithms
|
|
11
|
+
|
|
12
|
+
- **Karatsuba Multiplication (`Examples/karatsuba-mult.k`)**:
|
|
13
|
+
- Implemented standalone, minimal Karatsuba integer multiplication with
|
|
14
|
+
asymptotic time complexity $O(n^{\log_2 3}) \approx O(n^{1.585})$.
|
|
15
|
+
- Utilizes unary counter (`$unat`) splitting with a 512-bit threshold
|
|
16
|
+
switching to grade-school multiplication (`times_bits`) for small
|
|
17
|
+
inputs.
|
|
18
|
+
- Implements direct bit-level arithmetic (`plus_bits`, `minus_bits`,
|
|
19
|
+
`times_bits`) and direct $2m$ bit shifting (`shift2_bits_u`).
|
|
20
|
+
- Added dedicated test suite in `tests/test-karatsuba.mjs` verifying
|
|
21
|
+
squaring cases and mixed-sign pair multiplications against BigInt
|
|
22
|
+
oracle.
|
|
23
|
+
|
|
24
|
+
### Performance & Benchmarking
|
|
25
|
+
|
|
26
|
+
- **Multiplication Performance Harness**
|
|
27
|
+
(`scripts/perf-multiplication.mjs`):
|
|
28
|
+
- Added multi-backend performance runner comparing `times` and
|
|
29
|
+
`karatsuba` across LLVM, Wasm, kVM, and JS engines.
|
|
30
|
+
- Supports `--mode squaring` (doubling bit width per step) and
|
|
31
|
+
`--mode sizes` (random operands of fixed bit lengths).
|
|
32
|
+
- Includes per-step timeout protection and process RSS memory guards.
|
|
33
|
+
- Added `npm run perf:mult` script in `package.json`.
|
|
34
|
+
|
|
35
|
+
### CLI Usability & Backend Enhancements
|
|
36
|
+
|
|
37
|
+
- **Unified `-h` and `--help` CLI Documentation**:
|
|
38
|
+
- Added comprehensive option and environment variable documentation
|
|
39
|
+
across all benchmark, performance, and test scripts in `scripts/`
|
|
40
|
+
and `backends/*/scripts/`.
|
|
41
|
+
- **LLVM Direct `.kvm` Bytecode Compilation**:
|
|
42
|
+
- Added `compileKVMToExecutable` in `backends/llvm/src/executable.mjs`,
|
|
43
|
+
enabling direct binary compilation from lowered `.kvm` IR.
|
|
44
|
+
- **Runtime Mark Compaction Fixes**:
|
|
45
|
+
- Updated LLVM runtime compaction tracking (`%k_rt_tail_mark`) to
|
|
46
|
+
accurately preserve base and last compaction arena marks in
|
|
47
|
+
tail loops.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## [6.10.3] — 2026-10-04 — Unified File Formats Specification and Documentation Modernization
|
|
52
|
+
|
|
53
|
+
### Documentation & Core Architecture
|
|
54
|
+
|
|
55
|
+
- **Unified File Formats Specification (`DOCS/FILE_FORMATS.md`)**:
|
|
56
|
+
- Added comprehensive specification for all primary file formats: `.k`
|
|
57
|
+
(source), `.ko` (executable object), `.klib` (library object), and
|
|
58
|
+
`.kvm` (polymorphic register-IR template), plus target artifacts
|
|
59
|
+
(`.wasm`, native binary).
|
|
60
|
+
- Added Mermaid transformation flowchart mapping compilation, linking,
|
|
61
|
+
specialization, and execution workflows across CLI tools.
|
|
62
|
+
- **AOT Type Checking & Canonical Content-Addressing**:
|
|
63
|
+
- Formally specified that AOT type checking performs relation expansion,
|
|
64
|
+
structural type derivation, and constraint convergence in advance.
|
|
65
|
+
- Clarified canonical content-addressed hashes (`@hash`) vs. local aliases,
|
|
66
|
+
confirming there is no global symbol namespace, and documented explicit
|
|
67
|
+
`--export` semantics for `--lib`.
|
|
68
|
+
- **Relations as Values & Absence of Built-in Numbers**:
|
|
69
|
+
- Documented that numerical literals do not exist in `k`; names like `5`
|
|
70
|
+
or `10` are nullary relations mapping `${} -> $bits`. Arithmetic relations
|
|
71
|
+
operate on signed integer variants (`$int`), converting via `5 int`.
|
|
72
|
+
- Clarified stream transformers (open domain) vs. closed constant relations
|
|
73
|
+
(unit input domain `${}`).
|
|
74
|
+
- **Documentation Reformatting**:
|
|
75
|
+
- Systematically updated and wrapped prose across `README.md` and all
|
|
76
|
+
documents in `DOCS/`, `codecs/`, `objects/`, and `tests/` to <= 74
|
|
77
|
+
characters per line.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
8
81
|
## [6.10.2] — 2026-10-03 — Stack-Safe Value Serializer for REPL and Web REPL
|
|
9
82
|
|
|
10
83
|
### REPL & Codecs
|
package/DOCS/BIG_PICTURE.md
CHANGED
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
# Big Picture
|
|
2
2
|
|
|
3
|
-
`Kernel-code` is an experiment aiming to define a "perfect programming
|
|
3
|
+
`Kernel-code` is an experiment aiming to define a "perfect programming
|
|
4
|
+
language".
|
|
4
5
|
|
|
5
6
|
## Basics
|
|
6
7
|
|
|
7
|
-
The language describes "partial first-order functions" on "printable"
|
|
8
|
-
The printable values can be seen as rooted, edge-labeled trees,
|
|
9
|
-
XML or a JSON document. The values are always
|
|
10
|
-
runtime, a value may carry a pattern
|
|
11
|
-
with that tree.
|
|
8
|
+
The language describes "partial first-order functions" on "printable"
|
|
9
|
+
values. The printable values can be seen as rooted, edge-labeled trees,
|
|
10
|
+
intuitively similar to an XML or a JSON document. The values are always
|
|
11
|
+
typed; in the current codec-aware runtime, a value may carry a pattern
|
|
12
|
+
describing the family of types compatible with that tree.
|
|
12
13
|
|
|
13
14
|
### Types (codes)
|
|
14
15
|
|
|
15
|
-
Formally, a _type_ is a finite tree automaton. The type defines a set of
|
|
16
|
-
which corresponds to the set of trees accepted by the
|
|
17
|
-
Therefore, every type admits a unique normal form in terms of
|
|
16
|
+
Formally, a _type_ is a finite tree automaton. The type defines a set of
|
|
17
|
+
values, which corresponds to the set of trees accepted by the
|
|
18
|
+
automaton. Therefore, every type admits a unique normal form in terms of
|
|
19
|
+
its minimal deterministic tree automaton.
|
|
18
20
|
|
|
19
21
|
Types are defined by two constructs:
|
|
20
22
|
|
|
21
23
|
1. Product
|
|
22
24
|
2. Union (also called tagged or disjoint union)
|
|
23
25
|
|
|
24
|
-
> Notation: We use native k-like notation as canonical — products
|
|
25
|
-
>
|
|
26
|
+
> Notation: We use native k-like notation as canonical — products
|
|
27
|
+
> `{ T l, ... }` and unions `< T t, ... >`. For convenience, JSON-like
|
|
28
|
+
> forms `{ l: T, ... }` and `< t: T, ... >` are also supported and
|
|
29
|
+
> equivalent in meaning.
|
|
26
30
|
|
|
27
31
|
```bnf
|
|
28
32
|
type ::= name | '{' type_label_list '}' | '<' type_label_list '>'
|
|
@@ -31,18 +35,23 @@ name ::= IDENTIFIER
|
|
|
31
35
|
label ::= STRING
|
|
32
36
|
```
|
|
33
37
|
|
|
34
|
-
Given a finite (possibly empty) set of types `t1, t2, ..., tn` and a
|
|
38
|
+
Given a finite (possibly empty) set of types `t1, t2, ..., tn` and a
|
|
39
|
+
set of pairwise different tags (labels) `l1, l2, ..., ln`,
|
|
35
40
|
|
|
36
|
-
- by `{ t1 l1, t2 l2, ..., tn ln }`, we define a _product type_ with
|
|
37
|
-
_projection_ functions: `.l1`, `.l2`, `...`, `.ln`.
|
|
38
|
-
Each projection function maps a value of type
|
|
39
|
-
into a value of type `t1`, `t2`,
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
- by `{ t1 l1, t2 l2, ..., tn ln }`, we define a _product type_ with
|
|
42
|
+
exactly `n` _projection_ functions: `.l1`, `.l2`, `...`, `.ln`.
|
|
43
|
+
Each projection function maps a value of type
|
|
44
|
+
`{t1 l1, t2 l2, ..., tn ln}` into a value of type `t1`, `t2`,
|
|
45
|
+
`...`, `tn`, respectively.
|
|
46
|
+
- by `< t1 l1, t2 l2, ..., tn ln >`, we define a _union type_ with
|
|
47
|
+
exactly `n` projection functions `/l1`, `/l2`, `...`, `/ln`,
|
|
48
|
+
mapping a value of type `<t1 l1, t2 l2, ..., tn ln>` into a value
|
|
49
|
+
of type `t1`, `t2`, `...`, `tn`, respectively.
|
|
42
50
|
|
|
43
|
-
Intuitively, the projection functions on a product type are all total
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
Intuitively, the projection functions on a product type are all total
|
|
52
|
+
(meaning, they are defined for every value of the input product type),
|
|
53
|
+
whereas in the case of a union type, exactly one projection function
|
|
54
|
+
is defined for a given value of the union type.
|
|
46
55
|
|
|
47
56
|
Some properties of these types:
|
|
48
57
|
|
|
@@ -51,26 +60,32 @@ Some properties of these types:
|
|
|
51
60
|
|
|
52
61
|
#### Variant (union) value literal convention
|
|
53
62
|
|
|
54
|
-
- Variant values are written using "|" (pipe) followed by the variant
|
|
63
|
+
- Variant values are written using "|" (pipe) followed by the variant
|
|
64
|
+
tag.
|
|
55
65
|
- Unit variant `` `{}` `` | tag (e.g., `{} | nil`, `{} | zero`)
|
|
56
66
|
- Variant with payload `v` at label `tag`: ` v | tag `
|
|
57
67
|
- Example (list): with `$list = < {} nil, {X car, list cdr} cons >`:
|
|
58
68
|
- Empty list []: `{}|nil`
|
|
59
69
|
- Singleton `[v]`: `{ v car, {}|nil cdr } | cons`
|
|
60
|
-
- Angle brackets are for type definitions and merge expressions; use
|
|
70
|
+
- Angle brackets are for type definitions and merge expressions; use
|
|
71
|
+
"`| tag`" for a variant construction.
|
|
61
72
|
|
|
62
73
|
#### Equivalence of types (bisimilarity)
|
|
63
74
|
|
|
64
|
-
Two (possibly recursive) codes are equivalent iff they are bisimilar
|
|
75
|
+
Two (possibly recursive) codes are equivalent iff they are bisimilar
|
|
76
|
+
over their definition graphs. Concretely, there exists a relation B
|
|
77
|
+
such that `(t1, t2) ∈ B` if and only if:
|
|
65
78
|
- t1 and t2 have exactly the same set of labels/tags;
|
|
66
79
|
- t1 and t2 are simultaneously products or simultaneously unions;
|
|
67
|
-
- for each label/tag `ℓ` in the set, the subcodes under `ℓ` are again
|
|
80
|
+
- for each label/tag `ℓ` in the set, the subcodes under `ℓ` are again
|
|
81
|
+
related by B.
|
|
68
82
|
|
|
69
83
|
### Filters (patterns)
|
|
70
84
|
|
|
71
|
-
A _filter_ is a way of representing a _pattern_, i.e., a set of types
|
|
72
|
-
For example, if I wanted to refer to all product
|
|
73
|
-
|
|
85
|
+
A _filter_ is a way of representing a _pattern_, i.e., a set of types
|
|
86
|
+
sharing some structure. For example, if I wanted to refer to all product
|
|
87
|
+
types that have a field `f` of type `T`, I would write:
|
|
88
|
+
`?{ T f, ... }`. In general, a filter is defined by:
|
|
74
89
|
|
|
75
90
|
```bnf
|
|
76
91
|
filter ::= name | '$' type_expr | '{' filter_label_list '}'
|
|
@@ -92,29 +107,36 @@ Examples:
|
|
|
92
107
|
|
|
93
108
|
### Partial functions
|
|
94
109
|
|
|
95
|
-
A _partial function_ is a function that is not defined for every value
|
|
110
|
+
A _partial function_ is a function that is not defined for every value
|
|
111
|
+
of its domain.
|
|
96
112
|
|
|
97
113
|
There are three ways of combining partial functions:
|
|
98
114
|
|
|
99
|
-
1. __Composition__: we write a composition of `f` and `g` as `(f
|
|
100
|
-
meaning that if `f` is defined on value `x` producing `y`,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
1. __Composition__: we write a composition of `f` and `g` as `(f g)`,
|
|
116
|
+
meaning that if `f` is defined on value `x` producing `y`, and `g`
|
|
117
|
+
is defined on value `y` producing `z`, then `(f g)` is defined on
|
|
118
|
+
value `x` producing `z`.
|
|
119
|
+
2. __Union__: we write `< f1, f2 >` for a union of two functions `f1`
|
|
120
|
+
and `f2`, meaning that if `f1` is defined on value `x` producing
|
|
121
|
+
`y`, then `< f1, f2 >` is defined on value `x` producing `y`.
|
|
122
|
+
Otherwise, i.e., when `f1` is not defined for `x`, `< f1, f2 >`
|
|
123
|
+
acts as `f2`.
|
|
124
|
+
3. __Product__: we write `{f1 lab1, f2 lab2 }` for a product of two
|
|
125
|
+
functions `f1` and `f2`, meaning that if `f1` and `f2` are both
|
|
126
|
+
defined on value `x` producing `y1` and `y2`, respectively, then
|
|
127
|
+
`{f1 lab1, f2 lab2 }` is defined on value `x` producing
|
|
128
|
+
`{y1 lab1, y2 lab2}`. Otherwise, `{f1 lab1, f2 lab2 }` is not
|
|
129
|
+
defined for `x`.
|
|
130
|
+
|
|
131
|
+
Actually, composition, union, and product combine any number of
|
|
132
|
+
partial functions, not only two. For example, empty composition,
|
|
133
|
+
`()`, defines the identity function.
|
|
113
134
|
|
|
114
135
|
### Program
|
|
115
136
|
|
|
116
|
-
A `kernel-core` program is a set of definitions of types and partial
|
|
117
|
-
which is the partial function
|
|
137
|
+
A `kernel-core` program is a set of definitions of types and partial
|
|
138
|
+
functions, followed by an _expression_, which is the partial function
|
|
139
|
+
the program defines.
|
|
118
140
|
|
|
119
141
|
The language syntax is defined by:
|
|
120
142
|
|
|
@@ -132,47 +154,65 @@ expr_label_list ::= /* empty */
|
|
|
132
154
|
| (expression label_name ',')* expression label
|
|
133
155
|
```
|
|
134
156
|
|
|
135
|
-
We assume that in a `kernel-core` program the names (for types,
|
|
157
|
+
We assume that in a `kernel-core` program the names (for types,
|
|
158
|
+
functions, and labels) are identifiers (strings) such that:
|
|
136
159
|
|
|
137
160
|
1. All defined type names are distinct.
|
|
138
161
|
2. All defined function names are distinct.
|
|
139
|
-
3. All label names within a type definition or a `product` expression
|
|
162
|
+
3. All label names within a type definition or a `product` expression
|
|
163
|
+
are locally distinct.
|
|
140
164
|
|
|
141
|
-
Filters and type expressions act as a type annotation, i.e., an
|
|
142
|
-
function defined only for the values of the corresponding
|
|
165
|
+
Filters and type expressions act as a type annotation, i.e., an
|
|
166
|
+
identity function defined only for the values of the corresponding
|
|
167
|
+
types.
|
|
143
168
|
|
|
144
169
|
That's it.
|
|
145
170
|
|
|
146
|
-
No `builtin` types, no `if` statement, no `loop`, no `throw`, no
|
|
147
|
-
Just _types_, _filters_,
|
|
171
|
+
No `builtin` types, no `if` statement, no `loop`, no `throw`, no
|
|
172
|
+
_closure_, no _annotations_, and no macros. Just _types_, _filters_,
|
|
173
|
+
and _functions_.
|
|
148
174
|
|
|
149
|
-
### Normalization
|
|
175
|
+
### Normalization and Content-Addressing
|
|
150
176
|
|
|
151
|
-
All type names are replaced by the hash of their
|
|
177
|
+
All type names are replaced by the canonical hash (`@hash`) of their
|
|
178
|
+
minimal deterministic tree automaton representation.
|
|
152
179
|
|
|
153
|
-
|
|
154
|
-
|
|
180
|
+
Every relation is identified canonically by the content-addressed hash
|
|
181
|
+
of its normalized definition AST.
|
|
155
182
|
|
|
156
|
-
|
|
157
|
-
|
|
183
|
+
There is no global symbol namespace. Human-readable names (such as
|
|
184
|
+
`plus`, `int`, or `5`) are local aliases recorded in object metadata
|
|
185
|
+
(`relAlias`, `typeAliases`). When libraries are loaded with `--lib`,
|
|
186
|
+
definitions are identified by their canonical `@hash`, but local aliases
|
|
187
|
+
are not implicitly exported into the importing scope unless explicitly
|
|
188
|
+
mapped via `--export`.
|
|
189
|
+
|
|
190
|
+
This approach completely solves the problem of modules, name collisions,
|
|
191
|
+
and unversioned imports, opening the door to a universal registry of
|
|
192
|
+
types (schemas) and relations.
|
|
158
193
|
|
|
159
194
|
## Typing and Polymorphism (codes and patterns)
|
|
160
195
|
|
|
161
|
-
The abstract syntax tree of a program consists of a dictionary of
|
|
162
|
-
a dictionary of _function definitions_, and the
|
|
196
|
+
The abstract syntax tree of a program consists of a dictionary of
|
|
197
|
+
_type definitions_, a dictionary of _function definitions_, and the
|
|
198
|
+
final _main expression_.
|
|
163
199
|
|
|
164
|
-
In principle, the initial form of the Abstract Syntax Tree, _raw_ AST,
|
|
165
|
-
the program on an input.
|
|
200
|
+
In principle, the initial form of the Abstract Syntax Tree, _raw_ AST,
|
|
201
|
+
is enough to evaluate the program on an input.
|
|
166
202
|
|
|
167
|
-
Our objective, however, is to compute canonical representations for
|
|
168
|
-
representations for functions so they can be
|
|
203
|
+
Our objective, however, is to compute canonical representations for
|
|
204
|
+
types and normalized representations for functions so they can be
|
|
205
|
+
reused and compiled ahead-of-time.
|
|
169
206
|
|
|
170
207
|
The normalization steps are:
|
|
171
208
|
|
|
172
|
-
1. Build the _type graph_ from all types used by the program, i.e.,
|
|
173
|
-
as well as type expressions used in
|
|
174
|
-
|
|
175
|
-
|
|
209
|
+
1. Build the _type graph_ from all types used by the program, i.e.,
|
|
210
|
+
used in _type definitions_ as well as type expressions used in
|
|
211
|
+
_function definitions_ and the _main expression_.
|
|
212
|
+
2. Annotate the expressions with filters; every node of the AST is
|
|
213
|
+
annotated with a pair of filters.
|
|
214
|
+
3. Turn the _singleton_ filters into types and add them to the _type
|
|
215
|
+
graph_. Go to (2) unless no change.
|
|
176
216
|
|
|
177
217
|
### Examples
|
|
178
218
|
|
|
@@ -213,21 +253,25 @@ inc3
|
|
|
213
253
|
In the above program, we define type `bit` as union of two unit types,
|
|
214
254
|
and type `byte` as product, for simplicity, of four `bit`s.
|
|
215
255
|
|
|
216
|
-
Functions `bit0`, `bit1`, and `zero` are "constant polymorphic
|
|
256
|
+
Functions `bit0`, `bit1`, and `zero` are "constant polymorphic
|
|
257
|
+
functions", meaning:
|
|
217
258
|
|
|
218
259
|
- constant: if defined, they always return exactly the same value;
|
|
219
|
-
- polymorphic: they are defined for more than one pair of input and
|
|
220
|
-
`bit0` and `bit1` are of type `?X -> $bit`,
|
|
221
|
-
|
|
260
|
+
- polymorphic: they are defined for more than one pair of input and
|
|
261
|
+
output types: functions `bit0` and `bit1` are of type `?X -> $bit`,
|
|
262
|
+
and `zero` is of type `?X -> $byte`, where `?X` denotes an
|
|
263
|
+
unconstrained type pattern, also denoted as `?(...)`.
|
|
222
264
|
|
|
223
265
|
Functions `inc` and `inc3` are (non-polymorphic) functions of types
|
|
224
266
|
`$byte -> ${ bit overflown, byte byte }` and
|
|
225
|
-
`${ bit overflown, byte byte } -> ${ bit overflown, byte byte }`,
|
|
267
|
+
`${ bit overflown, byte byte } -> ${ bit overflown, byte byte }`,
|
|
268
|
+
respectively.
|
|
226
269
|
|
|
227
|
-
Function `inc_o` is a polymorphic function of type patterns:
|
|
228
|
-
with the following constraints:
|
|
270
|
+
Function `inc_o` is a polymorphic function of type patterns:
|
|
271
|
+
`?X -> ${ byte byte, bit overflown }` with the following constraints:
|
|
229
272
|
|
|
230
|
-
- `?X` is a product type with at least two fields: `byte` and
|
|
273
|
+
- `?X` is a product type with at least two fields: `byte` and
|
|
274
|
+
`overflown`, denoted by:
|
|
231
275
|
> `?{ $byte byte, Z overflown, ...}`;
|
|
232
276
|
- `?Z` is a union type with field `i` denoted by:
|
|
233
277
|
> `?< V i, ...>`;
|
|
@@ -235,8 +279,9 @@ with the following constraints:
|
|
|
235
279
|
|
|
236
280
|
We can write it as: `?{$byte byte, <(...) i, ...> overflown, ...}`.
|
|
237
281
|
|
|
238
|
-
The target type `${ byte byte, bit overflown }` corresponds to pattern
|
|
239
|
-
Such a pattern is called _singleton
|
|
282
|
+
The target type `${ byte byte, bit overflown }` corresponds to pattern
|
|
283
|
+
`?{ $byte byte, $bit overflown }`. Such a pattern is called _singleton
|
|
284
|
+
pattern_, as only one type fits the pattern.
|
|
240
285
|
|
|
241
286
|
#### Example 2
|
|
242
287
|
|
|
@@ -261,43 +306,61 @@ car = list? /cons .car; -- @...
|
|
|
261
306
|
|
|
262
307
|
## Universal Schema Registry
|
|
263
308
|
|
|
264
|
-
Since the normalization process for types is fast and deterministic,
|
|
265
|
-
schema registry that will store all invented
|
|
266
|
-
The registry will be a key-value store, where the key is the hash
|
|
267
|
-
and the value is the normalized type itself.
|
|
309
|
+
Since the normalization process for types is fast and deterministic,
|
|
310
|
+
we can build a universal schema registry that will store all invented
|
|
311
|
+
types. The registry will be a key-value store, where the key is the hash
|
|
312
|
+
of the normalized type, and the value is the normalized type itself.
|
|
268
313
|
|
|
269
|
-
All functions (non-polymorphic and polymorphic)
|
|
270
|
-
definition and stored in a similar key-value store.
|
|
314
|
+
All functions (non-polymorphic and polymorphic) are named by the hash
|
|
315
|
+
of their normalized definition and stored in a similar key-value store.
|
|
271
316
|
|
|
272
|
-
Non-polymorphic functions can be easily indexed by the hashes of their
|
|
273
|
-
so that we can quickly find the function we need.
|
|
317
|
+
Non-polymorphic functions can be easily indexed by the hashes of their
|
|
318
|
+
input and output types so that we can quickly find the function we need.
|
|
274
319
|
Indexing polymorphic functions seems complicated (TODO).
|
|
275
320
|
|
|
276
321
|
## Serialization and Compilation
|
|
277
322
|
|
|
278
|
-
The language is designed to transform _codes_, i.e., serialized typed
|
|
279
|
-
accepted by a tree automaton, into other _codes_.
|
|
280
|
-
The transformation is done by partial functions as defined in the
|
|
281
|
-
The non-recursive and tail-recursive (and even some
|
|
282
|
-
be compiled into deterministic finite
|
|
323
|
+
The language is designed to transform _codes_, i.e., serialized typed
|
|
324
|
+
values, i.e., trees accepted by a tree automaton, into other _codes_.
|
|
325
|
+
The transformation is done by partial functions as defined in the
|
|
326
|
+
language. The non-recursive and tail-recursive (and even some
|
|
327
|
+
non-tail-recursive) functions can be compiled into deterministic finite
|
|
328
|
+
(pushdown) transducers.
|
|
329
|
+
|
|
330
|
+
Ahead-Of-Time (AOT) compilation produces four primary file formats (see
|
|
331
|
+
[`DOCS/FILE_FORMATS.md`](./FILE_FORMATS.md)):
|
|
332
|
+
- `.k`: Plain source text.
|
|
333
|
+
- `.ko`: AOT type-checked executable object container (`KOBJ\n` + JSON).
|
|
334
|
+
- `.klib`: AOT type-checked library container (JSON).
|
|
335
|
+
- `.kvm`: Polymorphic register-IR template (`layer: "KVM-P"`).
|
|
336
|
+
|
|
337
|
+
Downstream backends compile or specialize these into WebAssembly
|
|
338
|
+
(`.wasm`) and native binaries.
|
|
283
339
|
|
|
284
340
|
### AND-OR graphs for encoding and decoding codes
|
|
285
341
|
|
|
286
|
-
This could be a generic and compact way to encode and decode typed
|
|
287
|
-
The idea is to use _prefix codes_ (a class of languages such
|
|
288
|
-
another word) to encode the values.
|
|
342
|
+
This could be a generic and compact way to encode and decode typed
|
|
343
|
+
values. The idea is to use _prefix codes_ (a class of languages such
|
|
344
|
+
that no word is a prefix of another word) to encode the values.
|
|
289
345
|
|
|
290
346
|
### Rust data structures
|
|
291
347
|
|
|
292
|
-
A type can be translated into a Rust data structure, and a function
|
|
348
|
+
A type can be translated into a Rust data structure, and a function
|
|
349
|
+
can be translated into a Rust function.
|
|
293
350
|
|
|
294
351
|
## Linking with Other Languages
|
|
295
352
|
|
|
296
353
|
## Streams and Arrays (Map-Reduce)
|
|
297
354
|
|
|
298
|
-
## Bits
|
|
355
|
+
## Bits and Absence of Built-in Numbers
|
|
356
|
+
|
|
357
|
+
In `k`, there are no primitive numbers or built-in integer literals.
|
|
358
|
+
Numerical identifiers such as `5` or `10` are nullary relations
|
|
359
|
+
(constants) mapping the unit `${}` to bit trees of type `${} -> $bits`.
|
|
360
|
+
Arithmetic relations operate on signed integers (`$int`), requiring
|
|
361
|
+
conversion via `5 int`.
|
|
299
362
|
|
|
300
|
-
|
|
363
|
+
Bit trees are defined algebraically:
|
|
301
364
|
|
|
302
365
|
```text
|
|
303
366
|
$ bits = < {} _, bits 0, bits 1 >;
|
|
@@ -318,17 +381,28 @@ $ bits = < {} _, bits 0, bits 1 >;
|
|
|
318
381
|
|
|
319
382
|
#### Eat `/`
|
|
320
383
|
|
|
321
|
-
- `$@bits / @bits` --- division, e.g., `0b1011 / 0b10` = `0b11`,
|
|
384
|
+
- `$@bits / @bits` --- division, e.g., `0b1011 / 0b10` = `0b11`,
|
|
385
|
+
`"abc" / "a"` = `"bc"`
|
|
322
386
|
|
|
323
387
|
#### Prepend `\`
|
|
324
388
|
|
|
325
|
-
- `$@bits \ @bits` --- multiplication, e.g., `0b11 \ 0b10` = `0b1011`,
|
|
389
|
+
- `$@bits \ @bits` --- multiplication, e.g., `0b11 \ 0b10` = `0b1011`,
|
|
390
|
+
`"bc" \ "a"` = `"abc"`
|
|
326
391
|
|
|
327
|
-
Empty `bits` can be checked by
|
|
392
|
+
Empty `bits` can be checked by:
|
|
328
393
|
|
|
329
394
|
```k
|
|
330
|
-
|
|
331
395
|
kind = $@bits
|
|
332
396
|
< {/ 0b0 \ 0b0 starts_with_0}, {/ 0b1 \ 0b1 starts_with_1}, {() empty} >
|
|
333
397
|
$< @bits starts_with_0, @bits starts_with_1, @bits empty >;
|
|
334
398
|
```
|
|
399
|
+
|
|
400
|
+
## Further Reading
|
|
401
|
+
|
|
402
|
+
- [DOCS/FILE_FORMATS.md](./FILE_FORMATS.md) — guide to
|
|
403
|
+
.k, .ko, .klib, and .kvm formats
|
|
404
|
+
- [DOCS/DICTIONARY.md](./DICTIONARY.md) — concept names and terminology
|
|
405
|
+
- [DOCS/TYPE_DERIVATION.md](./TYPE_DERIVATION.md) — type derivation
|
|
406
|
+
algorithm
|
|
407
|
+
- [DOCS/OBJECT_FILE_AND_PATTERN.md](./OBJECT_FILE_AND_PATTERN.md) —
|
|
408
|
+
object format and pattern encoding
|