@fraczak/k 2.1.5 → 3.0.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.
@@ -0,0 +1,10 @@
1
+ import { t, in_out } from './index.mjs';
2
+ import fs from 'node:fs';
3
+ import assert from 'assert';
4
+
5
+ t(fs.readFileSync("./Examples/bnat-patterns.k").toString("utf8"), (annotated) => {
6
+ const {input,output} = in_out(annotated);
7
+ assert.equal(output.code, annotated.representatives["bnat"]);
8
+ assert.equal(input.code, annotated.representatives["pair"]);
9
+ console.log("OK");
10
+ });
@@ -0,0 +1,19 @@
1
+ import { t, in_out } from './index.mjs';
2
+ import assert from 'assert';
3
+
4
+ function is_result_code(code) {
5
+ return function(annotated) {
6
+ const {output} = in_out(annotated);
7
+ assert.strictEqual(output.code, code);
8
+ console.log('OK');
9
+ }
10
+ }
11
+
12
+ t('true', is_result_code('bool'));
13
+ t('false $bool', is_result_code('bool'));
14
+ t('1', is_result_code('int'));
15
+ t('12 $int', is_result_code('int'));
16
+ t('"ala"', is_result_code('string'));
17
+ t('"a" $string', is_result_code('string'));
18
+
19
+ t('${} true $bool 1 $int "a" $string', is_result_code('string'));
@@ -0,0 +1,15 @@
1
+ import { t, in_out } from './index.mjs';
2
+ import assert from 'assert';
3
+
4
+ t(`
5
+ $b = < {} true, {} false > ;
6
+ $pair = { b one, b two } ;
7
+
8
+ $b {1 one, () two, () c} .one
9
+
10
+ `, (annotated) => {
11
+ const {input,output} = in_out(annotated);
12
+ assert.equal(input.code, annotated.representatives["b"]);
13
+ assert.equal(output.code, "int");
14
+ console.log("OK");
15
+ });
@@ -0,0 +1,20 @@
1
+ import { annotate } from "../index.mjs";
2
+
3
+ function in_out(annotated) {
4
+ const [input,output] = annotated.rels.__main__[0].patterns.map( (pat) =>
5
+ annotated.patternNodes[pat]
6
+ );
7
+ return { input, output };
8
+ }
9
+
10
+
11
+ function t(script, cb = (annotated) => console.log(in_out(annotated))) {
12
+ // console.log("--- Testing Code Derivation ---");
13
+ const annotated = annotate(script);
14
+ // console.log(JSON.stringify(annotated, "", 2));
15
+ return cb(annotated);
16
+ }
17
+
18
+ export default { t, in_out };
19
+ export { t, in_out };
20
+
@@ -0,0 +1,11 @@
1
+ import { t, in_out } from './index.mjs';
2
+ import assert from 'assert';
3
+
4
+ t(` < .a, () > `, (annotated) => {
5
+ const {input,output} = in_out(annotated);
6
+ assert.equal(input.type, "union");
7
+ assert.equal(output, input);
8
+ console.log("OK");
9
+ });
10
+
11
+ // Notice that the following are equivalent: '<(), .a>', '<()>', and '()';
@@ -0,0 +1,10 @@
1
+ import { t, in_out } from './index.mjs';
2
+ import fs from 'node:fs';
3
+ import assert from 'assert';
4
+
5
+ t(fs.readFileSync("./Examples/nat.k").toString("utf8"), (annotated) => {
6
+ const {input,output} = in_out(annotated);
7
+ assert.equal(output.code, annotated.representatives["nat"]);
8
+ assert.equal(input.code, annotated.representatives["nat"]);
9
+ console.log("OK");
10
+ });
@@ -0,0 +1,14 @@
1
+ import { t, in_out } from './index.mjs';
2
+ import assert from 'assert';
3
+
4
+ t(`$b = < {} true, {} false > ;
5
+ true = {{} true} $b;
6
+ false = {{} false} $b;
7
+ not = $b < .true false, .false true >;
8
+ not not
9
+ `, (annotated) => {
10
+ const {input,output} = in_out(annotated);
11
+ assert.equal(input.code, annotated.representatives["b"]);
12
+ assert.equal(output.code, annotated.representatives["b"]);
13
+ console.log("OK");
14
+ });
@@ -0,0 +1,21 @@
1
+ import { t, in_out } from './index.mjs';
2
+ import assert from 'assert';
3
+
4
+ t('{}', (annotated) => {
5
+ const {input,output} = in_out(annotated);
6
+ assert.equal(input.type, null);
7
+ assert.equal(output.code, annotated.representatives["{}"]);
8
+ console.log("OK");
9
+ });
10
+
11
+ t(`
12
+ $b = < {} true, {} false > ;
13
+ $pair = { b one, b two } ;
14
+
15
+ {() one, () two} $pair
16
+ `, (annotated) => {
17
+ const {input,output} = in_out(annotated);
18
+ assert.equal(input.code, annotated.representatives["b"]);
19
+ assert.equal(output.code, annotated.representatives["pair"]);
20
+ console.log("OK");
21
+ });
@@ -0,0 +1,14 @@
1
+ import { t, in_out } from './index.mjs';
2
+ import assert from 'assert';
3
+
4
+ t(`
5
+ $nat = < {} _, nat 0, nat 1>;
6
+ zero = {{{} _} 0} $nat;
7
+ rlz = <.0._ zero, .0 rlz, ()>;
8
+ rlz
9
+ `, (annotated) => {
10
+ const {input,output} = in_out(annotated);
11
+ assert.equal(output.code, annotated.representatives["nat"]);
12
+ assert.equal(input.code, annotated.representatives["nat"]);
13
+ console.log("OK");
14
+ });
@@ -0,0 +1,28 @@
1
+ import { t, in_out } from './index.mjs';
2
+ import assert from 'assert';
3
+
4
+ t('[]', (annotated) => {
5
+ const {input,output} = in_out(annotated);
6
+ assert.equal(input.type, null);
7
+ assert.equal(output.type, "vector");
8
+ console.log("OK");
9
+ });
10
+
11
+ t(`$int [ $int true, false ]`, (annotated) => {
12
+ const {input,output} = in_out(annotated);
13
+ assert.equal(input.code, "int");
14
+ assert.equal(output.type, "vector");
15
+ console.log("OK");
16
+ });
17
+
18
+ t(`$int [ $int true, false ] .0`, (annotated) => {
19
+ const {input,output} = in_out(annotated);
20
+ assert.equal(input.code, "int");
21
+ assert.equal(output.code, "bool");
22
+ console.log("OK");
23
+ });
24
+
25
+ // assert.throws(() => t(`$int [ $int true, 12 ]`), /Error/);
26
+ // console.log("OK");
27
+
28
+ // t(`[]`);
package/INTRO.md ADDED
@@ -0,0 +1,88 @@
1
+ ### Introduction to Kernel/Core
2
+
3
+ **Kernel/Core** is a minimal, gradually typed, first-order functional programming language designed for defining and transforming data using partial functions. It is built on the foundation of Algebraic Data Types (ADTs), specifically tagged unions and products.
4
+
5
+ #### Core Concepts
6
+
7
+ 1. **Statements**:
8
+ - The program consists of a possibly empty list of statements, each ending with a semicolon (`;`), followed by an expression.
9
+ - There are two types of statements:
10
+ - **Code Definitions**: Define data types and start with a dollar sign (`$`).
11
+ - **Relation Definitions**: Define partial functions (transformations) of data.
12
+
13
+ 2. **Codes**:
14
+ - Codes represent data types and can be either unions (`<...>`) or products (`{...}`).
15
+ - Example:
16
+ ```kernelcore
17
+ $ bool = <{} true, {} false>;
18
+ $ pair_of_bools = {bool x, bool y};
19
+ ```
20
+
21
+ 3. **Relations**:
22
+ - Relations are partial functions defined to transform data from one type to another.
23
+ - Example:
24
+ ```kernelcore
25
+ is_x_true = $pair_of_bools (.x .true);
26
+ ```
27
+
28
+ 4. **Composition of Partial Functions**:
29
+ - **Sequential (Functional) Composition**: Sequential application of partial functions.
30
+ ```kernelcore
31
+ (.x .true)
32
+ ```
33
+ - **Parallel (Product) Composition**: Combine multiple partial functions to construct a new product type.
34
+ ```kernelcore
35
+ {.x x_value, .y y_value}
36
+ ```
37
+ - **Concurrent (Union) Composition**: Try different functions in sequence, returning the first successful result.
38
+ ```kernelcore
39
+ <{.x .true false_bool}, {} true_bool>
40
+ ```
41
+
42
+ 5. **Constants**:
43
+ - Constants are defined as partial functions that ignore their input.
44
+ - Example:
45
+ ```kernelcore
46
+ true_bool = {{} true} $bool;
47
+ false_bool = {{} false} $bool;
48
+ ```
49
+
50
+ #### Example Program
51
+
52
+ ```kernelcore
53
+ // Define a boolean type as a union of true and false
54
+ $ bool = <{} true, {} false>;
55
+
56
+ // Define a pair of booleans as a product of two booleans
57
+ $ pair_of_bools = {bool x, bool y};
58
+
59
+ // Check if the `x` field is `true`
60
+ is_x_true = $pair_of_bools (.x .true);
61
+
62
+ // Extract both `x` and `y` fields into a new product
63
+ extract_both = $pair_of_bools {.x x_value, .y y_value} $pair_of_bools;
64
+
65
+ // Check if either `x` or `y` is `true`
66
+ is_any_true = $pair_of_bools <{.x .true false_bool}, {} true_bool> $bool;
67
+
68
+ // Define constants
69
+ true_bool = {{} true} $bool;
70
+ false_bool = {{} false} $bool;
71
+
72
+ // Create instances of `pair_of_bools`
73
+ pair1 = {true_bool x, true_bool y} $pair_of_bools;
74
+ pair2 = {true_bool x, false_bool y} $pair_of_bools;
75
+ pair3 = {false_bool x, false_bool y} $pair_of_bools;
76
+
77
+ // Example usage of the functions
78
+ result1 = pair1 is_x_true; // Should return true
79
+ result2 = pair2 is_x_true; // Should return true
80
+
81
+ both_values = pair1 extract_both; // Should return {x_value true, y_value true}
82
+
83
+ any_true1 = pair1 is_any_true; // Should return true
84
+ any_true2 = pair2 is_any_true; // Should return true
85
+ any_true3 = pair3 is_any_true; // Should return false
86
+ ```
87
+
88
+ This brief introduction covers the fundamental concepts of Kernel/Core, enabling you to start defining data types and writing partial functions to transform data.
package/README.md CHANGED
@@ -76,9 +76,10 @@ There are three ways of combining functions:
76
76
  ### Syntactic sugar
