@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 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 'f = .commit {.message message, .committer.name name}; %\
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 'map_html_url = <SNOC [.0 .html_url, .1 map_html_url] CONS, [.0 .html_url], []>; %\
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fraczak/k",
3
- "version": "2.0.2",
3
+ "version": "2.1.1",
4
4
  "description": "k-language for JSON-like data transformation",
5
5
  "main": "index.mjs",
6
6
  "scripts": {
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,15],$V3=[1,16],$V4=[1,8],$V5=[1,9],$V6=[1,10],$V7=[1,11],$V8=[1,14],$V9=[1,20],$Va=[4,6,8,12,15,18,21,23,32,34],$Vb=[2,28],$Vc=[1,25],$Vd=[1,26],$Ve=[1,27],$Vf=[4,6,8,12,14,15,18,20,21,22,23,24,27,32,33,34],$Vg=[2,47],$Vh=[2,31],$Vi=[2,32],$Vj=[4,6,8,12,14,15,18,20,21,22,23,24,27,28,32,33,34],$Vk=[2,8],$Vl=[2,13],$Vm=[20,27],$Vn=[22,24,27],$Vo=[20,24,27],$Vp=[2,41],$Vq=[2,42],$Vr=[2,43];
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,"non_empty_labelled":35,"comp_label":36,"non_empty_list":37,"$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"},
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],[35,1],[35,3],[36,2],[36,2],[36,2],[36,3],[36,3],[36,3],[31,0],[31,1],[37,1],[37,3]],
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 38: case 48:
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 49:
163
+ case 15: case 51:
164
164
  this.$ = [$$[$0]];
165
165
  break;
166
- case 16: case 50:
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: "product", product: []};
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 40:
220
+ case 42:
215
221
  $$[$0-2].product = [].concat($$[$0-2].product,$$[$0]); this.$ = $$[$0-2];
216
222
  break;
217
- case 41: case 42: case 43:
223
+ case 43: case 44: case 45:
218
224
  this.$ = {label: $$[$0], exp: $$[$0-1]};
219
225
  break;
220
- case 44: case 45: case 46:
226
+ case 46: case 47: case 48:
221
227
  this.$ = {label: $$[$0-2], exp: $$[$0]};
222
228
  break;
