const matchers = [
[/^\s*(!?\w+)\s*==\s*(!?\w+)\s*$/,
function(a, b) { return semieval(a, this) == semieval(b, this) }],
[/^\s*(!?\w+)\s*===\s*(!?\w+)\s*$/,
function(a, b) { return semieval(a, this) === semieval(b, this) }],
[/^\s*(!?\w+)\s*>=\s*(!?\w+)\s*$/,
function(a, b) { return semieval(a, this) >= semieval(b, this) }],
[/^\s*(!?\w+)\s*<=\s*(!?\w+)\s*$/,
function(a, b) { return semieval(a, this) <= semieval(b, this) }],
[/^\s*(!?\w+)\s*>\s*(!?\w+)\s*$/,
function(a, b) { return semieval(a, this) > semieval(b, this) }],
[/^\s*(!?\w+)\s*<\s*(!?\w+)\s*$/,
function(a, b) { return semieval(a, this) < semieval(b, this) }],
[/^\s*(!?\w+)\s*\|\|\s*(!?\w+)\s*$/,
function(a, b) { return semieval(a, this) || semieval(b, this) }],
[/^\s*(!?\w+)\s*&&\s*(!?\w+)\s*$/,
function(a, b) { return semieval(a, this) && semieval(b, this) }],
[/^\s*!(!?\w+)\s*$/,
function(a) { return !semieval(a, this) }],
[/^\s*true\s*$/,
function() { return true }],
[/^\s*false\s*$/,
function() { return false }],
[/^\s*([\d]+)\s*$/,
function(a) { return parseInt(a, 10) }],
[/^\s*(!?\w+)\s*$/,
function(a) { return this.hasOwnProperty(a) ? this[a] : a }]
];
function semieval(statement, object) {
for(let matcher of matchers) {
if(matcher[0].test(statement)) {
let parts = statement.match(matcher[0]);
return matcher[1].apply(object, parts.slice(1));
}
}
}
const state = {
isActive: true,
isRed: false,
count: 637
}
console.log(
semieval('isActive', state) // -> true
)
console.log(
semieval('!isRed', state) // -> true
)
console.log(
semieval('isRed == true', state) // -> false
)
console.log(
semieval('!!isRed', state) // -> false
)
console.log(
semieval('isActive && isRed', state) //-> false
)
console.log(
semieval('count > 100', state) // -> true
)
eval()is the quick-and-dirty way. Anything better will be complicated and require custom code.