77
77
 
78
78
  - parenthesis can be omitted, except for the empty composition `()`,
79
- - dot (`.`) in "projection" acts as a separator so the space around it can be omitted.
79
+ - dot (`.`) in "projection" acts as a separator so the space around it
80
+ can be omitted.
80
81
 
81
- For example, `[(.toto .titi (.0 .1))]` can be written as `[.toto.titi.0.1]`.
82
+ For example, `(.toto .titi (.0 .1))` can be written as `.toto.titi.0.1`.
82
83
 
83
84
  Comments can be introduced by `//`, `--`, `%`, or `#` and extends to
84
85
  the end of line. Multiline `C`-like comments, `/* ... */`, are also
@@ -118,8 +119,9 @@ projection to the canonicat string representation of the value, e.g.:
118
119
  #### Vector product
119
120
 
120
121
  Vector product can be seen as an abbreviation for product whose field
121
- names are integers starting from zero. E.g., `{.toto 0, .titi 1, 123 2}`
122
- can be written as `[.toto, .titi, 123]`.
122
+ names are integers starting from zero.
123
+ E.g., `{.toto 0, .titi 1, 123 2}` can be written as
124
+ `[.toto, .titi, 123]`.
123
125
 
124
126
  [.toto, .titi, 12] :
125
127
  {"toto": 5, "titi": 10 } --> [5, 10, 12]
