@fraczak/k 1.0.1 → 1.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
@@ -1,6 +1,6 @@
1
1
  # k-language
2
2
 
3
- Another JSON-to-JSON transformation notation. A `k`-expression
3
+ Another JSON transformation notation. A `k`-expression
4
4
  (script) defines a __partial function__, i.e., a function which, in
5
5
  general, is not defined for every input. `k`-expressions can be
6
6
  combined to build other `k`-expressions in three ways:
@@ -11,14 +11,15 @@ combined to build other `k`-expressions in three ways:
11
11
 
12
12
  Apart from empty composition, `()`, which defines _identity_, the paranthesis can be omitted.
13
13
 
14
- 2. product, e.g., vector:
14
+ 2. product, e.g., vector or structure:
15
15
 
16
16
  [ E1, E2, E3, ... ]
17
-
18
- or structure:
19
-
20
17
  { E1 "e1", E2 "e2", E3 "e3", ... }
21
18
 
19
+ Now, structure can also be written similarly to JSON, ie.,
20
+
21
+ { e1: E1, e2: E2, e3: E3, ... }
22
+
22
23
  3. union (merge), e.g.:
23
24
 
24
25
  < E1, E2, E3, ... >
@@ -42,15 +43,14 @@ Elementary partial functions are:
42
43
  'another "String"'
43
44
  123
44
45
  false
45
-
46
- Those functions are always defined, i.e., they ignore their argument.
46
+ null
47
47
 
48
48
  3. There is a number of built-in functions: `GT`, `EQ`, `PLUS`,
49
- `TIMES`, `MINUS`, `DIV`, `CONCAT`, `toJSON`, `fromJSON`. For example
49
+ `TIMES`, `MINUS`, `DIV`, `CONCAT`, `toJSON`, `fromJSON`, `CONS`, `SNOC`. For example
50
50
 
51
- [1, 2, 3] PLUS --> integer constant 6
52
- [4, 4] TIMES toJSON --> string constant "16"
53
- [3, 2] GT --> vector constant [3, 2]
51
+ [1, 2, 3] PLUS --> integer constant function 6
52
+ [4, 4] TIMES toJSON --> string constant function "16"
53
+ [3, 2] GT --> vector constant function [3, 2]
54
54
  [3, 4] GT --> is not defined!
55
55
 
56
56
  A more interesting example could be:
@@ -61,6 +61,47 @@ Elementary partial functions are:
61
61
 
62
62
  [3,8] < [.0, .1] GT, [.1, .0] GT > .0 --> 8
63
63
 
64
+ ## User defined functions
65
+
66
+ `k`-expression can be prefixed by function definitions. E.g.:
67
+
68
+ dec = [(),1] MINUS;
69
+ factorial = <
70
+ [1,()] GT 1,
71
+ [dec factorial, ()] TIMES
72
+ >;
73
+ { () x, factorial "x!" }
74
+
75
+ ## Value encodings (also called _types_ or _codes_)
76
+
77
+ There are three predefined value encodings: `int`, `string`, and `bool`. The language
78
+ supports `code`-expressions:
79
+
80
+ * product, e.g., `{int x, int y, bool flag}` (in JSON-like syntax `{x: int, y: int, flag: bool}`)
81
+ * disjoint union, e.g., `<{} true, {} false>` (in JSON-like syntax `<true: {}, false: {}>`)
82
+ * vector, e.g., `[ int ]` (all elements of the vector use the same encoding)
83
+
84
+ One can define recursive codes. E.g.:
85
+
86
+ $ tree = <string leaf, {tree left, tree right} tree>;
87
+
88
+ or, the same in JSON-like notation:
89
+
90
+ $ tree = <leaf: string, tree: {left: tree, right: tree}>;
91
+
92
+ Each _code_ definition starts with a `$`.
93
+ The above example defines new code called _tree_.
94
+
95
+ The code can be then used in a `k`-expression as a filter. A `code`-expression
96
+ within `k`-expression is again prefixed by `$`.
97
+
98
+ $tree = <string leaf, {tree left, tree right} tree>;
99
+ inc = [(),1] PLUS;
100
+ height = $ tree <
101
+ .leaf 0,
102
+ .tree [.left height, .right height] <GT .0, .1> inc
103
+ > $ int;
104
+ height
64
105
 
