lico
v0.1.0
Published
Lisp-like expressions/conditions compiler
Downloads
1
Readme
Conditions compiler
npm install lico
Lisp-like expressions/conditions compiler. General use-case is compile expressions from generated AST.
Usage
Lico uses lisp-like syntax for defining expressions.
import lico from 'lico';
const users = [
{name: 'Foo', active: true},
{name: 'bar', active: false}
];
// get "active" field from document and compare with "true"
// lico will always return a function that should be called for getting result
let active = lico(['eq', ['get', ['active']], ['ret', true]]);
console.log(users.filter(active)); // [{name: 'Foo', active: true}]
Operations
lico
uses polish notation, where first (0) element in array is a operation, rest of them is an arguments.
For example: + 1 2
will be 3
. In lico
it will be ['add', ['ret', 1], ['ret', 2]]
, where add
operation is sum all their arguments, ret
just return first argument.
###ret
In lico
you can't just return a constant, you should write ['ret', myvar]
instead, where myvar
is any variable, constant or something else.
Examples:
lico(['ret', true])(); // return "true"
lico(['ret', 10])(); // return 10
lico(['ret', ['ret', true]])(); // return array ['ret', true], because it not compiles their args
###get
For getting a property from object you should use get
operation. Syntax is similar to oq.
Examples:
let dog = {name: 'Lambda', age: 4};
lico(['get', ['name']])(dog); // return "Lambda"
###eq
Check for arguments is equal.
Examples:
lico(['eq', ['ret', true], ['ret', true]])(); // true
lico(['eq', ['ret', true], ['ret', false]])(); // false
lico(['eq', ['ret', true], ['ret', 1]])(); // true, because it is not strict equality
###ne
Check for arguments is not equal.
Examples:
lico(['ne', ['ret', true], ['ret', true]])(); // false
lico(['ne', ['ret', true], ['ret', false]])(); // true
lico(['ne', ['ret', false], ['ret', 0]])(); // true, because it is not strict equality
###lt
Check for first argument is less than second argument.
Examples:
lico(['lt', ['ret', 1], ['ret', 2]])(); // true
###gt
Check for first argument is greater than second argument.
Examples:
lico(['gt', ['ret', 1], ['ret', 2]])(); // false
###le
Check for first argument is less than second argument or equal.
Examples:
lico(['le', ['ret', 1], ['ret', 2]])(); // true
lico(['le', ['ret', 2], ['ret', 2]])(); // true
###ge
Check for first argument is greater than second argument or equal.
Examples:
lico(['ge', ['ret', 1], ['ret', 2]])(); // false
lico(['ge', ['ret', 2], ['ret', 2]])(); // true
###neg
Inverts a value of number.
Examples:
lico(['neg', ['ret', 1]])(); // -1
###or
Logical "OR".
Examples:
lico(['or', ['ret', 1], ['ret', 2]])(); // 1
lico(['or', ['ret', false], ['ret', 2]])(); // 2
###and
Logical "AND".
Examples:
lico(['and', ['ret', 1], ['ret', 2]])(); // 2
lico(['and', ['ret', false], ['ret', 2]])(); // false
###add
Sum of two arguments.
Examples:
lico(['add', ['ret', 1], ['ret', 2]])(); // 3
###sub
Subtracts second argument from first.
Examples:
lico(['sub', ['ret', 3], ['ret', 2]])(); // 1
###mul
Multiply arguments.
Examples:
lico(['mul', ['ret', 3], ['ret', 2]])(); // 6
###div
Divides first argument by second.
Examples:
lico(['div', ['ret', 6], ['ret', 2]])(); // 3
lico(['div', ['ret', 3], ['ret', 2]])(); // 1.5
###pow
Math.pow
.
Examples:
lico(['pow', ['ret', 2], ['ret', 3]])(); // 8
Extending
You can create your own operators. Just add it to lico.operators
dict.
Example:
import lico from 'lico';
lico.operators.myadd = (a, b) => {
let ca = lico(a); // compile first argument
let cb = lico(b); // compile second argument
// you always must return a function and passing "obj" parameter to compiled arguments
// because they can depend on it
return (obj) => ca(obj) + cb(obj);
}
let obj = {a: 2};
lico(['myadd', ['ret', 1], ['get', ['a']]])(obj); // 3