@fraczak/k 5.1.1 → 6.0.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/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/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.md +54 -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.md +53 -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/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.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 +18 -8
- package/parser.jison +27 -46
- package/parser.mjs +68 -100
- package/pretty.mjs +21 -40
- package/repl2.mjs +652 -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 +95 -0
- package/test.mjs +45 -70
- package/tests.sh +10 -1
- 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
package/core.k
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
-- core.k — the k standard core library
|
|
2
|
+
--
|
|
3
|
+
-- Defines:
|
|
4
|
+
-- 1. $bits — the canonical binary number / bit-path type
|
|
5
|
+
-- 2. $string — unicode strings (used for labels)
|
|
6
|
+
-- 3. $pattern — the type of pattern graphs
|
|
7
|
+
-- 4. Basic $bits arithmetic: succ, plus, times
|
|
8
|
+
|
|
9
|
+
---------------------------------------------------------------
|
|
10
|
+
-- §1. Bits
|
|
11
|
+
---------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
$ bit = < {} 0, {} 1 >;
|
|
14
|
+
b0 = {}|0 $bit;
|
|
15
|
+
b1 = {}|1 $bit;
|
|
16
|
+
|
|
17
|
+
$ bits = < {} _, bits 0, bits 1 >;
|
|
18
|
+
|
|
19
|
+
_ = {}|_;
|
|
20
|
+
|
|
21
|
+
0 = _ |0;
|
|
22
|
+
1 = _ |1;
|
|
23
|
+
|
|
24
|
+
inv = {() x, _ r} _inv;
|
|
25
|
+
_inv = ${bits x, bits r} < {.x /0 x, .r |0 r} _inv, {.x /1 x, .r |1 r} _inv, .r >;
|
|
26
|
+
|
|
27
|
+
concat = ${bits x, bits y} {.x inv x, .y y} concat_;
|
|
28
|
+
concat_ = ${bits x, bits y}
|
|
29
|
+
<
|
|
30
|
+
{.x /0 x, .y |0 y} concat_,
|
|
31
|
+
{.x /1 x, .y |1 y} concat_,
|
|
32
|
+
.y
|
|
33
|
+
>;
|
|
34
|
+
|
|
35
|
+
---------------------------------------------------------------
|
|
36
|
+
-- §2. Bits arithmetic
|
|
37
|
+
---------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
-- successor (increment by 1)
|
|
40
|
+
succ = {inv x, _ y} _inc;
|
|
41
|
+
|
|
42
|
+
_inc = ${bits x, bits y} <
|
|
43
|
+
{.x /0 x, .y |1 y} concat_,
|
|
44
|
+
{.x /1 x, .y |0 y} _inc,
|
|
45
|
+
.y |1
|
|
46
|
+
>;
|
|
47
|
+
|
|
48
|
+
-- constants
|
|
49
|
+
2 = 1 succ;
|
|
50
|
+
3 = 2 succ;
|
|
51
|
+
4 = 3 succ;
|
|
52
|
+
5 = 4 succ;
|
|
53
|
+
6 = 5 succ;
|
|
54
|
+
7 = 6 succ;
|
|
55
|
+
8 = 7 succ;
|
|
56
|
+
9 = 8 succ;
|
|
57
|
+
10 = 9 succ;
|
|
58
|
+
|
|
59
|
+
-- addition on $bits (unsigned, LSB-first with carry)
|
|
60
|
+
plus = ${bits x, bits y} {.x inv x, .y inv y, b0 c} _plus;
|
|
61
|
+
_plus = ${bits x, bits y, bit c}
|
|
62
|
+
<
|
|
63
|
+
{.x /_ if, .y /_ and, <.c/0 0, 1> then} .then,
|
|
64
|
+
{.x /_ if, .c/0 and, .y then} .then,
|
|
65
|
+
{.x y, .y /_|_ x, .c c} _plus,
|
|
66
|
+
{<.c/0 0, 1> x, .y y, .x /_ b0 c} _plus,
|
|
67
|
+
{.x /0 x, .y /0 y, .c/0 b0 c} _plus |0,
|
|
68
|
+
{.x /0 x, .y /0 y, .c/1 b0 c} _plus |1,
|
|
69
|
+
{.x /0 x, .y /1 y, .c/0 b0 c} _plus |1,
|
|
70
|
+
{.x /0 x, .y /1 y, .c/1 b1 c} _plus |0,
|
|
71
|
+
{.x /1 x, .y /0 y, .c/0 b0 c} _plus |1,
|
|
72
|
+
{.x /1 x, .y /0 y, .c/1 b1 c} _plus |0,
|
|
73
|
+
{.x /1 x, .y /1 y, .c/0 b1 c} _plus |0,
|
|
74
|
+
{.x /1 x, .y /1 y, .c/1 b1 c} _plus |1
|
|
75
|
+
>;
|
|
76
|
+
|
|
77
|
+
-- multiplication on $bits (unsigned, shift-and-add)
|
|
78
|
+
times = ${bits x, bits y} {0 result, .x inv _x, .y y} _times;
|
|
79
|
+
_times = ${bits result, bits _x, bits y}
|
|
80
|
+
<
|
|
81
|
+
{ .y /_ if, .result then } .then,
|
|
82
|
+
{
|
|
83
|
+
.result |0 result,
|
|
84
|
+
._x _x,
|
|
85
|
+
.y /0 y
|
|
86
|
+
} _times,
|
|
87
|
+
{
|
|
88
|
+
{._x x, .result |0 y, b0 c} _plus result,
|
|
89
|
+
._x _x,
|
|
90
|
+
.y /1 y
|
|
91
|
+
} _times
|
|
92
|
+
>;
|
|
93
|
+
|
|
94
|
+
---------------------------------------------------------------
|
|
95
|
+
-- §3. Unicode and String
|
|
96
|
+
---------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
-- 8-bit octet used as a building block for UTF-8 payload pieces.
|
|
99
|
+
$ byte = {
|
|
100
|
+
bit 0, bit 1, bit 2, bit 3,
|
|
101
|
+
bit 4, bit 5, bit 6, bit 7
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
-- 7-bit ASCII code point payload (U+0000..U+007F).
|
|
105
|
+
$ ascii = { bit 6, bit 5, bit 4, bit 3, bit 2, bit 1, bit 0 };
|
|
106
|
+
|
|
107
|
+
-- 11-bit payload used for Plane 0 code points U+0080..U+07FF.
|
|
108
|
+
-- Plane 0 is the Basic Multilingual Plane (BMP): U+0000..U+FFFF.
|
|
109
|
+
$ u0080_07FF = { bit 10, bit 9, bit 8, bit 7, bit 6, bit 5, bit 4, bit 3, bit 2, bit 1, bit 0 };
|
|
110
|
+
|
|
111
|
+
-- High-byte classes for common BMP ranges, excluding surrogate/private-use partitions.
|
|
112
|
+
-- BMP (Basic Multilingual Plane) is Plane 0: the first 65,536 code points.
|
|
113
|
+
$ bmp_hi_common = <
|
|
114
|
+
{ bit 2, bit 1, bit 0 } h08_0F,
|
|
115
|
+
{ bit 6, bit 5, bit 4, bit 3, bit 2, bit 1, bit 0 } h10_7F,
|
|
116
|
+
{ bit 6, bit 5, bit 4, bit 3, bit 2, bit 1, bit 0 } h80_CF,
|
|
117
|
+
{ bit 2, bit 1, bit 0 } hD0_D7,
|
|
118
|
+
{} hF9,
|
|
119
|
+
{ bit 0 } hFA_FB,
|
|
120
|
+
{ bit 0 } hFC_FD,
|
|
121
|
+
{ bit 0 } hFE_FF
|
|
122
|
+
>;
|
|
123
|
+
|
|
124
|
+
-- High-byte classes for BMP private-use/high-reserved slices.
|
|
125
|
+
-- These partitions keep Plane 0 subsets explicit in the type encoding.
|
|
126
|
+
$ bmp_hi_private_use = <
|
|
127
|
+
{ bit 3, bit 2, bit 1, bit 0 } hE0_EF,
|
|
128
|
+
{ bit 2, bit 1, bit 0 } hF0_F7,
|
|
129
|
+
{} hF8
|
|
130
|
+
>;
|
|
131
|
+
|
|
132
|
+
-- Plane selector for supplementary code points in Planes 2..16.
|
|
133
|
+
-- Supplementary planes are all planes above BMP (Plane 0).
|
|
134
|
+
$ plane_02_10 = <
|
|
135
|
+
{ bit 0 } p02_03,
|
|
136
|
+
{ bit 1, bit 0 } p04_07,
|
|
137
|
+
{ bit 2, bit 1, bit 0 } p08_0F,
|
|
138
|
+
{} p10
|
|
139
|
+
>;
|
|
140
|
+
|
|
141
|
+
-- Canonical Unicode scalar-value partition used by string encoding.
|
|
142
|
+
-- Branch meaning:
|
|
143
|
+
-- - ascii: U+0000..U+007F (subset of BMP / Plane 0)
|
|
144
|
+
-- - plane0: U+0080..U+07FF (still Plane 0)
|
|
145
|
+
-- - bmp_common, bmp_private_use: U+0800..U+FFFF partitions (Plane 0)
|
|
146
|
+
-- - supplementary_plane1: U+10000..U+1FFFF (Plane 1)
|
|
147
|
+
-- - supplementary_planes2_16: U+20000..U+10FFFF (Planes 2..16)
|
|
148
|
+
$ unicode = <
|
|
149
|
+
ascii ascii,
|
|
150
|
+
u0080_07FF plane0,
|
|
151
|
+
{ bmp_hi_common hi, byte lo } bmp_common,
|
|
152
|
+
{ bmp_hi_private_use hi, byte lo } bmp_private_use,
|
|
153
|
+
{ byte mid, byte lo } supplementary_plane1,
|
|
154
|
+
{ plane_02_10 plane, byte mid, byte lo } supplementary_planes2_16
|
|
155
|
+
>;
|
|
156
|
+
|
|
157
|
+
-- Linked-list string: nil or (unicode car, string cdr).
|
|
158
|
+
$ string = < {} nil, { unicode car, string cdr } cons >;
|
|
159
|
+
|
|
160
|
+
---------------------------------------------------------------
|
|
161
|
+
-- §4. Pattern
|
|
162
|
+
---------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
-- Edge: a labeled edge in a pattern graph.
|
|
165
|
+
-- 'label' is the field name or tag name.
|
|
166
|
+
-- 'target' is the index (as $bits) of the target node in the pattern list.
|
|
167
|
+
|
|
168
|
+
$ edge = { string label, bits target };
|
|
169
|
+
|
|
170
|
+
-- Edge list: the edges of a pattern node, sorted by label.
|
|
171
|
+
|
|
172
|
+
$ edges = < {} nil, { edge car, edges cdr } cons >;
|
|
173
|
+
|
|
174
|
+
-- Pattern node: one of five kinds.
|
|
175
|
+
-- "any" is the unconstrained position (...), carrying no edges.
|
|
176
|
+
-- The four others carry their edge list directly.
|
|
177
|
+
|
|
178
|
+
$ pattern-node = <
|
|
179
|
+
{} any,
|
|
180
|
+
edges open-product,
|
|
181
|
+
edges open-union,
|
|
182
|
+
edges closed-product,
|
|
183
|
+
edges closed-union
|
|
184
|
+
>;
|
|
185
|
+
|
|
186
|
+
-- Pattern: a cons-list of pattern nodes.
|
|
187
|
+
-- Node 0 (first element) is the root.
|
|
188
|
+
-- Edges reference nodes by their index in this list, encoded as $bits.
|
|
189
|
+
--
|
|
190
|
+
-- The singleton pattern of $pattern itself is a fixed constant.
|
|
191
|
+
-- That constant is the implicit framing for all k wire formats:
|
|
192
|
+
-- to decode any value, first decode a $pattern under that constant,
|
|
193
|
+
-- then decode the value under the pattern just obtained.
|
|
194
|
+
|
|
195
|
+
$ pattern = < {} nil, { pattern-node car, pattern cdr } cons >;
|
|
196
|
+
|
|
197
|
+
$pattern
|
package/export.mjs
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import hash from "./hash.mjs";
|
|
2
2
|
import { prettyRel, patterns2filters } from "./pretty.mjs";
|
|
3
|
-
import { hash } from "./hash.mjs";
|
|
4
3
|
|
|
5
|
-
function
|
|
4
|
+
function logNormalized(label, value, hashValue) {
|
|
5
|
+
if (process.env.K_DUMP_NORMALIZED) {
|
|
6
|
+
if (hashValue) {
|
|
7
|
+
console.log(`[k-normalize] ${label}: ${hashValue} = ${value}`);
|
|
8
|
+
} else {
|
|
9
|
+
console.log(`[k-normalize] ${label}: ${value}`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function simplifyRel(relDef,rels) {
|
|
6
15
|
// remove filters and codes
|
|
7
16
|
const prune = (rel) => {
|
|
8
17
|
const newRel = {...rel};
|
|
@@ -23,12 +32,6 @@ function simplifyRel(relDef,rels) {
|
|
|
23
32
|
if (newRel.comp.length == 0)
|
|
24
33
|
newRel.op = "identity";
|
|
25
34
|
break;
|
|
26
|
-
case "vector":
|
|
27
|
-
newRel.vector = rel.vector.map(exp => prune(exp));
|
|
28
|
-
break;
|
|
29
|
-
case "caret":
|
|
30
|
-
newRel.caret = prune(rel.caret);
|
|
31
|
-
break;
|
|
32
35
|
case 'code':
|
|
33
36
|
case 'filter':
|
|
34
37
|
newRel.op = "identity";
|
|
@@ -46,8 +49,8 @@ function simplifyRel(relDef,rels) {
|
|
|
46
49
|
};
|
|
47
50
|
|
|
48
51
|
const rel = relDef.def;
|
|
49
|
-
const filters = patterns2filters(relDef.typePatternGraph, ...rel.patterns).map(
|
|
50
|
-
({op: "filter", filter: filter}));
|
|
52
|
+
const filters = patterns2filters(relDef.typePatternGraph, ...rel.patterns).map((filter, index) =>
|
|
53
|
+
({op: "filter", filter: filter, patterns: [rel.patterns[index], rel.patterns[index]]}));
|
|
51
54
|
const newRel = prune(rel);
|
|
52
55
|
let resultRel = {...newRel};
|
|
53
56
|
if (newRel.op == "identity")
|
|
@@ -57,13 +60,15 @@ function simplifyRel(relDef,rels) {
|
|
|
57
60
|
resultRel.comp = [ filters[0], ...newRel.comp, filters[1] ];
|
|
58
61
|
return resultRel;
|
|
59
62
|
}
|
|
63
|
+
|
|
64
|
+
let oldOp = resultRel.op;
|
|
65
|
+
delete resultRel[oldOp];
|
|
60
66
|
return {...resultRel,
|
|
61
67
|
op: "comp",
|
|
62
68
|
comp: [filters[0], newRel, filters[1] ]
|
|
63
69
|
};
|
|
64
70
|
};
|
|
65
71
|
|
|
66
|
-
|
|
67
72
|
function theID(alias, rel, scc, name) {
|
|
68
73
|
const sccNames = new Set(scc);
|
|
69
74
|
const auxNames = {[name]: "X0"};
|
|
@@ -80,12 +85,6 @@ function theID(alias, rel, scc, name) {
|
|
|
80
85
|
case "comp":
|
|
81
86
|
newRel.comp = rel.comp.map(exp => reNameX(exp));
|
|
82
87
|
break;
|
|
83
|
-
case "vector":
|
|
84
|
-
newRel.vector = rel.vector.map(exp => reNameX(exp));
|
|
85
|
-
break;
|
|
86
|
-
case "caret":
|
|
87
|
-
newRel.caret = reNameX(rel.caret);
|
|
88
|
-
break;
|
|
89
88
|
case "ref": {
|
|
90
89
|
const n = rel.ref;
|
|
91
90
|
if (alias[n] != undefined) {
|
|
@@ -105,21 +104,21 @@ function theID(alias, rel, scc, name) {
|
|
|
105
104
|
|
|
106
105
|
const newRel = reNameX(rel);
|
|
107
106
|
const resultRelStr = prettyRel(newRel);
|
|
108
|
-
// console.log(` ${name} = ${resultRelStr}`);
|
|
109
107
|
const newName = hash(resultRelStr);
|
|
108
|
+
logNormalized(name, resultRelStr, newName);
|
|
109
|
+
// console.log(` ${name} = ${resultRelStr}`);
|
|
110
110
|
return newName;
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
-
function assignCanonicalNames(scc, rels, relAlias) {
|
|
113
|
+
export function assignCanonicalNames(scc, rels, relAlias) {
|
|
114
114
|
const newAlias = scc.reduce( (newAlias,relName) => {
|
|
115
115
|
const relDef = rels[relName];
|
|
116
116
|
if (relDef.def.op == "ref" && rels[relDef.def.ref] != undefined) {
|
|
117
117
|
// inlining if direct alias to a non built-in relation
|
|
118
118
|
// relDef.def = rels[relDef.def.ref]; // simplifyRel(rels[relDef.def.ref],rels);
|
|
119
119
|
rels[relName] = rels[relDef.def.ref];
|
|
120
|
-
} else {
|
|
121
|
-
relDef.def = simplifyRel(relDef,rels);
|
|
122
120
|
}
|
|
121
|
+
rels[relName].def = simplifyRel(rels[relName], rels);
|
|
123
122
|
newAlias[relName] = theID(relAlias, rels[relName].def, scc, relName);
|
|
124
123
|
return newAlias;
|
|
125
124
|
}, {});
|
|
@@ -136,7 +135,7 @@ function assignCanonicalNames(scc, rels, relAlias) {
|
|
|
136
135
|
};
|
|
137
136
|
}
|
|
138
137
|
|
|
139
|
-
function exportRelation(rels, alias, name) {
|
|
138
|
+
export function exportRelation(rels, alias, name) {
|
|
140
139
|
const queue = [name];
|
|
141
140
|
const inQueue = { [name]: true };
|
|
142
141
|
const result = {};
|
|
@@ -152,12 +151,6 @@ function exportRelation(rels, alias, name) {
|
|
|
152
151
|
case "comp":
|
|
153
152
|
newRel.comp = rel.comp.map(exp => reName(exp));
|
|
154
153
|
break;
|
|
155
|
-
case "vector":
|
|
156
|
-
newRel.vector = rel.vector.map(exp => reName(exp));
|
|
157
|
-
break;
|
|
158
|
-
case "caret":
|
|
159
|
-
newRel.caret = reName(rel.caret);
|
|
160
|
-
break;
|
|
161
154
|
case "ref": {
|
|
162
155
|
const n = rel.ref;
|
|
163
156
|
if (alias[n] == undefined) // built-in
|
|
@@ -180,6 +173,3 @@ function exportRelation(rels, alias, name) {
|
|
|
180
173
|
}
|
|
181
174
|
return result;
|
|
182
175
|
}
|
|
183
|
-
|
|
184
|
-
export default { assignCanonicalNames, exportRelation };
|
|
185
|
-
export { assignCanonicalNames, exportRelation };
|
package/hash.mjs
CHANGED
|
@@ -1,39 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
'0': 'A', '1': 'B', '2': 'C', '3': 'D',
|
|
3
|
-
'4': 'E', '5': 'F', '6': 'G', '7': 'H',
|
|
4
|
-
'8': 'I', '9': 'J', 'a': 'K', 'b': 'L',
|
|
5
|
-
'c': 'M', 'd': 'N', 'e': 'O', 'f': 'P',
|
|
6
|
-
'g': 'Q', 'h': 'R', 'i': 'S', 'j': 'T',
|
|
7
|
-
'k': 'U', 'l': 'V', 'm': 'W', 'n': 'X',
|
|
8
|
-
'o': 'Y', 'p': 'Z', 'q': 'q', 'r': 'r',
|
|
9
|
-
's': 's', 't': 't', 'u': 'u', 'v': 'v',
|
|
10
|
-
'w': 'w', 'x': 'x', 'y': 'y', 'z': 'z'
|
|
11
|
-
};
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
12
2
|
|
|
13
|
-
const
|
|
3
|
+
const BASE56_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz";
|
|
4
|
+
const BASE56_BASE = BigInt(BASE56_ALPHABET.length);
|
|
5
|
+
const SHA256_BASE56_LENGTH = 45;
|
|
6
|
+
function encodeBase56(bytes) {
|
|
7
|
+
let value = 0n;
|
|
8
|
+
for (const byte of bytes) {
|
|
9
|
+
value = (value << 8n) + BigInt(byte);
|
|
10
|
+
}
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
12
|
+
let encoded = "";
|
|
13
|
+
while (value > 0n) {
|
|
14
|
+
const mod = value % BASE56_BASE;
|
|
15
|
+
encoded = BASE56_ALPHABET[Number(mod)] + encoded;
|
|
16
|
+
value /= BASE56_BASE;
|
|
17
|
+
}
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
inputString = inputString.slice(4, -1);
|
|
26
|
-
|
|
27
|
-
let hashValue = BigInt(0);
|
|
28
|
-
const prime = BigInt(2);
|
|
29
|
-
const mod = BigInt('8494462356974657160929849007317');
|
|
19
|
+
return encoded || BASE56_ALPHABET[0];
|
|
20
|
+
}
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
22
|
+
function hash(inputString, options = {}) {
|
|
23
|
+
const { short = false, minLength = 7 } = options;
|
|
24
|
+
let input = inputString;
|
|
25
|
+
if (input.match(/^\$C0=.*;$/)) {
|
|
26
|
+
input = input.slice(4, -1);
|
|
27
|
+
}
|
|
35
28
|
|
|
36
|
-
|
|
29
|
+
const digest = createHash("sha256").update(input).digest();
|
|
30
|
+
const full = encodeBase56(digest);
|
|
31
|
+
const padded = full.padStart(SHA256_BASE56_LENGTH, BASE56_ALPHABET[0]);
|
|
32
|
+
const trimmed = padded.slice(1);
|
|
33
|
+
const body = short ? trimmed.slice(0, Math.max(1, minLength)) : trimmed;
|
|
34
|
+
return "@" + body;
|
|
37
35
|
}
|
|
38
36
|
|
|
39
37
|
export default hash;
|
package/index.mjs
CHANGED
|
@@ -1,33 +1,59 @@
|
|
|
1
1
|
import { parse } from "./parser.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { Value, fromObject } from "./Value.mjs";
|
|
3
|
+
import { parseValue } from "./valueIO.mjs";
|
|
4
|
+
import { compileTypes } from "./compiler.mjs";
|
|
3
5
|
import run from "./run.mjs";
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
function compile(script) {
|
|
7
|
-
run.defs = annotate(script);
|
|
8
|
-
|
|
6
|
+
import codes from "./codes.mjs";
|
|
7
|
+
|
|
8
|
+
function compile(script, options = {}) {
|
|
9
|
+
run.defs = annotate(script, options);
|
|
10
|
+
const mainRel = run.defs.rels.__main__;
|
|
11
|
+
return (value) => {
|
|
12
|
+
const result = run(codes.find, mainRel.def, value, mainRel.typePatternGraph);
|
|
13
|
+
if (result === undefined) return;
|
|
14
|
+
return result;
|
|
15
|
+
};
|
|
9
16
|
}
|
|
10
17
|
|
|
11
18
|
compile.doc = "Transforms k-script (string) into a function";
|
|
12
19
|
|
|
13
|
-
function runScriptOnData(script, data) {
|
|
14
|
-
|
|
20
|
+
function runScriptOnData(script, data, options = {}) {
|
|
21
|
+
let parsedData;
|
|
22
|
+
if (data instanceof Value) {
|
|
23
|
+
parsedData = data;
|
|
24
|
+
} else if (typeof data === "string") {
|
|
25
|
+
parsedData = parseValue(data, null, null);
|
|
26
|
+
} else {
|
|
27
|
+
parsedData = fromObject(data);
|
|
28
|
+
}
|
|
29
|
+
return compile(script, options)(parsedData);
|
|
15
30
|
}
|
|
16
31
|
runScriptOnData.doc = "Run 'script' (string) on 'data': (script,data) -> data";
|
|
17
32
|
|
|
18
33
|
|
|
19
|
-
function annotate(script) {
|
|
34
|
+
function annotate(script, options = {}) {
|
|
20
35
|
const { defs, exp } = parse(script);
|
|
21
|
-
//const { codes, representatives } = t.finalize(defs.codes);
|
|
22
36
|
|
|
23
|
-
const representatives =
|
|
37
|
+
const representatives = codes.register(defs.codes);
|
|
24
38
|
const rels = {...defs.rels, "__main__": {def: exp}};
|
|
25
39
|
|
|
26
|
-
|
|
40
|
+
// Inject library relations into the rels table so @hash refs resolve
|
|
41
|
+
if (options.libraries) {
|
|
42
|
+
for (const lib of options.libraries) {
|
|
43
|
+
const libRels = lib.rels || lib.defs?.rels || {};
|
|
44
|
+
for (const [name, rel] of Object.entries(libRels)) {
|
|
45
|
+
if (!(name in rels)) {
|
|
46
|
+
rels[name] = { ...rel, _library: true };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { relAlias, compileStats } = compileTypes(representatives, rels, options);
|
|
27
53
|
|
|
28
|
-
return {rels, representatives, relAlias};
|
|
54
|
+
return {rels, representatives, relAlias, compileStats};
|
|
29
55
|
}
|
|
30
56
|
annotate.doc = "Annotate all the script expressions with patterns";
|
|
31
57
|
|
|
32
|
-
export default { compile, run: runScriptOnData, parse, annotate };
|
|
33
|
-
export { compile, runScriptOnData as run, parse, annotate };
|
|
58
|
+
export default { compile, run: runScriptOnData, parse, annotate, parseValue, fromObject };
|
|
59
|
+
export { compile, runScriptOnData as run, parse, annotate, parseValue, fromObject };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"name": "Run K Language Extension",
|
|
6
|
+
"type": "extensionHost",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"runtimeExecutable": "${execPath}",
|
|
9
|
+
"args": [
|
|
10
|
+
"--extensionDevelopmentPath=${workspaceFolder}"
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# k language — VS Code extension
|
|
2
|
+
|
|
3
|
+
Syntax highlighting and snippets for the **k language**: a language for composing
|
|
4
|
+
first-order partial functions over algebraic data types (products and tagged unions).
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- **Syntax highlighting** for all current k constructs:
|
|
9
|
+
- Line comments (`--`, `//`, `%`, `#`) and block comments (`/* … */`)
|
|
10
|
+
- Named code (type) definitions: `$ name = …`
|
|
11
|
+
- Function/relation definitions: `name = …`
|
|
12
|
+
- All three operators: `.field` (product projection), `/tag` (union projection), `|tag` (variant introduction)
|
|
13
|
+
- Filter expressions: `?< … > = X`, `?{ … } = X` with pattern variables
|
|
14
|
+
- Type annotations: `$name`, `${…}`
|
|
15
|
+
- Canonical content-addressed references: `@base58hash`
|
|
16
|
+
- Quoted label strings: `"label"`, `'label'` (with escape sequences)
|
|
17
|
+
- The `...` any/open pattern marker
|
|
18
|
+
- **Snippets** for every common pattern (trigger via `Tab` after prefix):
|
|
19
|
+
|
|
20
|
+
| Prefix | Inserts |
|
|
21
|
+
|--------|---------|
|
|
22
|
+
| `codeunion` | Named code as tagged union |
|
|
23
|
+
| `codeprod` | Named code as product |
|
|
24
|
+
| `coderecunion` | Recursive named code |
|
|
25
|
+
| `fn` | Function definition |
|
|
26
|
+
| `comp` | Composition `(f g)` |
|
|
27
|
+
| `merge` | Merge `< f, g >` |
|
|
28
|
+
| `prod` | Product combinator `{ f l, g l }` |
|
|
29
|
+
| `filtunion` | Filter union `?< … > = X` |
|
|
30
|
+
| `filtprod` | Filter product `?{ … } = X` |
|
|
31
|
+
| `dot` | `.field` |
|
|
32
|
+
| `slash` | `/tag` |
|
|
33
|
+
| `vid` | `\|tag` |
|
|
34
|
+
| `typeref` | `$name` annotation |
|
|
35
|
+
| `typedprod` | `${ type label, … }` typed input |
|
|
36
|
+
| `id` | `()` identity |
|
|
37
|
+
| `unit` | `{}` empty product (leaf) |
|
|
38
|
+
| `undef` | `<>` always-undefined |
|
|
39
|
+
|
|
40
|
+
- **Bracket matching and auto-close** for `{ }`, `( )`, `< >`, `"…"`, `'…'`
|
|
41
|
+
- **Toggle line comment** bound to `--` (Ctrl+/ / Cmd+/)
|
|
42
|
+
- **Word selection** understands k identifiers including `?`, `!`, `+`, `-`
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
### Run locally (development)
|
|
47
|
+
|
|
48
|
+
1. Open the `k-vscode/` folder in VS Code.
|
|
49
|
+
2. Press **F5** — this opens an Extension Development Host with the extension loaded.
|
|
50
|
+
|
|
51
|
+
### Build and install a VSIX
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
cd k-vscode
|
|
55
|
+
npm install
|
|
56
|
+
npx vsce package # produces k-language-0.2.0.vsix
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Then in VS Code: **Extensions → ⋯ → Install from VSIX…** and select the generated file.
|
|
60
|
+
|
|
61
|
+
## Notes
|
|
62
|
+
|
|
63
|
+
- Language id: `k`
|
|
64
|
+
- File extension: `.k`
|
|
65
|
+
- The extension has no runtime dependencies.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"comments": {
|
|
3
|
+
"lineComment": "--",
|
|
4
|
+
"blockComment": ["/*", "*/"]
|
|
5
|
+
},
|
|
6
|
+
"brackets": [
|
|
7
|
+
["{", "}"],
|
|
8
|
+
["(", ")"],
|
|
9
|
+
["<", ">"]
|
|
10
|
+
],
|
|
11
|
+
"autoClosingPairs": [
|
|
12
|
+
{ "open": "{", "close": "}" },
|
|
13
|
+
{ "open": "(", "close": ")" },
|
|
14
|
+
{ "open": "<", "close": ">" },
|
|
15
|
+
{ "open": "\"", "close": "\"" },
|
|
16
|
+
{ "open": "'", "close": "'" },
|
|
17
|
+
{ "open": "/*", "close": "*/" }
|
|
18
|
+
],
|
|
19
|
+
"surroundingPairs": [
|
|
20
|
+
["{", "}"],
|
|
21
|
+
["(", ")"],
|
|
22
|
+
["<", ">"],
|
|
23
|
+
["\"", "\""],
|
|
24
|
+
["'", "'"]
|
|
25
|
+
],
|
|
26
|
+
"wordPattern": "[a-zA-Z0-9_+\\-][a-zA-Z0-9_?!+\\-]*",
|
|
27
|
+
"indentationRules": {
|
|
28
|
+
"increaseIndentPattern": "[{(<]\\s*$",
|
|
29
|
+
"decreaseIndentPattern": "^\\s*[})>]"
|
|
30
|
+
},
|
|
31
|
+
"onEnterRules": [
|
|
32
|
+
{
|
|
33
|
+
"beforeText": "/\\*.*\\*/$",
|
|
34
|
+
"action": { "indent": "none" }
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"beforeText": "/\\*",
|
|
38
|
+
"afterText": "\\*/",
|
|
39
|
+
"action": { "indent": "indentOutdent" }
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "k-language",
|
|
3
|
+
"displayName": "k language",
|
|
4
|
+
"description": "Syntax highlighting and snippets for the k language — first-order partial functions over algebraic data types",
|
|
5
|
+
"publisher": "wojtek",
|
|
6
|
+
"version": "0.2.0",
|
|
7
|
+
"license": "ISC",
|
|
8
|
+
"homepage": "https://github.com/fraczak/k",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/fraczak/k.git"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"k",
|
|
15
|
+
"algebraic",
|
|
16
|
+
"partial functions",
|
|
17
|
+
"ADT",
|
|
18
|
+
"types"
|
|
19
|
+
],
|
|
20
|
+
"engines": {
|
|
21
|
+
"vscode": "^1.90.0"
|
|
22
|
+
},
|
|
23
|
+
"categories": [
|
|
24
|
+
"Programming Languages"
|
|
25
|
+
],
|
|
26
|
+
"contributes": {
|
|
27
|
+
"languages": [
|
|
28
|
+
{
|
|
29
|
+
"id": "k",
|
|
30
|
+
"aliases": [
|
|
31
|
+
"k language",
|
|
32
|
+
"k"
|
|
33
|
+
],
|
|
34
|
+
"extensions": [
|
|
35
|
+
".k"
|
|
36
|
+
],
|
|
37
|
+
"configuration": "./language-configuration.json"
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"grammars": [
|
|
41
|
+
{
|
|
42
|
+
"language": "k",
|
|
43
|
+
"scopeName": "source.k",
|
|
44
|
+
"path": "./syntaxes/k.tmLanguage.json"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"snippets": [
|
|
48
|
+
{
|
|
49
|
+
"language": "k",
|
|
50
|
+
"path": "./snippets/k.json"
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@vscode/vsce": "^3.7.1"
|
|
56
|
+
}
|
|
57
|
+
}
|