@fraczak/k 4.0.0 → 4.0.2

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,7 +177,7 @@ is not supported in _code derivation_ (explained below).
177
177
  "[1,2.11,0.3e-32]" --> [1,2.11,3e-33]
178
178
 
179
179
  - other predefined parial functions are: `DIV`, `FDIV`, `CONS`,
180
- `SNOC`, `toDateMsec`, `toDateStr`, and `_log!`.
180
+ `SNOC`, `toVEC`, `toDateMsec`, `toDateStr`, and `_log!`.
181
181
 
182
182
  ---
183
183
 
package/codes.mjs CHANGED
@@ -12,7 +12,7 @@ function isBuiltIn(code) {
12
12
  return code.match(/^(int|string|bool)$/);
13
13
  }
14
14
 
15
- function encodeCodeToString(code, codes) {
15
+ function encodeCodeToString(code, codes = theRepository.codes) {
16
16
  if (isBuiltIn(code)) return code;
17
17
  var i = 0;
18
18
  const Q = [[code,i]];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fraczak/k",
3
- "version": "4.0.0",
3
+ "version": "4.0.2",
4
4
  "description": "k-language for JSON-like data transformation",
5
5
  "main": "index.mjs",
6
6
  "scripts": {
package/parser.jison CHANGED
@@ -3,6 +3,10 @@
3
3
  import { SymbolTable, comp, union, identity } from "./symbol-table.mjs";
4
4
  let s = new SymbolTable();
5
5
 
6
+ function anError(pos,msg) {
7
+ throw new Error(`Parse Error (lines ${pos.first_line}:${pos.first_column}...${pos.last_line}:${pos.last_column}): ${msg}`);
8
+ }
9
+
6
10
  function getToken(yytext,yy,lstack) {
7
11
  const yylloc = yy.lexer.yylloc;
8
12
  const loc = lstack[lstack.length - 1]; // { first_line: 5, last_line: 5, first_column: 2, last_column: 3 };
@@ -38,7 +42,7 @@ function fromEscString(escString) {
38
42
  %lex
39
43
 
40
44
  %%
41
- [/][*]([*][^/]|[^*])*[*][/] /* c-comment */
45
+ [/][*]([^*]*[*]+[^*/])*[^*]*[*]+[/] /* c-comment */
42
46
  ("//"|"#"|"%"|"--")[^\n]* /* one line comment */
43
47
  \s+ /* blanks */
44
48
  "<" return 'LA';
@@ -119,7 +123,10 @@ code
119
123
  ;
120
124
 
121
125
  codeDef
122
- : lc labelled_codes rc { $$ = { code: "product", product: $2, start: $1.start, end: $3.end }; }
126
+ : lc labelled_codes rc { if (Object.keys($2).length == 1)
127
+ $$ = { code: "union", union: $2, start: $1.start, end: $3.end };
128
+ else
129
+ $$ = { code: "product", product: $2, start: $1.start, end: $3.end }; }
123
130
  | lb code rb { $$ = { code: "vector", vector: s.as_ref($2), start: $1.start, end: $3.end }; }
124
131
  | la labelled_codes ra { $$ = { code: "union", union: $2, start: $1.start, end: $3.end }; }
125
132
  ;
@@ -127,9 +134,11 @@ codeDef
127
134
  labelled_codes
128
135
  : { $$ = {}; }
129
136
  | non_empty_labelled_codes { $$ = $1.reduce((r, lc) => {
130
- r[lc.label] = s.as_ref(lc.code);
131
- return r }
132
- , {}); }
137
+ if (r[lc.label])
138
+ anError(@0,`Duplicate label '${lc.label}'.`);
139
+ r[lc.label] = s.as_ref(lc.code);
140
+ return r }
141
+ , {}); }
133
142
  ;
134
143
 
135
144
  non_empty_labelled_codes
@@ -149,9 +158,15 @@ code_label
149
158
 
150
159
  filter_
151
160
  : dollar code { $$ = { type: "code", code: s.as_ref($2), start: $1.start, end: $2.end}; }
152
- | lp labelled_filters rp { $$ = { type: null, open: $2.open, fields: $2.fields, start: $1.start, end: $3.end}; }
161
+ | lp labelled_filters rp { if ( !$2.open && (Object.keys($2.fields).length == 1))
162
+ $$ = { type: "union", open: $2.open, fields: $2.fields, start: $1.start, end: $3.end};
163
+ else
164
+ $$ = { type: null, open: $2.open, fields: $2.fields, start: $1.start, end: $3.end}; }
153
165
  | la labelled_filters ra { $$ = { type: "union", open: $2.open, fields: $2.fields, start: $1.start, end: $3.end}; }
154
- | lc labelled_filters rc { $$ = { type: "product", open: $2.open, fields: $2.fields, start: $1.start, end: $3.end}; }
166
+ | lc labelled_filters rc { if ( !$2.open && (Object.keys($2.fields).length == 1))
167
+ $$ = { type: "union", open: $2.open, fields: $2.fields, start: $1.start, end: $3.end};
168
+ else
169
+ $$ = { type: "product", open: $2.open, fields: $2.fields, start: $1.start, end: $3.end}; }
155
170
  | lb filter rb { $$ = { type: "vector", vector: $2, start: $1.start, end: $3.end }; }
156
171
  ;
157
172
 
@@ -166,6 +181,8 @@ labelled_filters
166
181
  if (lc.dots) {
167
182
  r.open = true;
168
183
  } else {
184
+ if (r.fields[lc.label])
185
+ anError(@0,`Duplicate label '${lc.label}'.`);
169
186
  r.fields[lc.label] = lc.filter;
170
187
  }
171
188
  return r }
@@ -213,7 +230,12 @@ exp
213
230
 
214
231
  labelled
215
232
  : { $$ = {op: "product", product: []}; }
216
- | non_empty_labelled { $$ = $1; }
233
+ | non_empty_labelled { $1.product.reduce( (labels, {label}) =>
234
+ { if (labels[label])
235
+ anError(@0,`Duplicate label '${label}'.`)
236
+ labels[label] = true;
237
+ return labels; }, {});
238
+ $$ = $1; }
217
239
  ;
218
240
 
219
241
  non_empty_labelled
package/parser.mjs CHANGED
@@ -78,6 +78,10 @@
78
78
  import { SymbolTable, comp, union, identity } from "./symbol-table.mjs";
79
79
  let s = new SymbolTable();
80
80
 
81
+ function anError(pos,msg) {
82
+ throw new Error(`Parse Error (lines ${pos.first_line}:${pos.first_column}...${pos.last_line}:${pos.last_column}): ${msg}`);
83
+ }
84
+
81
85
  function getToken(yytext,yy,lstack) {
82
86
  const yylloc = yy.lexer.yylloc;
83
87
  const loc = lstack[lstack.length - 1]; // { first_line: 5, last_line: 5, first_column: 2, last_column: 3 };
@@ -154,11 +158,14 @@ break;
154
158
  case 27:
155
159
  this.$ = { code: "ref", ref: $$[$0].value, start: $$[$0].start, end: $$[$0].end};
156
160
  break;
157
- case 28: case 47: case 61: case 79: case 89:
161
+ case 28: case 47: case 61: case 89:
158
162
  this.$ = $$[$0];
159
163
  break;
160
164
  case 29:
161
- this.$ = { code: "product", product: $$[$0-1], start: $$[$0-2].start, end: $$[$0].end };
165
+ if (Object.keys($$[$0-1]).length == 1)
166
+ this.$ = { code: "union", union: $$[$0-1], start: $$[$0-2].start, end: $$[$0].end };
167
+ else
168
+ this.$ = { code: "product", product: $$[$0-1], start: $$[$0-2].start, end: $$[$0].end };
162
169
  break;
163
170
  case 30:
164
171
  this.$ = { code: "vector", vector: s.as_ref($$[$0-1]), start: $$[$0-2].start, end: $$[$0].end };
@@ -171,9 +178,11 @@ case 32:
171
178
  break;
172
179
  case 33:
173
180
  this.$ = $$[$0].reduce((r, lc) => {
174
- r[lc.label] = s.as_ref(lc.code);
175
- return r }
176
- , {});
181
+ if (r[lc.label])
182
+ anError(this._$,`Duplicate label '${lc.label}'.`);
183
+ r[lc.label] = s.as_ref(lc.code);
184
+ return r }
185
+ , {});
177
186
  break;
