@fraczak/k 1.3.4 → 2.0.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/INTRO.md DELETED
@@ -1,160 +0,0 @@
1
- # k - the way of building and manipulating JSON-like data
2
-
3
- Technically, `k` is a notation for defining __first-order partial functions__.
4
-
5
- An example of a _partial function_ is the _projection_, e.g., "`.toto`",
6
- which maps an object to its property named `toto`, or it is not defined if
7
- the property doesn't exist. E.g.,
8
-
9
- .toto :
10
- {"toto": 5, "titi": 10} --> 5
11
- {"titi": 10} ... undefined // it is not a value!
12
-
13
- ---
14
-
15
- ## Combining "partial functions"
16
-
17
- There are three ways of combining functions:
18
-
19
- 1. __composition__: `(f1 f2 ...)`, e.g. `(.toto .titi)` extracts
20
- nested field.
21
-
22
- (.toto .titi) :
23
- {"toto": {"titi": 10}} --> 10
24
- {"toto": 10 } ... undefined
25
- {} ... undefined
26
-
27
- 2. __merge__: `< f1, f2,... >`, e.g., `<.toto, .titi>` extracts field
28
- `toto` if present; otherwise extracts `titi`.
29
-
30
- <.toto, .titi> :
31
- {"toto": 5, "titi": 10} --> 5
32
- {"titi": 10 } --> 10
33
- {} ... undefined
34
-
35
- 3. __product__: `{ f1 label1, f2 label2, ...}`, e.g., `{.toto TOTO,
36
- .titi TITI}` extracts two fields and builds a record out of them.
37
-
38
- {.toto TOTO, .titi TITI} :
39
- {"toto": 5, "titi": 10} --> {"TOTO": 5, "TITI": 10}
40
- {"titi": 10 } ... undefined
41
-
42
- ---
43
-
44
- __QUIZ__: What is:
45
-
46
- - empty composition: `()` ?
47
- - empty merge: `<>` ?
48
- - empty product: `{}` ?
49
- - `{{{{} s} s} s}` ?
50
- - `({{{() a} b} c} .c .b .a)` ?
51
-
52
- ---
53
-
54
- #### Syntactic sugar:
55
-
56
- - parenthesis can be omitted, except for the empty composition `()`,
57
- - dot (`.`) in "projection" acts as a separator so the space around it can be omitted.
58
-
59
- For example, `[(.toto .titi (.0 .1))]` can be written as `[.toto.titi.0.1]`.
60
-
61
-
62
- ## Basic extensions
63
-
64
- ### Constants, i.e., literals for `strings`, `integers`, `booleans`, and `null`
65
-
66
- A constant defines a function which ignores its argument and produces
67
- the constant value. E.g.:
68
-
69
- {123 int, "kScript" str, true bool, null null} :
70
- <any> --> {"int":123,"str":"kScript","bool":true,"null":null}
71
-
72
- ### Vector product
73
-
74
- Vector product can be used as an abbreviation for product whose field
75
- names are integers starting from zero. E.g., `{.toto "0", .titi "1",
76
- 123 "2"}` can be written as `[.toto, .titi, 123]`.
77
-
78
- [.toto, .titi, 12] :
79
- {"toto": 5, "titi": 10 } --> [5, 10, 12] // {"0":5,"1":10,"2":12}
80
-
81
- .1 :
82
- ["A","B","C"] --> "B"
83
- ["a"] ... undefined
84
- ---
85
-
86
- ## Pragmatic extensions, aka "standard library"
87
-
88
- - `GT` : -- identity for lists of decreasing elements; undefined otherwise
89
-
90
- [4,3] --> [4,3]
91
- [3,4] ... undefined
92
- [] --> []
93
- [4,3,0] --> [4,3,0]
94
-
95
- - `EQ` : -- identity for lists of equal elements; undefined otherwise
96
-
97
- [4,4] --> [4,4]
98
- [4,5] ... undefined
99
- [4,4,4] --> [4,4,4]
100
- [] --> []
101
-
102
- - `{PLUS plus, TIMES times}` :
103
-
104
- [1,2] --> {"plus":3,"times":2}
105
- [2,2,2] --> {"plus":6,"times":8}
106
- [] --> {"plus":0,"times":1}
107
-
108
- - `CONCAT` :
109
-
110
- ["a","bc","d"] --> "abcd"
111
-
112
- - `toJSON` :
113
-
114
- {"a": 12} --> "{\"a\":12}"
115
-
116
- - `fromJSON` :
117
-
118
- "{\"a\":12}" --> {"a":12}
119
-
120
- - other predefined parial functions are: `DIV`, `FDIV`, `CONS`, `SNOC`, `toDateMsec`,
121
- `toDateStr`, and `_log!`.
122
-
123
- ---
124
-
125
- ## Recursive definitions
126
-
127
- -- factorial.k
128
- dec = [(),-1] PLUS;
129
- zero? = [(),0] EQ 0;
130
- factorial = <
131
- zero? 1,
132
- [dec factorial, ()] TIMES
133
- >;
134
- { () x, factorial "x!" }
135
-
136
- ## Codes (_types_)
137
-
138
- _Codes_ (prefixed by `$`) can be defined by taged union and product. E.g.:
139
-
140
- $nat = <nat 1, {} 0>;
141
- $pair = {nat x, nat y};
142
-
143
- suc = {$nat 1};
144
- add = $pair <{.x.1 x, .y suc y} add, .y>;
145
-
146
- ### Basic extension codes
147
-
148
- Since _basic extension_ introduces integers, booleans, and strings, there are three
149
- predefined types: `int`, `bool`, and `string`. A vector product code can also be defined
150
- by `[ codeExp ]`. All members of the vector are the same code. E.g.,
151
-
152
- $intVector = [ int ];
153
- $boolVector = [ bool ];
154
- $tree = [ tree ];
155
-
156
- emptyList? = $intVector $[ string ]; -- as only an empty vector can be a vector
157
- -- of integers and a vector of strings
158
-
159
-
160
-
package/codes.coffee DELETED
@@ -1,81 +0,0 @@
1
-
2
- are_different = (classes, representatives, name1, name2, codes) ->
3
- # console.log {classes, representatives, name1, name2, codes}
4
- return false if name1 is name2
5
- code1 = codes[name1]
6
- code2 = codes[name2]
7
- # console.log {name1, code1, name2, code2}
8
- return true unless code1.code is code2.code
9
- switch code1.code
10
- when "union", "product"
11
- [fields1,fields2] = [code1, code2]. map (code) ->
12
- do (arg = code[code.code]) ->
13
- Object.keys(arg).reduce (fields, label) ->
14
- fields[label] = representatives[arg[label]] ? arg[label]
15
- fields
16
- , {}
17
- return true unless Object.keys(fields1).length is Object.keys(fields2).length
18
- for field,rep of fields1
19
- # console.log {field,rep1:rep,rep2:fields2[field]}
20
- return true unless fields2[field] is rep
21
- when "vector"
22
- [arg1,arg2] = [code1, code2]. map ({vector}) ->
23
- representatives[vector] ? vector
24
- return true unless arg1 is arg2
25
- false
26
-
27
- minimize = (codes) ->
28
- names = Object.keys codes
29
- classes = {}
30
- classes["{}"] = names
31
- representatives = names.reduce (representatives, name) ->
32
- representatives[name] = "{}"
33
- representatives
34
- , {}
35
- changed = true
36
- while changed
37
- changed = false
38
- for name1, eq_names of classes
39
- code = codes[name1]
40
- [eq_names, dif_names] = eq_names.reduce ([eq_names, dif_names], name2) ->
41
- if are_different(classes, representatives, name1, name2, codes)
42
- dif_names.push name2
43
- else
44
- eq_names.push name2
45
- [eq_names,dif_names]
46
- , [[],[]]
47
- classes[name1] = eq_names
48
- do (new_rep = dif_names[0]) ->
49
- if new_rep?
50
- changed = true
51
- classes[new_rep] = dif_names
52
- for x in dif_names
53
- representatives[x] = new_rep
54
- {classes,representatives}
55
-
56
- normalize = (label_ref_map, representatives) ->
57
- # console.log {label_ref_map, representatives}
58
- Object.keys(label_ref_map).reduce (result, label) ->
59
- result[label] = do (name = label_ref_map[label]) ->
60
- representatives[name] ? name
61
- result
62
- , {}
63
-
64
- normalizeAll = (codes,representatives) ->
65
- names = Object.keys codes
66
- normalized = names.reduce (normalized, name) ->
67
- if name is representatives[name]
68
- do (code = codes[name]) ->
69
- switch code.code
70
- when "union", "product"
71
- normalized[name] = { code: code.code }
72
- normalized[name][code.code] = normalize code[code.code], representatives
73
- when "vector"
74
- normalized[name] = {code:"vector", vector: representatives[code.vector] ? code.vector}
75
-
76
- normalized
77
- , {}
78
-
79
- module.exports = {minimize,normalize,normalizeAll}
80
-
81
-
package/codes.js DELETED
@@ -1,134 +0,0 @@
1
- // Generated by CoffeeScript 2.7.0
2
- (function() {
3
- var are_different, minimize, normalize, normalizeAll;
4
-
5
- are_different = function(classes, representatives, name1, name2, codes) {
6
- var arg1, arg2, code1, code2, field, fields1, fields2, rep;
7
- if (name1 === name2) {
8
- // console.log {classes, representatives, name1, name2, codes}
9
- return false;
10
- }
11
- code1 = codes[name1];
12
- code2 = codes[name2];
13
- if (code1.code !== code2.code) {
14
- // console.log {name1, code1, name2, code2}
15
- return true;
16
- }
17
- switch (code1.code) {
18
- case "union":
19
- case "product":
20
- [fields1, fields2] = [code1, code2].map(function(code) {
21
- return (function(arg) {
22
- return Object.keys(arg).reduce(function(fields, label) {
23
- var ref;
24
- fields[label] = (ref = representatives[arg[label]]) != null ? ref : arg[label];
25
- return fields;
26
- }, {});
27
- })(code[code.code]);
28
- });
29
- if (Object.keys(fields1).length !== Object.keys(fields2).length) {
30
- return true;
31
- }
32
- for (field in fields1) {
33
- rep = fields1[field];
34
- if (fields2[field] !== rep) {
35
-
36
- // console.log {field,rep1:rep,rep2:fields2[field]}
37
- return true;
38
- }
39
- }
40
- break;
41
- case "vector":
42
- [arg1, arg2] = [code1, code2].map(function({vector}) {
43
- var ref;
44
- return (ref = representatives[vector]) != null ? ref : vector;
45
- });
46
- if (arg1 !== arg2) {
47
- return true;
48
- }
49
- }
50
- return false;
51
- };
52
-
53
- minimize = function(codes) {
54
- var changed, classes, code, dif_names, eq_names, name1, names, representatives;
55
- names = Object.keys(codes);
56
- classes = {};
57
- classes["{}"] = names;
58
- representatives = names.reduce(function(representatives, name) {
59
- representatives[name] = "{}";
60
- return representatives;
61
- }, {});
62
- changed = true;
63
- while (changed) {
64
- changed = false;
65
- for (name1 in classes) {
66
- eq_names = classes[name1];
67
- code = codes[name1];
68
- [eq_names, dif_names] = eq_names.reduce(function([eq_names, dif_names], name2) {
69
- if (are_different(classes, representatives, name1, name2, codes)) {
70
- dif_names.push(name2);
71
- } else {
72
- eq_names.push(name2);
73
- }
74
- return [eq_names, dif_names];
75
- }, [[], []]);
76
- classes[name1] = eq_names;
77
- (function(new_rep) {
78
- var i, len, results, x;
79
- if (new_rep != null) {
80
- changed = true;
81
- classes[new_rep] = dif_names;
82
- results = [];
83
- for (i = 0, len = dif_names.length; i < len; i++) {
84
- x = dif_names[i];
85
- results.push(representatives[x] = new_rep);
86
- }
87
- return results;
88
- }
89
- })(dif_names[0]);
90
- }
91
- }
92
- return {classes, representatives};
93
- };
94
-
95
- normalize = function(label_ref_map, representatives) {
96
- // console.log {label_ref_map, representatives}
97
- return Object.keys(label_ref_map).reduce(function(result, label) {
98
- result[label] = (function(name) {
99
- var ref;
100
- return (ref = representatives[name]) != null ? ref : name;
101
- })(label_ref_map[label]);
102
- return result;
103
- }, {});
104
- };
105
-
106
- normalizeAll = function(codes, representatives) {
107
- var names, normalized;
108
- names = Object.keys(codes);
109
- return normalized = names.reduce(function(normalized, name) {
110
- if (name === representatives[name]) {
111
- (function(code) {
112
- var ref;
113
- switch (code.code) {
114
- case "union":
115
- case "product":
116
- normalized[name] = {
117
- code: code.code
118
- };
119
- return normalized[name][code.code] = normalize(code[code.code], representatives);
120
- case "vector":
121
- return normalized[name] = {
122
- code: "vector",
123
- vector: (ref = representatives[code.vector]) != null ? ref : code.vector
124
- };
125
- }
126
- })(codes[name]);
127
- }
128
- return normalized;
129
- }, {});
130
- };
131
-
132
- module.exports = {minimize, normalize, normalizeAll};
133
-
134
- }).call(this);
package/index.coffee DELETED
@@ -1,28 +0,0 @@
1
- {parse} = require "./parser.js"
2
- run = require "./run"
3
- t = require "./codes"
4
-
5
-
6
- finalize = (codes) ->
7
- representatives = t.minimize(codes).representatives
8
- codes = t.normalizeAll codes, representatives
9
-
10
- {codes, representatives}
11
-
12
-
13
- compile = (script) ->
14
- do ({defs,exp} = parse script) ->
15
- # console.log defs
16
- {codes, representatives} = finalize defs.codes
17
- # console.log {codes, representatives}
18
- run.defs = {codes, representatives, rels: defs.rels}
19
-
20
- (data) -> run exp, data
21
-
22
- compile.doc = "Transforms k-script (string) into a function"
23
-
24
- runScriptOnData = (script, data) ->
25
- compile(script) data
26
- runScriptOnData.doc = "Run 'script' (string) on 'data': (script,data) -> data"
27
-
28
- module.exports = {compile, run: runScriptOnData, parse}
package/index.js DELETED
@@ -1,49 +0,0 @@
1
- // Generated by CoffeeScript 2.7.0
2
- (function() {
3
- var compile, finalize, parse, run, runScriptOnData, t;
4
-
5
- ({parse} = require("./parser.js"));
6
-
7
- run = require("./run");
8
-
9
- t = require("./codes");
10
-
11
- finalize = function(codes) {
12
- var representatives;
13
- representatives = t.minimize(codes).representatives;
14
- codes = t.normalizeAll(codes, representatives);
15
- return {codes, representatives};
16
- };
17
-
18
- compile = function(script) {
19
- return (function({defs, exp}) {
20
- var codes, representatives;
21
- // console.log defs
22
- ({codes, representatives} = finalize(defs.codes));
23
- // console.log {codes, representatives}
24
- run.defs = {
25
- codes,
26
- representatives,
27
- rels: defs.rels
28
- };
29
- return function(data) {
30
- return run(exp, data);
31
- };
32
- })(parse(script));
33
- };
34
-
35
- compile.doc = "Transforms k-script (string) into a function";
36
-
37
- runScriptOnData = function(script, data) {
38
- return compile(script)(data);
39
- };
40
-
41
- runScriptOnData.doc = "Run 'script' (string) on 'data': (script,data) -> data";
42
-
43
- module.exports = {
44
- compile,
45
- run: runScriptOnData,
46
- parse
47
- };
48
-
49
- }).call(this);
package/k.coffee DELETED
@@ -1,59 +0,0 @@
1
- #!/usr/bin/env coffee
2
- fs = require "fs"
3
- k = require "./"
4
-
5
- prog = process.argv[1]
6
-
7
- {kScript,jsonStream,oneJson} =
8
- do (oneJson = false, args = process.argv.slice(2)) ->
9
- try
10
- kScript = do (arg = args.shift()) ->
11
- throw new Error() unless arg?
12
- if arg is "-k"
13
- fs.readFileSync(args.shift()).toString "utf8"
14
- else
15
- arg
16
-
17
- kScript = k.compile kScript
18
-
19
- jsonStream = do (arg = args.shift()) ->
20
- if arg is "-1"
21
- oneJson = true
22
- arg = args.shift()
23
- return process.stdin unless arg?
24
- fs.createReadStream arg
25
-
26
- {kScript, jsonStream, oneJson}
27
- catch e
28
- console.error e
29
- console.error "Usage: #{prog} ( k-expr | -k k-file ) [ -1 ] [ json-file ]"
30
- console.error " E.g., echo '{\"a\": 12}' | #{prog} '[(),()]'"
31
- process.exit -1
32
-
33
- if oneJson
34
- do (buffer = []) ->
35
- jsonStream.on 'data', (data) ->
36
- buffer.push data
37
- jsonStream.on 'end', ->
38
- try
39
- console.log JSON.stringify kScript JSON.parse buffer.join('')
40
- catch e
41
- console.error e
42
- else
43
- do (buffer = [], line = 0) ->
44
- jsonStream.on 'data', (data) ->
45
- [first, rest...] = data.toString("utf8").split "\n"
46
- buffer.push first
47
- if rest.length > 0
48
- todo = buffer.join ""
49
- [rest..., last] = rest
50
- buffer = [last]
51
- todo = [todo, rest...]
52
- for json in todo
53
- if not json.match /^[ \n\t]*(?:#.*)?$/
54
- try
55
- console.log JSON.stringify kScript JSON.parse json
56
- catch e
57
- console.error "Problem [line #{line}]: '#{json}'"
58
- console.error e
59
- line = line + 1
package/k.js DELETED
@@ -1,93 +0,0 @@
1
- // Generated by CoffeeScript 2.7.0
2
- (function() {
3
- //!/usr/bin/env coffee
4
- var fs, jsonStream, k, kScript, oneJson, prog,
5
- splice = [].splice;
6
-
7
- fs = require("fs");
8
-
9
- k = require("./");
10
-
11
- prog = process.argv[1];
12
-
13
- ({kScript, jsonStream, oneJson} = (function(oneJson, args) {
14
- var e;
15
- try {
16
- kScript = (function(arg) {
17
- if (arg == null) {
18
- throw new Error();
19
- }
20
- if (arg === "-k") {
21
- return fs.readFileSync(args.shift()).toString("utf8");
22
- } else {
23
- return arg;
24
- }
25
- })(args.shift());
26
- kScript = k.compile(kScript);
27
- jsonStream = (function(arg) {
28
- if (arg === "-1") {
29
- oneJson = true;
30
- arg = args.shift();
31
- }
32
- if (arg == null) {
33
- return process.stdin;
34
- }
35
- return fs.createReadStream(arg);
36
- })(args.shift());
37
- return {kScript, jsonStream, oneJson};
38
- } catch (error) {
39
- e = error;
40
- console.error(e);
41
- console.error(`Usage: ${prog} ( k-expr | -k k-file ) [ -1 ] [ json-file ]`);
42
- console.error(` E.g., echo '{\"a\": 12}' | ${prog} '[(),()]'`);
43
- return process.exit(-1);
44
- }
45
- })(false, process.argv.slice(2)));
46
-
47
- if (oneJson) {
48
- (function(buffer) {
49
- jsonStream.on('data', function(data) {
50
- return buffer.push(data);
51
- });
52
- return jsonStream.on('end', function() {
53
- var e;
54
- try {
55
- return console.log(JSON.stringify(kScript(JSON.parse(buffer.join('')))));
56
- } catch (error) {
57
- e = error;
58
- return console.error(e);
59
- }
60
- });
61
- })([]);
62
- } else {
63
- (function(buffer, line) {
64
- return jsonStream.on('data', function(data) {
65
- var e, first, i, json, last, len, ref, rest, results, todo;
66
- [first, ...rest] = data.toString("utf8").split("\n");
67
- buffer.push(first);
68
- if (rest.length > 0) {
69
- todo = buffer.join("");
70
- ref = rest, [...rest] = ref, [last] = splice.call(rest, -1);
71
- buffer = [last];
72
- todo = [todo, ...rest];
73
- results = [];
74
- for (i = 0, len = todo.length; i < len; i++) {
75
- json = todo[i];
76
- if (!json.match(/^[ \n\t]*(?:#.*)?$/)) {
77
- try {
78
- console.log(JSON.stringify(kScript(JSON.parse(json))));
79
- } catch (error) {
80
- e = error;
81
- console.error(`Problem [line ${line}]: '${json}'`);
82
- console.error(e);
83
- }
84
- }
85
- results.push(line = line + 1);
86
- }
87
- return results;
88
- }
89
- });
90
- })([], 0);
91
- }
92
-
93
- }).call(this);
package/k.sh DELETED
@@ -1,94 +0,0 @@
1
- #!/usr/bin/env node
2
- // Generated by CoffeeScript 2.7.0
3
- (function() {
4
- //!/usr/bin/env coffee
5
- var fs, jsonStream, k, kScript, oneJson, prog,
6
- splice = [].splice;
7
-
8
- fs = require("fs");
9
-
10
- k = require("./");
11
-
12
- prog = process.argv[1];
13
-
14
- ({kScript, jsonStream, oneJson} = (function(oneJson, args) {
15
- var e;
16
- try {
17
- kScript = (function(arg) {
18
- if (arg == null) {
19
- throw new Error();
20
- }
21
- if (arg === "-k") {
22
- return fs.readFileSync(args.shift()).toString("utf8");
23
- } else {
24
- return arg;
25
- }
26
- })(args.shift());
27
- kScript = k.compile(kScript);
28
- jsonStream = (function(arg) {
29
- if (arg === "-1") {
30
- oneJson = true;
31
- arg = args.shift();
32
- }
33
- if (arg == null) {
34
- return process.stdin;
35
- }
36
- return fs.createReadStream(arg);
37
- })(args.shift());
38
- return {kScript, jsonStream, oneJson};
39
- } catch (error) {
40
- e = error;
41
- console.error(e);
42
- console.error(`Usage: ${prog} ( k-expr | -k k-file ) [ -1 ] [ json-file ]`);
43
- console.error(` E.g., echo '{\"a\": 12}' | ${prog} '[(),()]'`);
44
- return process.exit(-1);
45
- }
46
- })(false, process.argv.slice(2)));
47
-
48
- if (oneJson) {
49
- (function(buffer) {
50
- jsonStream.on('data', function(data) {
51
- return buffer.push(data);
52
- });
53
- return jsonStream.on('end', function() {
54
- var e;
55
- try {
56
- return console.log(JSON.stringify(kScript(JSON.parse(buffer.join('')))));
57
- } catch (error) {
58
- e = error;
59
- return console.error(e);
60
- }
61
- });
62
- })([]);
63
- } else {
64
- (function(buffer, line) {
65
- return jsonStream.on('data', function(data) {
66
- var e, first, i, json, last, len, ref, rest, results, todo;
67
- [first, ...rest] = data.toString("utf8").split("\n");
68
- buffer.push(first);
69
- if (rest.length > 0) {
70
- todo = buffer.join("");
71
- ref = rest, [...rest] = ref, [last] = splice.call(rest, -1);
72
- buffer = [last];
73
- todo = [todo, ...rest];
74
- results = [];
75
- for (i = 0, len = todo.length; i < len; i++) {
76
- json = todo[i];
77
- if (!json.match(/^[ \n\t]*(?:#.*)?$/)) {
78
- try {
79
- console.log(JSON.stringify(kScript(JSON.parse(json))));
80
- } catch (error) {
81
- e = error;
82
- console.error(`Problem [line ${line}]: '${json}'`);
83
- console.error(e);
84
- }
85
- }
86
- results.push(line = line + 1);
87
- }
88
- return results;
89
- }
90
- });
91
- })([], 0);
92
- }
93
-
94
- }).call(this);