New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@fraczak/k

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fraczak/k - npm Package Compare versions

Comparing version 1.2.0 to 1.2.1

Benchmark/range1000

8

package.json
{
"name": "@fraczak/k",
"version": "1.2.0",
"version": "1.2.1",
"description": "k-language for JSON-like data transformation",

@@ -8,3 +8,3 @@ "main": "index.js",

"prepare": "coffee -c symbol-table.coffee; jison parser.jison",
"prepublishOnly": "coffee -c *.coffee; echo '#!/usr/bin/env node' | cat - k.js > k.sh; echo '#!/usr/bin/env node' | cat - repl.js > repl.sh;",
"prepublishOnly": "coffee -c *.coffee; echo '#!/usr/bin/env node' | cat - k.js > k.sh; echo '#!/usr/bin/env node' | cat - repl.js > repl.sh;",
"all": "coffee -c *.coffee; npm run prepare; npm run prepublishOnly",

@@ -20,5 +20,5 @@ "test": "coffee -c symbol-table.coffee; jison parser.jison; coffee test.coffee"

"devDependencies": {
"jison": "^0.4.18",
"coffeescript": "^2.7.0"
"coffeescript": "^2.7.0",
"jison": "^0.4.18"
}
}

@@ -1,16 +0,24 @@

# k-language
# k-language
npm install @fraczak/k
npm install @fraczak/k
Another JSON transformation notation. A `k`-expression
(script) defines a __partial function__, i.e., a function which, in
general, is not defined for every input. `k`-expressions can be
combined to build other `k`-expressions in three ways:
From javascript:
var k = require("@fraczak/k"),
fn = k.compile("<.name,.nom,'?'>");
console.log([{name:"x"},{nom:"y"},{}].map(fn));
// returns: [ "x", "y", "?" ]
Another JSON transformation notation. A `k`-expression (script)
defines a __partial function__, i.e., a function which may fail
for some input. `k`-expressions can be combined to build
other `k`-expressions in three ways:
1. composition, e.g.:
(E1 E2 E3 ...)
Apart from empty composition, `()`, which defines _identity_, the paranthesis can be omitted.
Apart from empty composition, `()`, which defines _identity_, the
paranthesis can be omitted.
2. product, e.g., vector or structure:

@@ -21,86 +29,80 @@

