@fraczak/k 3.0.2 → 3.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/BIG_PICTURE.md CHANGED
@@ -170,7 +170,7 @@ Functions `bit0`, `bit1`, and `zero` are "constant polymorphic functions", meani
170
170
 
171
171
  - constant: if defined, they always return exactly the same value;
172
172
  - polymorphic: they are defined for more than one pair of input and output type: functions
173
- `bit1` and `bit2` are of type `X -> bit`, and `zero` is of type `X -> byte`, where `X`
173
+ `bit0` and `bit1` are of type `X -> bit`, and `zero` is of type `X -> byte`, where `X`
174
174
  denotes an unconstrained type pattern.
175
175
 
176
176
  Functions `inc` and `inc3` are (non-polymorphic) functions of types
@@ -191,20 +191,29 @@ following constraints:
191
191
  The type pattern for `Y` is _singleton_, as only one type fits the pattern,
192
192
  whereas the other type patterns are not.
193
193
 
194
- In this example, we were able to find the most general type pattern for all sub-expressions of the program. However, we still do not have a way to find the most general type patterns in the general case. This is work in progress.
194
+ In this example, we were able to find the most general type pattern for all sub-expressions of the program.
195
+ However, we still do not have a way to find the most general type patterns in the general case.
196
+ This is work in progress.
195
197
 
196
198
  ## Universal Schema Registry
197
199
 
198
- Since the normalization process for types is fast and deterministic, we can build a universal schema registry that will store all invented types. The registry will be a key-value store, where the key is the hash of the normalized type, and the value is the normalized type itself.
200
+ Since the normalization process for types is fast and deterministic, we can build a universal schema registry that will store all invented types.
201
+ The registry will be a key-value store, where the key is the hash of the normalized type, and the value is the normalized type itself.
199
202
 
200
203
  All functions (non-polymorphic and polymorphic) will be renamed by the hash of their normalized definition and stored in the similar key-value store.
201
204
 
202
- Non-polymorphic functions can be easily indexed by the hashes of their input and output types so that we can quickly find the function we need, e.g., for autocomplition. Searching for polymorphic functions is more complicated, as we need to find the function whose input and output type patterns fit given types.
203
-
205
+ Non-polymorphic functions can be easily indexed by the hashes of their input and output types so that we can quickly find the function we need, e.g., for autocomplition.
206
+ Searching for polymorphic functions is more complicated, as we need to find the function whose input and output type patterns fit given types.
204
207
 
205
208
  ## Serialization and Compilation
206
209
 
207
- The language is designed to transform _codes_, i.e., serialized typed values, i.e., trees accepted by a tree automaton, into other _codes_. The transformation is done by partial functions as defined in the language. The non-recursive and tail-recursive (and even some non-tail recursive) functions can be compiled into deterministic finite (pushdown) transducers.
210
+ The language is designed to transform _codes_, i.e., serialized typed values, i.e., trees accepted by a tree automaton, into other _codes_.
211
+ The transformation is done by partial functions as defined in the language.
212
+ The non-recursive and tail-recursive (and even some non-tail recursive) functions can be compiled into deterministic finite (pushdown) transducers.
213
+
214
+ ### AND-OR graphs for enconding and decoding codes
215
+
216
+
208
217
 
209
218
  ## Linking with Other Languages
210
219
 
@@ -0,0 +1,27 @@
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/blowup.k").toString("utf8"), (annotated) => {
6
+ // // console.log(JSON.stringify(annotated,null,2));
7
+ // const {input,output} = in_out(annotated);
8
+ // console.log(input);
9
+ // console.log(output);
10
+ // assert.equal(output.pattern, '<...>');
11
+ // assert.equal(input.pattern, '(...)');
12
+ // console.log("OK");
13
+ // });
14
+
15
+ t(`
16
+ B = {{} u} A;
17
+ A = < .a, .b A, .c {() z} A, B >;
18
+ A
19
+ `, (annotated) => {
20
+ // console.log(JSON.stringify(annotated,null,2));
21
+ const {input,output} = in_out(annotated);
22
+ console.log(input);
23
+ console.log(output);
24
+ assert.equal(output.type, annotated.representatives["bnat"]);
25
+ assert.equal(input.type, annotated.representatives["pair"]);
26
+ console.log("OK");
27
+ });
@@ -3,8 +3,10 @@ import fs from 'node:fs';
3
3
  import assert from 'assert';
4
4
 
5
5
  t(fs.readFileSync("./Examples/bnat-patterns.k").toString("utf8"), (annotated) => {
6
+ // console.log(JSON.stringify(annotated,null,2));
6
7
  const {input,output} = in_out(annotated);
7
- assert.equal(output.code, annotated.representatives["bnat"]);
8
- assert.equal(input.code, annotated.representatives["pair"]);
8
+ // console.log(output);
9
+ assert.equal(output.type, annotated.representatives["bnat"]);
10
+ assert.equal(input.type, annotated.representatives["pair"]);
9
11
  console.log("OK");
10
12
  });