65
106
 
66
107
  ## Command line script
@@ -70,7 +111,7 @@ run the language from command line.
70
111
 
71
112
  $ ./node_modules/.bin/k
72
113
  ... errors ...
73
- Usage: ./node_modules/.bin/k ( k-expr | -k k-file) [ json-file ]
114
+ Usage: ./node_modules/.bin/k ( k-expr | -k k-file) [ -1 ] [ json-file ]
74
115
  E.g., cat '{"a": 10}' | ./node_modules/.bin/k '[(),()]'
75
116
 
76
117
  ### Examples
@@ -113,7 +154,7 @@ run the language from command line.
113
154
 
114
155
  If we want to read `json` objects from a file, e.g., `my-objects.json`, we do
115
156
 
116
- $ ./k.coffee -k test.k -j my-objects.json
157
+ $ ./k.coffee -k test.k my-objects.json
117
158
  {"x&y":"x=432 & y=123"}
118
159
  {"x&y":"onlyx=987"}
119
160
  {"x&y":"no x nor y"}
@@ -178,4 +219,3 @@ run the language from command line.
178
219
 
179
220
  k_fn({"age":2,"name":"Mark"})
180
221
  // RETURNS: {"nom":"Mark","age":"enfant"}
181
-
package/bnat.k ADDED
@@ -0,0 +1,121 @@
1
+ -- Standard binary encoding of natural
2
+ -- numbers with addition (+).
3
+
4
+ _ = {{} _};
5
+ _1 = {() "1"};
6
+ _0 = {() "0"};
7
+
8
+ n0 = _ ;
9
+ n1 = _ _1;
10
+
11
+ from_digit = <
12
+ [0, ()] EQ _, -- {_: {}}
13
+ [1, ()] EQ n1, -- {"1": {_: {}}}
14
+ [2, ()] EQ _ _0 _1, -- {"1": {"0": {_: {}}}}
15
+ [3, ()] EQ _ _1 _1, -- {"1": {"1": {_: {}}}}
16
+ [4, ()] EQ _ _0 _0 _1, -- {"1": {"0": {"0": {_: {}}}}}
17
+ [5, ()] EQ _ _1 _0 _1,
18
+ [6, ()] EQ _ _0 _1 _1,
19
+ [7, ()] EQ _ _1 _1 _1,
20
+ [8, ()] EQ _ _0 _0 _0 _1,
21
+ [9, ()] EQ _ _1 _0 _0 _1,
22
+ [10, ()] EQ _ _0 _1 _0 _1
23
+ >;
24
+
25
+ to_digit = <
26
+ ._ 0,
27
+ ."1"._ 1,
28
+ ."1"."0"._ 2,
29
+ ."1"."1"._ 3,
30
+ ."1"."0"."0"._ 4,
31
+ ."1"."0"."1"._ 5,
32
+ ."1"."1"."0"._ 6,
33
+ ."1"."1"."1"._ 7,
34
+ ."1"."0"."0"."0"._ 8,
35
+ ."1"."0"."0"."1"._ 9,
36
+ ."1"."0"."1"."0"._ 10,
37
+ ."1"."0"."1"."1"._ 11,
38
+ ."1"."1"."0"."0"._ 12,
39
+ ."1"."1"."0"."1"._ 13,
40
+ ."1"."1"."1"."0"._ 14,
41
+ ."1"."1"."1"."1"._ 15
42
+ > ;
43
+
44
+ remove_leading_zeros =
45
+ < ."0" remove_leading_zeros, () >;
46
+
47
+ _append_zero =
48
+ < ._ _ _0, -- ( _ -> 0 _)
49
+ ."1" _append_zero _1, -- ('1 ... -> '1 [$.1 | _append_zero]),
50
+ ."0" _append_zero _0 -- ('0 ... -> '0 [$.0 | _append_zero]),
51
+ >
52
+ ;
53
+
54
+ _append_one =
55
+ <
56
+ ._ _ _1,
57
+ ."1" _append_one _1,
58
+ ."0" _append_one _0
59
+ >
60
+ ;
61
+
62
+ reverse_bnat = {() x, _ y} _reverse_bnat;
63
+
64
+ _reverse_bnat =
65
+ <
66
+ {.x._ x, .y y} .y,
67
+ {.x."0" x, .y _0 y} _reverse_bnat,
68
+ {.x."1" x, .y _1 y} _reverse_bnat
69
+ >;
70
+
71
+ _add2wc =
72
+ -- least significant bit first addition with carry
73
+ --- :{ :bnat x, :bnat y, :[0,1] c}
74
+ -- _log!
75
+ <
76
+ {.x."0" x, .y."0" y, .c."0" c} {.x x, .y y, _ _0 c} _add2wc _0,
77
+ {.x."0" x, .y."0" y, .c."1" c} {.x x, .y y, _ _0 c} _add2wc _1,
78
+
79
+ {.x."0" x, .y."1" y, .c."0" c} {.x x, .y y, _ _0 c} _add2wc _1,
80
+ {.x."0" x, .y."1" y, .c."1" c} {.x x, .y y, _ _1 c} _add2wc _0,
81
+
82
+ {.x."1" x, .y."0" y, .c."0" c} {.x x, .y y, _ _0 c} _add2wc _1,
83
+ {.x."1" x, .y."0" y, .c."1" c} {.x x, .y y, _ _1 c} _add2wc _0,
84
+
85
+ {.x."1" x, .y."1" y, .c."0" c} {.x x, .y y, _ _1 c} _add2wc _0,
86
+ {.x."1" x, .y."1" y, .c."1" c} {.x x, .y y, _ _1 c} _add2wc _1,
87
+ {.x._ x, .c."0" c, .y y} .y,
88
+ {.y._ y, .c."0" c, .x x} .x,
89
+ {.x._ x, .c."1" c, .y._ y} n1,
90
+ {.x._ x, .y."0" y, .c."1" c} .y _1,
91
+ {.x."0" x, .y._ y, .c."1" c} .x _1,
92
+ {.x._ x, .y."1" y, .c."1" c} {_ x, .y y, {} _1 c} _add2wc _0,
93
+ {.x."1" x, .y._ y, .c."1" c} {.x x, _ y, {} _1 c} _add2wc _0
94
+ >;
95
+
96
+ plus = <
97
+ SNOC {
98
+ x: .0 from_digit remove_leading_zeros reverse_bnat,
99
+ y: .1 plus remove_leading_zeros reverse_bnat,
100
+ c: {} _0 } _add2wc reverse_bnat,
101
+ .0 from_digit
102
+ >;
103
+
104
+ to_string = <
105
+ ._ "0",
106
+ toString
107
+ >;
108
+
109
+ toString = <
110
+ ._ "",
111
+ ["0", ."0" toString] CONCAT,
112
+ ["1", ."1" toString] CONCAT
113
+ >;
114
+
115
+ [(), plus]
116
+ {
117
+ input: .0,
118
+ sum: {raw: .1, digits: .1 <to_digit,"...too big...">, binary: .1 to_string}
119
+ }
120
+
121
+ -- example: > echo '[9,9,9,8]' | ./k.sh -k ./bnat.k
package/code.k ADDED
@@ -0,0 +1,18 @@
1
+ inc = [(),1] PLUS;
2
+ $tree = < string leaf, {tree left, tree right} tree>;
3
+ height = $tree <
4
+ .leaf 0,
5
+ .tree [.left height, .right height] <GT .0, .1> inc
6
+ > $int;
7
+
8
+ <$tree,
9
+ {tree:
10
+ { left: { leaf: "a"},
11
+ right: { tree:
12
+ { left: {leaf: "b"},
13
+ right: {leaf: "c"}
14
+ }
15
+ }
16
+ }
17
+ }
18
+ > _log! height
package/codes.coffee ADDED
@@ -0,0 +1,107 @@
1
+
2
+ are_different = (classes, representatives, name1, name2, codes) ->
3
+ return false if name1 is name2
4
+ code1 = codes[name1]
5
+ code2 = codes[name2]
6
+ # console.log {name1, code1, name2, code2}
7
+ return true unless code1.code is code2.code
8
+ switch code1.code
9
+ when "union", "product"
10
+ [fields1,fields2] = [code1, code2]. map (code) ->
11
+ Object.keys(code[code.code]).reduce (fields, label) ->
12
+ fields[label] = representatives[code[code.code][label]]
13
+ , {}
14
+ return true unless Object.keys(fields1).length is Object.keys(fields2).length
15
+ for field,rep of fields1
16
+ return true unless fields2[field] is rep
17
+ return false
18
+ when "vector"
19
+ return representatives[code1.vector] isnt representatives[code2.vector]
20
+ false
21
+
22
+ minimize = (codes) ->
23
+ names = Object.keys codes
24
+ classes = {}
25
+ classes["{}"] = names
26
+ representatives = names.reduce (representatives, name) ->
27
+ representatives[name] = "{}"
28
+ representatives
29
+ , {}
30
+ changed = true
31
+ while changed
32
+ changed = false
33
+ for name1, eq_names of classes
34
+ code = codes[name1]
35
+ [eq_names, dif_names] = eq_names.reduce ([eq_names, dif_names], name2) ->
36
+ if are_different(classes, representatives, name1, name2, codes)
37
+ dif_names.push name2
38
+ else
39
+ eq_names.push name2
40
+ [eq_names,dif_names]
41
+ , [[],[]]
42
+ classes[name1] = eq_names
43
+ do (new_rep = dif_names[0]) ->
44
+ if new_rep?
45
+ changed = true
46
+ classes[new_rep] = dif_names
47
+ for x in dif_names
48
+ representatives[x] = new_rep
49
+ {classes,representatives}
50
+
51
+ compareAs = (fn) ->
52
+ (a,b) ->
53
+ [a,b] = [a,b].map fn
54
+ return -1 if a < b
55
+ return 1 if a > b
56
+ 0
57
+
58
+ pretty_labels = (label_ref_map, codes, representatives) ->
59
+ labels = Object.keys(label_ref_map)
60
+ .sort compareAs (x) -> x
61
+ .map (label) ->
62
+ "#{pretty {code:"ref",ref:label_ref_map[label]}, codes, representatives} #{label}"
63
+ .join ", "
64
+
65
+ pretty = (codeExp, codes, representatives) ->
66
+ switch codeExp.code
67
+ when "ref"
68
+ name = representatives[codeExp.ref] ? codeExp.ref
69
+ if name.startsWith ":"
70
+ pretty codes[name], codes, representatives
71
+ else
72
+ name
73
+ when "product"
74
+ "{#{pretty_labels codeExp.product, codes, representatives}}"
75
+ when "union"
76
+ "<#{pretty_labels codeExp.union, codes, representatives}>"
77
+ when "vector"
78
+ "[#{representatives[codeExp.ref] ? codeExp.ref}]"
79
+ else
80
+ ":error"
81
+
82
+ normalize = (label_ref_map, representatives) ->
83
+ # console.log {label_ref_map, representatives}
84
+ Object.keys(label_ref_map).reduce (result, label) ->
85
+ result[label] = do (name = label_ref_map[label]) ->
86
+ representatives[name] ? name
87
+ result
88
+ , {}
89
+
90
+ normalizeAll = (codes,representatives) ->
91
+ names = Object.keys codes
92
+ normalized = names.reduce (normalized, name) ->
93
+ if name is representatives[name]
94
+ do (code = codes[name]) ->
95
+ switch code.code
96
+ when "union", "product"
97
+ normalized[name] = { code: code.code }
98
+ normalized[name][code.code] = normalize code[code.code], representatives
99
+ when "vector"
100
+ normalized[name] = {code:"vector", vector: representatives[code.vector]}
101
+
102
+ normalized
103
+ , {}
104
+
105
+ module.exports = {minimize,pretty,normalize,normalizeAll}
106
+
107
+
package/codes.js ADDED
@@ -0,0 +1,167 @@
1
+ // Generated by CoffeeScript 2.7.0
2
+ (function() {
3
+ var are_different, compareAs, minimize, normalize, normalizeAll, pretty, pretty_labels;
4
+
5
+ are_different = function(classes, representatives, name1, name2, codes) {
6
+ var code1, code2, field, fields1, fields2, rep;
7
+ if (name1 === name2) {
8
+ return false;
9
+ }
10
+ code1 = codes[name1];
11
+ code2 = codes[name2];
12
+ if (code1.code !== code2.code) {
13
+ // console.log {name1, code1, name2, code2}
14
+ return true;
15
+ }
16
+ switch (code1.code) {
17
+ case "union":
18
+ case "product":
19
+ [fields1, fields2] = [code1, code2].map(function(code) {
20
+ return Object.keys(code[code.code]).reduce(function(fields, label) {
21
+ return fields[label] = representatives[code[code.code][label]];
22
+ }, {});
23
+ });
24
+ if (Object.keys(fields1).length !== Object.keys(fields2).length) {
25
+ return true;
26
+ }
27
+ for (field in fields1) {
28
+ rep = fields1[field];
29
+ if (fields2[field] !== rep) {
30
+ return true;
31
+ }
32
+ }
33
+ return false;
34
+ case "vector":
35
+ return representatives[code1.vector] !== representatives[code2.vector];
36
+ }
37
+ return false;
38
+ };
39
+
40
+ minimize = function(codes) {
41
+ var changed, classes, code, dif_names, eq_names, name1, names, representatives;
42
+ names = Object.keys(codes);
43
+ classes = {};
44
+ classes["{}"] = names;
45
+ representatives = names.reduce(function(representatives, name) {
46
+ representatives[name] = "{}";
47
+ return representatives;
48
+ }, {});
49
+ changed = true;
50
+ while (changed) {
51
+ changed = false;
52
+ for (name1 in classes) {
53
+ eq_names = classes[name1];
54
+ code = codes[name1];
55
+ [eq_names, dif_names] = eq_names.reduce(function([eq_names, dif_names], name2) {
56
+ if (are_different(classes, representatives, name1, name2, codes)) {
57
+ dif_names.push(name2);
58
+ } else {
59
+ eq_names.push(name2);
60
+ }
61
+ return [eq_names, dif_names];
62
+ }, [[], []]);
63
+ classes[name1] = eq_names;
64
+ (function(new_rep) {
65
+ var i, len, results, x;
66
+ if (new_rep != null) {
67
+ changed = true;
68
+ classes[new_rep] = dif_names;
69
+ results = [];
70
+ for (i = 0, len = dif_names.length; i < len; i++) {
71
+ x = dif_names[i];
72
+ results.push(representatives[x] = new_rep);
73
+ }
74
+ return results;
75
+ }
76
+ })(dif_names[0]);
77
+ }
78
+ }
79
+ return {classes, representatives};
80
+ };
81
+
82
+ compareAs = function(fn) {
83
+ return function(a, b) {
84
+ [a, b] = [a, b].map(fn);
85
+ if (a < b) {
86
+ return -1;
87
+ }
88
+ if (a > b) {
89
+ return 1;
90
+ }
91
+ return 0;
92
+ };
93
+ };
94
+
95
+ pretty_labels = function(label_ref_map, codes, representatives) {
96
+ var labels;
97
+ return labels = Object.keys(label_ref_map).sort(compareAs(function(x) {
98
+ return x;
99
+ })).map(function(label) {
100
+ return `${pretty({
101
+ code: "ref",
102
+ ref: label_ref_map[label]
103
+ }, codes, representatives)} ${label}`;
104
+ }).join(", ");
105
+ };
106
+
107
+ pretty = function(codeExp, codes, representatives) {
108
+ var name, ref, ref1;
109
+ switch (codeExp.code) {
110
+ case "ref":
111
+ name = (ref = representatives[codeExp.ref]) != null ? ref : codeExp.ref;
112
+ if (name.startsWith(":")) {
113
+ return pretty(codes[name], codes, representatives);
114
+ } else {
115
+ return name;
116
+ }
117
+ break;
118
+ case "product":
119
+ return `{${pretty_labels(codeExp.product, codes, representatives)}}`;
120
+ case "union":
121
+ return `<${pretty_labels(codeExp.union, codes, representatives)}>`;
122
+ case "vector":
123
+ return `[${(ref1 = representatives[codeExp.ref]) != null ? ref1 : codeExp.ref}]`;
124
+ default:
125
+ return ":error";
126
+ }
127
+ };
128
+
129
+ normalize = function(label_ref_map, representatives) {
130
+ // console.log {label_ref_map, representatives}
131
+ return Object.keys(label_ref_map).reduce(function(result, label) {
132
+ result[label] = (function(name) {
133
+ var ref;
134
+ return (ref = representatives[name]) != null ? ref : name;
135
+ })(label_ref_map[label]);
136
+ return result;
137
+ }, {});
138
+ };
139
+
140
+ normalizeAll = function(codes, representatives) {
141
+ var names, normalized;
142
+ names = Object.keys(codes);
143
+ return normalized = names.reduce(function(normalized, name) {
144
+ if (name === representatives[name]) {
145
+ (function(code) {
146
+ switch (code.code) {
147
+ case "union":
148
+ case "product":
149
+ normalized[name] = {
150
+ code: code.code
151
+ };
152
+ return normalized[name][code.code] = normalize(code[code.code], representatives);
153
+ case "vector":
154
+ return normalized[name] = {
155
+ code: "vector",
156
+ vector: representatives[code.vector]
157
+ };
158
+ }
159
+ })(codes[name]);
160
+ }
161
+ return normalized;
162
+ }, {});
163
+ };
164
+
165
+ module.exports = {minimize, pretty, normalize, normalizeAll};
166
+
167
+ }).call(this);
package/factorial.k ADDED
@@ -0,0 +1,11 @@
1
+ -- factorial.k
2
+ -- E.g.:
3
+ -- > echo "5" | ./k.sh -k factorial.k
4
+ -- {"x":5,"x!":120}
5
+
6
+ dec = [(),1] MINUS;
7
+ factorial = <
8
+ [1,()] GT 1,
9
+ [dec factorial, ()] TIMES
10
+ >;
11
+ { x: (), "x!": factorial }
package/fib.k ADDED
@@ -0,0 +1,15 @@
1
+ fib_aux = _log!
2
+ <
3
+ { [.n, 1] GT [.0,-1] PLUS n,
4
+ ."[fib(n),fib(n-1)" [[.0,.1] PLUS, .0] "[fib(n),fib(n-1)"
5
+ } fib_aux,
6
+ ."[fib(n),fib(n-1)"
7
+ >
8
+ ;
9
+
10
+ fib = {() n, [1,1] "[fib(n),fib(n-1)"}
11
+ fib_aux .0;
12
+
13
+ ----------------------
14
+
15
+ fib
package/index.coffee CHANGED
@@ -1,10 +1,25 @@
1
1
  fs = require "fs"