@@ -128,6 +130,9 @@ can be written as `[.toto, .titi, 123]`.
128
130
  ["A","B","C"] --> "B"
129
131
  ["a"] ... undefined
130
132
 
133
+ The vector notation is introduced to satisfy JSON syntax and, for example,
134
+ is not supported in _code derivation_ (explained below).
135
+
131
136
  ---
132
137
 
133
138
  ### Pragmatic extensions, aka "standard library"
@@ -172,8 +177,8 @@ can be written as `[.toto, .titi, 123]`.
172
177
  "[1,2.11,0.3e-32]" --> [1,2.11,3e-33]
173
178
 
174
179
 
175
- - other predefined parial functions are: `DIV`, `FDIV`, `CONS`, `SNOC`, `toDateMsec`,
176
- `toDateStr`, and `_log!`.
180
+ - other predefined parial functions are: `DIV`, `FDIV`, `CONS`,
181
+ `SNOC`, `toDateMsec`, `toDateStr`, and `_log!`.
177
182
 
178
183
  ---
179
184
 
@@ -183,7 +188,8 @@ can be written as `[.toto, .titi, 123]`.
183
188
  max = <SNOC [.0, .1 max] <GT.0, .1>, .0> ;
184
189
  factorial = < [(),0] GT .0 [dec factorial, ()] TIMES, 1 >;