Now, structure can also be written similarly to JSON, ie.,
{ e1: E1, e2: E2, e3: E3, ... }
3. union (merge), e.g.:
< E1, E2, E3, ... >
Elementary partial functions are:
1. _projection_, i.e., extracting the value of a given field or
index. Examples:
.x
."field name"
.4
The function is defined only if its argument is a structure with
the field (or a vector with the index).
2. _constants_, literals for Strings, Booleans, and
Elementary partial functions are:
4. _projection_, i.e., extracting the value of a given field or
index. Examples:
.x
."field name"
.4
The function is defined only if its argument is a structure with
the field (or a vector with the index).
5. _constants_, literals for Strings, Booleans, and
Integers. Examples:
"a string"
'another "String"'
123
false
null
3. There is a number of built-in functions: `GT`, `EQ`, `PLUS`,
`TIMES`, `MINUS`, `DIV`, `CONCAT`, `toJSON`, `fromJSON`, `CONS`, `SNOC`. For example
[1, 2, 3] PLUS --> integer constant function 6
[4, 4] TIMES toJSON --> string constant function "16"
[3, 2] GT --> vector constant function [3, 2]
[3, 4] GT --> is not defined!
A more interesting example could be:
< GT .0, .1>
which selects the maximum element in two element vector, i.e.,
[3,8] < GT .0, .1 > --> 8
"a string"
'another "String"'
123
false
null
6. There is a number of built-in functions: `GT`, `EQ`, `PLUS`,
`TIMES`, `MINUS`, `DIV`, `CONCAT`, `toJSON`, `fromJSON`, `CONS`,
`SNOC`, `_log!`, ... For example:
[1, 2, 3] PLUS --> integer constant function 6
[4, 4] TIMES toJSON --> string constant function "16"
[3, 2] GT --> vector constant function [3, 2]
[3, 4] GT --> is not defined!
A more interesting example could be:
< GT .0, .1>
which selects the maximum element in two element vector, i.e.,
[3,8] < GT .0, .1 > --> 8
## User defined functions
`k`-expression can be prefixed by function definitions. E.g.:
`k`-expression can be prefixed by function definitions. E.g.:
dec = [(),1] MINUS;
factorial = <
[1,()] GT 1,
[dec factorial, ()] TIMES
>;
{ () x, factorial "x!" }
dec = [(),1] MINUS;
factorial = <
[(),1] EQ 1,
[dec factorial, ()] TIMES
>;
{ () x, < factorial, "not defined" > "x!" }
Another example could be finding the biggest (max) value in a vector:
max = <
SNOC -- [x0, x1, x2, ...] -> [x0, [x1, x2, ...]]
[.0, .1 max] -- [x0, [x1, x2, ...]] -> [x0, max(x1,x2,...)], i.e., recursive call
<GT.0,.1>, -- if x0 > max(x1,x2,...) then x0 else max(x1,x2,...)
-- when SNOC is not defined, e.g. the argument is a singleton vector [x0]
.0 -- [x0] -> x0,
>;
max
max = <
SNOC -- [x0, x1, x2, ...] -> [x0, [x1, x2, ...]]
[.0, .1 max] -- [x0, [x1, x2, ...]] -> [x0, max(x1,x2,...)], i.e., recursive call
<GT.0,.1>, -- if x0 > max(x1,x2,...) then x0 else max(x1,x2,...)
-- when SNOC is not defined, e.g. the argument is a singleton vector [x0]
.0 -- [x0] -> x0,
>;
max
## Value encodings (also called _codes_)
## Value encodings (_codes_)
There are three predefined value encodings: `int`, `string`, and `bool`. The language
supports `code`-expressions:
There are three predefined value encodings: `int`, `string`, and
`bool`. The language supports `code`-expressions:
* product, e.g., `{int x, int y, bool flag}` (in JSON-like syntax `{x: int, y: int, flag: bool}`)
* disjoint union, e.g., `<{} true, {} false>` (in JSON-like syntax `<true: {}, false: {}>`)
* vector, e.g., `[ int ]` (all elements of the vector use the same encoding)
* product, e.g., `{int x, int y, bool flag}`
* disjoint union, e.g., `<{} true, {} false>`
* vector, e.g., `[ int ]` (all elements of the vector use the same
encoding)
One can define recursive codes. E.g.:
$ tree = <string leaf, {tree left, tree right} tree>;
tree = <string leaf, {tree left, tree right} tree>;
or, the same in JSON-like notation:
$ tree = <leaf: string, tree: {left: tree, right: tree}>;
Each _code_ definition starts with a `$`.

@@ -112,12 +114,11 @@ The above example defines new code called _tree_.

$ tree = <string leaf, {tree left, tree right} tree>;
inc = [(),1] PLUS;
max = <GT .0, .1>;
height = $ tree <
.leaf 0,
.tree [.left height, .right height] max inc
> $ int;
height
$ tree = <string leaf, {tree left, tree right} tree>;
inc = [(),1] PLUS;
max = <GT .0, .1>;
height = $ tree <
.leaf 0,
.tree [.left height, .right height] max inc
> $ int;
height
## Command line script

@@ -128,6 +129,6 @@

$ ./node_modules/.bin/k
... errors ...
Usage: ./node_modules/.bin/k ( k-expr | -k k-file) [ -1 ] [ json-file ]
E.g., cat '{"a": 10}' | ./node_modules/.bin/k '[(),()]'
> ./node_modules/.bin/k
... errors ...
Usage: ./node_modules/.bin/k ( k-expr | -k k-file) [ -1 ] [ json-file ]
E.g., cat '{"a": 10}' | ./node_modules/.bin/k '[(),()]'

@@ -138,112 +139,139 @@ ### Examples