223
- case 47:
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:19,4:$V1,5:12,6:$V2,7:13,8:$V3,12:[1,17],15:$V9,18:$V4,21:$V5,23:$V6,29:18,32:$V7,34:$V8},o($Va,$Vb,{13:[1,21]}),{3:22,4:$V1,16:24,17:23,18:$Vc,21:$Vd,23:$Ve},o($Vf,[2,23]),o([4,6,8,12,13,14,15,18,20,21,22,23,24,27,28,32,33,34],[2,1]),{3:32,4:$V1,5:33,6:$V2,7:34,8:$V3,11:31,15:$V9,18:$V4,20:[2,37],21:$V5,23:$V6,29:6,30:28,32:$V7,34:$V8,35:29,36:30},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:37,15:$V9,18:$V4,21:$V5,22:$Vg,23:$V6,29:6,31:35,32:$V7,34:$V8,37:36},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:37,15:$V9,18:$V4,21:$V5,23:$V6,24:$Vg,29:6,31:38,32:$V7,34:$V8,37:36},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:40,15:$V9,18:$V4,21:$V5,23:$V6,29:6,32:$V7,33:[1,39],34:$V8},o($Vf,$Vh),o($Vf,$Vi),{3:43,4:$V1,5:42,6:$V2,7:41,8:$V3},o($Vj,[2,2]),o($Vj,[2,3]),{1:[2,4]},o($Vf,[2,24]),o($Vf,$Vb),{3:44,4:$V1,16:24,17:23,18:$Vc,21:$Vd,23:$Ve},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:45,15:$V9,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8},o($Va,$Vk,{13:[1,46]}),o($Vf,[2,36]),o($Vf,[2,9]),{3:51,4:$V1,5:52,6:$V2,7:53,8:$V3,16:24,17:50,18:$Vc,19:47,20:$Vl,21:$Vd,23:$Ve,25:48,26:49},{3:44,4:$V1,16:24,17:54,18:$Vc,21:$Vd,23:$Ve},{3:51,4:$V1,5:52,6:$V2,7:53,8:$V3,16:24,17:50,18:$Vc,19:55,21:$Vd,23:$Ve,24:$Vl,25:48,26:49},{20:[1,56]},{20:[2,38],27:[1,57]},o($Vm,[2,39]),{3:58,4:$V1,5:59,6:$V2,7:60,8:$V3,15:$V9,18:$V4,21:$V5,23:$V6,29:18,32:$V7,34:$V8},o($V0,$Vb,{28:[1,61]}),o($V0,$Vh,{28:[1,62]}),o($V0,$Vi,{28:[1,63]}),{22:[1,64]},o([22,24],[2,48],{27:[1,65]}),o($Vn,[2,49],{5:12,7:13,29:18,3:19,4:$V1,6:$V2,8:$V3,15:$V9,18:$V4,21:$V5,23:$V6,32:$V7,34:$V8}),{24:[1,66]},o($Vf,[2,29]),{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,15:$V9,18:$V4,21:$V5,23:$V6,29:18,32:$V7,33:[1,67],34:$V8},o($Vf,[2,33]),o($Vf,[2,34]),o($Vf,[2,35]),o($Vf,$Vk),{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,14:[1,68],15:$V9,18:$V4,21:$V5,23:$V6,29:18,32:$V7,34:$V8},{16:69,18:$Vc,21:$Vd,23:$Ve},{20:[1,70]},o([20,24],[2,14],{27:[1,71]}),o($Vo,[2,15]),{3:72,4:$V1,5:73,6:$V2,7:74,8:$V3},o([4,6,8],$Vk,{28:[1,75]}),{28:[1,76]},{28:[1,77]},{22:[1,78]},{24:[1,79]},o($Vf,[2,25]),{3:32,4:$V1,5:33,6:$V2,7:34,8:$V3,11:31,15:$V9,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8,36:80},o($V0,$Vb,{20:$Vp,27:$Vp}),o($V0,$Vh,{20:$Vq,27:$Vq}),o($V0,$Vi,{20:$Vr,27:$Vr}),{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:81,15:$V9,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:82,15:$V9,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8},{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:83,15:$V9,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8},o($Vf,[2,26]),{3:19,4:$V1,5:12,6:$V2,7:13,8:$V3,11:84,15:$V9,18:$V4,21:$V5,23:$V6,29:6,32:$V7,34:$V8},o($Vf,[2,27]),o($Vf,[2,30]),o($V0,[2,6]),{14:[1,85]},o($Vf,[2,10]),{3:51,4:$V1,5:52,6:$V2,7:53,8:$V3,16:24,17:50,18:$Vc,21:$Vd,23:$Ve,26:86},o($Vo,[2,17]),o($Vo,[2,18]),o($Vo,[2,19]),{3:44,4:$V1,16:24,17:87,18:$Vc,21:$Vd,23:$Ve},{3:44,4:$V1,16:24,17:88,18:$Vc,21:$Vd,23:$Ve},{3:44,4:$V1,16:24,17:89,18:$Vc,21:$Vd,23:$Ve},o($Vf,[2,11]),o($Vf,[2,12]),o($Vm,[2,40]),o($Vm,[2,44],{5:12,7:13,29:18,3:19,4:$V1,6:$V2,8:$V3,15:$V9,18:$V4,21:$V5,23:$V6,32:$V7,34:$V8}),o($Vm,[2,45],{5:12,7:13,29:18,3:19,4:$V1,6:$V2,8:$V3,15:$V9,18:$V4,21:$V5,23:$V6,32:$V7,34:$V8}),o($Vm,[2,46],{5:12,7:13,29:18,3:19,4:$V1,6:$V2,8:$V3,15:$V9,18:$V4,21:$V5,23:$V6,32:$V7,34:$V8}),o($Vn,[2,50],{5:12,7:13,29:18,3:19,4:$V1,6:$V2,8:$V3,15:$V9,18:$V4,21:$V5,23:$V6,32:$V7,34:$V8}),o($V0,[2,7]),o($Vo,[2,16]),o($Vo,[2,20]),o($Vo,[2,21]),o($Vo,[2,22])],
229
- defaultActions: {17:[2,4]},
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 6;
743
+ case 17:return 35;
744
+ break;
745
+ case 18:return 36;
746
+ break;
747
+ case 19:return 6;
738
748
  break;
739
- case 18:return 4;
749
+ case 20:return 4;
740
750
  break;
741
- case 19:return 8;
751
+ case 21:return 8;
742
752
  break;
743
- case 20:return 12;
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 `<${prettyCode_labels(codes, representatives, codeExp.union)}>`;
37
+ return `< ${prettyCode_labels(codes, representatives, codeExp.union)} >`;
38
38
  case "vector":
39
- return `[${representatives[codeExp.vector] || codeExp.vector}]`;
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
- break;
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
- return builtin[exp.ref](value);
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
- const result = [];
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
- result.push(r);
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
- const result = {};
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
- result[label] = r;
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
- return console.error(exp.op);
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.op === "comp" && e2.op === "comp")
61
- return {
62
- op: "comp",
63
- comp: [].concat(e1.comp, e2.comp),
64
- };
65
- if (e1.op === "comp")
66
- return {
67
- op: "comp",
68
- comp: [].concat(e1.comp, [e2]),
69
- };
70
- if (e2.op === "comp")
71
- return {
72
- op: "comp",
73
- comp: [].concat([e1], e2.comp),
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],