185
190
 
186
- _Codes_ (prefixed by `$`) can be defined by taged union and product. E.g.:
191
+ ### Codes (schemas, i.e., _non-functional types_)
192
+ _Codes_ (prefixed by `$`) can be defined by tagged union and product. E.g.:
187
193
 
188
194
 
189
195
  $nat = <nat 1, {} 0>;
@@ -192,18 +198,67 @@ _Codes_ (prefixed by `$`) can be defined by taged union and product. E.g.:
192
198
  suc = {$nat 1};
193
199
  add = $pair <{.x.1 x, .y suc y} add, .y>;
194
200
 
201
+ Two codes are considered equal when they are isomorphic (preserving
202
+ union/product and field names). E.g., `$pair`, `${nat y, nat x}`, and
203
+ `${<nat 1, {} 0> x, nat y}` are all equal.
204
+
195
205
  #### Basic extension codes
196
206
 
197
- Since _basic extension_ introduces integers, booleans, and strings, there are three
198
- predefined types: `int`, `bool`, and `string`. A vector product code can also be defined
199
- by `[ codeExp ]`. All members of the vector are the same code. E.g.,
207
+ Since _basic extension_ introduces integers, booleans, and strings,
208
+ there are three predefined types: `int`, `bool`, and `string`. A
209
+ vector product code can also be defined by `[ codeExp ]`. All members
210
+ of the vector are the same code. E.g.,
200
211
 
201
212
  $intVector = [ int ];
202
213
  $boolVector = [ bool ];
203
214
  $tree = [ tree ];
204
215
 
205
- emptyList? = $intVector $[ string ]; -- as only an empty vector can be a vector
206
- -- of integers and a vector of strings
216
+ ### Code derivation and Patterns
217
+
218
+ Intuitively, a _pattern_ represents some set of contraints on
219
+ codes. For example, expression `.toto` is a projection from a value of
220
+ a product or a union with field `toto`. Therefore, expression `.toto`
221
+ introduces two patterns `p_i` and `p_o` (for input and output codes,
222
+ respectively); `p_o` imposes no constraint on code, however `p_i` is a
223
+ product or union code with field `toto` leading to a code fulfilling
224
+ `p_o`, i.e., something like `< ? toto, ... >` or `{ ? toto, ... }`.
225
+
226
+ .toto
227
+ p_i p_o
228
+
229
+ In a more complex expression each (occurrence of) subexpression will
230
+ introduce some new patterns.
231
+ For example, concider `<.toto, ()>`:
232
+
233
+ < .toto , () >
234
+ p1 p2 p3 p4 p5 p6
235
+
236
+ where `p1` is the pattern for the input code of the whole expression,
237
+ and `p6` is the pattern for the output. We can deduce that patterns
238
+ (`p1`, `p2`, `p4`) defines the same code, as well as (`p6`, `p5`, `p3`),
239
+ because union combines partial functions with the same input and output codes.
240
+ Identity, `()`, implies that (`p4`, `p5`) define the
241
+ same code. That means that in our expression, we deal with only one
242
+ code, `c`, product or union, with field `toto` of type `c`, i.e.,
243
+
244
+ $c = < c toto, ... >;
245
+
246
+ or
247
+
248
+ $c = { c toto, ... };
249
+
250
+ Since the product code pattern (i.e., latter case) doesn't admmit any
251
+ (finite) value, we conclude that the code `c` is a union (i.e.,
252
+ former case).
253
+
254
+ For a given `kScript`, code derivation (as any static analysis) can
255
+ fail, indicating that the script is invalid. In some other cases the
256
+ code derivation can succeed even to the point of reducig every pattern
257
+ to a single code making the program fully annotated by codes.
258
+
259
+ For now, `code derivation` is supported by the core language, i.e., `composition`,
260
+ `projection` and `union` with product and tagged union types.
261
+
207
262
  ---
