@fraczak/k 6.1.3 → 6.2.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/AGENTS.md +4 -4
- package/CLAUDE.md +1 -1
- package/DOCS/KIR_SPECIALIZATION_DESIGN.md +11 -2
- package/DOCS/KVM_EXECUTION_MODEL.md +413 -0
- package/DOCS/OBJECT_FILE_AND_PATTERN.md +6 -0
- package/DOCS/REPL.md +22 -17
- package/{NAT.k~ → Examples/arithmetics.k} +1 -1
- package/Examples/bnat.k +291 -0
- package/Examples/byte.k +67 -0
- package/Examples/code.k +44 -0
- package/Examples/esc.k +9 -0
- package/Examples/ieee.k +15766 -0
- package/Examples/list.k +7 -0
- package/Examples/nat.k +12 -0
- package/Examples/vhdl_to_k.k +50 -0
- package/README.md +14 -5
- package/backend-api.mjs +12 -0
- package/codecs/runtime/codec.mjs +1 -0
- package/export.mjs +10 -0
- package/k-vscode/README.md +10 -1
- package/k-vscode/extension.js +273 -0
- package/k-vscode/package.json +22 -0
- package/k-vscode/syntaxes/k.tmLanguage.json +493 -137
- package/k-vscode/test/background-ranges.test.js +50 -0
- package/k-vscode/themes/k-contrast-color-theme.json +104 -0
- package/kvm.mjs +523 -0
- package/package.json +4 -3
- package/repl.mjs +43 -2
- package/run.mjs +1 -1
- package/scripts/run-tests.mjs +55 -0
- package/tests/README.md +35 -0
- package/{Code-derivation-tests → tests/code-derivation}/codec-witness-pattern.mjs +4 -4
- package/{Code-derivation-tests → tests/code-derivation}/convergence-strategy.mjs +1 -1
- package/{Code-derivation-tests → tests/code-derivation}/dot.mjs +1 -1
- package/{Code-derivation-tests → tests/code-derivation}/filter-syntax.mjs +1 -1
- package/{Code-derivation-tests → tests/code-derivation}/index.mjs +1 -1
- package/{Code-derivation-tests → tests/code-derivation}/pattern-envelope.mjs +5 -5
- package/{Code-derivation-tests → tests/code-derivation}/product.mjs +1 -1
- package/{tests.sh → tests/integration.sh} +11 -6
- package/{test-fingerprint.mjs → tests/test-fingerprint.mjs} +3 -3
- package/{test-hash-fuzz.mjs → tests/test-hash-fuzz.mjs} +1 -1
- package/{test-hash-normalization.mjs → tests/test-hash-normalization.mjs} +2 -2
- package/{test-ieee-arithmetic.mjs → tests/test-ieee-arithmetic.mjs} +14 -27
- package/{test-k-object.mjs → tests/test-k-object.mjs} +8 -8
- package/tests/test-kvm.mjs +163 -0
- package/{test-repl.mjs → tests/test-repl.mjs} +22 -4
- package/{test.mjs → tests/test.mjs} +1 -1
- package/.codex +0 -0
- package/DOCS/a.html +0 -398
- package/DOCS/dependency-graph.html +0 -140
- package/DOCS/dependency-graph.md +0 -144
- package/UU/ta.k +0 -1
- package/UU/ta.k~ +0 -0
- package/UU/tb.k +0 -0
- package/UU/tc.k +0 -0
- package/a.k +0 -138
- package/a.klib +0 -1
- package/codecs/BINARY_FORMAT.html +0 -471
- package/codecs/POLYMORPHIC_BINARY_FORMAT.html +0 -355
- package/core.json +0 -1
- package/core.klib +0 -1
- package/core.klib~ +0 -0
- package/ieee.klib +0 -1
- package/k-vscode/package-lock.json +0 -4176
- package/kkk.k +0 -197
- package/kkk.klib +0 -0
- package/kkk.klib~ +0 -0
- package/nak.klib +0 -1
- package/nak2.klib +0 -1
- package/nat.k +0 -10
- package/nat2.k +0 -9
- package/p.json +0 -5475
- package/type_registry/registry.mjs~ +0 -105
- package/type_registry/typeParser.jison~ +0 -132
- /package/{Code-derivation-tests → tests/code-derivation}/blowup.mjs +0 -0
- /package/{Code-derivation-tests → tests/code-derivation}/bnat.mjs +0 -0
- /package/{Code-derivation-tests → tests/code-derivation}/loop.mjs +0 -0
- /package/{Code-derivation-tests → tests/code-derivation}/nat.mjs +0 -0
- /package/{Code-derivation-tests → tests/code-derivation}/not-not.mjs +0 -0
- /package/{Code-derivation-tests → tests/code-derivation}/rlz.mjs +0 -0
package/Examples/list.k
ADDED
package/Examples/nat.k
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
$ nat = < {} 0, nat +1 >;
|
|
2
|
+
0 = {} | 0 ;
|
|
3
|
+
0? = $ nat { / 0 if, () then} .then;
|
|
4
|
+
succ = | +1 $ nat ;
|
|
5
|
+
pred = $nat / +1 ;
|
|
6
|
+
add = ?{ $nat x, ... } = X <{.x pred x, .y succ y} ?X add, .y> ;
|
|
7
|
+
mult = <
|
|
8
|
+
{{.x pred x, .y y} mult x, .y y} add,
|
|
9
|
+
0
|
|
10
|
+
> ;
|
|
11
|
+
|
|
12
|
+
succ {()x,()y} add
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
-- VHDL to K Translation Patterns
|
|
2
|
+
|
|
3
|
+
-- VHDL: signal a : std_logic;
|
|
4
|
+
-- K: $ bit = <{} 0, {} 1>;
|
|
5
|
+
|
|
6
|
+
-- VHDL: signal bus : std_logic_vector(7 downto 0);
|
|
7
|
+
-- K: $ byte = {bit 0, bit 1, bit 2, bit 3, bit 4, bit 5, bit 6, bit 7};
|
|
8
|
+
|
|
9
|
+
-- VHDL: entity adder is port(a,b: in std_logic; sum: out std_logic); end;
|
|
10
|
+
-- K: adder = ${bit a, bit b} {.a a_out, .b b_out, xor_gate sum_out};
|
|
11
|
+
|
|
12
|
+
-- VHDL: process(clk) begin if rising_edge(clk) then q <= d; end if; end;
|
|
13
|
+
-- K: dff = $bit .; -- Identity (register holds value)
|
|
14
|
+
|
|
15
|
+
-- VHDL: y <= a and b;
|
|
16
|
+
-- K: and_gate = ${bit a, bit b} <{.a.1 1, .b.1 1, 1}, 0>;
|
|
17
|
+
|
|
18
|
+
-- VHDL: y <= a or b;
|
|
19
|
+
-- K: or_gate = ${bit a, bit b} <{.a.0 0, .b.0 0, 0}, 1>;
|
|
20
|
+
|
|
21
|
+
-- VHDL: y <= not a;
|
|
22
|
+
-- K: not_gate = $bit <{.0 0, 1}, {.1 1, 0}>;
|
|
23
|
+
|
|
24
|
+
-- VHDL: with sel select y <= a when "00", b when "01", c when others;
|
|
25
|
+
-- K: mux = ${bit sel0, bit sel1, bit a, bit b, bit c} <
|
|
26
|
+
-- {.sel0.0 0, .sel1.0 0, .a},
|
|
27
|
+
-- {.sel0.1 1, .sel1.0 0, .b},
|
|
28
|
+
-- .c>;
|
|
29
|
+
|
|
30
|
+
-- VHDL: architecture of 4-bit adder
|
|
31
|
+
four_bit_adder = ${
|
|
32
|
+
{bit 0, bit 1, bit 2, bit 3} a,
|
|
33
|
+
{bit 0, bit 1, bit 2, bit 3} b
|
|
34
|
+
} {
|
|
35
|
+
{.a.0 a0, .b.0 b0} full_adder fa0,
|
|
36
|
+
{.a.1 a1, .b.1 b1, .fa0.carry c_in} full_adder fa1,
|
|
37
|
+
{.a.2 a2, .b.2 b2, .fa1.carry c_in} full_adder fa2,
|
|
38
|
+
{.a.3 a3, .b.3 b3, .fa2.carry c_in} full_adder fa3,
|
|
39
|
+
{.fa0.sum 0, .fa1.sum 1, .fa2.sum 2, .fa3.sum 3} sum,
|
|
40
|
+
.fa3.carry overflow
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
-- VHDL: Full adder component
|
|
44
|
+
full_adder = ${bit a, bit b, bit c_in} {
|
|
45
|
+
{.a a_val, .b b_val} xor_gate ab_xor,
|
|
46
|
+
{.ab_xor xor_val, .c_in c_val} xor_gate sum,
|
|
47
|
+
{.a a_val, .b b_val} and_gate ab_and,
|
|
48
|
+
{.ab_xor xor_val, .c_in c_val} and_gate xor_cin_and,
|
|
49
|
+
{.ab_and and1, .xor_cin_and and2} or_gate carry
|
|
50
|
+
};
|
package/README.md
CHANGED
|
@@ -55,8 +55,8 @@ from `x` to `y` and recurses. When that no longer applies, it returns `y`.
|
|
|
55
55
|
In the REPL:
|
|
56
56
|
|
|
57
57
|
```text
|
|
58
|
-
> {
|
|
59
|
-
{}|0|+1|+1|+1 ?<X0 +1, {} 0
|
|
58
|
+
> { 0 inc inc x, 0 inc y } add
|
|
59
|
+
{}|0|+1|+1|+1 ?<X0 +1, {} 0>=X0
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
That evaluates `2 + 1` to `3`: a value starts at `0`, and each `+1` tag adds
|
|
@@ -195,6 +195,14 @@ Installed binary names are `k-` plus the source basename without `.mjs`, except
|
|
|
195
195
|
for `k.mjs` itself. Source names that already include `k-`, such as
|
|
196
196
|
`codecs/k-parse.mjs`, keep that name.
|
|
197
197
|
|
|
198
|
+
## WebAssembly Backend
|
|
199
|
+
|
|
200
|
+
The experimental WebAssembly backend lives in the separate
|
|
201
|
+
[`fraczak/k-wasm`](https://github.com/fraczak/k-wasm) repository. Keeping the
|
|
202
|
+
backend separate avoids adding its WABT dependency to the core runtime. External
|
|
203
|
+
backends integrate with the compiler and binary codecs through
|
|
204
|
+
[`backend-api.mjs`](backend-api.mjs).
|
|
205
|
+
|
|
198
206
|
## Node.js API
|
|
199
207
|
|
|
200
208
|
```js
|
|
@@ -277,13 +285,14 @@ compose with `.result` when only the floating-point value is needed.
|
|
|
277
285
|
|
|
278
286
|
```bash
|
|
279
287
|
npm run prepare # regenerate parsers from .jison grammars
|
|
280
|
-
npm test # run the full suite
|
|
288
|
+
npm test # run the fail-fast full suite with per-test timings
|
|
281
289
|
```
|
|
282
290
|
|
|
283
|
-
The test
|
|
291
|
+
The test runner prints each test before execution and reports its elapsed time
|
|
292
|
+
afterward. It stops immediately when a test fails. The suite covers:
|
|
284
293
|
|
|
285
294
|
- core runtime and parser behavior
|
|
286
|
-
- type derivation cases in `
|
|
295
|
+
- type derivation cases in `tests/code-derivation/`
|
|
287
296
|
- hash/fingerprint stability
|
|
288
297
|
- object file round-trips
|
|
289
298
|
- REPL scripted interaction
|
package/backend-api.mjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { annotate } from "./index.mjs";
|
|
2
|
+
export { lowerToKVM, executeKVM } from "./kvm.mjs";
|
|
3
|
+
export { decodeWire, encodeToWire } from "./codecs/runtime/prefix-codec.mjs";
|
|
4
|
+
export { exportPatternGraph, NODE_KIND } from "./codecs/runtime/codec.mjs";
|
|
5
|
+
export { patternToPropertyList, propertyListToPattern } from "./codecs/runtime/pattern-json.mjs";
|
|
6
|
+
export { Product, Variant, fromObject } from "./Value.mjs";
|
|
7
|
+
export { decodeObject, loadLibrary } from "./object.mjs";
|
|
8
|
+
export { createState, evaluateInput } from "./repl.mjs";
|
|
9
|
+
export { parse as parseFloat64, print as printFloat64 } from "./codecs/ieee.mjs";
|
|
10
|
+
export { valueForCode } from "./repl-codecs.mjs";
|
|
11
|
+
export { default as codes } from "./codes.mjs";
|
|
12
|
+
export { default as run, run_converged } from "./run.mjs";
|
package/codecs/runtime/codec.mjs
CHANGED
|
@@ -614,6 +614,7 @@ function refinePatternForValue(pattern, value) {
|
|
|
614
614
|
}
|
|
615
615
|
|
|
616
616
|
if (baseNode.kind === NODE_KIND.CLOSED_PRODUCT || baseNode.kind === NODE_KIND.OPEN_PRODUCT) {
|
|
617
|
+
result.kind = NODE_KIND.CLOSED_PRODUCT;
|
|
617
618
|
const values = occurrences.get(patternNodeId) || [];
|
|
618
619
|
const explicit = new Map(baseNode.edges.map((edge) => [edge.label, edge.target]));
|
|
619
620
|
let labels = [...explicit.keys()].sort();
|
package/export.mjs
CHANGED
|
@@ -113,6 +113,16 @@ function theID(alias, rel, scc, name) {
|
|
|
113
113
|
export function assignCanonicalNames(scc, rels, relAlias) {
|
|
114
114
|
const newAlias = scc.reduce( (newAlias,relName) => {
|
|
115
115
|
const relDef = rels[relName];
|
|
116
|
+
// Rehashing an imported recursive relation would create a wrapper around its canonical hash.
|
|
117
|
+
if (
|
|
118
|
+
relDef.def.op == "ref" &&
|
|
119
|
+
relDef.def.ref.startsWith("@") &&
|
|
120
|
+
rels[relDef.def.ref]?._library
|
|
121
|
+
) {
|
|
122
|
+
rels[relName] = rels[relDef.def.ref];
|
|
123
|
+
newAlias[relName] = relDef.def.ref;
|
|
124
|
+
return newAlias;
|
|
125
|
+
}
|
|
116
126
|
if (relDef.def.op == "ref" && rels[relDef.def.ref] != undefined) {
|
|
117
127
|
// inlining if direct alias to a non built-in relation
|
|
118
128
|
// relDef.def = rels[relDef.def.ref]; // simplifyRel(rels[relDef.def.ref],rels);
|
package/k-vscode/README.md
CHANGED
|
@@ -16,6 +16,13 @@ unions).
|
|
|
16
16
|
- Canonical content-addressed references: `@base58hash`
|
|
17
17
|
- Quoted label strings: `"label"`, `'label'` (with escape sequences)
|
|
18
18
|
- The `...` any/open pattern marker
|
|
19
|
+
- **Code-definition backgrounds** applied uniformly from the opening `$` through
|
|
20
|
+
the terminating `;`
|
|
21
|
+
- **Nested expression backgrounds** for filters and `$` code expressions inside
|
|
22
|
+
relations, with code-expression backgrounds layered over filter backgrounds
|
|
23
|
+
- **k Contrast color theme** with:
|
|
24
|
+
- Separate foreground colors for type names, relation identifiers, labels, tags,
|
|
25
|
+
filter variables, canonical type names, and canonical relation names
|
|
19
26
|
- **Snippets** for every common pattern (trigger via `Tab` after prefix):
|
|
20
27
|
|
|
21
28
|
| Prefix | Inserts |
|
|
@@ -48,13 +55,15 @@ unions).
|
|
|
48
55
|
|
|
49
56
|
1. Open the `k-vscode/` folder in VS Code.
|
|
50
57
|
2. Press **F5** — this opens an Extension Development Host with the extension loaded.
|
|
58
|
+
3. Expression backgrounds activate automatically. Run **Preferences: Color Theme**
|
|
59
|
+
and select **k Contrast** to use the bundled foreground token palette.
|
|
51
60
|
|
|
52
61
|
### Build and install a VSIX
|
|
53
62
|
|
|
54
63
|
```bash
|
|
55
64
|
cd k-vscode
|
|
56
65
|
npm install
|
|
57
|
-
npx vsce package
|
|
66
|
+
npx vsce package --no-dependencies # produces k-language-0.2.0.vsix
|
|
58
67
|
```
|
|
59
68
|
|
|
60
69
|
Then in VS Code: **Extensions → ⋯ → Install from VSIX…** and select the generated file.
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
const vscode = require("vscode");
|
|
2
|
+
|
|
3
|
+
const NAME_START = /[a-zA-Z0-9_+\-]/;
|
|
4
|
+
const NAME_PART = /[a-zA-Z0-9_?!+\-]/;
|
|
5
|
+
const OPEN_TO_CLOSE = new Map([
|
|
6
|
+
["{", "}"],
|
|
7
|
+
["<", ">"],
|
|
8
|
+
["(", ")"]
|
|
9
|
+
]);
|
|
10
|
+
const CLOSERS = new Set(OPEN_TO_CLOSE.values());
|
|
11
|
+
|
|
12
|
+
function lex(text) {
|
|
13
|
+
const tokens = [];
|
|
14
|
+
let index = 0;
|
|
15
|
+
|
|
16
|
+
while (index < text.length) {
|
|
17
|
+
const char = text[index];
|
|
18
|
+
const next = text[index + 1];
|
|
19
|
+
|
|
20
|
+
if (/\s/.test(char)) {
|
|
21
|
+
index++;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (char === "/" && next === "*") {
|
|
26
|
+
const end = text.indexOf("*/", index + 2);
|
|
27
|
+
index = end === -1 ? text.length : end + 2;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (
|
|
32
|
+
(char === "/" && next === "/") ||
|
|
33
|
+
(char === "-" && next === "-") ||
|
|
34
|
+
(char === "\\" && next === "\\") ||
|
|
35
|
+
char === "#" ||
|
|
36
|
+
char === "%"
|
|
37
|
+
) {
|
|
38
|
+
const end = text.indexOf("\n", index + 1);
|
|
39
|
+
index = end === -1 ? text.length : end + 1;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (char === "\"" || char === "'") {
|
|
44
|
+
const start = index++;
|
|
45
|
+
while (index < text.length) {
|
|
46
|
+
const current = text[index++];
|
|
47
|
+
if (current === "\\") {
|
|
48
|
+
index++;
|
|
49
|
+
} else if (current === char) {
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
tokens.push({ value: text.slice(start, index), start, end: index });
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (NAME_START.test(char)) {
|
|
58
|
+
const start = index++;
|
|
59
|
+
while (index < text.length && NAME_PART.test(text[index])) index++;
|
|
60
|
+
tokens.push({ value: text.slice(start, index), start, end: index });
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
tokens.push({ value: char, start: index, end: index + 1 });
|
|
65
|
+
index++;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return tokens;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isName(token) {
|
|
72
|
+
return token != null && NAME_START.test(token.value[0]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function findDefinitionEnd(tokens, startIndex) {
|
|
76
|
+
const stack = [];
|
|
77
|
+
|
|
78
|
+
for (let index = startIndex; index < tokens.length; index++) {
|
|
79
|
+
const value = tokens[index].value;
|
|
80
|
+
const closer = OPEN_TO_CLOSE.get(value);
|
|
81
|
+
if (closer) {
|
|
82
|
+
stack.push(closer);
|
|
83
|
+
} else if (CLOSERS.has(value)) {
|
|
84
|
+
if (value !== stack.at(-1)) return -1;
|
|
85
|
+
stack.pop();
|
|
86
|
+
} else if (value === ";" && stack.length === 0) {
|
|
87
|
+
return index;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return -1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function findMatching(tokens, startIndex) {
|
|
95
|
+
const firstCloser = OPEN_TO_CLOSE.get(tokens[startIndex]?.value);
|
|
96
|
+
if (!firstCloser) return -1;
|
|
97
|
+
|
|
98
|
+
const stack = [firstCloser];
|
|
99
|
+
for (let index = startIndex + 1; index < tokens.length; index++) {
|
|
100
|
+
const value = tokens[index].value;
|
|
101
|
+
const closer = OPEN_TO_CLOSE.get(value);
|
|
102
|
+
if (closer) {
|
|
103
|
+
stack.push(closer);
|
|
104
|
+
} else if (CLOSERS.has(value)) {
|
|
105
|
+
if (value !== stack.at(-1)) return -1;
|
|
106
|
+
stack.pop();
|
|
107
|
+
if (stack.length === 0) return index;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return -1;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function parseCodeEnd(tokens, startIndex) {
|
|
115
|
+
const token = tokens[startIndex];
|
|
116
|
+
if (!token) return -1;
|
|
117
|
+
|
|
118
|
+
if (isName(token)) return startIndex + 1;
|
|
119
|
+
|
|
120
|
+
if (token.value === "@" && isName(tokens[startIndex + 1])) {
|
|
121
|
+
return startIndex + 2;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (token.value === "{" || token.value === "<") {
|
|
125
|
+
const matching = findMatching(tokens, startIndex);
|
|
126
|
+
return matching === -1 ? -1 : matching + 1;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return -1;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function parseFilterEnd(tokens, startIndex) {
|
|
133
|
+
const token = tokens[startIndex];
|
|
134
|
+
if (!token) return -1;
|
|
135
|
+
|
|
136
|
+
let endIndex;
|
|
137
|
+
if (token.value === "$") {
|
|
138
|
+
endIndex = parseCodeEnd(tokens, startIndex + 1);
|
|
139
|
+
} else if (token.value === "(" || token.value === "{" || token.value === "<") {
|
|
140
|
+
const matching = findMatching(tokens, startIndex);
|
|
141
|
+
endIndex = matching === -1 ? -1 : matching + 1;
|
|
142
|
+
} else if (isName(token)) {
|
|
143
|
+
endIndex = startIndex + 1;
|
|
144
|
+
} else {
|
|
145
|
+
return -1;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (
|
|
149
|
+
endIndex !== -1 &&
|
|
150
|
+
tokens[endIndex]?.value === "=" &&
|
|
151
|
+
isName(tokens[endIndex + 1])
|
|
152
|
+
) {
|
|
153
|
+
endIndex += 2;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return endIndex;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function collectBackgroundRanges(text) {
|
|
160
|
+
const tokens = lex(text);
|
|
161
|
+
const type = [];
|
|
162
|
+
const filter = [];
|
|
163
|
+
|
|
164
|
+
let index = tokens[0]?.value === "~" ? 1 : 0;
|
|
165
|
+
while (index < tokens.length) {
|
|
166
|
+
const isTypeDefinition =
|
|
167
|
+
tokens[index]?.value === "$" &&
|
|
168
|
+
isName(tokens[index + 1]) &&
|
|
169
|
+
tokens[index + 2]?.value === "=";
|
|
170
|
+
const isRelationDefinition =
|
|
171
|
+
isName(tokens[index]) &&
|
|
172
|
+
tokens[index + 1]?.value === "=";
|
|
173
|
+
|
|
174
|
+
if (!isTypeDefinition && !isRelationDefinition) break;
|
|
175
|
+
|
|
176
|
+
const equalsIndex = index + (isTypeDefinition ? 2 : 1);
|
|
177
|
+
const endIndex = findDefinitionEnd(tokens, equalsIndex + 1);
|
|
178
|
+
if (endIndex === -1) break;
|
|
179
|
+
|
|
180
|
+
if (isTypeDefinition) {
|
|
181
|
+
type.push({
|
|
182
|
+
start: tokens[index].start,
|
|
183
|
+
end: tokens[endIndex].end
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
index = endIndex + 1;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
for (let tokenIndex = 0; tokenIndex < tokens.length; tokenIndex++) {
|
|
190
|
+
if (tokens[tokenIndex].value === "?") {
|
|
191
|
+
const endIndex = parseFilterEnd(tokens, tokenIndex + 1);
|
|
192
|
+
if (endIndex !== -1) {
|
|
193
|
+
filter.push({
|
|
194
|
+
start: tokens[tokenIndex].start,
|
|
195
|
+
end: tokens[endIndex - 1].end
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (tokens[tokenIndex].value !== "$") continue;
|
|
202
|
+
|
|
203
|
+
const isDefinition =
|
|
204
|
+
isName(tokens[tokenIndex + 1]) &&
|
|
205
|
+
tokens[tokenIndex + 2]?.value === "=";
|
|
206
|
+
if (isDefinition) continue;
|
|
207
|
+
|
|
208
|
+
const endIndex = parseCodeEnd(tokens, tokenIndex + 1);
|
|
209
|
+
if (endIndex !== -1) {
|
|
210
|
+
type.push({
|
|
211
|
+
start: tokens[tokenIndex].start,
|
|
212
|
+
end: tokens[endIndex - 1].end
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return { type, filter };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function toVscodeRanges(document, ranges) {
|
|
221
|
+
return ranges.map(({ start, end }) => new vscode.Range(
|
|
222
|
+
document.positionAt(start),
|
|
223
|
+
document.positionAt(end)
|
|
224
|
+
));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function activate(context) {
|
|
228
|
+
const filterDecoration = vscode.window.createTextEditorDecorationType({
|
|
229
|
+
backgroundColor: "rgba(58, 45, 32, 0.82)"
|
|
230
|
+
});
|
|
231
|
+
const typeDecoration = vscode.window.createTextEditorDecorationType({
|
|
232
|
+
backgroundColor: "rgba(38, 53, 39, 0.92)"
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
context.subscriptions.push(filterDecoration, typeDecoration);
|
|
236
|
+
|
|
237
|
+
function updateEditor(editor) {
|
|
238
|
+
if (editor.document.languageId !== "k") return;
|
|
239
|
+
|
|
240
|
+
const ranges = collectBackgroundRanges(editor.document.getText());
|
|
241
|
+
editor.setDecorations(
|
|
242
|
+
filterDecoration,
|
|
243
|
+
toVscodeRanges(editor.document, ranges.filter)
|
|
244
|
+
);
|
|
245
|
+
editor.setDecorations(
|
|
246
|
+
typeDecoration,
|
|
247
|
+
toVscodeRanges(editor.document, ranges.type)
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function updateVisibleEditors() {
|
|
252
|
+
for (const editor of vscode.window.visibleTextEditors) updateEditor(editor);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
context.subscriptions.push(
|
|
256
|
+
vscode.window.onDidChangeVisibleTextEditors(updateVisibleEditors),
|
|
257
|
+
vscode.workspace.onDidChangeTextDocument(({ document }) => {
|
|
258
|
+
for (const editor of vscode.window.visibleTextEditors) {
|
|
259
|
+
if (editor.document === document) updateEditor(editor);
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
updateVisibleEditors();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function deactivate() {}
|
|
268
|
+
|
|
269
|
+
module.exports = {
|
|
270
|
+
activate,
|
|
271
|
+
collectBackgroundRanges,
|
|
272
|
+
deactivate
|
|
273
|
+
};
|
package/k-vscode/package.json
CHANGED
|
@@ -23,6 +23,21 @@
|
|
|
23
23
|
"categories": [
|
|
24
24
|
"Programming Languages"
|
|
25
25
|
],
|
|
26
|
+
"main": "./extension.js",
|
|
27
|
+
"activationEvents": [
|
|
28
|
+
"onLanguage:k"
|
|
29
|
+
],
|
|
30
|
+
"files": [
|
|
31
|
+
"extension.js",
|
|
32
|
+
"language-configuration.json",
|
|
33
|
+
"README.md",
|
|
34
|
+
"snippets/k.json",
|
|
35
|
+
"syntaxes/k.tmLanguage.json",
|
|
36
|
+
"themes/k-contrast-color-theme.json"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"test": "node test/background-ranges.test.js"
|
|
40
|
+
},
|
|
26
41
|
"contributes": {
|
|
27
42
|
"languages": [
|
|
28
43
|
{
|
|
@@ -44,6 +59,13 @@
|
|
|
44
59
|
"path": "./syntaxes/k.tmLanguage.json"
|
|
45
60
|
}
|
|
46
61
|
],
|
|
62
|
+
"themes": [
|
|
63
|
+
{
|
|
64
|
+
"label": "k Contrast",
|
|
65
|
+
"uiTheme": "vs-dark",
|
|
66
|
+
"path": "./themes/k-contrast-color-theme.json"
|
|
67
|
+
}
|
|
68
|
+
],
|
|
47
69
|
"snippets": [
|
|
48
70
|
{
|
|
49
71
|
"language": "k",
|