$ echo '{"x": 12, "y": 13}' | ./k.coffee '{ <.x, "no x"> x, () input}'
{"x":12,"input":{"x":12,"y":13}}
> echo '{"x": 12, "y": 13}' | ./k.coffee '{ <.x, "no x"> x, () input}'
{"x":12,"input":{"x":12,"y":13}}
2. By providing only `k`-expression, the script will compile the
`k`-expression and apply the generated function to the `stdin`, line by line:
`k`-expression and apply the generated function to the `stdin`,
line by line:
$ ./node_modules/.bin/k '<["x=",.x," & y=",.y],["only x=",.x],["only y=",.y],["no x nor y"]>{CONCAT "x&y"}'
{"y": 123, "x": 432,"others": "..."} --> {"x&y":"x=432 & y=123"}
{"x":987} --> {"x&y":"only x=987"}
{"z":123} --> {"x&y":"no x nor y"}
^D - to interrupt
> ./node_modules/.bin/k '<["x=",.x," & y=",.y],["only x=",.x],["only y=",.y],["no x nor y"]>{CONCAT "x&y"}'
{"y": 123, "x": 432,"others": "..."} --> {"x&y":"x=432 & y=123"}
{"x":987} --> {"x&y":"only x=987"}
{"z":123} --> {"x&y":"no x nor y"}
^D - to interrupt
3. If the `k`-expression is long, it can be put in a file, e.g.:
$ cat test.k
--------- comments start by #, --, or // ----------------------------------
< -- merge of 4 partial functions...
["x=", .x, " & y=", .y], -- produces a vector of 4 values, if fields 'x' and 'y' are present
["only x=", .x], -- produces a pair '["only x=", "value-of-x"]', for input like {"x":"value-of-x"}
-- it is defined only if field 'x' is present
["only y=", .y],
["no x nor y"] -- defined for all input, returns always the same one element vector
>
-- one of the string vectors is passed to the following partial function,
-- which produces a record (map) with one field "x&y", whose value is the
-- result of concatenating elements of the passed in vector
{ CONCAT "x&y" }
------------------------------------------------------------------------------
We can use it by:
$ ./node_modules/.bin/k -k test.k
If we want to read `json` objects from a file, e.g., `my-objects.json`, we do
$ ./node_modules/.bin/k -k test.k my-objects.json
{"x&y":"x=432 & y=123"}
{"x&y":"onlyx=987"}
{"x&y":"no x nor y"}
where:
$ cat my-objects.json
####################################################
# empty lines and lines starting with # are ignored
{"y": 123, "x": 432,"others": "..."}
{"x":987}
{"z":123}
####################################################
# Using from `javascript`
var k = require("k");
> cat test.k
--------- comments start by #, --, or // ----------------------------------
< -- merge of 4 partial functions...
["x=", .x, " & y=", .y], -- produces a vector of 4 values, if fields 'x' and 'y' are present
["only x=", .x], -- produces a pair '["only x=", "value-of-x"]', for input like {"x":"value-of-x"}
-- it is defined only if field 'x' is present
["only y=", .y],
["no x nor y"] -- defined for all input, returns always the same one element vector
>
-- one of the string vectors is passed to the following partial function,
-- which produces a record (map) with one field "x&y", whose value is the
-- result of concatenating elements of the passed in vector
{ CONCAT "x&y" }
------------------------------------------------------------------------------
k_expression = '()';
k.run(k_expression,"ANYTHING...");
// RETURNS: "ANYTHING..."
We can use it by:
k_expression = '{"ala" name, 23 age}';
k.run(k_expression,"ANYTHING...");
// RETURNS: {"name":"ala","age":23}
> ./node_modules/.bin/k -k test.k
k_expression = '[.year, .age]';
k.run(k_expression,{"year":2002,"age":19});
// RETURNS: [2002,19]
If we want to read `json` objects from a file, e.g., `my-objects.json`, we do
k_expression = '[(), ()]';
k.run(k_expression,"duplicate me");
// RETURNS: ["duplicate me","duplicate me"]
> ./node_modules/.bin/k -k test.k my-objects.json
{"x&y":"x=432 & y=123"}
{"x&y":"onlyx=987"}
{"x&y":"no x nor y"}
k_expression = '[[[()]]]';
k.run(k_expression,"nesting");
// RETURNS: [[["nesting"]]]
where:
k_expression = '[[()]] {() nested, .0.0 val}';
k.run(k_expression,"nesting and accessing");
// RETURNS: {"nested":[["nesting and accessing"]],"val":"nesting and accessing"}
> cat my-objects.json
####################################################
# empty lines and lines starting with # are ignored
{"y": 123, "x": 432,"others": "..."}
{"x":987}
{"z":123}
####################################################
k_expression = '0000';
k.run(k_expression,{"test":"parse integer"});
// RETURNS: 0
### k-REPL (Read-Evaluate-Print Loop)
k_expression = '[.y,.x] PLUS';
k.run(k_expression,{"x":3,"y":4});
// RETURNS: 7
Also there is a REPL, `./node_modules/.bin/k-repl`, which acts like a toy
shell for the language. E.g.:
var k_fn = k.compile('{.name nom, <[.age, 18] GT .0, [.age, 12] GT "ado", "enfant"> age}');
> ./node_modules/.bin/k-repl
{'a' a, 'b' b} toJSON
=> "{\"a\":\"a\",\"b\":\"b\"}"
{"a" a} toJSON fromJSON
=> {"a":"a"}
inc = [(),1] PLUS; 1 inc inc
=> 3
inc inc inc inc
=> 7
k_fn({"age":23,"name":"Emily"});
// RETURNS: {"nom":"Emily","age":23}
## Using from `javascript`
k_fn({"age":16,"name":"Katrina"});
// RETURNS: {"nom":"Katrina","age":"ado"}
var k = require("k");
k_fn({"age":2,"name":"Mark"});
// RETURNS: {"nom":"Mark","age":"enfant"}
k_expression = '()';
k.run(k_expression,"ANYTHING...");
// RETURNS: "ANYTHING..."
var k_fn = k.compile('$t = < i: int, t: [ t ] > ; <$t, $int>');
k_expression = '{"ala" name, 23 age}';
k.run(k_expression,"ANYTHING...");
// RETURNS: {"name":"ala","age":23}
k_fn(1);
// RETURNS: 1
k_expression = '[.year, .age]';
k.run(k_expression,{"year":2002,"age":19});
// RETURNS: [2002,19]
k_fn({"i":1});
// RETURNS: {"i":1}
k_expression = '[(), ()]';
k.run(k_expression,"duplicate me");
// RETURNS: ["duplicate me","duplicate me"]
k_fn([{"i":2},{"i":3},{"t":[]}]);
// RETURNS: undefined
k_expression = '[[[()]]]';
k.run(k_expression,"nesting");
// RETURNS: [[["nesting"]]]
k_fn({"t":[{"i":2},{"i":3},{"t":[]}]});
// RETURNS: {"t":[{"i":2},{"i":3},{"t":[]}]}
k_expression = '[[()]] {() nested, .0.0 val}';
k.run(k_expression,"nesting and accessing");
// RETURNS: {"nested":[["nesting and accessing"]],"val":"nesting and accessing"}
k_expression = '0000';
k.run(k_expression,{"test":"parse integer"});
// RETURNS: 0
k_expression = '[.y,.x] PLUS';
k.run(k_expression,{"x":3,"y":4});
// RETURNS: 7
var k_fn = k.compile('{.name nom, <[.age, 18] GT .0, [.age, 12] GT "ado", "enfant"> age}');
k_fn({"age":23,"name":"Emily"});
// RETURNS: {"nom":"Emily","age":23}
k_fn({"age":16,"name":"Katrina"});
// RETURNS: {"nom":"Katrina","age":"ado"}
k_fn({"age":2,"name":"Mark"});
// RETURNS: {"nom":"Mark","age":"enfant"}
var k_fn = k.compile('$t = < i: int, t: [ t ] > ; <$t, $int>');
k_fn(1);
// RETURNS: 1
k_fn({"i":1});
// RETURNS: {"i":1}
k_fn([{"i":2},{"i":3},{"t":[]}]);
// RETURNS: undefined
k_fn({"t":[{"i":2},{"i":3},{"t":[]}]});
// RETURNS: {"t":[{"i":2},{"i":3},{"t":[]}]}
var k_fn = k.compile('$ < < [ int ] ints, [ bool ] bools > list, string None>');
k_fn({"None":"None"});
// RETURNS: {"None":"None"}
k_fn({"list":{"ints":[]}});
// RETURNS: {"list":{"ints":[]}}
k_fn({"list":{"ints":[1,2,3]}});
// RETURNS: {"list":{"ints":[1,2,3]}}