178
187
  case 34: case 52: case 90:
179
188
  this.$ = [$$[$0]];
@@ -191,13 +200,19 @@ case 42:
191
200
  this.$ = { type: "code", code: s.as_ref($$[$0]), start: $$[$0-1].start, end: $$[$0].end};
192
201
  break;
193
202
  case 43:
194
- this.$ = { type: null, open: $$[$0-1].open, fields: $$[$0-1].fields, start: $$[$0-2].start, end: $$[$0].end};
203
+ if ( !$$[$0-1].open && (Object.keys($$[$0-1].fields).length == 1))
204
+ this.$ = { type: "union", open: $$[$0-1].open, fields: $$[$0-1].fields, start: $$[$0-2].start, end: $$[$0].end};
205
+ else
206
+ this.$ = { type: null, open: $$[$0-1].open, fields: $$[$0-1].fields, start: $$[$0-2].start, end: $$[$0].end};
195
207
  break;
196
208
  case 44:
197
209
  this.$ = { type: "union", open: $$[$0-1].open, fields: $$[$0-1].fields, start: $$[$0-2].start, end: $$[$0].end};
198
210
  break;
199
211
  case 45:
200
- this.$ = { type: "product", open: $$[$0-1].open, fields: $$[$0-1].fields, start: $$[$0-2].start, end: $$[$0].end};
212
+ if ( !$$[$0-1].open && (Object.keys($$[$0-1].fields).length == 1))
213
+ this.$ = { type: "union", open: $$[$0-1].open, fields: $$[$0-1].fields, start: $$[$0-2].start, end: $$[$0].end};
214
+ else
215
+ this.$ = { type: "product", open: $$[$0-1].open, fields: $$[$0-1].fields, start: $$[$0-2].start, end: $$[$0].end};
201
216
  break;
