@fraczak/k 7.0.1 → 7.1.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.
- package/CHANGELOG.md +78 -0
- package/DOCS/BIG_PICTURE.md +5 -5
- package/DOCS/FILE_FORMATS.md +241 -18
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +9 -9
- package/DOCS/PATTERNS.md +3 -3
- package/DOCS/POLYMORPHIC_IR.md +104 -0
- package/DOCS/PROFILING_AND_TRACING.md +60 -72
- package/DOCS/REPL.md +3 -3
- package/DOCS/book/03-types-as-finite-automata.md +4 -4
- package/DOCS/book/06-values-in-memory.md +9 -9
- package/DOCS/book/08-operational-semantics-and-execution.md +1 -1
- package/DOCS/book/09-compiler-architecture.md +2 -2
- package/DOCS/book/10-from-ast-to-intermediate-representation.md +2 -2
- package/DOCS/book/14-canonical-serialization.md +1 -1
- package/Examples/arithmetics.k +2 -2
- package/Examples/bnat.k +1 -1
- package/Examples/karatsuba-mult.k +2 -2
- package/JOURNAL.md +288 -0
- package/README.md +13 -10
- package/access-table.mjs +343 -0
- package/backend-api.mjs +18 -0
- package/backends/llvm/README.md +20 -21
- package/backends/llvm/bin/k-llvm-build.mjs +105 -32
- package/backends/llvm/bin/k-llvm-compile.mjs +63 -24
- package/backends/llvm/bin/k-llvm.mjs +292 -0
- package/backends/llvm/runtime/krt.c +41 -0
- package/backends/llvm/runtime/krt.h +2 -0
- package/backends/llvm/src/cli.mjs +95 -17
- package/backends/llvm/src/executable.mjs +132 -15
- package/backends/llvm/src/kvm2llvm.mjs +50 -23
- package/backends/llvm/src/llvm.mjs +133 -20
- package/backends/llvm/tests/integration.sh +11 -11
- package/backends/llvm/{bin → tests}/k-llvm-run.mjs +48 -22
- package/backends/llvm/tests/perf-support.mjs +25 -58
- package/backends/llvm/tests/test-llvm.mjs +25 -4
- package/backends/wasm/bin/k-wasm-compile.mjs +46 -20
- package/backends/wasm/bin/k-wasm-run.mjs +61 -20
- package/backends/wasm/bin/k-wasm.mjs +47 -13
- package/backends/wasm/src/cli.mjs +141 -19
- package/backends/wasm/src/wasm.mjs +132 -24
- package/backends/wasm/tests/test-wasm.mjs +5 -5
- package/browser/repl-browser.mjs +16 -5
- package/browser/vfs-data.mjs +5 -5
- package/codecs/k-parse.mjs +29 -8
- package/codecs/k-print.mjs +22 -6
- package/codecs/runtime/codec-sdk.mjs +8 -4
- package/codecs/show.mjs +20 -6
- package/core.k +8 -8
- package/harness/format.mjs +2 -2
- package/harness/registry.mjs +0 -2
- package/k.mjs +56 -16
- package/kir.mjs +200 -75
- package/kvm.mjs +49 -12
- package/objects/compile.mjs +37 -23
- package/objects/decompile.mjs +40 -10
- package/objects/extract-aliases.mjs +44 -14
- package/objects/inspect.mjs +19 -14
- package/objects/validate.mjs +18 -11
- package/package.json +10 -7
- package/pkir.mjs +772 -0
- package/repl.mjs +36 -18
- package/scripts/benchmark-idempotency.mjs +12 -8
- package/scripts/benchmark.mjs +5 -9
- package/scripts/build-repl-html.mjs +16 -4
- package/scripts/perf-ieee.mjs +253 -103
- package/scripts/perf-int.mjs +585 -297
- package/scripts/perf-multiplication.mjs +66 -25
- package/scripts/perf-poly.mjs +292 -164
- package/scripts/run-tests.mjs +3 -0
- package/tests/code-derivation/pattern-envelope.mjs +4 -4
- package/tests/test-access-table.mjs +213 -0
- package/tests/test-kvm-polymorphic.mjs +2 -2
- package/tests/test-pkir.mjs +530 -0
- package/tests/test-polymorphic-tdd.mjs +196 -0
- package/tests/test-repl-html.mjs +15 -2
- package/tests/test-repl.mjs +30 -1
- package/backends/arm64/README.md +0 -103
- package/backends/arm64/bin/k-arm64-compile.mjs +0 -93
- package/backends/arm64/bin/k-arm64-run.mjs +0 -58
- package/backends/arm64/bin/k-arm64.mjs +0 -88
- package/backends/arm64/scripts/run-tests.mjs +0 -57
- package/backends/arm64/src/arm64.mjs +0 -229
- package/backends/arm64/src/cli.mjs +0 -155
- package/backends/arm64/src/kvm2arm64.mjs +0 -906
- package/backends/arm64/src/runtime.c +0 -744
- package/backends/arm64/tests/integration.sh +0 -112
- package/backends/arm64/tests/test-arm64.mjs +0 -240
- package/backends/llvm/bin/k-llvm-jit.mjs +0 -160
- package/harness/adapters/arm64.mjs +0 -105
|
@@ -5,7 +5,6 @@ and function-level call profiling infrastructure for `k` backends.
|
|
|
5
5
|
|
|
6
6
|
The profiling framework allows fine-grained performance analysis of polymorphic `k`
|
|
7
7
|
programs across multiple execution targets:
|
|
8
|
-
- **Linux ARM64** (native standalone ELF executable via direct kVM assembly emission)
|
|
9
8
|
- **WebAssembly** (in-process Wasm module via single-pass kVM lowering)
|
|
10
9
|
- **LLVM** (native specialized executable via KIR-P lowering)
|
|
11
10
|
- **kVM Interpreter** (in-process TypeScript/JavaScript kVM evaluator)
|
|
@@ -15,17 +14,23 @@ programs across multiple execution targets:
|
|
|
15
14
|
|
|
16
15
|
## 1. Motivation: Apples-to-Apples Backend Comparison
|
|
17
16
|
|
|
18
|
-
When measuring end-to-end request latency across backends, wall-clock
|
|
19
|
-
dominated by factors outside the core relation algorithm:
|
|
20
|
-
- **Process IPC**: Out-of-process native executables (
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- **
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
17
|
+
When measuring end-to-end request latency across backends, wall-clock
|
|
18
|
+
time can be dominated by factors outside the core relation algorithm:
|
|
19
|
+
- **Process IPC**: Out-of-process native executables (LLVM)
|
|
20
|
+
communicate via stdin/stdout pipes, incurring OS context switches and
|
|
21
|
+
pipe buffer copies.
|
|
22
|
+
- **Wire Codec**: Decoding and validating the binary wire format
|
|
23
|
+
(`pattern + value`) and encoding the response.
|
|
24
|
+
- **In-Memory Representation**: WebAssembly converts incoming values into
|
|
25
|
+
a flat linear memory arena layout.
|
|
26
|
+
- **Pure Evaluation**: The actual relational instruction loop performing
|
|
27
|
+
the algorithm.
|
|
28
|
+
|
|
29
|
+
Without detailed accounting, native LLVM binaries communicating over
|
|
30
|
+
pipes can appear slower than in-process WebAssembly or the interpreter
|
|
31
|
+
simply because of IPC overhead. The tracing infrastructure breaks
|
|
32
|
+
request latency down into nanosecond-level phases so that pure
|
|
33
|
+
execution time can be measured and compared directly.
|
|
29
34
|
|
|
30
35
|
In addition, **per-function invocation profiling** verifies that every backend performs the
|
|
31
36
|
exact same number of relational evaluations and loop iterations for a given input.
|
|
@@ -56,37 +61,41 @@ Following `k`'s canonical content-addressed design:
|
|
|
56
61
|
|
|
57
62
|
When tracing is enabled, each request is instrumented to measure 7 discrete phases with nanosecond precision:
|
|
58
63
|
|
|
59
|
-
| Phase | Description |
|
|
60
|
-
| :--- | :--- | :---: | :---: | :---: |
|
|
61
|
-
| **1. IPC Read (Pipe In)** | Waiting for and reading input payload from stdin | Yes |
|
|
62
|
-
| **2. Wire Decode & Validate** | Decoding wire buffer and validating against pattern | Yes |
|
|
63
|
-
| **3. Flat Input Prep (Arena)** | Flattening decoded structures into linear arena memory |
|
|
64
|
-
| **4. Pure Evaluation** | Core relational execution loop | **Yes** | **Yes** | **Yes** |
|
|
65
|
-
| **5. Flat Output Prep (Arena)** | Serializing/reading in-memory representations |
|
|
66
|
-
| **6. Wire Encode** | Encoding result to canonical wire format | Yes |
|
|
67
|
-
| **7. IPC Write (Pipe Out)** | Writing output wire bytes to stdout pipe | Yes | Yes
|
|
64
|
+
| Phase | Description | LLVM | WebAssembly | kVM Interp |
|
|
65
|
+
| :--- | :--- | :---: | :---: | :---: |
|
|
66
|
+
| **1. IPC Read (Pipe In)** | Waiting for and reading input payload from stdin | Yes | N/A (in-process) | N/A (in-process) |
|
|
67
|
+
| **2. Wire Decode & Validate** | Decoding wire buffer and validating against pattern | Yes | N/A (in-process) | N/A (in-process) |
|
|
68
|
+
| **3. Flat Input Prep (Arena)** | Flattening decoded structures into linear arena memory | N/A | Yes | N/A |
|
|
69
|
+
| **4. Pure Evaluation** | Core relational execution loop | **Yes** | **Yes** | **Yes** |
|
|
70
|
+
| **5. Flat Output Prep (Arena)** | Serializing/reading in-memory representations | N/A | Yes | N/A |
|
|
71
|
+
| **6. Wire Encode** | Encoding result to canonical wire format | Yes | N/A (in-process) | N/A (in-process) |
|
|
72
|
+
| **7. IPC Write (Pipe Out)** | Writing output wire bytes to stdout pipe | Yes | Yes (driver) | N/A |
|
|
68
73
|
|
|
69
74
|
### Phase Timing Output Example
|
|
70
75
|
|
|
71
76
|
```text
|
|
72
77
|
--- Operation: reverse (len 40) ---
|
|
73
|
-
Phase |
|
|
74
|
-
|
|
75
|
-
1. IPC Read (Pipe In) |
|
|
76
|
-
2. Wire Decode & Validate |
|
|
77
|
-
3. Flat Input Prep (Arena) |
|
|
78
|
-
4. Pure Evaluation | 0.
|
|
79
|
-
5. Flat Output Prep (Arena) |
|
|
80
|
-
6. Wire Encode |
|
|
81
|
-
7. IPC Write (Pipe Out) | 11.
|
|
82
|
-
|
|
83
|
-
Total Request Time |
|
|
78
|
+
Phase | LLVM | WebAssembly | kVM Interp
|
|
79
|
+
-------------------------+---------------+---------------+---------------
|
|
80
|
+
1. IPC Read (Pipe In) | 161.42 µs | - | -
|
|
81
|
+
2. Wire Decode & Validate | 1.58 µs | - | -
|
|
82
|
+
3. Flat Input Prep (Arena) | - | 80.88 µs | -
|
|
83
|
+
4. Pure Evaluation | 0.54 µs | 1.71 µs | 26.04 µs
|
|
84
|
+
5. Flat Output Prep (Arena) | - | 76.71 µs | -
|
|
85
|
+
6. Wire Encode | 4.88 µs | - | -
|
|
86
|
+
7. IPC Write (Pipe Out) | 11.08 µs | 0.62 µs | -
|
|
87
|
+
-------------------------+---------------+---------------+---------------
|
|
88
|
+
Total Request Time | 179.50 µs | 159.92 µs | 26.04 µs
|
|
84
89
|
```
|
|
85
90
|
|
|
86
91
|
**Key Takeaways**:
|
|
87
|
-
- **Pure evaluation** in
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
- **Pure evaluation** in LLVM native code (`0.54 µs`) is ~3.2× faster
|
|
93
|
+
than WebAssembly (`1.71 µs`) and ~48× faster than the interpreter
|
|
94
|
+
(`26.04 µs`).
|
|
95
|
+
- **End-to-end request time** for native binaries is dominated by pipe
|
|
96
|
+
IPC read (`~160 µs`).
|
|
97
|
+
- **WebAssembly overhead** is concentrated in flat arena conversion
|
|
98
|
+
(`~80 µs` in, `~76 µs` out).
|
|
90
99
|
|
|
91
100
|
---
|
|
92
101
|
|
|
@@ -100,22 +109,20 @@ every backend executes the exact same call path.
|
|
|
100
109
|
|
|
101
110
|
```text
|
|
102
111
|
Function Call Profile: reverse
|
|
103
|
-
Function Name |
|
|
104
|
-
|
|
105
|
-
reverse |
|
|
106
|
-
_reverse |
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
-------------------------+-------------------+-------------------+------------------
|
|
114
|
-
Total Calls | 163 | 163 | 163
|
|
112
|
+
Function Name | WebAssembly Calls | kVM Interp Calls
|
|
113
|
+
-------------------------+-------------------+------------------
|
|
114
|
+
reverse | 1 | 1
|
|
115
|
+
_reverse | 41 | 41
|
|
116
|
+
car | 40 | 40
|
|
117
|
+
cdr | 40 | 40
|
|
118
|
+
cons | 40 | 40
|
|
119
|
+
nil | 1 | 1
|
|
120
|
+
-------------------------+-------------------+------------------
|
|
121
|
+
Total Calls | 163 | 163
|
|
115
122
|
```
|
|
116
123
|
|
|
117
|
-
*(Note:
|
|
118
|
-
|
|
124
|
+
*(Note: Both backends arrive at the exact same total call count:
|
|
125
|
+
163 calls for reversing a list of length 40).*
|
|
119
126
|
|
|
120
127
|
---
|
|
121
128
|
|
|
@@ -143,9 +150,7 @@ node scripts/perf-poly.mjs --trace
|
|
|
143
150
|
| `TRACE_SAMPLES` | `5` | Repetitions sampled and averaged for phase timings. |
|
|
144
151
|
| `TRACE` | `0` | Set to `1` (or pass `--trace`) to enable phase breakdown. |
|
|
145
152
|
| `PROFILE` | `1` (with trace) | Set to `0` to disable function call counters. |
|
|
146
|
-
| `ARM64_OPT` | `-O2` | Optimization level for the native ARM64 runtime (`-O0`, `-O1`, `-O2`, `-O3`). |
|
|
147
153
|
| `WASM_RESET` | `1` | Reset the WebAssembly linear memory arena between calls (`1` or `0`). |
|
|
148
|
-
| `ARM64_ONLY` | `0` | Run only the Linux ARM64 native target. |
|
|
149
154
|
| `WASM_ONLY` | `0` | Run only the WebAssembly target. |
|
|
150
155
|
| `LLVM_ONLY` | `0` | Run only the LLVM target. |
|
|
151
156
|
| `BACKENDS_ONLY` | `0` | Skip the native JS baseline lanes. |
|
|
@@ -156,34 +161,17 @@ node scripts/perf-poly.mjs --trace
|
|
|
156
161
|
# Fast smoke check with list length 10 and 1 iteration:
|
|
157
162
|
ITERATIONS=1 LIST_LENGTH=10 npm run perf:poly:trace
|
|
158
163
|
|
|
159
|
-
#
|
|
160
|
-
LIST_LENGTH=100
|
|
164
|
+
# Trace WebAssembly on large lists (100 elements):
|
|
165
|
+
LIST_LENGTH=100 WASM_ONLY=1 npm run perf:poly:trace
|
|
161
166
|
|
|
162
|
-
# Isolate
|
|
163
|
-
|
|
167
|
+
# Isolate LLVM native execution:
|
|
168
|
+
LLVM_ONLY=1 npm run perf:poly:trace
|
|
164
169
|
```
|
|
165
170
|
|
|
166
171
|
---
|
|
167
172
|
|
|
168
173
|
## 6. Implementation Architecture
|
|
169
174
|
|
|
170
|
-
### Linux ARM64 Backend
|
|
171
|
-
- **Code Emission** ([`backends/arm64/src/kvm2arm64.mjs`](../backends/arm64/src/kvm2arm64.mjs)): When `options.profile` is active, each function emits counter increment instructions in its entry sequence:
|
|
172
|
-
```asm
|
|
173
|
-
adrp x9, k_prof_<func>
|
|
174
|
-
add x9, x9, :lo12:k_prof_<func>
|
|
175
|
-
ldr x10, [x9]
|
|
176
|
-
add x10, x10, #1
|
|
177
|
-
str x10, [x9]
|
|
178
|
-
```
|
|
179
|
-
Counters are emitted into a dedicated `.data` section, and an exported metadata table `k_profile_entries[]` is generated.
|
|
180
|
-
- **Runtime Reporting** ([`backends/arm64/src/runtime.c`](../backends/arm64/src/runtime.c)):
|
|
181
|
-
- Nanosecond phase timestamps are sampled via `clock_gettime(CLOCK_MONOTONIC, ...)` and emitted over stderr formatted as:
|
|
182
|
-
```text
|
|
183
|
-
K_TRACE_PHASES backend=arm64 ipc_read_ns=... decode_ns=... flat_in_ns=... eval_ns=... flat_out_ns=... encode_ns=... ipc_write_ns=... total_ns=...
|
|
184
|
-
```
|
|
185
|
-
- `dump_profile_counts()` emits nonzero function call counts between `K_PROFILE_BEGIN` and `K_PROFILE_END` tags.
|
|
186
|
-
|
|
187
175
|
### WebAssembly Backend
|
|
188
176
|
- **Code Emission** ([`backends/wasm/src/kvm2wasm.mjs`](../backends/wasm/src/kvm2wasm.mjs)): Emits mutable 64-bit Wasm globals:
|
|
189
177
|
```wat
|
package/DOCS/REPL.md
CHANGED
|
@@ -58,7 +58,7 @@ Examples:
|
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
```k
|
|
61
|
-
> bool = ?<{} true, {} false>;
|
|
61
|
+
> bool? = ?<{} true, {} false>;
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
```k
|
|
@@ -147,7 +147,7 @@ aliases, and metadata into the session. Aliases are recovered from
|
|
|
147
147
|
|
|
148
148
|
In `k`, there are no primitive numbers or built-in numerical literals.
|
|
149
149
|
Values such as integers are represented as algebraic bit trees (e.g.
|
|
150
|
-
`bits = ?< {} _, B 0, B 1 > = B;`).
|
|
150
|
+
`bits? = ?< {} _, B 0, B 1 > = B;`).
|
|
151
151
|
|
|
152
152
|
A codec translates between external text and enveloped *k* values:
|
|
153
153
|
- `parse(text)`: parses an external string into an enveloped *k* value.
|
|
@@ -309,7 +309,7 @@ Evaluated values print in k syntax together with the inferred envelope:
|
|
|
309
309
|
## Example Session
|
|
310
310
|
|
|
311
311
|
```text
|
|
312
|
-
> nat = ?< {} 0, N +1 > = N;
|
|
312
|
+
> nat? = ?< {} 0, N +1 > = N;
|
|
313
313
|
> inc = | +1;
|
|
314
314
|
> {} | 0
|
|
315
315
|
{}|0 ?<{} 0, ...>
|
|
@@ -7,8 +7,8 @@ A schema in `k` describes a set of finite labeled trees, which can be recognized
|
|
|
7
7
|
For example, the recursive schema of a `list`:
|
|
8
8
|
|
|
9
9
|
```k-lang
|
|
10
|
-
bool = ?< {} true, {} false >;
|
|
11
|
-
list = ?< {} nil, { < {} true, {} false > head, L tail } cons > = L;
|
|
10
|
+
bool? = ?< {} true, {} false >;
|
|
11
|
+
list? = ?< {} nil, { < {} true, {} false > head, L tail } cons > = L;
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
corresponds to the following 4-rule grammar:
|
|
@@ -44,7 +44,7 @@ Each schema structure introduces one or more *states* in the automaton. A union
|
|
|
44
44
|
For example, consider the `bool` schema:
|
|
45
45
|
|
|
46
46
|
```k-lang
|
|
47
|
-
bool = ?< {} true, {} false >;
|
|
47
|
+
bool? = ?< {} true, {} false >;
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
This schema translates to an automaton with two states:
|
|
@@ -88,7 +88,7 @@ This traversal produces a unique and deterministic numbering for any finite dire
|
|
|
88
88
|
For a schema representing binary natural numbers:
|
|
89
89
|
|
|
90
90
|
```k-lang
|
|
91
|
-
bnat = ?< Bnat 0, Bnat 1, {} _ > = Bnat;
|
|
91
|
+
bnat? = ?< Bnat 0, Bnat 1, {} _ > = Bnat;
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
the canonical automaton form is:
|
|
@@ -111,11 +111,11 @@ Each node in the value tree is encoded based on its automaton state:
|
|
|
111
111
|
|
|
112
112
|
#### **Example: Natural numbers**
|
|
113
113
|
|
|
114
|
-
For type `bnat
|
|
114
|
+
For type `bnat?`, intuitively binary natural numbers defined by `bnat? = ?< Bnat 0, Bnat 1, {} _ > = Bnat;`, we get
|
|
115
115
|
|
|
116
116
|
```text
|
|
117
|
-
> :rel bnat
|
|
118
|
-
bnat = ?< Bnat 0, Bnat 1, {} _ > = Bnat; -- @...
|
|
117
|
+
> :rel bnat?
|
|
118
|
+
bnat? = ?< Bnat 0, Bnat 1, {} _ > = Bnat; -- @...
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
The corresponding Context-Free grammar is:
|
|
@@ -191,7 +191,7 @@ Subtrees that happen to produce the same local payload bits under different type
|
|
|
191
191
|
Consider a binary tree with repeated leaf patterns:
|
|
192
192
|
|
|
193
193
|
```k-lang
|
|
194
|
-
tree = ?< { T left, T right } branch, int leaf > = T;
|
|
194
|
+
tree? = ?< { T left, T right } branch, int? leaf > = T;
|
|
195
195
|
```
|
|
196
196
|
|
|
197
197
|
Value: A tree corresponding to the structure:
|
|
@@ -293,8 +293,8 @@ These are encoder-side construction choices for reaching the same canonical resu
|
|
|
293
293
|
Consider a list of similar records:
|
|
294
294
|
|
|
295
295
|
```k-lang
|
|
296
|
-
record = ?{ string name, int age, string department };
|
|
297
|
-
company = ?< { record head, C tail } cons, {} nil > = C;
|
|
296
|
+
record? = ?{ string? name, int? age, string? department };
|
|
297
|
+
company? = ?< { record? head, C tail } cons, {} nil > = C;
|
|
298
298
|
```
|
|
299
299
|
|
|
300
300
|
Value representing 1000 employees where 80% work in "Engineering":
|
|
@@ -712,9 +712,9 @@ const Arena = struct {
|
|
|
712
712
|
Consider processing a large JSON-like structure where we only need one field:
|
|
713
713
|
|
|
714
714
|
```k-lang
|
|
715
|
-
metadata = ?{ timestamp created, string author };
|
|
716
|
-
list = ?< { nat value, L next } cons, {} nil > = L;
|
|
717
|
-
record = ?{ string name, list data, metadata meta };
|
|
715
|
+
metadata? = ?{ timestamp created, string? author };
|
|
716
|
+
list? = ?< { nat? value, L next } cons, {} nil > = L;
|
|
717
|
+
record? = ?{ string? name, list? data, metadata? meta };
|
|
718
718
|
```
|
|
719
719
|
|
|
720
720
|
For the input program `\x.x.name` (extract name field):
|
|
@@ -73,8 +73,8 @@ These tables ensure that generated code can find fields and variants by number r
|
|
|
73
73
|
Consider a simple k program:
|
|
74
74
|
|
|
75
75
|
```k-lang
|
|
76
|
-
bool = ?< {} true, {} false >;
|
|
77
|
-
neg = bool < /true | false, /false | true > bool
|
|
76
|
+
bool? = ?< {} true, {} false >;
|
|
77
|
+
neg = bool? < /true | false, /false | true > bool?;
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
1. **Parsing:**
|
|
@@ -42,7 +42,7 @@ Each function in the program becomes a small list or tree of such IR instruction
|
|
|
42
42
|
Source program:
|
|
43
43
|
|
|
44
44
|
```k-lang
|
|
45
|
-
bool = ?< {} true, {} false >;
|
|
45
|
+
bool? = ?< {} true, {} false >;
|
|
46
46
|
neg = ?< {} true, {} false > < /true | false, /false | true >;
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -50,7 +50,7 @@ The IR for `neg` can be written informally as:
|
|
|
50
50
|
|
|
51
51
|
```text
|
|
52
52
|
neg:
|
|
53
|
-
CHECK_FILTER bool
|
|
53
|
+
CHECK_FILTER bool?
|
|
54
54
|
UNION [
|
|
55
55
|
SEQ [ PROJECT true, CONST false ],
|
|
56
56
|
SEQ [ PROJECT false, CONST true ]
|
|
@@ -68,7 +68,7 @@ This rule allows the decoder to know, from the type alone, how many bits to read
|
|
|
68
68
|
For the type
|
|
69
69
|
|
|
70
70
|
```k-lang
|
|
71
|
-
bnat = ?< Bnat 0, Bnat 1, {} _ > = Bnat;
|
|
71
|
+
bnat? = ?< Bnat 0, Bnat 1, {} _ > = Bnat;
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
the canonical form has three transitions from state C0.
|
package/Examples/arithmetics.k
CHANGED
|
@@ -3,7 +3,7 @@ swap_yes_no = < /yes |no, /no |yes >;
|
|
|
3
3
|
yes = {}|yes;
|
|
4
4
|
no = yes swap_yes_no;
|
|
5
5
|
|
|
6
|
-
bits = ?< {} _, bits 0, bits 1 > = bits
|
|
6
|
+
bits? = ?< {} _, bits? 0, bits? 1 > = bits?;
|
|
7
7
|
|
|
8
8
|
0b = {} | _;
|
|
9
9
|
-- |1 = | 1;
|
|
@@ -64,7 +64,7 @@ GT = {inOrder /no if, () then} . then;
|
|
|
64
64
|
EQ = {inOrder /yes if, {.x y, .y x} inOrder /yes and, () then} .then;
|
|
65
65
|
|
|
66
66
|
--------------------------------------
|
|
67
|
-
int = ?< <bits 0, bits 1, {} _>=bits "+", bits "-" >;
|
|
67
|
+
int? = ?< <bits 0, bits 1, {} _>=bits "+", bits "-" >;
|
|
68
68
|
|
|
69
69
|
remove_leading_zeros = <
|
|
70
70
|
/0 remove_leading_zeros,
|
package/Examples/bnat.k
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
yes = {} | yes;
|
|
6
6
|
no = {} | no;
|
|
7
7
|
|
|
8
|
-
bits = ?< {} _, bits 0, bits 1 > = bits
|
|
8
|
+
bits? = ?< {} _, bits? 0, bits? 1 > = bits?;
|
|
9
9
|
0b = {} | _;
|
|
10
10
|
0 = 0b |0;
|
|
11
11
|
1 = 0b |1;
|
|
12
12
|
|
|
13
|
-
unat = ?< {} _, unat 1 > = unat
|
|
13
|
+
unat? = ?< {} _, unat? 1 > = unat?;
|
|
14
14
|
0u = {} | _;
|
|
15
15
|
|
|
16
16
|
empty = < /_ yes, no >;
|