208
263
 
209
264
  ### List comprehension on vectors (experimental!)
@@ -259,8 +314,7 @@ times value `x` appears in the list. (see `Examples/list-comprehension.k` for a
259
314
  ."field name"
260
315
  .4
261
316
 
262
- The function is defined only if its argument is a structure with
263
- the field (or a vector with the index).
317
+ The function is defined if its argument "has" the field.
264
318
 
265
319
  2. _constants_, literals for Strings, Booleans, and
266
320
  Integers. Examples:
package/TODO.md ADDED
@@ -0,0 +1,54 @@
1
+ # TODO list
2
+
3
+ - [ ] Incremental compilation
4
+ - [ ] After `annotation` is done, find fully closed patterns, turn them into codes, then rerun
5
+ the code minimization step
6
+ - [ ] Named relations can be polymorphic:
7
+ -- can we introduce polymorphic patterns? E.g.,: `{ .x if, .y then} .then`.
8
+ Here, the input pattern could be "open" product with two fields `.x` and `.y`, end the ouput pattern could be the pattern of field `.y`.
9
+ -- should we introduce a scope (e.g., syntactic or dynamic?) for all calls to the relation and
10
+ run annotations for all scopes separately?
11
+ - [ ] Implement support for different relations under a same name as long as they have
12
+ "very" different input or output patterns.
13
+ - [ ] In type graphs, we should detect cycles over only product types and reject such programs, e.g.,:
14
+
15
+ ```k
16
+ $boo = {{} _, boo b};
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Type system
22
+
23
+ Example:
24
+
25
+ ```Examples/pats.k
26
+ xy = .x y;
27
+ y = .y;
28
+ $A = < {} a, {} other >;
29
+ $B = < {} b, {} other >;
30
+ $ya = < {} a, $A y >;
31
+ $yb = < {} b, $B y >;
32
+ $input = {{ya x, {} y} one, {yb x, {} y} two};
33
+ $input {.one xy one, .two xy two}
34
+ ```
35
+
36
+ We would like to correctly type the above program as `$input -> { A one, B two }`.
37
+
38
+ filters for typing `__main__`:
39
+
40
+ ```?
41
+ __main__
42
+ 0 / \ 1
43
+ / \
44
+ $input {.one xy one, .two xy two}
45
+ 2 3 4 / \ 5
46
+ / \
47
+ (.one xy) (.two xy)
48
+ / \ / \
49
+ 6 / \ 7 8 / \ 9
50
+ / \ / \
51
+ .one xy .two xy
52
+ 10 11 12 13 14 15 16 17
53
+
54
+ ```
package/TYPES.md ADDED
@@ -0,0 +1,32 @@
1
+ # What if we concider partial functions as filter-to-filter mappings?
2
+
3
+ ## Examples
4
+
5
+ ```k
6
+ .x :: ( X x, ... ) -> X
7
+ { f1 x1, f2 x2, ..., fn xn } :: X -> { f1(X) x1, f2(X) x2, ..., fn(X) xn }
8
+ { f x } :: X -> < f(X) x, ... >
9
+ < f1, f2, ..., fn > :: X -> f1(X) // f1 == f2 == ... == fn
10
+ [ f1, f2, ..., fn ] :: X -> [f1(X)] // f1 == f2 == ... == fn
11
+ $code ::
12
+ ```
13
+
14
+ Let's consider the following example:
15
+
16
+ ```k
17
+ $nat = < {} _, nat s >;
18
+ z = {{} _}; -- X -> <{} _, ...>
19
+ s = {() s}; -- X -> <X s, ...>
20
+
21
+ add =
22
+ <
23
+ {.x ._ if, .y then} .then,
24
+ {.x .s x, .y s y } add
25
+ >
26
+ ;
27
+
28
+ double = {() x, () y} add;
29
+
30
+ z s s $nat double;
31
+ ```
32
+