2
2
  {parse} = require "./parser.js"
3
3
  run = require "./run"
4
+ t = require "./codes"
5
+
6
+
7
+ finalize = (codes) ->
8
+ representatives = t.minimize(codes).representatives
9
+ codes = t.normalizeAll codes, representatives
10
+
11
+ {codes, representatives}
12
+
4
13
 
5
14
  compile = (script) ->
6
- do (exp = parse script) ->
15
+ do ({defs,exp} = parse script) ->
16
+ # console.log defs
17
+ {codes, representatives} = finalize defs.codes
18
+ # console.log {codes, representatives}
19
+ run.defs = {codes, representatives, rels: defs.rels}
20
+
7
21
  (data) -> run exp, data
22
+
8
23
  compile.doc = "Transforms k-script (string) into a function"
9
24
 
10
25
  compile_file = (fileName) ->
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // Generated by CoffeeScript 2.7.0
2
2
  (function() {
3
- var compile, compile_file, fs, parse, run, runScriptOnData;
3
+ var compile, compile_file, finalize, fs, parse, run, runScriptOnData, t;
4
4
 
5
5
  fs = require("fs");
6
6
 
@@ -8,8 +8,26 @@
8
8
 
9
9
  run = require("./run");
10
10
 
11
+ t = require("./codes");
12
+
13
+ finalize = function(codes) {
14
+ var representatives;
15
+ representatives = t.minimize(codes).representatives;
16
+ codes = t.normalizeAll(codes, representatives);
17
+ return {codes, representatives};
18
+ };
19
+
11
20
  compile = function(script) {
12
- return (function(exp) {
21
+ return (function({defs, exp}) {
22
+ var codes, representatives;
23
+ // console.log defs
24
+ ({codes, representatives} = finalize(defs.codes));
25
+ // console.log {codes, representatives}
26
+ run.defs = {
27
+ codes,
28
+ representatives,
29
+ rels: defs.rels
30
+ };
13
31
  return function(data) {
14
32
  return run(exp, data);
15
33
  };
package/k.coffee CHANGED
@@ -4,7 +4,8 @@ k = require "./"
4
4
 
5
5
  prog = process.argv[1]
6
6
 
7
- {kScript,jsonStream} = do (args = process.argv.slice(2)) ->
7
+ {kScript,jsonStream,oneJson} =
8
+ do (oneJson = false, args = process.argv.slice(2)) ->
8
9
  try
9
10
  kScript = do (arg = args.shift()) ->
10
11
  throw new Error() unless arg?
@@ -16,30 +17,43 @@ prog = process.argv[1]
16
17
  kScript = k.compile kScript
17
18
 
18
19
  jsonStream = do (arg = args.shift()) ->
20
+ if arg is "-1"
21
+ oneJson = true
22
+ arg = args.shift()
19
23
  return process.stdin unless arg?
20
24
  fs.createReadStream arg
21
25
 
22
- {kScript, jsonStream}
26
+ {kScript, jsonStream, oneJson}
23
27
  catch e
24
28
  console.error e
25
- console.error "Usage: #{prog} ( k-expr | -k k-file ) [ json-file ]"
29
+ console.error "Usage: #{prog} ( k-expr | -k k-file ) [ -1 ] [ json-file ]"
26
30
  console.error " E.g., echo '{\"a\": 12}' | #{prog} '[(),()]'"
27
31
  process.exit -1
28
32
 
29
- do (buffer = [], line = 0) ->
30
- jsonStream.on 'data', (data) ->
31
- [first, rest...] = data.toString("utf8").split "\n"
32
- buffer.push first
33
- if rest.length > 0
34
- todo = buffer.join ""
35
- [rest..., last] = rest
36
- buffer = [last]
37
- todo = [todo, rest...]
38
- for json in todo
39
- if not json.match /^[ \n\t]*(?:#.*)?$/
40
- try
41
- console.log JSON.stringify kScript JSON.parse json
42
- catch e
43
- console.error "Problem [line #{line}]: '#{json}'"
44
- console.error e
45
- line = line + 1
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