202
217
  case 46:
203
218
  this.$ = { type: "vector", vector: $$[$0-1], start: $$[$0-2].start, end: $$[$0].end };
@@ -216,6 +231,8 @@ case 51:
216
231
  if (lc.dots) {
217
232
  r.open = true;
218
233
  } else {
234
+ if (r.fields[lc.label])
235
+ anError(this._$,`Duplicate label '${lc.label}'.`);
219
236
  r.fields[lc.label] = lc.filter;
220
237
  }
221
238
  return r }
@@ -275,6 +292,14 @@ break;
275
292
  case 78:
276
293
  this.$ = {op: "product", product: []};
277
294
  break;
295
+ case 79:
296
+ $$[$0].product.reduce( (labels, {label}) =>
297
+ { if (labels[label])
298
+ anError(this._$,`Duplicate label '${label}'.`)
299
+ labels[label] = true;
300
+ return labels; }, {});
301
+ this.$ = $$[$0];
302
+ break;
278
303
  case 80:
279
304
  this.$ = {op: "product", product: [$$[$0]]};
280
305
  break;
@@ -821,7 +846,7 @@ case 25:return 47;
821
846
  break;
822
847
  }
823
848
  },
824
- rules: [/^(?:[/][*]([*][^/]|[^*])*[*][/])/,/^(?:(\/\/|#|%|--)[^\n]*)/,/^(?:\s+)/,/^(?:<)/,/^(?:\{)/,/^(?:\[)/,/^(?:\()/,/^(?:>)/,/^(?:\})/,/^(?:\])/,/^(?:\))/,/^(?:=)/,/^(?:\.\.\.)/,/^(?:\.)/,/^(?:,)/,/^(?:;)/,/^(?::)/,/^(?:\$)/,/^(?:\?)/,/^(?:\|)/,/^(?:\^)/,/^(?:"([^"\\]|\\(.|\n))*"|'([^'\\]|\\(.|\n))*')/,/^(?:[a-zA-Z_][a-zA-Z0-9_?!]*)/,/^(?:0|[-]?[1-9][0-9]*)/,/^(?:\+\+\+)/,/^(?:$)/],
849
+ rules: [/^(?:[/][*]([^*]*[*]+[^*/])*[^*]*[*]+[/])/,/^(?:(\/\/|#|%|--)[^\n]*)/,/^(?:\s+)/,/^(?:<)/,/^(?:\{)/,/^(?:\[)/,/^(?:\()/,/^(?:>)/,/^(?:\})/,/^(?:\])/,/^(?:\))/,/^(?:=)/,/^(?:\.\.\.)/,/^(?:\.)/,/^(?:,)/,/^(?:;)/,/^(?::)/,/^(?:\$)/,/^(?:\?)/,/^(?:\|)/,/^(?:\^)/,/^(?:"([^"\\]|\\(.|\n))*"|'([^'\\]|\\(.|\n))*')/,/^(?:[a-zA-Z_][a-zA-Z0-9_?!]*)/,/^(?:0|[-]?[1-9][0-9]*)/,/^(?:\+\+\+)/,/^(?:$)/],
825
850
  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,23,24,25],"inclusive":true}}
826
851
  });
827
852
  return lexer;
package/patterns.mjs CHANGED
@@ -210,7 +210,7 @@ function patterns(representatives, rels) {
210
210
  newPatternId = context[filter.name];
211
211
  break;
212
212
  case "code":
213
- newPatternId = rootDef.typePatternGraph.getTypeId(filter.code);
213
+ newPatternId = rootDef.typePatternGraph.getTypeId(representatives[filter.code] || filter.code);
214
214
  break;
215
215
  case "union":
216
216
  newPatternId = rootDef.typePatternGraph.addNewNode(
@@ -360,7 +360,7 @@ function patterns(representatives, rels) {
360
360
  rel.patterns[0] = rootDef.typePatternGraph.addNewNode({pattern: '[]'}, {"vector-member": [rel.patterns[1]]});
361
361
  break;
362
362
  case "toVEC":
363
- rel.patterns[0] = rootDef.typePatternGraph.addNewNode();
363
+ rel.patterns[0] = rootDef.typePatternGraph.getTypeId('string')
364
364
  rel.patterns[1] = rootDef.typePatternGraph.addNewNode({pattern: '[]'}, {"vector-member": [rel.patterns[0]]});
365
365
  break;
366
366
  case "toDateMsec":
@@ -384,19 +384,24 @@ function patterns(representatives, rels) {
384
384
  rel.patterns[1] = rootDef.typePatternGraph.addNewNode();
385
385
  break;
386
386
  case "CONS": {
387
- let member = rootDef.typePatternGraph.addNewNode();
387
+ const member = rootDef.typePatternGraph.addNewNode();
388
388
  rel.patterns[1] = rootDef.typePatternGraph.addNewNode({pattern: '[]'}, {"vector-member": [member]});
389
389
  rel.patterns[0] = rootDef.typePatternGraph.addNewNode({pattern: '{}'}, {"car": [member], "cdr": [rel.patterns[1]]});
390
390
  }; break;
391
391
  case "SNOC": {
392
- let member = rootDef.typePatternGraph.addNewNode();
392
+ const member = rootDef.typePatternGraph.addNewNode();
393
393
  rel.patterns[0] = rootDef.typePatternGraph.addNewNode({pattern: '[]'}, {"vector-member": [member]});
394
394
  rel.patterns[1] = rootDef.typePatternGraph.addNewNode({pattern: '{}'}, {"car": [member], "cdr": [rel.patterns[0]]});
395
395
  }; break;
396
+ case "DIV": {
397
+ const intId = rootDef.typePatternGraph.getTypeId('int');
398
+ rel.patterns[0] = rootDef.typePatternGraph.addNewNode({pattern: '[]'}, {"vector-member": [intId]});
399
+ rel.patterns[1] = rootDef.typePatternGraph.addNewNode({pattern: '{}'}, {"div": [intId], "rem": [intId]});
400
+ }; break;
401
+ break;
396
402
  // TO DO
397
- case "null":
398
- case "DIV":
399
403
  case "FDIV":
404
+ case "null":
400
405
  rel.patterns = [rootDef.typePatternGraph.addNewNode(), rootDef.typePatternGraph.addNewNode()];
401
406
  break;
402
407
  default:
package/repl.mjs CHANGED
@@ -1,29 +1,27 @@
1
1
  #!/usr/bin/env node
2
+ import readline from "node:readline";
3
+ import fs from "node:fs";
2
4
 
3
5
  import k from "./index.mjs";
4
6
  import {run, closeVector } from "./run.mjs";
5
7
  import { prettyCode, prettyRel, patterns2filters } from "./pretty.mjs";
6
8
  import { find } from "./codes.mjs";
7
9
 
8
- import fs from "node:fs";
9
10
 
10
11
  const splice = [].splice;
11
12
 
12
13
  console.log("Very! experimental repl shell for 'k-language'...");
13
14
 
14
15
  const help = function () {
15
- console.log(" --h print help");
16
- console.log(" --a print codes and relations");
17
- console.log(" --c print aliased codes");
18
- console.log(" --C CODE print code definition");
19
- console.log(" --r print rels");
20
- console.log(" --p pretty-print last value");
21
- console.log(" --pp print last value via node.js 'console.log'");
22
- console.log(" --s reg store the last value in register 'reg'");
23
- console.log(" --g reg get the value from register 'reg'");
24
- console.log(" --regs print registers names");
25
- console.log(" --l file.k load 'file.k'");
26
- console.log(" --x rel Print out the type of 'rel'");
16
+ // console.log(" --debug loads codes and relations as value");
17
+ console.log(" --c print aliased codes");
18
+ console.log(" --C code print code definition");
19
+ console.log(" --r print rels");
20
+ console.log(" --R rel print out the type pattern of 'rel'");
21
+ console.log(" --p (--pp) pretty-print last value");
22
+ console.log(" --s (--g) reg store (get) the last value in register 'reg'");
23
+ console.log(" --regs print register names");
24
+ console.log(" --l file.k load 'file.k'");
27
25
  };
28
26
 
29
27
  help();
@@ -31,143 +29,163 @@ help();
31
29
  const re__l = /^[ \n\t]*(?:--l[ ]+)(.+)[ ]*?$/;
32
30
  const re__s = /^[ \n\t]*(?:--s[ ]+)(.+)[ ]*?$/;
33
31
  const re__g = /^[ \n\t]*(?:--g[ ]+)(.+)[ ]*?$/;
34
- const re__x = /^[ \n\t]*(?:--x[ ]+)(.+)[ ]*?$/;
32
+ const re__R = /^[ \n\t]*(?:--R[ ]+)(.+)[ ]*?$/;
35
33
  const re__C = /^[ \n\t]*(?:--C[ ]+)(.+)[ ]*?$/;
36
34
 
37
- const registers = {};
35
+ const rl = readline.createInterface({
36
+ input: process.stdin,
37
+ output: process.stdout,
38
+ prompt: '> '
39
+ });
40
+
41
+ rl.prompt();
42
+
43
+ rl.on('line', (line) => {
44
+ evaluate(line);
45
+ rl.prompt();
46
+ }).on('close', () => {
47
+ console.log('REPL closed');
48
+ process.exit(0);
49
+ });
38
50
 
39
- (function (val, buffer) {
40
- return process.stdin.on("data", function (data) {
41
- var e, file, first, i, kScript, last, len, line, ref, rest, todo;
42
- [first, ...rest] = data.toString("utf8").split("\n");
43
- buffer.push(first);
44
- if (rest.length > 0) {
45
- todo = buffer.join("");
46
- (ref = rest), ([...rest] = ref), ([last] = splice.call(rest, -1));
47
- buffer = [last];
48
- todo = [todo, ...rest];
49
- for (i = 0, len = todo.length; i < len; i++) {
50
- try {
51
- line = todo[i];
52
- if (val === void 0) {
53
- val = {};
51
+ let old_val = {};
52
+ let val = {};
53
+ const printVal = function (v = val) {
54
+ if (v === undefined)
55
+ console.log("...",v);
56
+ else
57
+ console.log(`=> ${JSON.stringify(v)}`);
58
+ rl.setPrompt('> ');
59
+ }
60
+ const registers = {};
61
+ const buffer = [];
62
+ function evaluate(line) {
63
+ if (line.trim().endsWith('\\')) {
64
+ buffer.push(line.slice(0, -1));
65
+ rl.setPrompt(' ');
66
+ return;
67
+ }
68
+ line = [...buffer, line].join('\n');
69
+ buffer.length = 0;
70
+ try {
71
+ if (val === undefined)
72
+ val = old_val;
73
+ else
74
+ old_val = val;
75
+ if (line.match(/^[ \n\t]*(?:--h)?$/)) {
76
+ // --h
77
+ help();
78
+ } else if (line.match(/^[ \n\t]*\^$/)) {
79
+ val = closeVector(val);
80
+ printVal();
81
+
82
+ } else if (line.match(re__l)) {
83
+ // --l
84
+ const file = line.match(re__l)[1];
85
+ console.log(` ... loading file: ${file} ...`);
86
+ const kScript = fs.readFileSync(file).toString();
87
+ console.log(` Done!`);
88
+ // console.log(kScript);
89
+ val = k.compile("+++\n" + kScript + "\n()")(val);
90
+ printVal();
91
+ } else if (line.match(/^[ \n\t]*--debug$/)) {
92
+ // --debug
93
+ val = run.defs;
94
+ console.log(val);
95
+ // --r
96
+ } else if (line.match(/^[ \n\t]*(?:--r)?$/)) {
97
+ console.log(
98
+ (function (defs, result) {
99
+ if (defs == null) {
100
+ return result;
54
101
  }
55
- if (line.match(/^[ \n\t]*(?:--h)?$/)) {
56
- // --h
57
- help();
58
- } else if (line.match(/^[ \n\t]*\^$/)) {
59
- val = closeVector(val);
60
- console.log(`=> ${JSON.stringify(val)}`);
61
- } else if (line.match(re__l)) {
62
- // --l
63
- file = line.match(re__l)[1];
64
- console.log(` -- loading file: ${file} ...`);
65
- kScript = fs.readFileSync(file).toString();
66
- console.log(` ----------------------------- compiling file: ${file} ...`);
67
- // console.log(kScript);
68
- val = k.compile("+++" + kScript + "\n()")(val);
69
- console.log(`=> ${JSON.stringify(val)}`);
70
- } else if (line.match(/^[ \n\t]*(?:--a)?$/)) {
71
- // --a
72
- val = run.defs;
73
- console.log(val);
74
- // --r
75
- } else if (line.match(/^[ \n\t]*(?:--r)?$/)) {
76
- console.log(
77
- (function (defs, result) {
78
- if (defs == null) {
79
- return result;
80
- }
81
- return (function (prettyRel) {
82
- var ref1, relName;
83
- ref1 = defs.rels;
84
- for (relName in ref1) {
85
- result[relName] = prettyRel(ref1[relName].def);
86
- }
87
- return result;
88
- })(
89
- prettyRel.bind(
90
- null,
91
- prettyCode.bind(null, defs.representatives)
92
- )
93
- );
94
- })(run.defs, {}));
95
- // --c
96
- } else if (line.match(/^[ \n\t]*(?:--c)?$/)) {
97
- console.log(
98
- (function (defs, result) {
99
- for (const codeName of Object.keys(defs.representatives || {})) {
100
- const codeExp = find(defs.representatives[codeName] || codeName);
101
- result[codeName] = prettyCode(
102
- defs.representatives,
103
- codeExp
104
- );
105
- }
106
- return result;
107
- })(run.defs || {}, {})
108
- );
109
- // --C
110
- } else if (line.match(re__C)) {
111
- let codeName = line.match(re__C)[1];
112
- if (codeName.startsWith("?"))
113
- codeName = codeName.slice(1);
114
- if (codeName.startsWith("$"))
115
- codeName = codeName.slice(1);
116
- const canonicalName = run.defs.representatives[codeName] || codeName;
117
- const codeExp = find( canonicalName );
118
- console.log(` $ ${canonicalName} = ${prettyCode(run.defs.representatives, codeExp)}; -- ${codeExp.def}`);
119
- // --pp
120
- } else if (line.match(/^[ \n\t]*(?:--pp)?$/)) {
121
- console.log(val);
122
- // --p
123
- } else if (line.match(/^[ \n\t]*(?:--p)?$/)) {
124
- console.log(JSON.stringify(val, null, 2));
125
- // --regs
126
- } else if (line.match(/^[ \n\t]*(?:--regs)?$/)) {
127
- console.log(` -- registers: ${Object.keys(registers).join(", ")}`);
128
- // --s
129
- } else if (line.match(re__s)) {
130
- let reg = line.match(re__s)[1];
131
- registers[reg] = val;
132
- console.log(` -- current value stored in register: '${reg}'`);
133
- // --g
134
- } else if (line.match(re__g)) {
135
- console.log(" -- getting value from register...");
136
- let reg = line.match(re__g)[1];
137
- val = registers[reg];
138
- console.log(val);
139
- // --x
140
- } else if (line.match(re__x)) {
141
- const relName = line.match(re__x)[1];
142
- const rel = run.defs?.rels[relName];
143
- if (!rel) {
144
- console.log(` -- relation '${relName}' not found`);
145
- continue;
146
- }
147
- const filters = patterns2filters(rel.typePatternGraph, ...rel.def.patterns);
148
- // console.log(filters);
149
- // console.log(" variables:", JSON.stringify(variables));
150
- // console.log(JSON.stringify({filters, variables}, null, 2));
151
- // for (const filter of filters) {
152
- const pcodef= prettyCode.bind(null, run.defs.representatives);
153
- const filtersStr = filters.map( x => prettyRel(pcodef, {op: "filter", filter: x}));
154
- console.log(` ${relName} : ${filtersStr[0]} --> ${filtersStr[1]}`);
155
- // }
156
- // ------ k code
157
- } else if (!line.match(/^[ \n\t]*(?:#.*)?$/)) {
158
- try {
159
- val = k.run(`+++ ${line}\n ()`, val);
160
- console.log(`=> ${JSON.stringify(val)}`);
161
- } catch (error) {
162
- e = error;
163
- console.error("ERROR:");
164
- console.error(e);
102
+ return (function (prettyRel) {
103
+ let ref1, relName;
104
+ ref1 = defs.rels;
105
+ for (relName in ref1) {
106
+ result[relName] = prettyRel(ref1[relName].def);
165
107
  }
108
+ return result;
109
+ })(
110
+ prettyRel.bind(
111
+ null,
112
+ prettyCode.bind(null, defs.representatives)
113
+ )
114
+ );
115
+ })(run.defs, {}));
116
+ // --c
117
+ } else if (line.match(/^[ \n\t]*(?:--c)?$/)) {
118
+ console.log(
119
+ (function (defs, result) {
120
+ for (const codeName of Object.keys(defs.representatives || {})) {
121
+ const codeExp = find(defs.representatives[codeName] || codeName);
122
+ result[codeName] = prettyCode(
123
+ defs.representatives,
124
+ codeExp
125
+ );
166
126
  }
167
- } catch (e) {
168
- console.error(e.message);
169
- }
127
+ return result;
128
+ })(run.defs || {}, {})
129
+ );
130
+ // --C
131
+ } else if (line.match(re__C)) {
132
+ let codeName = line.match(re__C)[1];
133
+ if (codeName.startsWith("?"))
134
+ codeName = codeName.slice(1);
135
+ if (codeName.startsWith("$"))
136
+ codeName = codeName.slice(1);
137
+ const canonicalName = run.defs.representatives[codeName] || codeName;
138
+ const codeExp = find( canonicalName );
139
+ console.log(` $ ${canonicalName} = ${prettyCode(run.defs.representatives, codeExp)}; -- ${codeExp.def}`);
140
+ // --pp
141
+ } else if (line.match(/^[ \n\t]*(?:--pp)?$/)) {
142
+ console.log(val);
143
+ // --p
144
+ } else if (line.match(/^[ \n\t]*(?:--p)?$/)) {
145
+ console.log(JSON.stringify(val, null, 2));
146
+ // --regs
147
+ } else if (line.match(/^[ \n\t]*(?:--regs)?$/)) {
148
+ console.log(` -- registers: ${Object.keys(registers).join(", ")}`);
149
+ // --s
150
+ } else if (line.match(re__s)) {
151
+ let reg = line.match(re__s)[1];
152
+ registers[reg] = val;
153
+ console.log(` -- current value stored in register: '${reg}'`);
154
+ // --g
155
+ } else if (line.match(re__g)) {
156
+ console.log(" -- getting value from register...");
157
+ let reg = line.match(re__g)[1];
158
+ val = registers[reg];
159
+ console.log(val);
160
+ // --R rel
161
+ } else if (line.match(re__R)) {
162
+ const relName = line.match(re__R)[1];
163
+ const rel = run.defs?.rels[relName];
164
+ if (!rel) {
165
+ console.log(` -- relation '${relName}' not found`);
166
+ return;
167
+ }
168
+ const filters = patterns2filters(rel.typePatternGraph, ...rel.def.patterns);
169
+ // console.log(filters);
170
+ // console.log(" variables:", JSON.stringify(variables));
171
+ // console.log(JSON.stringify({filters, variables}, null, 2));
172
+ // for (const filter of filters) {
173
+ const pcodef= prettyCode.bind(null, run.defs.representatives);
174
+ const filtersStr = filters.map( x => prettyRel(pcodef, {op: "filter", filter: x}));
175
+ console.log(` ${relName} : ${filtersStr[0]} --> ${filtersStr[1]}`);
176
+ // }
177
+ // ------ k code
178
+ } else if (!line.match(/^[ \n\t]*(?:#.*)?$/)) {
179
+ try {
180
+ val = k.run(`+++\n${line}\n()`, val);
181
+ printVal();
182
+ } catch (error) {
183
+ e = error;
184
+ console.error("ERROR:");
185
+ console.error(e);
170
186
  }
171
187
  }
172
- });
173
- })({}, []);
188
+ } catch (e) {
189
+ console.error(e.message);
190
+ }
191
+ }
package/run.mjs CHANGED
@@ -55,14 +55,14 @@ const builtin = {
55
55
  },
56
56
  FDIV: ([x, y]) => x / y,
57
57
  CONCAT: (strs) => strs.join(""),
58
- toVEC: (str) => [...str],
58
+ toVEC: (str) => [...`${str}`],
59
59
  true: () => true,
60
60
  false: () => false,
61
61
  null: () => null,
62
62
  toJSON: (x) => JSON.stringify(x),
63
63
  fromJSON: (x) => JSON.parse(x),
64
64
  CONS: ({car, cdr}) => { try { return [car, ...cdr]; } catch (e) { return undefined; } },
65
- SNOC: (x) => (x.length > 1 ? {car: x[0], cdr: x.slice(1)} : undefined),
65
+ SNOC: (x) => (x.length > 0 ? {car: x[0], cdr: x.slice(1)} : undefined),
66
66
  toDateMsec: (x) => new Date(x).getTime(),
67
67
  toDateStr: (x) => new Date(x).toISOString(),
68
68
  };
package/symbol-table.mjs CHANGED
@@ -124,7 +124,7 @@ class SymbolTable {
124
124
 
125
125
  add_rel(name, rel) {
126
126
  if (this.rels[name] != undefined)
127
- console.error(`SymbolTable: rel ${name} already defined (lines ${rel.start?.line}:${rel.start?.column}...${rel.end?.line}:${rel.end?.column})`);
127
+ console.error(`SymbolTable: rel '${name}' is redefined (lines ${rel.start?.line}:${rel.start?.column}...${rel.end?.line}:${rel.end?.column})`);
128
128
 
129
129
  this.rels[name] = {def: rel};
130
130
  }
@@ -1,5 +1,5 @@
1
1
  import k from './index.mjs';
2
- import { encodeCodeToString } from './codes.mjs';
2
+ import { encodeCodeToString, find } from './codes.mjs';
3
3
  import hash from './hash.mjs';
4
4
  [
5
5
  `
@@ -7,7 +7,7 @@ import hash from './hash.mjs';
7
7
  $pair = {nat x, nat y};
8
8
  $b = {int"x", bool y};
9
9
  $vector = [int];
10
- $tree = <{nat value, tree left, tree right} binary, {nat value} leaf, {nat value, tree tree} unary, [tree] list_of_trees>;
10
+ $tree = <{nat value, tree left, tree right} binary, nat leaf, {nat value, tree tree} unary, [tree] list_of_trees>;
11
11
 
12
12
  succ = { $nat succ} $nat;
13
13
  plus = $pair <
@@ -17,22 +17,27 @@ import hash from './hash.mjs';
17
17
  {{} zero} succ succ {() x, () y} plus
18
18
  `
19
19
  ].map(function (script) {
20
- console.log(`k_expression = '${script}';`);
20
+ console.log("test-fingerprint:");
21
+ // console.log(`k_expression = '${script}';`);
21
22
  const annotated = k.annotate(script);
22
- for (const code in annotated.codes) {
23
- console.log(`CODE: ${code}`);
24
- const s = encodeCodeToString(code,annotated.codes);
25
- console.log(` - DEFS: ${s}`);;
23
+ // console.log(annotated);
24
+ let ERRORS = 0;
25
+ for (const code in annotated.representatives) {
26
+ // console.log(`CODE: ${code}`);
27
+ const s = encodeCodeToString(annotated.representatives[code]);
28
+ // console.log(` - DEFS: ${s}`);;
26
29
  const annotated2 = k.annotate(s+" {}");;
27
- const s2 = encodeCodeToString(annotated2.representatives["C0"],annotated2.codes);
28
- console.log(` - reparsed FINGERPRINT: ${hash(s2)}`);
29
- if ((s === s2) && (hash(s) === hash(s2))) {
30
- console.log('--- OK');
31
- } else {
32
- console.log('--- ERROR');
33
- }
34
-
35
- console.log('-------------------');
30
+ const s2 = encodeCodeToString(annotated2.representatives["C0"]);
31
+ // console.log(` - reparsed FINGERPRINT: ${hash(s2)}`);
32
+ if (!((s === s2) && (hash(s) === hash(s2)))) {
33
+ ERRORS++;
34
+ console.log(` ERROR - reparsed FINGERPRINT for ${code} is different`);
35
+ }
36
+ }
37
+ if (ERRORS === 0) {
38
+ console.log("OK");
39
+ } else {
40
+ console.log(" ----- ERRORS");
36
41
  }
37
42
  });
38
43