@@ -4,7 +4,7 @@ import assert from 'assert';
4
4
  function is_result_code(code) {
5
5
  return function(annotated) {
6
6
  const {output} = in_out(annotated);
7
- assert.strictEqual(output.code, code);
7
+ assert.strictEqual(output.type, code);
8
8
  console.log('OK');
9
9
  }
10
10
  }
@@ -9,7 +9,32 @@ $b {1 one, () two, () c} .one
9
9
 
10
10
  `, (annotated) => {
11
11
  const {input,output} = in_out(annotated);
12
- assert.equal(input.code, annotated.representatives["b"]);
13
- assert.equal(output.code, "int");
12
+ // console.log({input,output});
13
+ assert.equal(input.type, annotated.representatives["b"]);
14
+ assert.equal(output.type, "int");
14
15
  console.log("OK");
15
- });
16
+ });
17
+
18
+ t(`
19
+ $a = < int true, bool false > ;
20
+ $a .true
21
+ `, (annotated) => {
22
+ const {input,output} = in_out(annotated);
23
+ console.log({input,output});
24
+ });
25
+
26
+ t(`
27
+ x = .x;
28
+ xy = x.y;
29
+ f = {
30
+ { {5 y} x} xy i,
31
+ { {true y} x} xy b
32
+ };
33
+ f .b
34
+ `, (annotated) => {
35
+ const {input,output} = in_out(annotated);
36
+ console.log({input,output});
37
+ assert.equal(input.pattern, '(...)');
38
+ assert.equal(output.type, "bool");
39
+ console.log("OK");
40
+ });
@@ -1,8 +1,8 @@
1
1
  import { annotate } from "../index.mjs";
2
2
 
3
3
  function in_out(annotated) {
4
- const [input,output] = annotated.rels.__main__[0].patterns.map( (pat) =>
5
- annotated.patternNodes[pat]
4
+ const [input,output] = annotated.rels.__main__.def.patterns.map( (pat) =>
5
+ annotated.rels.__main__.typePatternGraph.get_pattern(pat)
6
6
  );
7
7
  return { input, output };
8
8
  }
@@ -3,7 +3,7 @@ import assert from 'assert';
3
3
 
4
4
  t(` < .a, () > `, (annotated) => {
5
5
  const {input,output} = in_out(annotated);
6
- assert.equal(input.type, "union");
6
+ assert.equal(input.pattern, "(...)");
7
7
  assert.equal(output, input);
8
8
  console.log("OK");
9
9
  });
@@ -4,7 +4,7 @@ import assert from 'assert';
4
4
 
5
5
  t(fs.readFileSync("./Examples/nat.k").toString("utf8"), (annotated) => {
6
6
  const {input,output} = in_out(annotated);
7
- assert.equal(output.code, annotated.representatives["nat"]);
8
- assert.equal(input.code, annotated.representatives["nat"]);
7
+ assert.equal(output.type, annotated.representatives["nat"]);
8
+ assert.equal(input.type, annotated.representatives["nat"]);
9
9
  console.log("OK");
10
10
  });
@@ -8,7 +8,7 @@ t(`$b = < {} true, {} false > ;
8
8
  not not
9
9
  `, (annotated) => {
10
10
  const {input,output} = in_out(annotated);
11
- assert.equal(input.code, annotated.representatives["b"]);
12
- assert.equal(output.code, annotated.representatives["b"]);
11
+ assert.equal(input.type, annotated.representatives["b"]);
12
+ assert.equal(output.type, annotated.representatives["b"]);
13
13
  console.log("OK");
14
14
  });
@@ -1,10 +1,13 @@
1
1
  import { t, in_out } from './index.mjs';
2
2
  import assert from 'assert';
3
+ import hash from "../hash.mjs";
4
+
5
+ const unitCode = hash('$C0={};');
3
6
 
4
7
  t('{}', (annotated) => {
5
8
  const {input,output} = in_out(annotated);
6
- assert.equal(input.type, null);
7
- assert.equal(output.code, annotated.representatives["{}"]);
9
+ assert.equal(input.pattern, '(...)');
10
+ assert.equal(output.type, unitCode);
8
11
  console.log("OK");
9
12
  });
10
13
 
@@ -12,10 +15,11 @@ t(`
12
15
  $b = < {} true, {} false > ;
13
16
  $pair = { b one, b two } ;
14
17
 
