@fraczak/k 6.1.0 → 6.1.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/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/copilot.data.migration.agent.xml +6 -0
- package/.idea/copilot.data.migration.ask.xml +6 -0
- package/.idea/copilot.data.migration.ask2agent.xml +6 -0
- package/.idea/copilot.data.migration.edit.xml +6 -0
- package/.idea/k.iml +9 -0
- package/.idea/misc.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/k_compiler/runtime.c +205 -0
- package/k_compiler/runtime.h +34 -0
- package/package.json +1 -1
- package/repl.mjs +28 -9
- package/test-repl.mjs +12 -1
- package/.codex +0 -0
- package/DOCS/a.html +0 -398
- package/NAT.k~ +0 -452
- 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/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 -0
- package/k-vscode/package-lock.json +0 -4176
- package/kkk.k +0 -197
- package/kkk.klib +0 -0
- package/kkk.klib~ +0 -0
- package/p.json +0 -5475
- package/type_registry/registry.mjs~ +0 -105
- package/type_registry/typeParser.jison~ +0 -132
package/.idea/k.iml
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="JAVA_MODULE" version="4">
|
|
3
|
+
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
4
|
+
<exclude-output />
|
|
5
|
+
<content url="file://$MODULE_DIR$" />
|
|
6
|
+
<orderEntry type="inheritedJdk" />
|
|
7
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
8
|
+
</component>
|
|
9
|
+
</module>
|
package/.idea/misc.xml
ADDED
package/.idea/vcs.xml
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#include "runtime.h"
|
|
2
|
+
|
|
3
|
+
#include <stdio.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include <string.h>
|
|
6
|
+
|
|
7
|
+
typedef enum {
|
|
8
|
+
K_NODE_PRODUCT = 1,
|
|
9
|
+
K_NODE_VARIANT = 2
|
|
10
|
+
} KNodeKind;
|
|
11
|
+
|
|
12
|
+
typedef struct {
|
|
13
|
+
const char *label;
|
|
14
|
+
KValue value;
|
|
15
|
+
} KField;
|
|
16
|
+
|
|
17
|
+
struct KNode {
|
|
18
|
+
KNodeKind kind;
|
|
19
|
+
const char *type_id;
|
|
20
|
+
union {
|
|
21
|
+
struct {
|
|
22
|
+
int field_count;
|
|
23
|
+
KField *fields;
|
|
24
|
+
} product;
|
|
25
|
+
struct {
|
|
26
|
+
const char *tag;
|
|
27
|
+
KValue child;
|
|
28
|
+
} variant;
|
|
29
|
+
} as;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
static char *krt_strdup(const char *value) {
|
|
33
|
+
size_t len = strlen(value);
|
|
34
|
+
char *result = (char *)malloc(len + 1);
|
|
35
|
+
memcpy(result, value, len + 1);
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static const char *krt_infer_variant_type(const char *label, KValue child) {
|
|
40
|
+
if (child == NULL) return "";
|
|
41
|
+
if (child->type_id != NULL && child->type_id[0] != '\0') {
|
|
42
|
+
return child->type_id;
|
|
43
|
+
}
|
|
44
|
+
if (strcmp(label, "zero") == 0 || strcmp(label, "succ") == 0) {
|
|
45
|
+
return "@w8iSHeQQE738vEmWNGja3FQWk3XuExQKZ2pbm8ApEdkF";
|
|
46
|
+
}
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static KOpt krt_ok(KValue value) {
|
|
51
|
+
KOpt result;
|
|
52
|
+
result.ok = 1;
|
|
53
|
+
result.value = value;
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static const char *json_extract_string(const char *json, const char *key) {
|
|
58
|
+
static char buffer[256];
|
|
59
|
+
char pattern[64];
|
|
60
|
+
const char *cursor;
|
|
61
|
+
const char *start;
|
|
62
|
+
size_t length = 0;
|
|
63
|
+
|
|
64
|
+
snprintf(pattern, sizeof(pattern), "\"%s\":\"", key);
|
|
65
|
+
cursor = strstr(json, pattern);
|
|
66
|
+
if (cursor == NULL) return NULL;
|
|
67
|
+
start = cursor + strlen(pattern);
|
|
68
|
+
|
|
69
|
+
while (start[length] != '\0' && start[length] != '"') {
|
|
70
|
+
if (start[length] == '\\' && start[length + 1] != '\0') {
|
|
71
|
+
length += 2;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
length += 1;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (length >= sizeof(buffer)) {
|
|
78
|
+
length = sizeof(buffer) - 1;
|
|
79
|
+
}
|
|
80
|
+
memcpy(buffer, start, length);
|
|
81
|
+
buffer[length] = '\0';
|
|
82
|
+
return buffer;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static KValue product_field(KValue input, const char *label) {
|
|
86
|
+
int index;
|
|
87
|
+
if (input == NULL || input->kind != K_NODE_PRODUCT) return NULL;
|
|
88
|
+
for (index = 0; index < input->as.product.field_count; index += 1) {
|
|
89
|
+
if (strcmp(input->as.product.fields[index].label, label) == 0) {
|
|
90
|
+
return input->as.product.fields[index].value;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return NULL;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
KOpt krt_fail(void) {
|
|
97
|
+
KOpt result;
|
|
98
|
+
result.ok = 0;
|
|
99
|
+
result.value = NULL;
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
KOpt krt_return_input(KValue input) {
|
|
104
|
+
return krt_ok(input);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
KValue krt_new_product(const char *type_id, int field_count, const char *const *labels, KValue const *values) {
|
|
108
|
+
int index;
|
|
109
|
+
KNode *node = (KNode *)calloc(1, sizeof(KNode));
|
|
110
|
+
node->kind = K_NODE_PRODUCT;
|
|
111
|
+
node->type_id = krt_strdup(type_id == NULL ? "" : type_id);
|
|
112
|
+
node->as.product.field_count = field_count;
|
|
113
|
+
node->as.product.fields = field_count > 0 ? (KField *)calloc((size_t)field_count, sizeof(KField)) : NULL;
|
|
114
|
+
|
|
115
|
+
for (index = 0; index < field_count; index += 1) {
|
|
116
|
+
node->as.product.fields[index].label = krt_strdup(labels[index]);
|
|
117
|
+
node->as.product.fields[index].value = values[index];
|
|
118
|
+
}
|
|
119
|
+
return node;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
KValue krt_new_variant(const char *type_id, const char *label, KValue child) {
|
|
123
|
+
KNode *node = (KNode *)calloc(1, sizeof(KNode));
|
|
124
|
+
node->kind = K_NODE_VARIANT;
|
|
125
|
+
node->type_id = krt_strdup(type_id == NULL ? "" : type_id);
|
|
126
|
+
node->as.variant.tag = krt_strdup(label);
|
|
127
|
+
node->as.variant.child = child;
|
|
128
|
+
return node;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
KOpt krt_guard_code(KValue input, const char *type_id) {
|
|
132
|
+
if (input == NULL) return krt_fail();
|
|
133
|
+
if (type_id == NULL || type_id[0] == '\0') return krt_ok(input);
|
|
134
|
+
if (strcmp(input->type_id, type_id) == 0) return krt_ok(input);
|
|
135
|
+
return krt_fail();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
KOpt krt_guard_type_var(KValue input, const char *var_name) {
|
|
139
|
+
(void)var_name;
|
|
140
|
+
if (input == NULL) return krt_fail();
|
|
141
|
+
return krt_ok(input);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
KOpt krt_guard_shape(KValue input, const char *shape_descriptor_json) {
|
|
145
|
+
const char *shape;
|
|
146
|
+
if (input == NULL) return krt_fail();
|
|
147
|
+
shape = json_extract_string(shape_descriptor_json, "shape");
|
|
148
|
+
if (shape == NULL || strcmp(shape, "any") == 0) return krt_ok(input);
|
|
149
|
+
if (strcmp(shape, "product") == 0 && input->kind == K_NODE_PRODUCT) return krt_ok(input);
|
|
150
|
+
if (strcmp(shape, "union") == 0 && input->kind == K_NODE_VARIANT) return krt_ok(input);
|
|
151
|
+
return krt_fail();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
KOpt krt_project_field(KValue input, const char *projection_descriptor_json) {
|
|
155
|
+
const char *label = json_extract_string(projection_descriptor_json, "label");
|
|
156
|
+
KValue child = product_field(input, label);
|
|
157
|
+
if (label == NULL || child == NULL) return krt_fail();
|
|
158
|
+
return krt_ok(child);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
KOpt krt_project_variant(KValue input, const char *projection_descriptor_json) {
|
|
162
|
+
const char *label = json_extract_string(projection_descriptor_json, "label");
|
|
163
|
+
if (label == NULL || input == NULL || input->kind != K_NODE_VARIANT) return krt_fail();
|
|
164
|
+
if (strcmp(input->as.variant.tag, label) != 0) return krt_fail();
|
|
165
|
+
return krt_ok(input->as.variant.child);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
KOpt krt_make_product(const char *type_id, int field_count, const char *const *labels, KValue const *values) {
|
|
169
|
+
return krt_ok(krt_new_product(type_id, field_count, labels, values));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
KOpt krt_make_variant(KValue child, const char *label, const char *type_id) {
|
|
173
|
+
const char *resolved_type = type_id;
|
|
174
|
+
if (resolved_type == NULL || resolved_type[0] == '\0') {
|
|
175
|
+
resolved_type = krt_infer_variant_type(label, child);
|
|
176
|
+
}
|
|
177
|
+
return krt_ok(krt_new_variant(resolved_type, label, child));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
void krt_print_value(KValue value) {
|
|
181
|
+
int index;
|
|
182
|
+
if (value == NULL) {
|
|
183
|
+
printf("<null>");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (value->kind == K_NODE_PRODUCT) {
|
|
188
|
+
if (value->as.product.field_count == 0) {
|
|
189
|
+
printf("{}");
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
printf("{");
|
|
193
|
+
for (index = 0; index < value->as.product.field_count; index += 1) {
|
|
194
|
+
if (index > 0) printf(", ");
|
|
195
|
+
printf("%s:", value->as.product.fields[index].label);
|
|
196
|
+
krt_print_value(value->as.product.fields[index].value);
|
|
197
|
+
}
|
|
198
|
+
printf("}");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
printf("%s(", value->as.variant.tag);
|
|
203
|
+
krt_print_value(value->as.variant.child);
|
|
204
|
+
printf(")");
|
|
205
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#ifndef K_COMPILER_RUNTIME_H
|
|
2
|
+
#define K_COMPILER_RUNTIME_H
|
|
3
|
+
|
|
4
|
+
#ifdef __cplusplus
|
|
5
|
+
extern "C" {
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
typedef struct KNode KNode;
|
|
9
|
+
typedef KNode *KValue;
|
|
10
|
+
|
|
11
|
+
typedef struct {
|
|
12
|
+
int ok;
|
|
13
|
+
KValue value;
|
|
14
|
+
} KOpt;
|
|
15
|
+
|
|
16
|
+
KOpt krt_fail(void);
|
|
17
|
+
KOpt krt_return_input(KValue input);
|
|
18
|
+
KOpt krt_guard_code(KValue input, const char *type_id);
|
|
19
|
+
KOpt krt_guard_type_var(KValue input, const char *var_name);
|
|
20
|
+
KOpt krt_guard_shape(KValue input, const char *shape_descriptor_json);
|
|
21
|
+
KOpt krt_project_field(KValue input, const char *projection_descriptor_json);
|
|
22
|
+
KOpt krt_project_variant(KValue input, const char *projection_descriptor_json);
|
|
23
|
+
KOpt krt_make_product(const char *type_id, int field_count, const char *const *labels, KValue const *values);
|
|
24
|
+
KOpt krt_make_variant(KValue child, const char *label, const char *type_id);
|
|
25
|
+
|
|
26
|
+
KValue krt_new_product(const char *type_id, int field_count, const char *const *labels, KValue const *values);
|
|
27
|
+
KValue krt_new_variant(const char *type_id, const char *label, KValue child);
|
|
28
|
+
void krt_print_value(KValue value);
|
|
29
|
+
|
|
30
|
+
#ifdef __cplusplus
|
|
31
|
+
}
|
|
32
|
+
#endif
|
|
33
|
+
|
|
34
|
+
#endif
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fraczak/k",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"description": "k — a language for composing first-order partial functions over algebraic data types (products and tagged unions); includes runtime, type derivation, REPL, and codec toolchain",
|
|
5
5
|
"main": "index.mjs",
|
|
6
6
|
"scripts": {
|
package/repl.mjs
CHANGED
|
@@ -261,10 +261,18 @@ function listAliases(aliases) {
|
|
|
261
261
|
return entries.map(([name, hash]) => `${name} = ${hash}`).join("\n");
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
function printValue(value
|
|
264
|
+
function printValue(value) {
|
|
265
265
|
return valueWithEnvelopeToK(value);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
+
function commitResult(state, result, lastMain) {
|
|
269
|
+
if (result !== undefined) {
|
|
270
|
+
state.value = result;
|
|
271
|
+
state.lastMain = lastMain;
|
|
272
|
+
}
|
|
273
|
+
return [printValue(result)];
|
|
274
|
+
}
|
|
275
|
+
|
|
268
276
|
function userDefinedNames(source) {
|
|
269
277
|
let parsed;
|
|
270
278
|
try {
|
|
@@ -347,6 +355,17 @@ function aliasNames(state) {
|
|
|
347
355
|
])].sort();
|
|
348
356
|
}
|
|
349
357
|
|
|
358
|
+
function displayAliases(state) {
|
|
359
|
+
const aliases = {};
|
|
360
|
+
for (const [name, hash] of [
|
|
361
|
+
...Object.entries(state.typeAliases),
|
|
362
|
+
...Object.entries(state.relAliases)
|
|
363
|
+
].sort(([a], [b]) => a.localeCompare(b))) {
|
|
364
|
+
if (!aliases[hash]) aliases[hash] = name;
|
|
365
|
+
}
|
|
366
|
+
return aliases;
|
|
367
|
+
}
|
|
368
|
+
|
|
350
369
|
function expandHome(input) {
|
|
351
370
|
if (input === "~") return os.homedir();
|
|
352
371
|
if (input.startsWith("~/")) return path.join(os.homedir(), input.slice(2));
|
|
@@ -659,14 +678,14 @@ async function runExpression(input, state) {
|
|
|
659
678
|
}
|
|
660
679
|
const mainRel = annotated.rels.__main__;
|
|
661
680
|
run.defs = annotated;
|
|
681
|
+
let result;
|
|
662
682
|
try {
|
|
663
|
-
|
|
683
|
+
result = run(codes.find, mainRel.def, state.value, mainRel.typePatternGraph);
|
|
664
684
|
} catch (error) {
|
|
665
685
|
throw remapError(error, preambleLineCount(preamble));
|
|
666
686
|
}
|
|
667
|
-
state.lastMain = expression;
|
|
668
687
|
restoreCodes(state);
|
|
669
|
-
return
|
|
688
|
+
return commitResult(state, result, expression);
|
|
670
689
|
}
|
|
671
690
|
|
|
672
691
|
async function runSnippet(input, state, options = {}) {
|
|
@@ -685,14 +704,14 @@ async function runSnippet(input, state, options = {}) {
|
|
|
685
704
|
|
|
686
705
|
const mainRel = annotated.rels.__main__;
|
|
687
706
|
run.defs = annotated;
|
|
707
|
+
let result;
|
|
688
708
|
try {
|
|
689
|
-
|
|
709
|
+
result = run(codes.find, mainRel.def, state.value, mainRel.typePatternGraph);
|
|
690
710
|
} catch (error) {
|
|
691
711
|
throw remapError(error, lineOffset);
|
|
692
712
|
}
|
|
693
|
-
state.lastMain = snippet;
|
|
694
713
|
restoreCodes(state);
|
|
695
|
-
return
|
|
714
|
+
return commitResult(state, result, snippet);
|
|
696
715
|
}
|
|
697
716
|
|
|
698
717
|
async function evaluateInput(input, state) {
|
|
@@ -803,13 +822,13 @@ async function evaluateCommand(line, state) {
|
|
|
803
822
|
if (!arg) throw new Error(`${usagePrefix}d requires a relation name`);
|
|
804
823
|
const { hash, rel } = resolveRel(state, arg);
|
|
805
824
|
if (!rel) throw new Error(`Unknown relation '${arg}'`);
|
|
806
|
-
return [`${arg} = ${prettyRelation(rel)}; -- ${hash}`];
|
|
825
|
+
return [`${arg} = ${prettyRelation(rel, displayAliases(state), state.relAliases)}; -- ${hash}`];
|
|
807
826
|
}
|
|
808
827
|
case "C": {
|
|
809
828
|
if (!arg) throw new Error(`${usagePrefix}C requires a type name`);
|
|
810
829
|
const hash = state.typeAliases[arg] || (arg.startsWith("@") ? arg : null);
|
|
811
830
|
if (!hash || !(hash in state.codes)) throw new Error(`Unknown type '${arg}'`);
|
|
812
|
-
return [`$ ${arg} = ${prettyCode(
|
|
831
|
+
return [`$ ${arg} = ${prettyCode(displayAliases(state), codes.find, codes.find(hash))}; -- ${hash}`];
|
|
813
832
|
}
|
|
814
833
|
default:
|
|
815
834
|
throw new Error(`Unknown command ':${command}'. Try :help`);
|
package/test-repl.mjs
CHANGED
|
@@ -36,6 +36,13 @@ assert.match(output[0], /^succ = @/m);
|
|
|
36
36
|
output = await evaluateInput(":run succ", state);
|
|
37
37
|
assert.equal(output[0], "{}|succ ?<{} succ, ...>");
|
|
38
38
|
|
|
39
|
+
output = await evaluateInput("/zero", state);
|
|
40
|
+
assert.equal(output[0], "... undefined");
|
|
41
|
+
assert.equal(state.value.toJSON(), "succ");
|
|
42
|
+
|
|
43
|
+
output = await evaluateInput("succ", state);
|
|
44
|
+
assert.match(output[0], /^\{\}\|succ\|succ \?</);
|
|
45
|
+
|
|
39
46
|
output = await evaluateInput(":t succ", state);
|
|
40
47
|
assert.match(output[0], /^succ : /);
|
|
41
48
|
|
|
@@ -97,7 +104,7 @@ const objectFn = objectToFunction(decodeObject(fs.readFileSync(koPath)));
|
|
|
97
104
|
const objectResult = objectFn(new Product({}, [["closed-product", []]]));
|
|
98
105
|
assert.equal(objectResult.toJSON(), "succ");
|
|
99
106
|
|
|
100
|
-
fs.writeFileSync(sourcePath, "$ nat = <{} zero, nat succ>;\nsucc = |succ;\n");
|
|
107
|
+
fs.writeFileSync(sourcePath, "$ nat = <{} zero, nat succ>;\nsucc = $nat |succ $nat;\ntwice = succ succ;\n");
|
|
101
108
|
const loadedSource = createState();
|
|
102
109
|
output = await evaluateInput(`:load ${sourcePath}`, loadedSource);
|
|
103
110
|
assert.equal(output[0], `loaded ${sourcePath}`);
|
|
@@ -105,6 +112,10 @@ output = await evaluateInput(":codes", loadedSource);
|
|
|
105
112
|
assert.match(output[0], /^nat = @/m);
|
|
106
113
|
output = await evaluateInput(":rels", loadedSource);
|
|
107
114
|
assert.match(output[0], /^succ = @/m);
|
|
115
|
+
output = await evaluateInput(":d twice", loadedSource);
|
|
116
|
+
assert.match(output[0], /^twice = \$nat succ succ \$nat; -- @/);
|
|
117
|
+
output = await evaluateInput(":C nat", loadedSource);
|
|
118
|
+
assert.match(output[0], /^\$ nat = < nat succ, @[^ ]+ zero >; -- @/);
|
|
108
119
|
|
|
109
120
|
const replPath = fileURLToPath(new URL("./repl.mjs", import.meta.url));
|
|
110
121
|
try {
|
package/.codex
DELETED
|
File without changes
|