@fraczak/k 2.0.2 → 2.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/README.md +50 -10
- package/package.json +1 -1
- package/parser.jison +5 -1
- package/parser.mjs +30 -20
- package/pretty.mjs +3 -2
- package/run.mjs +109 -8
- package/symbol-table.mjs +31 -15
package/README.md
CHANGED
|
@@ -177,14 +177,12 @@ can be written as `[.toto, .titi, 123]`.
|
|
|
177
177
|
|
|
178
178
|
---
|
|
179
179
|
|
|
180
|
-
### Function definitions
|
|
180
|
+
### Function and code (i.e., _type_) definitions
|
|
181
181
|
|
|
182
182
|
dec = [(),-1] PLUS;
|
|
183
183
|
max = <SNOC [.0, .1 max] <GT.0, .1>, .0> ;
|
|
184
184
|
factorial = < [(),0] GT .0 [dec factorial, ()] TIMES, 1 >;
|
|
185
185
|
|
|
186
|
-
### Codes (_types_)
|
|
187
|
-
|
|
188
186
|
_Codes_ (prefixed by `$`) can be defined by taged union and product. E.g.:
|
|
189
187
|
|
|
190
188
|
$nat = <nat 1, {} 0>;
|
|
@@ -207,6 +205,53 @@ by `[ codeExp ]`. All members of the vector are the same code. E.g.,
|
|
|
207
205
|
-- of integers and a vector of strings
|
|
208
206
|
---
|
|
209
207
|
|
|
208
|
+
### List comprehension on vectors (experimental!)
|
|
209
|
+
|
|
210
|
+
A vector can be "open" by PIPE (`|`) operator so the following partial function is applied to
|
|
211
|
+
each element of the vector one by one, yielding another open value. An open value can be "closed",
|
|
212
|
+
i.e., turn into a regular vector using `CARET` (`^`) operator. E.g.:
|
|
213
|
+
|
|
214
|
+
```k
|
|
215
|
+
| .x ^ :
|
|
216
|
+
[{x:12}, {x:8,y:10}, {y:98}] --> [12,8]
|
|
217
|
+
[1,2,3] --> []
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The PIPE operator can be used, e.g., to define a Cartesian product:
|
|
221
|
+
|
|
222
|
+
```k
|
|
223
|
+
[.0 |, .1 |] ^ :
|
|
224
|
+
[[1,2], [3,4]] --> [[1,3],[1,4],[2,3],[2,4]]
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
or
|
|
228
|
+
|
|
229
|
+
```k
|
|
230
|
+
{ | x, | y } ^ :
|
|
231
|
+
[1,2] --> [{"x":1,"y":1},{"x":2,"y":1},{"x":1,"y":2},{"x":2,"y":2}]
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**QUIZ**: Write a function which will take a list of integers and an integer `x`, and count how many
|
|
235
|
+
times value `x` appears in the list. (see `Examples/list-comprehension.k` for a solution)
|
|
236
|
+
|
|
237
|
+
```k
|
|
238
|
+
count_occurrences =
|
|
239
|
+
$ { [int] list, int x }
|
|
240
|
+
-- ???
|
|
241
|
+
$ int;
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**WARNING**: The `CARET` operator makes composition not associative, i.e., if you use
|
|
245
|
+
nested _list comprehension_ you cannot drop paranthesis anymore.
|
|
246
|
+
E.g., `| (| PLUS ^ .0) ^` and `| | PLUS ^ .0 ^` are two different functions:
|
|
247
|
+
|
|
248
|
+
```k
|
|
249
|
+
{ |(| PLUS ^ .0) ^ x, | | PLUS ^ .0 ^ y }:
|
|
250
|
+
[[[1,2],[3,4]],[[5,6],[7,8]]] --> {"x":[3,11],"y":[3,7]}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
210
255
|
## Examples
|
|
211
256
|
|
|
212
257
|
1. projection:
|
|
@@ -381,15 +426,10 @@ For example:
|
|
|
381
426
|
examples 4 and 5 of the `jq` tutorial are equivalent.
|
|
382
427
|
5.
|
|
383
428
|
jq '[.[] | {message: .commit.message, name: .commit.committer.name}]'
|
|
384
|
-
k '
|
|
385
|
-
map_f = <SNOC [.0 f,.1 map_f] CONS, [.0 f], []>; %\
|
|
386
|
-
map_f' -1
|
|
429
|
+
k '| .commit {.message message, .committer.name name} ^' -1
|
|
387
430
|
6.
|
|
388
431
|
jq '[.[] | {message: .commit.message, name: .commit.committer.name, parents: [.parents[].html_url]}]'
|
|
389
|
-
k '
|
|
390
|
-
f = {.commit.message message, .commit.committer.name name, .parents map_html_url parents}; %\
|
|
391
|
-
map_f = <SNOC [.0 f, .1 map_f] CONS, [.0 f] , []>; %\
|
|
392
|
-
map_f' -1
|
|
432
|
+
k '| {.commit.message message, .commit.committer.name name, .parents | .html_url ^ parents} ^' -1
|
|
393
433
|
|
|
394
434
|
---
|
|
395
435
|
|
package/package.json
CHANGED
package/parser.jison
CHANGED
|
@@ -44,6 +44,8 @@ function fromEscString(escString) {
|
|
|
44
44
|
";" return 'SC';
|
|
45
45
|
":" return 'COL';
|
|
46
46
|
"$" return 'DOLLAR';
|
|
47
|
+
"|" return 'PIPE';
|
|
48
|
+
"^" return 'CARET';
|
|
47
49
|
\"([^"\\]|\\(.|\n))*\"|\'([^'\\]|\\(.|\n))*\' return 'STRING';
|
|
48
50
|
[a-zA-Z_][a-zA-Z0-9_?!]* return 'NAME';
|
|
49
51
|
0|[-]?[1-9][0-9]* return 'INT';
|
|
@@ -52,7 +54,7 @@ function fromEscString(escString) {
|
|
|
52
54
|
/lex
|
|
53
55
|
|
|
54
56
|
%token NAME STRING INT
|
|
55
|
-
%token LA LC LB LP RA RP RB RC EQ DOT COMMA SC COL DOLLAR
|
|
57
|
+
%token LA LC LB LP RA RP RB RC EQ DOT COMMA SC COL DOLLAR PIPE CARET
|
|
56
58
|
%token EOF
|
|
57
59
|
|
|
58
60
|
%start input_with_eof
|
|
@@ -126,6 +128,8 @@ exp
|
|
|
126
128
|
| DOT str { $$ = {op: "dot", dot: $2}; }
|
|
127
129
|
| DOT name { $$ = {op: "dot", dot: $2}; }
|
|
128
130
|
| DOLLAR code { $$ = {op: "code", code: s.as_ref($2)}; }
|
|
131
|
+
| PIPE { $$ = {op: "pipe"}; }
|
|
132
|
+
| CARET { $$ = {op: "caret"}; }
|
|
129
133
|
;
|
|
130
134
|
|
|
131
135
|
labelled
|
package/parser.mjs
CHANGED
|
@@ -100,12 +100,12 @@ function fromEscString(escString) {
|
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
var parser = (function(){
|
|
103
|
-
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[4,6,8,15,18,21,23,32,34],$V1=[1,7],$V2=[1,
|
|
103
|
+
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[4,6,8,15,18,21,23,32,34,35,36],$V1=[1,7],$V2=[1,17],$V3=[1,18],$V4=[1,8],$V5=[1,9],$V6=[1,10],$V7=[1,11],$V8=[1,14],$V9=[1,15],$Va=[1,16],$Vb=[1,22],$Vc=[4,6,8,12,15,18,21,23,32,34,35,36],$Vd=[2,28],$Ve=[1,27],$Vf=[1,28],$Vg=[1,29],$Vh=[4,6,8,12,14,15,18,20,21,22,23,24,27,32,33,34,35,36],$Vi=[2,49],$Vj=[2,31],$Vk=[2,32],$Vl=[4,6,8,12,14,15,18,20,21,22,23,24,27,28,32,33,34,35,36],$Vm=[2,8],$Vn=[2,13],$Vo=[20,27],$Vp=[22,24,27],$Vq=[20,24,27],$Vr=[2,43],$Vs=[2,44],$Vt=[2,45];
|
|
104
104
|
var parser = {trace: function trace () { },
|
|
105
105
|
yy: {},
|
|
106
|
-
symbols_: {"error":2,"name":3,"NAME":4,"str":5,"STRING":6,"int":7,"INT":8,"input_with_eof":9,"defs":10,"comp":11,"EOF":12,"EQ":13,"SC":14,"DOLLAR":15,"codeDef":16,"code":17,"LC":18,"labelled_codes":19,"RC":20,"LB":21,"RB":22,"LA":23,"RA":24,"non_empty_labelled_codes":25,"code_label":26,"COMMA":27,"COL":28,"exp":29,"labelled":30,"list":31,"LP":32,"RP":33,"DOT":34,"
|
|
107
|
-
terminals_: {2:"error",4:"NAME",6:"STRING",8:"INT",12:"EOF",13:"EQ",14:"SC",15:"DOLLAR",18:"LC",20:"RC",21:"LB",22:"RB",23:"LA",24:"RA",27:"COMMA",28:"COL",32:"LP",33:"RP",34:"DOT"},
|
|
108
|
-
productions_: [0,[3,1],[5,1],[7,1],[9,3],[10,0],[10,5],[10,6],[17,1],[17,1],[16,3],[16,3],[16,3],[19,0],[19,1],[25,1],[25,3],[26,2],[26,2],[26,2],[26,3],[26,3],[26,3],[11,1],[11,2],[29,3],[29,3],[29,3],[29,1],[29,2],[29,3],[29,1],[29,1],[29,2],[29,2],[29,2],[29,2],[30,0],[30,1],[
|
|
106
|
+
symbols_: {"error":2,"name":3,"NAME":4,"str":5,"STRING":6,"int":7,"INT":8,"input_with_eof":9,"defs":10,"comp":11,"EOF":12,"EQ":13,"SC":14,"DOLLAR":15,"codeDef":16,"code":17,"LC":18,"labelled_codes":19,"RC":20,"LB":21,"RB":22,"LA":23,"RA":24,"non_empty_labelled_codes":25,"code_label":26,"COMMA":27,"COL":28,"exp":29,"labelled":30,"list":31,"LP":32,"RP":33,"DOT":34,"PIPE":35,"CARET":36,"non_empty_labelled":37,"comp_label":38,"non_empty_list":39,"$accept":0,"$end":1},
|
|
107
|
+
terminals_: {2:"error",4:"NAME",6:"STRING",8:"INT",12:"EOF",13:"EQ",14:"SC",15:"DOLLAR",18:"LC",20:"RC",21:"LB",22:"RB",23:"LA",24:"RA",27:"COMMA",28:"COL",32:"LP",33:"RP",34:"DOT",35:"PIPE",36:"CARET"},
|
|
108
|
+
productions_: [0,[3,1],[5,1],[7,1],[9,3],[10,0],[10,5],[10,6],[17,1],[17,1],[16,3],[16,3],[16,3],[19,0],[19,1],[25,1],[25,3],[26,2],[26,2],[26,2],[26,3],[26,3],[26,3],[11,1],[11,2],[29,3],[29,3],[29,3],[29,1],[29,2],[29,3],[29,1],[29,1],[29,2],[29,2],[29,2],[29,2],[29,1],[29,1],[30,0],[30,1],[37,1],[37,3],[38,2],[38,2],[38,2],[38,3],[38,3],[38,3],[31,0],[31,1],[39,1],[39,3]],
|
|
109
109
|
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
|
|
110
110
|
/* this == yyval */
|
|
111
111
|
|
|
@@ -139,7 +139,7 @@ break;
|
|
|
139
139
|
case 8:
|
|
140
140
|
this.$ = {code: "ref", ref: $$[$0]};
|
|
141
141
|
break;
|
|
142
|
-
case 9: case 23: case
|
|
142
|
+
case 9: case 23: case 40: case 50:
|
|
143
143
|
this.$ = $$[$0];
|
|
144
144
|
break;
|
|
145
145
|
case 10:
|
|
@@ -160,10 +160,10 @@ case 14:
|
|
|
160
160
|
return r }
|
|
161
161
|
, {});
|
|
162
162
|
break;
|
|
163
|
-
case 15: case
|
|
163
|
+
case 15: case 51:
|
|
164
164
|
this.$ = [$$[$0]];
|
|
165
165
|
break;
|
|
166
|
-
case 16: case
|
|
166
|
+
case 16: case 52:
|
|
167
167
|
this.$ = [].concat($$[$0-2],$$[$0]);
|
|
168
168
|
break;
|
|
169
169
|
case 17: case 18: case 19:
|
|
@@ -206,27 +206,33 @@ case 36:
|
|
|
206
206
|
this.$ = {op: "code", code: s.as_ref($$[$0])};
|
|
207
207
|
break;
|
|
208
208
|
case 37:
|
|
209
|
-
this.$ = {op: "
|
|
209
|
+
this.$ = {op: "pipe"};
|
|
210
|
+
break;
|
|
211
|
+
case 38:
|
|
212
|
+
this.$ = {op: "caret"};
|
|
210
213
|
break;
|
|
211
214
|
case 39:
|
|
215
|
+
this.$ = {op: "product", product: []};
|
|
216
|
+
break;
|
|
217
|
+
case 41:
|
|
212
218
|
this.$ = {op: "product", product: [$$[$0]]};
|
|
213
219
|
break;
|
|
214
|
-
case
|
|
220
|
+
case 42:
|
|
215
221
|
$$[$0-2].product = [].concat($$[$0-2].product,$$[$0]); this.$ = $$[$0-2];
|
|
216
222
|
break;
|
|
217
|
-
case
|
|
223
|
+
case 43: case 44: case 45:
|
|
218
224
|
this.$ = {label: $$[$0], exp: $$[$0-1]};
|
|
219
225
|
break;
|
|
220
|
-
case
|
|
226
|
+
case 46: case 47: case 48:
|
|
221
227
|
this.$ = {label: $$[$0-2], exp: $$[$0]};
|
|
222
228
|
break;
|
|
223
|
-
case
|
|
229
|
+
case 49:
|
|
224
230
|
this.$ = [];
|
|
225
231
|
break;
|
|
226
232
|
}
|
|
227
233
|
},
|
|
228
|
-
table: [o($V0,[2,5],{9:1,10:2}),{1:[3]},{3:4,4:$V1,5:12,6:$V2,7:13,8:$V3,11:3,15:[1,5],18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8},{3:
|
|
229
|
-
defaultActions: {
|
|
234
|
+
table: [o($V0,[2,5],{9:1,10:2}),{1:[3]},{3:4,4:$V1,5:12,6:$V2,7:13,8:$V3,11:3,15:[1,5],18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8,35:$V9,36:$Va},{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,12:[1,19],15:$Vb,18:$V4,21:$V5,23:$V6,29:20,32:$V7,34:$V8,35:$V9,36:$Va},o($Vc,$Vd,{13:[1,23]}),{3:24,4:$V1,16:26,17:25,18:$Ve,21:$Vf,23:$Vg},o($Vh,[2,23]),o([4,6,8,12,13,14,15,18,20,21,22,23,24,27,28,32,33,34,35,36],[2,1]),{3:34,4:$V1,5:35,6:$V2,7:36,8:$V3,11:33,15:$Vb,18:$V4,20:[2,39],21:$V5,23:$V6,29:6,30:30,32:$V7,34:$V8,35:$V9,36:$Va,37:31,38:32},{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,11:39,15:$Vb,18:$V4,21:$V5,22:$Vi,23:$V6,29:6,31:37,32:$V7,34:$V8,35:$V9,36:$Va,39:38},{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,11:39,15:$Vb,18:$V4,21:$V5,23:$V6,24:$Vi,29:6,31:40,32:$V7,34:$V8,35:$V9,36:$Va,39:38},{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,11:42,15:$Vb,18:$V4,21:$V5,23:$V6,29:6,32:$V7,33:[1,41],34:$V8,35:$V9,36:$Va},o($Vh,$Vj),o($Vh,$Vk),{3:45,4:$V1,5:44,6:$V2,7:43,8:$V3},o($Vh,[2,37]),o($Vh,[2,38]),o($Vl,[2,2]),o($Vl,[2,3]),{1:[2,4]},o($Vh,[2,24]),o($Vh,$Vd),{3:46,4:$V1,16:26,17:25,18:$Ve,21:$Vf,23:$Vg},{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,11:47,15:$Vb,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8,35:$V9,36:$Va},o($Vc,$Vm,{13:[1,48]}),o($Vh,[2,36]),o($Vh,[2,9]),{3:53,4:$V1,5:54,6:$V2,7:55,8:$V3,16:26,17:52,18:$Ve,19:49,20:$Vn,21:$Vf,23:$Vg,25:50,26:51},{3:46,4:$V1,16:26,17:56,18:$Ve,21:$Vf,23:$Vg},{3:53,4:$V1,5:54,6:$V2,7:55,8:$V3,16:26,17:52,18:$Ve,19:57,21:$Vf,23:$Vg,24:$Vn,25:50,26:51},{20:[1,58]},{20:[2,40],27:[1,59]},o($Vo,[2,41]),{3:60,4:$V1,5:61,6:$V2,7:62,8:$V3,15:$Vb,18:$V4,21:$V5,23:$V6,29:20,32:$V7,34:$V8,35:$V9,36:$Va},o($V0,$Vd,{28:[1,63]}),o($V0,$Vj,{28:[1,64]}),o($V0,$Vk,{28:[1,65]}),{22:[1,66]},o([22,24],[2,50],{27:[1,67]}),o($Vp,[2,51],{5:12,7:13,29:20,3:21,4:$V1,6:$V2,8:$V3,15:$Vb,18:$V4,21:$V5,23:$V6,32:$V7,34:$V8,35:$V9,36:$Va}),{24:[1,68]},o($Vh,[2,29]),{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,15:$Vb,18:$V4,21:$V5,23:$V6,29:20,32:$V7,33:[1,69],34:$V8,35:$V9,36:$Va},o($Vh,[2,33]),o($Vh,[2,34]),o($Vh,[2,35]),o($Vh,$Vm),{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,14:[1,70],15:$Vb,18:$V4,21:$V5,23:$V6,29:20,32:$V7,34:$V8,35:$V9,36:$Va},{16:71,18:$Ve,21:$Vf,23:$Vg},{20:[1,72]},o([20,24],[2,14],{27:[1,73]}),o($Vq,[2,15]),{3:74,4:$V1,5:75,6:$V2,7:76,8:$V3},o([4,6,8],$Vm,{28:[1,77]}),{28:[1,78]},{28:[1,79]},{22:[1,80]},{24:[1,81]},o($Vh,[2,25]),{3:34,4:$V1,5:35,6:$V2,7:36,8:$V3,11:33,15:$Vb,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8,35:$V9,36:$Va,38:82},o($V0,$Vd,{20:$Vr,27:$Vr}),o($V0,$Vj,{20:$Vs,27:$Vs}),o($V0,$Vk,{20:$Vt,27:$Vt}),{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,11:83,15:$Vb,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8,35:$V9,36:$Va},{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,11:84,15:$Vb,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8,35:$V9,36:$Va},{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,11:85,15:$Vb,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8,35:$V9,36:$Va},o($Vh,[2,26]),{3:21,4:$V1,5:12,6:$V2,7:13,8:$V3,11:86,15:$Vb,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8,35:$V9,36:$Va},o($Vh,[2,27]),o($Vh,[2,30]),o($V0,[2,6]),{14:[1,87]},o($Vh,[2,10]),{3:53,4:$V1,5:54,6:$V2,7:55,8:$V3,16:26,17:52,18:$Ve,21:$Vf,23:$Vg,26:88},o($Vq,[2,17]),o($Vq,[2,18]),o($Vq,[2,19]),{3:46,4:$V1,16:26,17:89,18:$Ve,21:$Vf,23:$Vg},{3:46,4:$V1,16:26,17:90,18:$Ve,21:$Vf,23:$Vg},{3:46,4:$V1,16:26,17:91,18:$Ve,21:$Vf,23:$Vg},o($Vh,[2,11]),o($Vh,[2,12]),o($Vo,[2,42]),o($Vo,[2,46],{5:12,7:13,29:20,3:21,4:$V1,6:$V2,8:$V3,15:$Vb,18:$V4,21:$V5,23:$V6,32:$V7,34:$V8,35:$V9,36:$Va}),o($Vo,[2,47],{5:12,7:13,29:20,3:21,4:$V1,6:$V2,8:$V3,15:$Vb,18:$V4,21:$V5,23:$V6,32:$V7,34:$V8,35:$V9,36:$Va}),o($Vo,[2,48],{5:12,7:13,29:20,3:21,4:$V1,6:$V2,8:$V3,15:$Vb,18:$V4,21:$V5,23:$V6,32:$V7,34:$V8,35:$V9,36:$Va}),o($Vp,[2,52],{5:12,7:13,29:20,3:21,4:$V1,6:$V2,8:$V3,15:$Vb,18:$V4,21:$V5,23:$V6,32:$V7,34:$V8,35:$V9,36:$Va}),o($V0,[2,7]),o($Vq,[2,16]),o($Vq,[2,20]),o($Vq,[2,21]),o($Vq,[2,22])],
|
|
235
|
+
defaultActions: {19:[2,4]},
|
|
230
236
|
parseError: function parseError (str, hash) {
|
|
231
237
|
if (hash.recoverable) {
|
|
232
238
|
this.trace(str);
|
|
@@ -734,18 +740,22 @@ case 15:return 28;
|
|
|
734
740
|
break;
|
|
735
741
|
case 16:return 15;
|
|
736
742
|
break;
|
|
737
|
-
case 17:return
|
|
743
|
+
case 17:return 35;
|
|
744
|
+
break;
|
|
745
|
+
case 18:return 36;
|
|
746
|
+
break;
|
|
747
|
+
case 19:return 6;
|
|
738
748
|
break;
|
|
739
|
-
case
|
|
749
|
+
case 20:return 4;
|
|
740
750
|
break;
|
|
741
|
-
case
|
|
751
|
+
case 21:return 8;
|
|
742
752
|
break;
|
|
743
|
-
case
|
|
753
|
+
case 22:return 12;
|
|
744
754
|
break;
|
|
745
755
|
}
|
|
746
756
|
},
|
|
747
|
-
rules: [/^(?:[/][*]([*][^/]|[^*])*[*][/])/,/^(?:(\/\/|#|%|--)[^\n]*)/,/^(?:\s+)/,/^(?:<)/,/^(?:\{)/,/^(?:\[)/,/^(?:\()/,/^(?:>)/,/^(?:\})/,/^(?:\])/,/^(?:\))/,/^(?:=)/,/^(?:\.)/,/^(?:,)/,/^(?:;)/,/^(?::)/,/^(?:\$)/,/^(?:"([^"\\]|\\(.|\n))*"|'([^'\\]|\\(.|\n))*')/,/^(?:[a-zA-Z_][a-zA-Z0-9_?!]*)/,/^(?:0|[-]?[1-9][0-9]*)/,/^(?:$)/],
|
|
748
|
-
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],"inclusive":true}}
|
|
757
|
+
rules: [/^(?:[/][*]([*][^/]|[^*])*[*][/])/,/^(?:(\/\/|#|%|--)[^\n]*)/,/^(?:\s+)/,/^(?:<)/,/^(?:\{)/,/^(?:\[)/,/^(?:\()/,/^(?:>)/,/^(?:\})/,/^(?:\])/,/^(?:\))/,/^(?:=)/,/^(?:\.)/,/^(?:,)/,/^(?:;)/,/^(?::)/,/^(?:\$)/,/^(?:\|)/,/^(?:\^)/,/^(?:"([^"\\]|\\(.|\n))*"|'([^'\\]|\\(.|\n))*')/,/^(?:[a-zA-Z_][a-zA-Z0-9_?!]*)/,/^(?:0|[-]?[1-9][0-9]*)/,/^(?:$)/],
|
|
758
|
+
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22],"inclusive":true}}
|
|
749
759
|
});
|
|
750
760
|
return lexer;
|
|
751
761
|
})();
|
package/pretty.mjs
CHANGED
|
@@ -34,9 +34,10 @@ function prettyCode (codes, representatives, codeExp) {
|
|
|
34
34
|
case "product":
|
|
35
35
|
return `{${prettyCode_labels(codes, representatives, codeExp.product)}}`;
|
|
36
36
|
case "union":
|
|
37
|
-
return
|
|
37
|
+
return `< ${prettyCode_labels(codes, representatives, codeExp.union)} >`;
|
|
38
38
|
case "vector":
|
|
39
|
-
return `[${representatives
|
|
39
|
+
return `[${prettyCode(codes,representatives, {code:'ref', ref:codeExp.vector})}]`;
|
|
40
|
+
// return `[${representatives[codeExp.vector] || codeExp.vector}]`;
|
|
40
41
|
default:
|
|
41
42
|
return ":error";
|
|
42
43
|
}
|
package/run.mjs
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
|
|
1
3
|
const modulo = (a, b) => ((+a % (b = +b)) + b) % b;
|
|
2
4
|
const valid = (x) => (isNaN(x) ? undefined : x);
|
|
3
5
|
|
|
6
|
+
function isOpen(x) {
|
|
7
|
+
return (Array.isArray(x) && x.open);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function isClosed(x) {
|
|
11
|
+
return (Array.isArray(x) && !x.open);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
Array.prototype.toJSON = function () {
|
|
15
|
+
if (this.open) {
|
|
16
|
+
// throw new Error(`Cannot serialize open vector: ${JSON.stringify([...this])}.`);
|
|
17
|
+
return {"OPEN VECTOR": [...this]};
|
|
18
|
+
}
|
|
19
|
+
return this;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
|
|
4
23
|
const builtin = {
|
|
5
24
|
"_log!": (arg) => {
|
|
6
25
|
console.error(`_log!: ${JSON.stringify(arg)}`);
|
|
@@ -83,12 +102,25 @@ function verify(code, value) {
|
|
|
83
102
|
function run(exp, value) {
|
|
84
103
|
"use strict";
|
|
85
104
|
if (value === undefined) return;
|
|
105
|
+
if (isOpen(value)) {
|
|
106
|
+
if (exp.op === "caret") {
|
|
107
|
+
return [...value];
|
|
108
|
+
} else {
|
|
109
|
+
const result = [];
|
|
110
|
+
result.open = true
|
|
111
|
+
for (const v of value) {
|
|
112
|
+
const r = run(exp, v);
|
|
113
|
+
if (r !== undefined) result.push(r);
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
86
118
|
switch (exp.op) {
|
|
87
119
|
case "code":
|
|
88
120
|
if (verify(exp.code, value)) {
|
|
89
121
|
return value;
|
|
90
122
|
}
|
|
91
|
-
|
|
123
|
+
return;
|
|
92
124
|
case "identity":
|
|
93
125
|
return value;
|
|
94
126
|
case "str":
|
|
@@ -99,7 +131,11 @@ function run(exp, value) {
|
|
|
99
131
|
if (defn != null) {
|
|
100
132
|
return run(defn[defn.length - 1], value);
|
|
101
133
|
}
|
|
102
|
-
|
|
134
|
+
const builtin_func = builtin[exp.ref];
|
|
135
|
+
if (builtin_func != null) {
|
|
136
|
+
return builtin_func(value);
|
|
137
|
+
}
|
|
138
|
+
throw(`Unknown ref: '${exp.ref}'`);
|
|
103
139
|
case "dot":
|
|
104
140
|
// a hack to allow something like 'null . null' or '0 . 0' to work by returning unit
|
|
105
141
|
if (value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
@@ -107,6 +143,12 @@ function run(exp, value) {
|
|
|
107
143
|
return;
|
|
108
144
|
}
|
|
109
145
|
return value[exp.dot];
|
|
146
|
+
case "pipe": {
|
|
147
|
+
assert(isClosed(value), `PIPE (|): Only a regular vector value can be "open".`);
|
|
148
|
+
const result = [...value];
|
|
149
|
+
result.open = true;
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
110
152
|
case "comp":
|
|
111
153
|
return exp.comp.reduce((value, exp) => {
|
|
112
154
|
if (value !== undefined) return run(exp, value);
|
|
@@ -120,26 +162,85 @@ function run(exp, value) {
|
|
|
120
162
|
}
|
|
121
163
|
return;
|
|
122
164
|
case "vector": {
|
|
123
|
-
|
|
165
|
+
let result = [];
|
|
166
|
+
let open = false;
|
|
124
167
|
for (let i = 0, len = exp.vector.length; i < len; i++) {
|
|
125
168
|
const r = run(exp.vector[i], value);
|
|
126
169
|
if (r === undefined) return;
|
|
127
|
-
|
|
170
|
+
if (open) {
|
|
171
|
+
if (isOpen(r)) {
|
|
172
|
+
const newResult = [];
|
|
173
|
+
newResult.open = true;
|
|
174
|
+
for (const x of result) {
|
|
175
|
+
for (const y of r) {
|
|
176
|
+
newResult.push([...x, y]);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
result = newResult;
|
|
180
|
+
} else {
|
|
181
|
+
for (const x of result) x.push(r);
|
|
182
|
+
}
|
|
183
|
+
} else {
|
|
184
|
+
if (isOpen(r)) {
|
|
185
|
+
open = true;
|
|
186
|
+
const newResult = [];
|
|
187
|
+
newResult.open = true;
|
|
188
|
+
for (const x of r) {
|
|
189
|
+
newResult.push([...result, x]);
|
|
190
|
+
}
|
|
191
|
+
result = newResult;
|
|
192
|
+
} else {
|
|
193
|
+
result.push(r);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
128
196
|
}
|
|
129
197
|
return result;
|
|
130
198
|
}
|
|
131
199
|
case "product": {
|
|
132
|
-
|
|
200
|
+
let result = {};
|
|
201
|
+
let open = false;
|
|
133
202
|
for (let i = 0, len = exp.product.length; i < len; i++) {
|
|
134
203
|
const { label, exp: e } = exp.product[i];
|
|
135
204
|
const r = run(e, value);
|
|
136
205
|
if (r === undefined) return;
|
|
137
|
-
|
|
206
|
+
if (open) {
|
|
207
|
+
if (isOpen(r)) {
|
|
208
|
+
let newResult = [];
|
|
209
|
+
newResult.open = true;
|
|
210
|
+
for (const v of r) {
|
|
211
|
+
for (const x of result) {
|
|
212
|
+
newResult.push({...x, [label]: v});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
result = newResult;
|
|
216
|
+
} else {
|
|
217
|
+
let newResult = [];
|
|
218
|
+
newResult.open = true;
|
|
219
|
+
for (const x of result) {
|
|
220
|
+
newResult.push({...x, [label]: r});
|
|
221
|
+
}
|
|
222
|
+
result = newResult;
|
|
223
|
+
}
|
|
224
|
+
} else {
|
|
225
|
+
if (isOpen(r)) {
|
|
226
|
+
open = true;
|
|
227
|
+
let newResult = [];
|
|
228
|
+
newResult.open = true;
|
|
229
|
+
for (const v of r.values()) {
|
|
230
|
+
newResult.push({...result, [label]: v});
|
|
231
|
+
}
|
|
232
|
+
result = newResult;
|
|
233
|
+
} else {
|
|
234
|
+
result[label] = r;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
138
237
|
}
|
|
139
|
-
return result
|
|
238
|
+
return result
|
|
140
239
|
}
|
|
240
|
+
case "caret":
|
|
241
|
+
assert(false, "CARET (^): Only an 'open' vector can be closed.");
|
|
141
242
|
default:
|
|
142
|
-
|
|
243
|
+
assert(false,`Unknown operation: '${exp.op}'`);
|
|
143
244
|
}
|
|
144
245
|
}
|
|
145
246
|
|
package/symbol-table.mjs
CHANGED
|
@@ -52,26 +52,42 @@ function is_full_rel(rel) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
function does_list_comprehension (e) {
|
|
56
|
+
switch (e.op) {
|
|
57
|
+
case "caret":
|
|
58
|
+
return true;
|
|
59
|
+
case "comp":
|
|
60
|
+
return e.comp.some((e) => e.op === "caret");
|
|
61
|
+
default:
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
55
66
|
function comp_first(e1, e2) {
|
|
56
67
|
if (is_identity_rel(e1)) return e2;
|
|
57
68
|
if (is_identity_rel(e2)) return e1;
|
|
58
69
|
if (is_empty_rel(e1)) return e1;
|
|
59
70
|
if (is_empty_rel(e2)) return e2;
|
|
60
|
-
if (e1
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
if (! does_list_comprehension(e1) && ! does_list_comprehension(e2)) {
|
|
72
|
+
if (e1.op === "comp" && e2.op === "comp") {
|
|
73
|
+
return {
|
|
74
|
+
op: "comp",
|
|
75
|
+
comp: [].concat(e1.comp, e2.comp),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (e1.op === "comp") {
|
|
79
|
+
return {
|
|
80
|
+
op: "comp",
|
|
81
|
+
comp: [].concat(e1.comp, [e2]),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
if (e2.op === "comp") {
|
|
85
|
+
return {
|
|
86
|
+
op: "comp",
|
|
87
|
+
comp: [].concat([e1], e2.comp),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
75
91
|
return {
|
|
76
92
|
op: "comp",
|
|
77
93
|
comp: [e1, e2],
|