@fraczak/k 5.1.2 → 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.
Files changed (99) hide show
  1. package/Code-derivation-tests/blowup.mjs +3 -3
  2. package/Code-derivation-tests/bnat.mjs +2 -2
  3. package/Code-derivation-tests/codec-witness-pattern.mjs +50 -0
  4. package/Code-derivation-tests/convergence-strategy.mjs +24 -0
  5. package/Code-derivation-tests/dot.mjs +12 -9
  6. package/Code-derivation-tests/filter-syntax.mjs +21 -0
  7. package/Code-derivation-tests/loop.mjs +8 -2
  8. package/Code-derivation-tests/nat.mjs +1 -1
  9. package/Code-derivation-tests/not-not.mjs +3 -3
  10. package/Code-derivation-tests/pattern-envelope.mjs +68 -0
  11. package/Code-derivation-tests/rlz.mjs +2 -2
  12. package/{BIG_PICTURE.md → DOCS/BIG_PICTURE.md} +103 -50
  13. package/DOCS/REPL.md +191 -0
  14. package/DOCS/book/01-introduction.md +51 -0
  15. package/DOCS/book/02-syntax-and-values.md +111 -0
  16. package/DOCS/book/03-types-as-finite-automata.md +156 -0
  17. package/DOCS/book/04-partial-functions-and-composition.md +146 -0
  18. package/DOCS/book/05-typing-filters-and-normalization.md +111 -0
  19. package/DOCS/book.md +54 -0
  20. package/README.md +204 -508
  21. package/TypeGraph.mjs +43 -0
  22. package/TypePatternGraph.mjs +251 -0
  23. package/Value.mjs +192 -0
  24. package/augmentation.mjs +198 -0
  25. package/codecs/BINARY_FORMAT.md +53 -0
  26. package/codecs/POLYMORPHIC_BINARY_FORMAT.md +303 -0
  27. package/codecs/README.md +215 -0
  28. package/codecs/example-pipeline.mjs +149 -0
  29. package/codecs/ieee.mjs +140 -0
  30. package/codecs/int.mjs +104 -0
  31. package/codecs/json-codec.mjs +215 -0
  32. package/codecs/json.mjs +40 -0
  33. package/codecs/k-parse.mjs +90 -0
  34. package/codecs/k-pattern.mjs +75 -0
  35. package/codecs/k-print.mjs +46 -0
  36. package/codecs/runtime/codec.mjs +768 -0
  37. package/codecs/runtime/ieee-pattern.mjs +30 -0
  38. package/codecs/runtime/pattern-json.mjs +96 -0
  39. package/codecs/runtime/prefix-codec.mjs +425 -0
  40. package/codecs/runtime/show-value.mjs +68 -0
  41. package/codecs/runtime/typeFromValue.mjs +34 -0
  42. package/codecs/runtime/unicode-string.mjs +220 -0
  43. package/codecs/show.mjs +41 -0
  44. package/codecs/string-codec.mjs +80 -0
  45. package/codecs/unit.mjs +51 -0
  46. package/codecs/utf16.mjs +66 -0
  47. package/codecs/utf8.mjs +37 -0
  48. package/codes.mjs +146 -44
  49. package/compiler.mjs +111 -0
  50. package/convergence.mjs +197 -0
  51. package/core.k +197 -0
  52. package/export.mjs +22 -32
  53. package/hash.mjs +29 -31
  54. package/index.mjs +41 -15
  55. package/k-vscode/.vscode/launch.json +14 -0
  56. package/k-vscode/README.md +65 -0
  57. package/k-vscode/language-configuration.json +42 -0
  58. package/k-vscode/package.json +57 -0
  59. package/k-vscode/snippets/k.json +92 -0
  60. package/k-vscode/syntaxes/k.tmLanguage.json +243 -0
  61. package/k.mjs +56 -54
  62. package/object.mjs +517 -0
  63. package/objects/README.md +38 -0
  64. package/objects/compile-lib.mjs +42 -0
  65. package/objects/compile.mjs +42 -0
  66. package/objects/decompile.mjs +32 -0
  67. package/package.json +18 -8
  68. package/parser.jison +27 -46
  69. package/parser.mjs +68 -100
  70. package/pretty.mjs +21 -40
  71. package/repl2.mjs +652 -0
  72. package/run.mjs +264 -231
  73. package/symbol-table.mjs +3 -17
  74. package/test-fingerprint.mjs +7 -7
  75. package/test-hash-fuzz.mjs +107 -0
  76. package/test-hash-normalization.mjs +134 -0
  77. package/test-k-object.mjs +74 -0
  78. package/test-repl2.mjs +95 -0
  79. package/test.mjs +45 -70
  80. package/tests.sh +10 -1
  81. package/typing.mjs +129 -676
  82. package/unification.mjs +157 -0
  83. package/valueIO.mjs +54 -0
  84. package/valueParser.jison +143 -0
  85. package/valueParser.mjs +713 -0
  86. package/Code-derivation-tests/built-in.mjs +0 -19
  87. package/Code-derivation-tests/vector.mjs +0 -19
  88. package/Filters/bug.k +0 -3
  89. package/Filters/composing.k +0 -15
  90. package/Filters/filter.k +0 -9
  91. package/TODO.md +0 -53
  92. package/TYPING.md +0 -365
  93. package/k-repl.cast +0 -1913
  94. package/k.cast +0 -618
  95. package/my-objects.json +0 -6
  96. package/patterns.mjs +0 -543
  97. package/repl.mjs +0 -213
  98. package/test-filters.mjs +0 -45
  99. package/typing-test.mjs +0 -40