@@ -123,7 +123,13 @@ // Generated by CoffeeScript 2.7.0

verify = function(code, value) {
// representatives = run.defs.representatives
// defCodes = JSON.stringify run.defs.codes
// console.log {code,value, representatives, defCodes}
if (code == null) {
// representatives = run.defs.representatives
// defCodes = JSON.stringify run.defs.codes
// console.log {code,value, representatives, defCodes}
return false;
}
switch (code.code) {
case "vector":
if (!Array.isArray(value)) {
return false;
}
return value.every(function(x) {

@@ -133,2 +139,5 @@ return verify(code.vector, x);

case "product":
if ("object" !== typeof value) {
return false;
}
return (function(fields) {

@@ -143,2 +152,5 @@ if (fields.length !== Object.keys(code.product).length) {

case "union":
if ("object" !== typeof value) {
return false;
}
return (function(fields) {

@@ -161,3 +173,4 @@ if (fields.length !== 1) {

run = function(exp, value) {
var e, i, len, ref, ref1, result;
"use strict";
var defn, e, i, j, k, label, len, len1, len2, r, ref, ref1, ref2, ref3, result;
if (value === void 0) {

@@ -167,74 +180,64 @@ // console.log {exp,value}

}
try {
switch (exp.op) {
case "code":
if (verify(exp.code, value)) {
return value;
switch (exp.op) {
case "code":
if (verify(exp.code, value)) {
return value;
}
break;
case "identity":
return value;
case "str":
case "int":
return exp[exp.op];
case "ref":
defn = (ref = run.defs.rels[exp.ref]) != null ? ref[0] : void 0;
if (defn != null) {
return run(defn, value);
}
return builtin[exp.ref](value);
case "dot":
return value[exp.dot];
case "comp":
return exp.comp.reduce(function(value, exp) {
if (value !== void 0) {
return run(exp, value);
}
break;
case "identity":
return value;
case "str":
case "int":
return exp[exp.op];
case "ref":
return (function(defn) {
if (defn != null) {
return run(defn, value);
} else {
return (function(value) {
if (value === void 0) {
throw new Error("Undefined");
}
return value;
})(builtin[exp.ref](value));
}
})((ref = run.defs.rels[exp.ref]) != null ? ref[0] : void 0);
case "dot":
return value[exp.dot];
case "comp":
return exp.comp.reduce(function(value, exp) {
value = run(exp, value);
if (value === void 0) {
throw new Error("Undefined");
}
return value;
}, value);
case "vector":
return exp.vector.map(function(exp) {
var result;
result = run(exp, value);
if (result === void 0) {
throw new Error("Undefined");
}
}, value);
case "union":
ref1 = exp.union;
for (i = 0, len = ref1.length; i < len; i++) {
e = ref1[i];
result = run(e, value);
if (result !== void 0) {
return result;
});
case "union":
ref1 = exp.union;
for (i = 0, len = ref1.length; i < len; i++) {
e = ref1[i];
result = (function() {
try {
return run(e, value);
} catch (error) {}
})();
if (result !== void 0) {
return result;
}
}
return void 0;
case "product":
return exp.product.reduce(function(result, {label, exp}) {
return (function(value) {
if (value === void 0) {
throw new Error("Undefined");
}
result[label] = value;
return result;
})(run(exp, value));
}, {});
default:
return console.log(exp.op);
}
} catch (error) {}
}
return void 0;
case "vector":
result = [];
ref2 = exp.vector;
for (j = 0, len1 = ref2.length; j < len1; j++) {
e = ref2[j];
r = run(e, value);
if (r === void 0) {
return;
}
result.push(r);
}
return result;
case "product":
result = {};
ref3 = exp.product;
for (k = 0, len2 = ref3.length; k < len2; k++) {
({label, exp} = ref3[k]);
r = run(exp, value);
if (r === void 0) {
return;
}
result[label] = r;
}
return result;
default:
return console.error(exp.op);
}
};

@@ -241,0 +244,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc