@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
|
@@ -1,19 +0,0 @@
|
|
|
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.type, 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'));
|
|
@@ -1,19 +0,0 @@
|
|
|
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.pattern, '(...)');
|
|
7
|
-
assert.equal(output.pattern, "[]");
|
|
8
|
-
console.log("OK");
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
t("$@int [ $@int true, false ] .0", (annotated) => {
|
|
12
|
-
const {input,output} = in_out(annotated);
|
|
13
|
-
assert.equal(input.type, "@int");
|
|
14
|
-
assert.equal(output.type, "@bool");
|
|
15
|
-
console.log("OK");
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
assert.throws(() => t(`$@int [ $@int true, 12 ]`), /Error/);
|
|
19
|
-
console.log("OK");
|
package/Filters/bug.k
DELETED
package/Filters/composing.k
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
remap = ?T {.x y} ?T ?<X z, ...>;
|
|
2
|
-
swap = ?T {.x y, .y x} ?T;
|
|
3
|
-
|
|
4
|
-
$t = <int x, int y>;
|
|
5
|
-
|
|
6
|
-
$t2 = <int x, int y, int z>;
|
|
7
|
-
|
|
8
|
-
-- {12 x} $t remap $t
|
|
9
|
-
-- {[1,2] x} remap
|
|
10
|
-
-- {"ala" x, 3 y} swap
|
|
11
|
-
|
|
12
|
-
{
|
|
13
|
-
{12 x} $t2 remap $t2 remap,
|
|
14
|
-
{"ala" x, "ola" y} swap
|
|
15
|
-
}
|
package/Filters/filter.k
DELETED
package/TODO.md
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# To do list for canonical names
|
|
2
|
-
|
|
3
|
-
- [ ] Write a script to search for conflicting names
|
|
4
|
-
- [*] Export a relation. i.e., rewrite it as a list of all
|
|
5
|
-
dependency definitions using canonical names
|
|
6
|
-
- [ ] Find a way of adding 'comments' or some way of 'tagging' the definitions
|
|
7
|
-
- [X] The definitions should be simplied by removing useless filters
|
|
8
|
-
- [X] Definitions, which are just aliases to non built-in rels should not introduce a new canonical name
|
|
9
|
-
- [ ] Can we inline some references w/o changing the canonical name?
|
|
10
|
-
|
|
11
|
-
## Simplification rules
|
|
12
|
-
|
|
13
|
-
It seems to me that after calculating input and output patterns, all
|
|
14
|
-
filters and code expressions could be replaced by just input and output
|
|
15
|
-
filters corresponding to the patterns. [DONE]
|
|
16
|
-
|
|
17
|
-
The filer variables have to be renamed for normalization if they take part of
|
|
18
|
-
the canonical name calculation. [DONE]
|
|
19
|
-
|
|
20
|
-
## DESER
|
|
21
|
-
|
|
22
|
-
Serialization and deserialization of values.
|
|
23
|
-
|
|
24
|
-
### Can we define byte-array via prefix-free codes?
|
|
25
|
-
|
|
26
|
-
### Non prefix-free de/serialization
|
|
27
|
-
|
|
28
|
-
How programatically change encoding of a value? Is it possible to add some
|
|
29
|
-
annotations on the type graph?
|
|
30
|
-
|
|
31
|
-
Maybe it belongs to "execution environment", e.g., `k --deser JSON`,
|
|
32
|
-
`k --deser AVRO/UTF8`, where `JSON`, `AVRO`, `UTF8` are provided
|
|
33
|
-
by some external spec?
|
|
34
|
-
|
|
35
|
-
E.g.:
|
|
36
|
-
|
|
37
|
-
```DESER:
|
|
38
|
-
$ BsAqRMv = < BsAqRMv 0, BsAqRMv 1, KL _ >; -- $C0=<C0"0",C0"1",C1"_">;$C1={};
|
|
39
|
-
|
|
40
|
-
$ bnat = < {} _ @as '', bnat 0 @as '0' , bnat 1 >;
|
|
41
|
-
::UTF8::
|
|
42
|
-
{{} _} => ()
|
|
43
|
-
{$bnat 0} => \u2602
|
|
44
|
-
|
|
45
|
-
Ok, it looks for me like what we need is the "Monad", i.e., a set of
|
|
46
|
-
functions with side-effects (like `_log!`).
|
|
47
|
-
Get straight, we have `write_0!`, `write_1!`, `read_0!`, and `read_1!`,
|
|
48
|
-
or whatever is supported by the target.
|
|
49
|
-
|
|
50
|
-
#### How to implement `JSON`?
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
package/TYPING.md
DELETED
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
# Annotating subexpressions with type patterns
|
|
2
|
-
|
|
3
|
-
## Input
|
|
4
|
-
|
|
5
|
-
As input we get AST of a program in terms of a set of function definitions,
|
|
6
|
-
i.e., mappings from function names to expressions. Expressions are trees defined
|
|
7
|
-
by the following grammar:
|
|
8
|
-
|
|
9
|
-
```bfn-like
|
|
10
|
-
Expression := variable -- reference to a function (has to be defined in AST or built-in)
|
|
11
|
-
| COMP ( Expression, ..., Expression ) -- functional composition
|
|
12
|
-
| type -- identity function forcing type of its input and output
|
|
13
|
-
| PROD { Expression label, ..., Expression label } -- product
|
|
14
|
-
| MERGE < Expression, ..., Expression > -- union (merge)
|
|
15
|
-
| DOT label -- projection
|
|
16
|
-
-- extended with
|
|
17
|
-
| VECT [ Expression, ..., Expression ] -- vector
|
|
18
|
-
-- extended with EXPERIMENTAL list-comprehension
|
|
19
|
-
| CARET Expression -- list-comprehension aggregation
|
|
20
|
-
| PIPE -- unboxing for list-comprehension (only under CARET)
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Output
|
|
24
|
-
|
|
25
|
-
The output consists of the input AST with all of its nodes annotated with pairs of "type patterns".
|
|
26
|
-
Those type patterns define sets of types. Those tye patterns are represented by nodes of the
|
|
27
|
-
"type pattern graph" produced by the algorithm.
|
|
28
|
-
Ituitively, "type pattern graph" represents correlation between different subexpressions
|
|
29
|
-
in the input AST in terms of their input and output types.
|
|
30
|
-
|
|
31
|
-
More formally, a "type pattern graph" is a directed graph with nodes representing those
|
|
32
|
-
"type patterns" and edges, labeled by _projection labels_, representing
|
|
33
|
-
correlations between them.
|
|
34
|
-
|
|
35
|
-
Type pattern, i.e., node in the type pattern graph, is a value of the follwowing type:
|
|
36
|
-
|
|
37
|
-
```k
|
|
38
|
-
$typePattern = < string code, open? product, open? union, {} vector, open? unknown >;
|
|
39
|
-
$open? = <{} open, {} closed >;
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
The fields (from union and product types) are represented by edges coming out of the node.
|
|
43
|
-
The edges are labeled by the corresponding labels of the product or union types.
|
|
44
|
-
Except for the vector type, which is represented by a unique `vector-member` edge
|
|
45
|
-
pointing to the type pattern of the vector memebers.
|
|
46
|
-
Flag `open?` indicates if a given type can have more fields than the fields
|
|
47
|
-
represented by the outgoing edges.
|
|
48
|
-
Variant `unknown` is used to represent an arbitrary type.
|
|
49
|
-
Still, the fields corresponding to the out-going edges must exist in the type.
|
|
50
|
-
|
|
51
|
-
The output is a mapping from the nodes of the input AST to the nodes of the type pattern graph.
|
|
52
|
-
|
|
53
|
-
## Algorithm
|
|
54
|
-
|
|
55
|
-
For every node of the input AST, we define a pair of type patterns.
|
|
56
|
-
Intuitively, such a pair, `(in,out)`, represents the
|
|
57
|
-
type of the partial function defined by the subtree rooted at the given node.
|
|
58
|
-
|
|
59
|
-
Let `L` be the list of all those type patterns, i.e., a list of the length
|
|
60
|
-
twice the size of the input AST (mesured in number of nodes).
|
|
61
|
-
All patterns in `L` are set to `{{open open?} unknown}`.
|
|
62
|
-
The list `L` is used to build the type pattern graph by constructing equivalence
|
|
63
|
-
classes of the type patterns.
|
|
64
|
-
The representation of equivalence classes is slightly different from
|
|
65
|
-
the standard disjoint-set data structure, however
|
|
66
|
-
we have the same operaitions `find` and `union` on the type patterns.
|
|
67
|
-
The difference is that we never modify already exising type patterns, e.g.,
|
|
68
|
-
the union (or even just a modification) generates a new type pattern node, so that
|
|
69
|
-
the history of unions and modifications of type patterns is preserved.
|
|
70
|
-
The equvalence classes, the root nodes of the type patterns forest, are going to be
|
|
71
|
-
the nodes of the type pattern graph.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
### Rules for type pattern derivation
|
|
75
|
-
|
|
76
|
-
#### Rule 1: Variable occurrence -- `ref`
|
|
77
|
-
|
|
78
|
-
In an expression, a variable is a reference to a function (build-in or defined in the AST).
|
|
79
|
-
The input and output type patterns of the variable expression have to match the type
|
|
80
|
-
patterns of the function.
|
|
81
|
-
Since the function can be used in many contexts, the type patterns of the function are
|
|
82
|
-
not modified by the expression using the variable.
|
|
83
|
-
Let `v` is an occurrence of the variable, i.e., a node in the AST, and `def(v)` is the definition, i.e.,
|
|
84
|
-
the root node of the AST subtree defining the function (or built-in) referenced by `v`.
|
|
85
|
-
|
|
86
|
-
```pseudo
|
|
87
|
-
let (in_v, out_v) = annotation(v)
|
|
88
|
-
let (in_def, out_def) = annotation(def(v))
|
|
89
|
-
let cloned = clone([in_def, out_def])
|
|
90
|
-
let rep_in_v = find(in_v)
|
|
91
|
-
let rep_out_v = find(out_v)
|
|
92
|
-
let rep_in_def = cloned[find(in_def)]
|
|
93
|
-
let rep_out_def = cloned[find(out_def)]
|
|
94
|
-
|
|
95
|
-
UNIFY(rep_in_v, rep_in_def) BECAUSE "ref: unified with $rep_in_def"
|
|
96
|
-
UNIFY(rep_out_v, rep_out_def) BECAUSE "ref: unified with $rep_out_def"
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
The procedure `UNIFY` will be difined later.
|
|
100
|
-
|
|
101
|
-
#### Rule 2: Functional composition -- `comp`
|
|
102
|
-
|
|
103
|
-
The input and output type patterns of the composition, `e = COMP(e1, ..., en)`, have to match
|
|
104
|
-
the input type pattern of `e1` and the output type pattern of `en`, respectively.
|
|
105
|
-
In addition, the output type pattern of `ei` has to match the input type pattern of `ei+1`.
|
|
106
|
-
|
|
107
|
-
```pseudo
|
|
108
|
-
let (in_e, out_e) = annotation(e)
|
|
109
|
-
let (in_e1, out_e1) = annotation(e1)
|
|
110
|
-
...
|
|
111
|
-
let (in_en, out_en) = annotation(en)
|
|
112
|
-
let rep_in_e = find(in_e)
|
|
113
|
-
let rep_out_e = find(out_e)
|
|
114
|
-
let rep_in_e1 = find(in_e1)
|
|
115
|
-
let rep_out_e1 = find(out_e1)
|
|
116
|
-
...
|
|
117
|
-
let rep_in_en = find(in_en)
|
|
118
|
-
let rep_out_en = find(out_en)
|
|
119
|
-
|
|
120
|
-
UNIFY(rep_in_e, rep_in_e1) BECAUSE "comp: start"
|
|
121
|
-
UNIFY(rep_out_e, rep_out_en) BECAUSE "comp: end"
|
|
122
|
-
|
|
123
|
-
for i = 2 to n:
|
|
124
|
-
let rep_in_ei = find(in_ei)
|
|
125
|
-
let rep_out_ei = find(out_ei)
|
|
126
|
-
UNIFY(rep_out_ei-1, rep_in_ei) BECAUSE "comp: chaining"
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
#### Rule 3: Type -- `type`
|
|
130
|
-
|
|
131
|
-
The input and output type patterns of a type expression, `type`, are the same,
|
|
132
|
-
namely `{type code}`, where `type` is the canonical name for the type.
|
|
133
|
-
|
|
134
|
-
```pseudo
|
|
135
|
-
let (in_type, out_type) = annotation(type)
|
|
136
|
-
let rep_in_type = find(in_type)
|
|
137
|
-
let rep_out_type = find(out_type)
|
|
138
|
-
let type_node = CREATE_OR_FIND_TYPE_PATTERN_GRAPH_NODE_FOR_TYPE(type)
|
|
139
|
-
UNIFY (type_node, rep_in_type ,rep_out_type) BECAUSE "type"
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
#### Rule 3: Product -- `prod` and `variant`
|
|
143
|
-
|
|
144
|
-
Let `p = PROD{e1 l1, ..., en ln}` be a product expression, i.e., n != 1.
|
|
145
|
-
There are two rules, one saying that input types of all inner
|
|
146
|
-
expressions must be the same and it is the input type of `p`.
|
|
147
|
-
The second rule says, that the output type is a product with
|
|
148
|
-
fiels `l1, ..., ln` of types corresponding to the output
|
|
149
|
-
types of `e1,..., en`, respectively.
|
|
150
|
-
|
|
151
|
-
```pseudo
|
|
152
|
-
let (in_p, out_p) = annotation(p)
|
|
153
|
-
let rep_in_p = find(in_p)
|
|
154
|
-
let rep_out_p = find(out_p)
|
|
155
|
-
for i = 1 to n
|
|
156
|
-
let (in_ei,out_ei) = annotation(ei)
|
|
157
|
-
let rep_in_ei = find(in_ei)
|
|
158
|
-
let rep_out_ei = find(out_ei)
|
|
159
|
-
UNIFY(rep_in_p, rep_in_e1, ..., rep_in_en) BECAUSE "prod: input"
|
|
160
|
-
|
|
161
|
-
IF : CHECK IF WE SHOULD DO IT BY CHECKING IF rep_out_p IS ALREADY
|
|
162
|
-
: a closed product and has the edges going where they should
|
|
163
|
-
let aux_out_p = CREATE_TYPE_PATTERN_GRAPH_NODE({}) WITH_EDGES
|
|
164
|
-
TO rep_out_e1 BY l1,
|
|
165
|
-
...,
|
|
166
|
-
rep_out_en BY ln
|
|
167
|
-
UNIFY(aux_out_p, rep_out_p) BECAUSE "prod: output"
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
If `p = {e1 l1}`, the result will be of variant type, with at least one variant
|
|
171
|
-
label `l1` and of type corresponding to output type of `e1`.
|
|
172
|
-
|
|
173
|
-
```pseudo
|
|
174
|
-
let (in_p, out_p) = annotation(p)
|
|
175
|
-
let rep_in_p = find(in_p)
|
|
176
|
-
let rep_out_p = find(out_p)
|
|
177
|
-
let (in_e1,out_e1) = annotation(e1)
|
|
178
|
-
let rep_in_e1 = find(in_e1)
|
|
179
|
-
let_rep_out_e1 = find(out_e1)
|
|
180
|
-
UNIFY(rep_in_p, rep_in_e1) BECAUSE "variant: input"
|
|
181
|
-
|
|
182
|
-
IF : CHECK IF WE SHOULD DO IT BY CHECKING IF rep_out_p IS ALREADY
|
|
183
|
-
: an open union and has an edge labeled by l1 going to rep_out_e1
|
|
184
|
-
let aux_out_p = CREATE_TYPE_PATTERN_GRAPH_NODE(<...>) WITH_EDGES
|
|
185
|
-
TO rep_out_e1 BY l1
|
|
186
|
-
UNIFY(aux_out_p, rep_out_p) BECAUSE "variant: output"
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
#### Rule 4: Merge -- 'merge'
|
|
190
|
-
|
|
191
|
-
Let `u = MERGE<e1, ..., en>` be a merge expression. There is one rule,
|
|
192
|
-
all pairs of types for `u, e1, ..., en` have to be the same.
|
|
193
|
-
|
|
194
|
-
```pseudo
|
|
195
|
-
let (in_u, out_u) = annotation(u)
|
|
196
|
-
let rep_in_u = find(in_u)
|
|
197
|
-
let rep_out_u = find(out_u)
|
|
198
|
-
for i = 1 to n
|
|
199
|
-
let (in_ei,out_ei) = annotation(ei)
|
|
200
|
-
let rep_in_ei = find(in_ei)
|
|
201
|
-
let_rep_out_ei = find(out_ei)
|
|
202
|
-
UNIFY(rep_in_u, rep_in_e1, ..., rep_in_en) BECAUSE "merge:input"
|
|
203
|
-
UNIFY(rep_out_u, rep_out_e1, ..., rep_out_en) BECAUSE "merge:output"
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
#### Rule 5: Projection - `dot`
|
|
207
|
-
|
|
208
|
-
Let `d = DOT(l)` be a projection expression. The input type will have to have a field `l`.
|
|
209
|
-
The output type is the type of the field `l`.
|
|
210
|
-
|
|
211
|
-
WARNING: .3, .true. ."bla", etc... may be used with built-in types!!!
|
|
212
|
-
|
|
213
|
-
```pseudo
|
|
214
|
-
let (in_d, out_d) = annatation(d)
|
|
215
|
-
let rep_in_d = find(in_d)
|
|
216
|
-
let rep_out_d = find(out_d)
|
|
217
|
-
|
|
218
|
-
IF : CHECK IF WE SHOULD DO IT BY CHECKING IF rep_in_d
|
|
219
|
-
: has already an edge labeled by l going to rep_out_d
|
|
220
|
-
let new_in_d = CREATE_TYPE_PATTERN_GRAPH_NODE((...)) WITH_EDGES
|
|
221
|
-
TO rep_out_d BY l
|
|
222
|
-
UNIFY(aux_in_d, rep_in_d) BECAUSE "dot"
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
**Special cases are needed** for `vector` and built-in string, int, bool
|
|
226
|
-
|
|
227
|
-
#### Rule 6: Vector - `vector`
|
|
228
|
-
|
|
229
|
-
If `v = VECT[e1,...,en]` is a vector expression, then the input type for
|
|
230
|
-
`v, e1, ..., en` is the same, and the output type for all `e1, ..., en`
|
|
231
|
-
is the same, say `t`.
|
|
232
|
-
The output type for `v` is `[t]`.
|
|
233
|
-
|
|
234
|
-
```pseudo
|
|
235
|
-
let (in_v, out_v) = annotation(v)
|
|
236
|
-
let rep_in_v = find(in_v)
|
|
237
|
-
let rep_out_v = find(out_v)
|
|
238
|
-
for i = 1 to n
|
|
239
|
-
let (in_ei,out_ei) = annotation(ei)
|
|
240
|
-
let rep_in_ei = find(in_ei)
|
|
241
|
-
let_rep_out_ei = find(out_ei)
|
|
242
|
-
UNIFY(rep_in_v, rep_in_e1, ..., rep_in_en) BECAUSE "vector: input"
|
|
243
|
-
|
|
244
|
-
IF : CHECK IF WE SHOULD DO IT BY CHECKING IF rep_out_v is a vector
|
|
245
|
-
: with edge labeled by "vector-member" going to rep_in_v
|
|
246
|
-
let new_out_v = CREATE_TYPE_PATTERN_GRAPH_NODE([]) WITH_EDGES
|
|
247
|
-
TO rep_in_v d BY 'vector-member'
|
|
248
|
-
UNIFY(new_out_v, rep_out_v) BECAUSE "vector: output"
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
#### Rule 7: Caret - `caret`
|
|
252
|
-
|
|
253
|
-
Let `c = CARET(e)` be a list comprehension aggregation.
|
|
254
|
-
The input type is the same as the input type of `e`.
|
|
255
|
-
The output type of `c` is the vector of the output type of `e`.
|
|
256
|
-
|
|
257
|
-
```pseudo
|
|
258
|
-
let (in_c, out_c) = annotation(c)
|
|
259
|
-
let rep_in_c = find(in_c)
|
|
260
|
-
let rep_out_c = find(out_c)
|
|
261
|
-
let (in_e, out_e) = annotation(e)
|
|
262
|
-
let rep_in_e = find(in_e)
|
|
263
|
-
let rep_out_e = find(out_e)
|
|
264
|
-
UNIFY(rep_in_c, rep_in_e) BECAUSE "caret: input"
|
|
265
|
-
|
|
266
|
-
IF : CHECK IF WE SHOULD DO IT BY CHECKING IF rep_out_c is a vector
|
|
267
|
-
: with edge labeled by "vector-member" going to rep_out_e
|
|
268
|
-
let aux_out_c = CREATE_TYPE_PATTERN_GRAPH_NODE([]) WITH_EDGES
|
|
269
|
-
TO rep_out_e BY "vector_member"
|
|
270
|
-
UNIFY(aux_out_c, rep_out_c) BECAUSE "caret: output"
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
#### Rule 8: Pipe - `pipe`
|
|
274
|
-
|
|
275
|
-
Let `p = PIPE` be an unboxing operator for list comprehension.
|
|
276
|
-
The input type is a vector type.
|
|
277
|
-
The output type is the type of the vector members.
|
|
278
|
-
|
|
279
|
-
```pseudo
|
|
280
|
-
let (in_p, out_p) = annotation(p)
|
|
281
|
-
let rep_in_p = find(in_p)
|
|
282
|
-
let rep_out_p = find(out_p)
|
|
283
|
-
|
|
284
|
-
IF : CHECK IF WE SHOULD DO IT BY CHECKING IF rep_in_p is a vector
|
|
285
|
-
: with edge labeled by "vector-member" going to rep_out_p
|
|
286
|
-
let aux_in_p = CREATE_TYPE_PATTERN_GRAPH_NODE([]) WITH_EDGES
|
|
287
|
-
TO rep_out_p BY "vector_member"
|
|
288
|
-
UNIFY(aux_in_p, rep_in_p) BECAUSE "pipe"
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
---
|
|
292
|
-
|
|
293
|
-
## Helper functions
|
|
294
|
-
|
|
295
|
-
There are two data-structures:
|
|
296
|
-
|
|
297
|
-
1. `typePatternForest` -- the leaves of the forest are the type patterns of
|
|
298
|
-
the input AST nodes. Inner nodes are the type patterns generated by the rules.
|
|
299
|
-
|
|
300
|
-
2. `typePatternGraph` -- the nodes are the roots of the typePatternForest.
|
|
301
|
-
The edges are labeled by the projection labels plus "vector_member", and
|
|
302
|
-
in general can lead to many nodes (represented as a list w/o repetition).
|
|
303
|
-
|
|
304
|
-
### `UNIFY _, _, ...`
|
|
305
|
-
|
|
306
|
-
The procedure `UNIFY` takes as parameter a list of `typePatternGraph` nodes which all have to represent the same pattern.
|
|
307
|
-
The procedure modifies both, the `typePatternForest` and the `typePatternGraph`.
|
|
308
|
-
|
|
309
|
-
Also, the procedure may Fail if the nodes are not unifiable.
|
|
310
|
-
|
|
311
|
-
The recursive procedure `UNIFY(n1,...,nn)` is defined as follows:
|
|
312
|
-
|
|
313
|
-
```pseudo
|
|
314
|
-
INPUT: n1,...,nn
|
|
315
|
-
let rep_n1,...,rep_nn = find(n1), ..., find(nn)
|
|
316
|
-
if rep_n1 = ... = rep_nn RETURN
|
|
317
|
-
let new_rep = flat-unify(rep_n1, ..., rep_nn)
|
|
318
|
-
ADD new_rep AS_REPRESENTATIVE_FOR rep_n1,..., rep_nn BY_RULE "unify"
|
|
319
|
-
MIGRADE_EDGES_FROM rep_n1,..., rep_nn TO new_rep
|
|
320
|
-
forech edge=(label,{x1,...xk}) FROM new-rep
|
|
321
|
-
CALL UNIFY(x1,...,xk)
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
Notice that UNIFY is no-op when called with none or one node.
|
|
325
|
-
|
|
326
|
-
#### `MIGRADE_EDGES_FROM _, _, ... TO _`
|
|
327
|
-
|
|
328
|
-
Just copy the edges from the source nodes to the target node by combining destinations of the edges by the same label into a set (list without repetition).
|
|
329
|
-
|
|
330
|
-
#### `flat-unify _, _, ...`
|
|
331
|
-
|
|
332
|
-
`Flat-unify` is defined as reduce over the list of nodes, with initial value being `(...)`.
|
|
333
|
-
The binary reduce function is defined as follows (it is commutative):
|
|
334
|
-
|
|
335
|
-
| f-unify | (...) | {...} | <...> | () | [] | {} | <> | type
|
|
336
|
-
|----------|-------|-------|-------|------|------|------|------|------
|
|
337
|
-
|**type** | type | type | type | type | type | type | type
|
|
338
|
-
|**<>** | <> | ERROR | <> | <> | ERROR| ERROR| <>
|
|
339
|
-
|**{}** | {} | {} | ERROR | {} | ERROR| {}
|
|
340
|
-
|**[]** | [] | [] | ERROR | [] | []
|
|
341
|
-
|**()** | () | {} | <> | ()
|
|
342
|
-
|**<...>** | <...> | ERROR | <...>
|
|
343
|
-
|**{...}** | {...} | {...}
|
|
344
|
-
|**(...)** | (...)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
### `ADD _ AS_REPRESENTATIVE_FOR _, _, ... BY_RULE _`
|
|
348
|
-
|
|
349
|
-
Create a new type pattern node as a parrent in `typePatternForest` of other nodes.
|
|
350
|
-
A comment explaining how the node was created is added as well.
|
|
351
|
-
|
|
352
|
-
### `ADD_EDGES_FROM _ TO _, _, ... BY _`
|
|
353
|
-
|
|
354
|
-
As the name indicates, adds an edge which can lead to many nodes.
|
|
355
|
-
|
|
356
|
-
Repeat the procedure until the type pattern graph is not changing anymore.
|
|
357
|
-
|
|
358
|
-
## TODO:
|
|
359
|
-
|
|
360
|
-
- [X] Redefine built-in CONS and SNOC to allign with no support for non-homogeneous lists
|
|
361
|
-
- [X] Integrate filters into typePatters (execution is not affected)
|
|
362
|
-
- [/] better type error repporting - the info exists in the pattern parent tree ... in progress
|
|
363
|
-
- [X] Introduce a space/time bounds for type derivation
|
|
364
|
-
- [ ] Check for loops, e.g., `$x = < x f, ...>`, `$x = [x]`, `$x = {x f, ...}` -- this
|
|
365
|
-
looks a little arbitrary, but maybe this is actually an important part
|