@@ -2,7 +2,7 @@ import { t, in_out } from './index.mjs';
2
2
  import fs from 'node:fs';
3
3
  import assert from 'assert';
4
4
 
5
- // t(fs.readFileSync("./Examples/blowup.k").toString("utf8"), (annotated) => {
5
+ // t(fs.readFileSync("./Examples/blowup.k", "utf8"), (annotated) => {
6
6
  // // console.log(JSON.stringify(annotated,null,2));
7
7
  // const {input,output} = in_out(annotated);
8
8
  // console.log(input);
@@ -13,8 +13,8 @@ import assert from 'assert';
13
13
  // });
14
14
 
15
15
  t(`
16
- B = {{} u} A;
17
- A = < .a, .b A, .c {() z} A, B >;
16
+ B = {}|u A;
17
+ A = ?X < /a, /b ?X A, /c |z ?X A, B >;
18
18
  A
19
19
  `, (annotated) => {
20
20
  // console.log(JSON.stringify(annotated,null,2));
@@ -2,10 +2,10 @@ import { t, in_out } from './index.mjs';
2
2
  import fs from 'node:fs';
3
3
  import assert from 'assert';
4
4
 
5
- t(fs.readFileSync("./Examples/bnat-patterns.k").toString("utf8"), (annotated) => {
5
+ t(fs.readFileSync("./Examples/bnat.k", "utf8"), (annotated) => {
6
6
  // console.log(JSON.stringify(annotated,null,2));
7
7
  const {input,output} = in_out(annotated);
8
- console.log(output);
8
+ // console.log(output);
9
9
  assert.equal(output.type, annotated.representatives["bnat"]);
10
10
  assert.equal(input.type, annotated.representatives["pair"]);
11
11
  console.log("OK");
@@ -0,0 +1,50 @@
1
+ import assert from 'assert';
2
+ import { parseValue } from '../valueIO.mjs';
3
+ import { encodeToWire, decodeWire } from '../codecs/runtime/prefix-codec.mjs';
4
+ import { Product, Variant } from '../Value.mjs';
5
+
6
+ const value = parseValue('{a:{b:x,c:{}}}');
7
+ const repeatedClosedValue = parseValue('{a:{m:{},n:{}},b:{m:{},n:{}}}');
8
+ const repeatedOpenValue = parseValue('{a:x,b:x}');
9
+
10
+ const defaultWire = decodeWire(encodeToWire(value, null));
11
+ assert.deepEqual(defaultWire.pattern, [
12
+ ["open-union", [["a", 1]]],
13
+ ["closed-product", [["b", 2], ["c", 3]]],
14
+ ["open-union", [["x", 3]]],
15
+ ["closed-product", []]
16
+ ]);
17
+
18
+ const explicitProductWire = decodeWire(encodeToWire(value, [
19
+ ["open-product", [["a", 1]]],
20
+ ["any", []]
21
+ ]));
22
+ assert.deepEqual(explicitProductWire.pattern, [
23
+ ["open-product", [["a", 1]]],
24
+ ["closed-product", [["b", 2], ["c", 3]]],
25
+ ["open-union", [["x", 3]]],
26
+ ["closed-product", []]
27
+ ]);
28
+
29
+ const decoded = explicitProductWire.value;
30
+ assert(decoded instanceof Product);
31
+ assert(decoded.product.a instanceof Product);
32
+ assert(decoded.product.a.product.b instanceof Variant);
33
+ assert.equal(decoded.product.a.product.b.tag, "x");
34
+
35
+ const repeatedClosedWire = decodeWire(encodeToWire(repeatedClosedValue, null));
36
+ assert.deepEqual(repeatedClosedWire.pattern, [
37
+ ["closed-product", [["a", 1], ["b", 1]]],
38
+ ["closed-product", [["m", 2], ["n", 2]]],
39
+ ["closed-product", []]
40
+ ]);
41
+
42
+ const repeatedOpenWire = decodeWire(encodeToWire(repeatedOpenValue, null));
43
+ assert.deepEqual(repeatedOpenWire.pattern, [
44
+ ["closed-product", [["a", 1], ["b", 3]]],
45
+ ["open-union", [["x", 2]]],
46
+ ["closed-product", []],
47
+ ["open-union", [["x", 2]]]
48
+ ]);
49
+
50
+ console.log("OK");
@@ -0,0 +1,24 @@
1
+ import assert from "assert";
2
+ import { annotate } from "../index.mjs";
3
+
4
+ const script = `
5
+ f = .x;
6
+ g = f;
7
+ g
8
+ `;
9
+
10
+ const autoAnnotated = annotate(script);
11
+ assert.deepEqual(
12
+ autoAnnotated.compileStats.sccs.map(({ strategy }) => strategy),
13
+ ["single_pass", "single_pass", "single_pass"]
14
+ );
15
+
16
+ const fixedPointAnnotated = annotate(script, {
17
+ convergence: { strategy: "fixed_point" }
18
+ });
19
+ assert.deepEqual(
20
+ fixedPointAnnotated.compileStats.sccs.map(({ strategy }) => strategy),
21
+ ["fixed_point", "fixed_point", "fixed_point"]
22
+ );
23
+
24
+ console.log("OK");
@@ -1,40 +1,43 @@
1
1
  import { t, in_out } from './index.mjs';
2
+ import { hash } from '../hash.mjs';
2
3
  import assert from 'assert';
3
4
 
4
5
  t(`
5
6
  $b = < {} true, {} false > ;
6
7
  $pair = { b one, b two } ;
7
-
8
+ $bit = <{} 0, {} 1> ;
9
+ 1 = {} |1 $bit;
8
10
  $b {1 one, () two, () c} .one
9
11
 
10
12
  `, (annotated) => {
11
13
  const {input,output} = in_out(annotated);
12
14
  // console.log({input,output});
13
15
  assert.equal(input.type, annotated.representatives["b"]);
14
- assert.equal(output.type, "@int");
16
+ assert.equal(output.type, annotated.representatives["bit"]);
15
17
  console.log("OK");
16
18
  });
17
19
 
18
20
  t(`
19
- $a = < @int true, @bool false > ;
20
- $a .true
21
+ $bit = <{} 0, {} 1> ;
22
+ $a = < bit true, bit false > ;
23
+ $a /true
21
24
  `, (annotated) => {
22
25
  const {input,output} = in_out(annotated);
23
26
  console.log({input,output});
24
27
  });
25
28
 
26
29
  t(`
27
- x = .x;
28
- xy = x.y;
30
+ x = /x;
31
+ xy = x/y;
29
32
  f = {
30
- { {5 y} x} xy i,
31
- { {true y} x} xy b
33
+ {} | y | x xy i,
34
+ {} | y | x xy b
32
35
  };
33
36
  f .b
34
37
  `, (annotated) => {
35
38
  const {input,output} = in_out(annotated);
36
39
  console.log({input,output});
37
40
  assert.equal(input.pattern, '(...)');
38
- assert.equal(output.type, "@bool");
41
+ assert.equal(output.type, hash("$C0={};"));
39
42
  console.log("OK");
40
43
  });
@@ -0,0 +1,21 @@
1
+ import assert from 'assert';
2
+ import { annotate } from '../index.mjs';
3
+
4
+ function succeeds(script) {
5
+ assert.doesNotThrow(() => annotate(script));
6
+ }
7
+
8
+ function fails(script) {
9
+ assert.throws(() => annotate(script));
10
+ }
11
+
12
+ succeeds('?(...)');
13
+ succeeds('?{...}');
14
+ succeeds('?<...>');
15
+ succeeds('?{}');
16
+ succeeds('?<>');
17
+
18
+ fails('?()');
19
+ fails('?(X x, ...)');
20
+
21
+ console.log("OK");
@@ -1,11 +1,17 @@
1
1
  import { t, in_out } from './index.mjs';
2
2
  import assert from 'assert';
3
3
 
4
+ t(` < /a, () > `, (annotated) => {
5
+ const {input,output} = in_out(annotated);
6
+ assert.equal(input.pattern, "<...>");
7
+ assert.equal(output, input);
8
+ console.log("OK");
9
+ });
4
10
  t(` < .a, () > `, (annotated) => {
5
11
  const {input,output} = in_out(annotated);
6
- assert.equal(input.pattern, "(...)");
12
+ assert.equal(input.pattern, "{...}");
7
13
  assert.equal(output, input);
8
14
  console.log("OK");
9
15
  });
10
16
 
11
- // Notice that the following are equivalent: '<(), .a>', '<()>', and '()';
17
+ // Notice that the following are equivalent: '<(), /a>', '<()>', and '()';
@@ -2,7 +2,7 @@ import { t, in_out } from './index.mjs';
2
2
  import fs from 'node:fs';
3
3
  import assert from 'assert';
4
4
 
5
- t(fs.readFileSync("./Examples/nat.k").toString("utf8"), (annotated) => {
5
+ t(fs.readFileSync("./Examples/nat.k", "utf8"), (annotated) => {
6
6
  const {input,output} = in_out(annotated);
7
7
  assert.equal(output.type, annotated.representatives["nat"]);
8
8
  assert.equal(input.type, annotated.representatives["nat"]);
@@ -2,9 +2,9 @@ import { t, in_out } from './index.mjs';
2
2
  import assert from 'assert';
3
3
 
4
4
  t(`$b = < {} true, {} false > ;
5
- true = {{} true} $b;
6
- false = {{} false} $b;
7
- not = $b < .true false, .false true >;
5
+ true = {} |true $b;
6
+ false = {} |false $b;
7
+ not = $b < /true false, /false true >;
8
8
  not not
9
9
  `, (annotated) => {
10
10
  const {input,output} = in_out(annotated);
@@ -0,0 +1,68 @@
1
+ import assert from "node:assert/strict";
2
+ import k from "../index.mjs";
3
+ import { Product, Variant, mergePatterns, withPattern } from "../Value.mjs";
4
+ import { decodeWire, encodeToWire } from "../codecs/runtime/prefix-codec.mjs";
5
+ import run from "../run.mjs";
6
+ import codes from "../codes.mjs";
7
+
8
+ const INT_PATTERN = [
9
+ ["closed-union", [["+", 1], ["-", 1]]],
10
+ ["closed-union", [["0", 1], ["1", 1], ["_", 2]]],
11
+ ["closed-product", []]
12
+ ];
13
+
14
+ const script = `
15
+ $ bits = < {} _, bits 0, bits 1 >;
16
+ $ int = < bits +, bits - >;
17
+ {}|_|0|1|+ $int
18
+ `;
19
+
20
+ const result = k.compile(script)(new Product({}));
21
+ assert.deepEqual(result.pattern, INT_PATTERN);
22
+
23
+ const decoded = decodeWire(encodeToWire(result, result.pattern));
24
+ assert.deepEqual(decoded.pattern, INT_PATTERN);
25
+
26
+ const two = new Variant("+",
27
+ new Variant("1",
28
+ new Variant("0",
29
+ new Variant("_", new Product({}))
30
+ )
31
+ )
32
+ );
33
+ const witnessPattern = [
34
+ ["closed-union", [["+", 1]]],
35
+ ["closed-union", [["1", 2]]],
36
+ ["closed-union", [["0", 3]]],
37
+ ["closed-union", [["_", 4]]],
38
+ ["closed-product", []]
39
+ ];
40
+ const overExpandedSingleton = mergePatterns(INT_PATTERN, witnessPattern);
41
+ const decodedMerged = decodeWire(encodeToWire(two, overExpandedSingleton));
42
+ assert.deepEqual(decodedMerged.pattern, INT_PATTERN);
43
+
44
+ const identityResult = k.compile("()")(withPattern(two, INT_PATTERN));
45
+ assert.deepEqual(identityResult.pattern, INT_PATTERN);
46
+
47
+ assert.throws(
48
+ () => k.compile(".x")(withPattern(two, INT_PATTERN)),
49
+ /Type Error in 'comp'.*Value envelope does not intersect expression input pattern/s
50
+ );
51
+
52
+ const projectionScript = `
53
+ $ bits = < {} _, bits 0, bits 1 >;
54
+ $ int = < bits +, bits - >;
55
+ $int /+
56
+ `;
57
+ const annotated = k.annotate(projectionScript);
58
+ run.defs = annotated;
59
+ const projected = run(
60
+ codes.find,
61
+ annotated.rels.__main__.def,
62
+ two,
63
+ annotated.rels.__main__.typePatternGraph
64
+ );
65
+ assert.deepEqual(projected.pattern, [
66
+ ["closed-union", [["0", 0], ["1", 0], ["_", 1]]],
67
+ ["closed-product", []]
68
+ ]);
@@ -3,8 +3,8 @@ import assert from 'assert';
3
3
 
4
4
  t(`
5
5
  $nat = < {} _, nat 0, nat 1>;
6
- zero = {{{} _} 0} $nat;
7
- rlz = <.0._ zero, .0 rlz, ()>;
6
+ zero = {}|_|0 $nat;
7
+ rlz = </0/_ zero, /0 rlz, ()>;
8
8
  rlz
9
9
  `, (annotated) => {
10
10
  const {input,output} = in_out(annotated);
@@ -6,11 +6,13 @@
6
6
 
7
7
  The language describes "partial first-order functions" on "printable" values.
8
8
  The printable values can be seen as rooted, edge-labeled trees, intuitively similar to an
9
- XML or a JSON document. The values are always typed.
9
+ XML or a JSON document. The values are always typed; in the current codec-aware
10
+ runtime, a value may carry a pattern describing the family of types compatible
11
+ with that tree.
10
12
 
11
13
  ### Types (codes)
12
14
 
13
- Formally, a _type_ is a (subclass of) finite tree automata. The type defines a set of its values,
15
+ Formally, a _type_ is a (subclass of finite tree automata. The type defines a set of its values,
14
16
  which corresponds to the set of trees accepted by the automaton.
15
17
  Therefore, every type admits a unique normal form in terms of its minimal deterministic tree automaton.
16
18
 
@@ -19,6 +21,9 @@ Types are defined by two constructs:
19
21
  1. Product
20
22
  2. Union (also called tagged or disjoint union)
21
23
 
24
+ > Notation: We use native k-like notation as canonical — products `{ T l, ... }` and unions `< T t, ... >`.
25
+ > For convenience, JSON-like forms `{ l: T, ... }` and `< t: T, ... >` are also supported and equivalent in meaning.
26
+
22
27
  ```bnf
23
28
  type ::= name | '{' type_label_list '}' | '<' type_label_list '>'
24
29
  type_label_list ::= /* empty */ | ( type label ',' )* type label
@@ -30,10 +35,10 @@ Given a finite (possibly empty) set of types `t1, t2, ..., tn` and a set of pair
30
35
 
31
36
  - by `{ t1 l1, t2 l2, ..., tn ln }`, we define a _product type_ with exactly `n`
32
37
  _projection_ functions: `.l1`, `.l2`, `...`, `.ln`.
33
- Each projection function is mapping a value of type `{t1 l1, t2 l2, ..., tn ln}`
38
+ Each projection function maps a value of type `{t1 l1, t2 l2, ..., tn ln}`
34
39
  into a value of type `t1`, `t2`, `...`, `tn`, respectively.
35
- - by `< t1 l1, t2 l2, ..., tn ln >`, we define a _union type_ with exactly `n` projection functions `.l1`, `.l2`, `...`, `.ln`,
36
- mapping a value of type `<t1 l1, t2 l2, ..., tn ln>` into a value of type `t1`, `t2`, `...`, `tn`, respectively.
40
+ - by `< t1 l1, t2 l2, ..., tn ln >`, we define a _union type_ with exactly `n` projection functions `/l1`, `/l2`, `...`, `/ln`,
41
+ maps a value of type `<t1 l1, t2 l2, ..., tn ln>` into a value of type `t1`, `t2`, `...`, `tn`, respectively.
37
42
 
38
43
  Intuitively, the projection functions on a product type are all total (meaning, they are defined for every value of the
39
44
  input product type), whereas in the case of a union type, exactly one projection function is defined
@@ -41,20 +46,31 @@ for a given value of the union type.
41
46
 
42
47
  Some properties of these types:
43
48
 
44
- 1. Singleton product and singleton union types, `{ t label }` and `< t label >`, are equivalent as they have
45
- the same set of values (and the same projection function `.label`). That's why, we not allow singleton product nor
46
- singleton union types in the syntax of the language. The other benefit is that we will be able to use the same syntax
47
- for writing out values of both product and union types, interpretting every singleton product-like value, e.g., `{ a_value label }`,
48
- as a union type value (a variant).
49
- 2. The empty product type, `{}`, has a single value, called the _unit_
50
- and also denoted by `{}`, which has no fields.
51
- 3. The empty union type, `<>`, has no values.
49
+ 1. The empty product type, `{}`, has a single value, called the _unit_.
50
+ 2. The empty union type, `<>`, has no values.
51
+
52
+ #### Variant (union) value literal convention
53
+
54
+ - Variant values are written using "|" (pipe) followed by the variant tag.
55
+ - Unit variant `` `{}` `` | tag (e.g., `{} | nil`, `{} | zero`)
56
+ - Variant with payload `v` at label `tag`: ` v | tag `
57
+ - Example (list): with `$list = < {} nil, {X car, list cdr} cons >`:
58
+ - Empty list []: `{}|nil`
59
+ - Singleton `[v]`: `{ v car, {}|nil cdr } | cons`
60
+ - Angle brackets are for type definitions and merge expressions; use "`| tag`" for a variant construction.
61
+
62
+ #### Equivalence of types (bisimilarity)
63
+
64
+ Two (possibly recursive) codes are equivalent iff they are bisimilar over their definition graphs. Concretely, there exists a relation B such that `(t1, t2) ∈ B` if and only if:
65
+ - t1 and t2 have exactly the same set of labels/tags;
66
+ - t1 and t2 are simultaneously products or simultaneously unions;
67
+ - for each label/tag `ℓ` in the set, the subcodes under `ℓ` are again related by B.
52
68
 
53
69
  ### Filters (patterns)
54
70
 
55
- A _filter_ is a way of representing a _type class_, i.e, a set of types sharing some struture.
71
+ A _filter_ is a way of representing a _pattern_, i.e, a set of types sharing some structure.
56
72
  For example, if I wanted to refer to all product types that have a field `f` of type `T`,
57
- I would write a pattern: `?{ T f, ... }`. In general, a filter is defined by:
73
+ I would write: `?{ T f, ... }`. In general, a filter is defined by:
58
74
 
59
75
  ```bnf
60
76
  filter ::= name | '$' type_expr | '{' filter_label_list '}'
@@ -71,8 +87,7 @@ Examples:
71
87
  ( ... ) -- any type
72
88
  { ... } -- any product type
73
89
  ( X x, X y ) -- any type with two fields of the same type
74
- < X x, ... > = X -- a (recursive) type, 'X', with variant 'x'
75
- -- of the same type 'X'
90
+ < X x, ... > = X -- a (recursive) variant type, 'X', with variant 'x' of the same type 'X'
76
91
  ```
77
92
 
78
93
  ### Partial functions
@@ -86,7 +101,7 @@ There are three ways of combining partial functions:
86
101
  and `g` is defined on value `y` producing `z`, then `(f g)` is defined on value `x` producing `z`.
87
102
  2. __Union__: we write `< f1, f2 >` for a union of two functions `f1` and `f2`, meaning that
88
103
  if `f1` is defined on value `x` producing `y`, then `< f1, f2 >`
89
- is defined on value `x` producing `y`. Otherwise, i.e., when `f1` is not defined for `x`, `< f1 f2 >` acts as `f2`.
104
+ is defined on value `x` producing `y`. Otherwise, i.e., when `f1` is not defined for `x`, `< f1, f2 >` acts as `f2`.
90
105
  3. __Product__: we write `{f1 lab1, f2 lab2 }` for a product of two functions `f1` and `f2`,
91
106
  meaning that if `f1` and `f2` are both defined on value `x` producing `y1` and `y2`,
92
107
  respectively, then `{f1 lab1, f2 lab2 }` is defined on value `x` producing
@@ -109,7 +124,7 @@ type_definition ::= '$' type_name '=' type ';'
109
124
  function_definition ::= name '=' expression ';'
110
125
  expression ::= name | '$' type | '?' filter
111
126
  | projection | composition | union | product
112
- projection ::= '.' label
127
+ projection ::= '.' label | '/' label
113
128
  composition ::= '(' expression * ')'
114
129
  union ::= '<' (expression ',') + expression '>'
115
130
  product ::= '{' expr_label_list '}'
@@ -123,7 +138,7 @@ We assume that in a `kernel-core` program the names (for types, functions, and l
123
138
  2. All defined function names are distinct.
124
139
  3. All label names within a type definition or a `product` expression are locally distinct.
125
140
 
126
- `Filter` or `type` expressions act as a type annotation, i.e., an identity
141
+ Filters and type expressions act as a type annotation, i.e., an identity
127
142
  function defined only for the values of the corresponding types.
128
143
 
129
144
  That's it.
@@ -141,7 +156,7 @@ Obviously, a function may have many different definitions so the hash-based name
141
156
  This approach solves the problem of modules, imports, etc., and opens the door to a universal
142
157
  registry of types (schemas) and functions.
143
158
 
144
- ## Typing and Polymorphism (codes and filters/patterns)
159
+ ## Typing and Polymorphism (codes and patterns)
145
160
 
146
161
  Abstract Syntax Tree of a program consists of a dictionary of _type definitions_,
147
162
  a dictionary of _function definitions_, and the final _main expression_.
@@ -154,7 +169,7 @@ representations for functions, so they could be reused.
154
169
 
155
170
  The normalization steps are:
156
171
 
157
- 1. Build the _type graph_ from all types used by the program, i.e., used in _type definitions_
172
+ 1. Build the _type graph_ from all types used by the program, i.e., used in _type definitions_
158
173
  as well as type expressions used in _function definitions_ and the _main expression_.
159
174
  2. Annotate the expressions with filters; every node of the AST is annotated with a pair of filters.
160
175
  3. Turn the _singleton_ filters into types and add them to the _type graph_. Go to (2) unless no change.
@@ -165,23 +180,23 @@ The normalization steps are:
165
180
 
166
181
  ```k-repl
167
182
  $ bit = < {} o, {} i >;
168
- bit0 = {{} o} $bit;
169
- bit1 = {{} i} $bit;
183
+ bit0 = | o $bit;
184
+ bit1 = | i $bit;
170
185
 
171
186
  $ byte = { bit b0, bit b1, bit b2, bit b3 };
172
187
  zero = bit0 { () b0, () b1, () b2, () b3 } $byte;
173
188
 
174
- inc = $byte
189
+ inc = $ byte
175
190
  <
176
- { .b0.o bit0 overflown, {bit1 b0, .b1 b1, .b2 b2, .b3 b3 } byte },
177
- { .b1.o bit0 overflown, {bit0 b0, bit1 b1, .b2 b2, .b3 b3 } byte },
178
- { .b2.o bit0 overflown, {bit0 b0, bit0 b1, bit1 b2, .b3 b3 } byte },
179
- { .b3.o bit0 overflown, {bit0 b0, bit0 b1, bit0 b2, bit1 b3 } byte },
180
- { bit1 overflown, zero byte }
191
+ { bit0 overflown, { .b0/o bit1 b0, .b1 b1, .b2 b2, .b3 b3 } byte },
192
+ { bit0 overflown, { bit0 b0, .b1/o bit1 b1, .b2 b2, .b3 b3 } byte },
193
+ { bit0 overflown, { bit0 b0, bit0 b1, .b2/o bit1 b2, .b3 b3 } byte },
194
+ { bit0 overflown, { bit0 b0, bit0 b1, bit0 b2, ,b3/o bit1 b3 } byte },
195
+ { bit1 overflown, zero byte }
181
196
  >
182
197
  ;
183
198
 
184
- -- inc with overflown flag (polymorphism)
199
+ -- inc with overflown flag
185
200
  inc_o =
186
201
  { .byte inc inc, .overflown overflown }
187
202
  {
@@ -195,8 +210,8 @@ inc3 = inc inc_o inc_o;
195
210
  inc3
196
211
  ```
197
212
 
198
- In the above program, we define a type `bit` a union of two unit types,
199
- and a type `byte` as a product, for simplicity, of four `bit`s.
213
+ In the above program, we define type `bit` as union of two unit types,
214
+ and type `byte` as product, for simplicity, of four `bit`s.
200
215
 
201
216
  Functions `bit0`, `bit1`, and `zero` are "constant polymorphic functions", meaning:
202
217
 
@@ -209,18 +224,18 @@ Functions `inc` and `inc3` are (non-polymorphic) functions of types
209
224
  `$byte -> ${ bit overflown, byte byte }` and
210
225
  `${ bit overflown, byte byte } -> ${ bit overflown, byte byte }`, respectively.
211
226
 
212
- Function `inc_o` is a polymorphic function of type patterns: `?X -> ${ byte byte, bit overflown }`
227
+ Function `inc_o` is a polymorphic function of type patterns: `?X -> ${ byte byte, bit overflown }`
213
228
  with following constraints:
214
229
 
215
- - `?X` is a product or union type with at least two fields: `byte` and `overflown`, denoted by:
216
- > `?( $byte byte, Z overflown, ...)`;
217
- - `?Z` is a type (union or product) with field `i` denoted by:
218
- > `?( V i, ...)`;
230
+ - `?X` is a product type with at least two fields: `byte` and `overflown`, denoted by:
231
+ > `?{ $byte byte, Z overflown, ...}`;
232
+ - `?Z` is a union type with field `i` denoted by:
233
+ > `?< V i, ...>`;
219
234
  - `V` is unconstrained, denoted by `(...)`;
220
235
 
221
- We can write it as: `?($byte byte, ((...) i, ...) overflown, ...)`.
236
+ We can write it as: `?{$byte byte, <(...) i, ...> overflown, ...}`.
222
237
 
223
- The target type `${ byte byte, bit overflown }` was derived from pattern `?{ $byte byte, $bit overflown }`.
238
+ The target type `${ byte byte, bit overflown }` corresponds to pattern `?{ $byte byte, $bit overflown }`.
224
239
  Such a pattern is called _singleton pattern_, as only one type fits the pattern.
225
240
 
226
241
  #### Example 2
@@ -229,12 +244,12 @@ Polymorphic list functions:
229
244
 
230
245
  ```k-repl
231
246
  list? = ?< {} nil, {X car, Y cdr} cons > = Y;
232
- nil = {{} nil} list?;
233
- singleton = {{() car, nil cdr} cons} list?;
234
- cons = {{.car car, .cdr cdr} cons} list?;
235
- nil? = list? .nil nil;
236
- car = list? .cons .car;
237
- cdr = list? .cons .cdr;
247
+ nil = {} |nil list?;
248
+ singleton = {() car, nil cdr} |cons list?;
249
+ cons = {.car car, .cdr cdr} | cons list?;
250
+ nil? = list? /nil nil;
251
+ car = list? /cons .car;
252
+ cdr = list? /cons .cdr;
238
253
  ```
239
254
 
240
255
  For example, the filter annotation for `car` is:
@@ -272,16 +287,54 @@ The transformation is done by partial functions as defined in the language.
272
287
  The non-recursive and tail-recursive (and even some non-tail recursive) functions can
273
288
  be compiled into deterministic finite (pushdown) transducers.
274
289
 
275
- ### AND-OR graphs for enconding and decoding codes
290
+ ### AND-OR graphs for encoding and decoding codes
276
291
 
277
- This could be generic and compact way to encode and decode typed values.
292
+ This could be a generic and compact way to encode and decode typed values.
278
293
  The idea is to use _prefix codes_ (a class of languages such that no word is a prefix of
279
294
  another word) to encode the values.
280
295
 
281
- ### RUST data structures
296
+ ### Rust data structures
282
297
 
283
298
  A type can be translated into a Rust data structure, and a function can be translated into a Rust function.
284
299
 
285
300
  ## Linking with Other Languages
286
301
 
287
- ## Streams and Arrays (Map-Reduce)
302
+ ## Streams and Arrays (Map-Reduce)
303
+
304
+ ## Bits
305
+
306
+ Extending `@string` into `@bits`.
307
+
308
+ ```k-repl
309
+ $ bits = < {} _, bits 0, bits 1 >;
310
+ ```
311
+
312
+ ### Literals for `@bits` are:
313
+
314
+ - `0b` for 0 bits
315
+ - `0b10` for 2 bits
316
+ - `0xF` for 4 bits
317
+ - `0xF0` for 8 bits
318
+ - `0o1` for 3 bits
319
+ - `0o7` for 3 bits
320
+ - "" for 0 bits
321
+ - "ala" for 24 bits
322
+
323
+ ### Two operations on `@bits`:
324
+
325
+ #### Eat `/`
326
+
327
+ - `$@bits / @bits` --- division, e.g., `0b1011 / 0b10` = `0b11`, `"abc" / "a"` = `"bc"`
328
+
329
+ #### Prepend `\`
330
+
331
+ - `$@bits \ @bits` --- multiplication, e.g., `0b11 \ 0b10` = `0b1011`, `"bc" \ "a"` = `"abc"`
332
+
333
+ Empty `bits` can be checked by
334
+
335
+ ```k
336
+
337
+ kind = $@bits
338
+ < {/ 0b0 \ 0b0 starts_with_0}, {/ 0b1 \ 0b1 starts_with_1}, {() empty} >
339
+ $< @bits starts_with_0, @bits starts_with_1, @bits empty >;
340
+ ```