15
- {() one, () two} $pair
18
+ {() one, () two} $pair
16
19
  `, (annotated) => {
17
20
  const {input,output} = in_out(annotated);
18
- assert.equal(input.code, annotated.representatives["b"]);
19
- assert.equal(output.code, annotated.representatives["pair"]);
21
+
22
+ assert.equal(input.type, annotated.representatives["b"]);
23
+ assert.equal(output.type, annotated.representatives["pair"]);
20
24
  console.log("OK");
21
25
  });
@@ -8,7 +8,7 @@ t(`
8
8
  rlz
9
9
  `, (annotated) => {
10
10
  const {input,output} = in_out(annotated);
11
- assert.equal(output.code, annotated.representatives["nat"]);
12
- assert.equal(input.code, annotated.representatives["nat"]);
11
+ assert.equal(output.type, annotated.representatives["nat"]);
12
+ assert.equal(input.type, annotated.representatives["nat"]);
13
13
  console.log("OK");
14
14
  });
@@ -3,26 +3,20 @@ import assert from 'assert';
3
3
 
4
4
  t('[]', (annotated) => {
5
5
  const {input,output} = in_out(annotated);
6
- assert.equal(input.type, null);
7
- assert.equal(output.type, "vector");
6
+ assert.equal(input.pattern, '(...)');
7
+ assert.equal(output.pattern, "[]");
8
8
  console.log("OK");
9
9
  });
10
10
 
11
- t(`$int [ $int true, false ]`, (annotated) => {
11
+ t("$int [ $int true, false ] .0", (annotated) => {
12
12
  const {input,output} = in_out(annotated);
13
- assert.equal(input.code, "int");
14
- assert.equal(output.type, "vector");
13
+ assert.equal(input.type, "int");
14
+ assert.equal(output.type, "bool");
15
15
  console.log("OK");
16
16
  });
17
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");
18
+ assert.throws(() => t(`$int [ $int true, 12 ]`), /Error/);
19
+ console.log("The both errors are expected...");
20
+ console.log("OK");
27
21
 
28
22
  // t(`[]`);
package/Graph.mjs ADDED
@@ -0,0 +1,95 @@
1
+ class Graph {
2
+ constructor(edges, vertices = {}) {
3
+ this.edges = edges;
4
+ this.vertices = vertices;
5
+ for (const dir of ['src', 'dst']) {
6
+ this[dir] = {};
7
+ for (let i=0; i < edges.length; i++) {
8
+ const e = edges[i];
9
+ if (vertices[e[dir]] == undefined) {
10
+ vertices[e[dir]] = {
11
+ _rem: "discovered"
12
+ };
13
+ }
14
+ if (this[dir][e[dir]] == null) {
15
+ this[dir][e[dir]] = [];
16
+ }
17
+ this[dir][e[dir]].push(i);
18
+ }
19
+ }
20
+ }
21
+ }
22
+
23
+ function sccs(graph) {
24
+ const stack = [];
25
+ const disc = {};
26
+ const low = {};
27
+ const inStack = {};
28
+ const sccs = [];
29
+ let time = 0;
30
+
31
+ const dfs = (u) => {
32
+ disc[u] = low[u] = time++;
33
+ stack.push(u);
34
+ inStack[u] = true;
35
+
36
+ for (const e of graph.src[u] || []) {
37
+ const v = graph.edges[e].dst;
38
+ if (disc[v] == undefined) {
39
+ dfs(v);
40
+ low[u] = Math.min(low[u], low[v]);
41
+ } else if (inStack[v]) {
42
+ low[u] = Math.min(low[u], disc[v]);
43
+ }
44
+ }
45
+
46
+ if (low[u] === disc[u]) {
47
+ const scc = [];
48
+ let w;
49
+ do {
50
+ w = stack.pop();
51
+ inStack[w] = false;
52
+ scc.push(w);
53
+ } while (w !== u);
54
+ sccs.push(scc);
55
+ }
56
+ };
57
+
58
+ for (const x in graph.vertices) {
59
+ if (disc[x] == undefined) {
60
+ dfs(x);
61
+ }
62
+ }
63
+ return sccs;
64
+ };
65
+
66
+ function topoOrder(graph){
67
+ const starts = [];
68
+ const result = [];
69
+ const inDegree = {};
70
+ for (const v in graph.vertices) {
71
+ const degree = graph.dst[v]?.length || 0;
72
+ if (degree == 0) {
73
+ starts.push(v);
74
+ } else {
75
+ inDegree[v] = degree;
76
+ }
77
+ }
78
+
79
+ let x;
80
+ while (x = starts.pop()) {
81
+ result.push(x);
82
+ const outs = graph.src[x] || [];
83
+ for (const e of outs) {
84
+ const y = graph.edges[e].dst;
85
+ inDegree[y]--;
86
+ if (inDegree[y] == 0) {
87
+ starts.push(y);
88
+ }
89
+ }
90
+ }
91
+ return result;
92
+ }
93
+
94
+ export { Graph, sccs, topoOrder };
95
+ export default { Graph, sccs, topoOrder };