You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The rule engine has trouble parsing rules with constructs like:
when {
p : Property p.name != null && p.value != -1 {name:pn,value:pv};
d : Dimension d.name!=null && isTrue(d.range.contains(pv));
}
but this works:
when {
d : Dimension d.name!=null && isTrue(d.range.contains(20));
}
Here range is a class "Range" that encapsulates the "contains" function that determines if the value is in range.
The pv doesn't seem to be considered a valid symbol by the parser when parsing the "contains(pv)" function call and returns the error that "pv is not defined" (I have tried p.value here also). Pulling off the "isTrue" parses, but the rule no longer functions correctly (it always fires).
Simple models without functions work as seen in the following:
when {
p : Property p.name != null && p.value != -1;
d : Dimension2 d.name!=null && p.value >= d.low && d.high >= p.value;
}
Is there a fix for this? Allowing function calls here is a step up in the expressive range of the language.
if (!(typeof exports === "undefined")) {
var nools = require("nools");
var range_module = require("./modules/range/range.class.js");
var enum_module = require("./modules/enum/enum.js");
var Range = range_module.Range;
var Enum = enum_module.Enum;
}
var flow = nools.compile(__dirname + "/rules/routebroken.nools");
Dimension = flow.getDefined("Dimension");
Property = flow.getDefined("Property");
r = new Range(4,200);
d = new Dimension("Quantity",r);
var session = flow.getSession();
session.assert(new Dimension("Quantity",r));
session.assert(new Property("Quantity",10));
session.assert(new Property("Quantity",100));
session.assert(new Property("Quantity",1000)); // should not fire a rule.
session.match().then(
function(){
console.log("Done");
},
function(err){
//uh oh an error occurred
console.error(err);
});
/modules/enum/enum.js
(function (exports) {
function copyOwnFrom(target, source) {
Object.getOwnPropertyNames(source).forEach(function(propName) {
Object.defineProperty(target, propName,
Object.getOwnPropertyDescriptor(source, propName));
});
return target;
}
function Symbol(name, props) {
this.name = name;
if (props) {
copyOwnFrom(this, props);
}
Object.freeze(this);
}
/** We don’t want the mutable Object.prototype in the prototype chain */
Symbol.prototype = Object.create(null);
Symbol.prototype.constructor = Symbol;
/**
* Without Object.prototype in the prototype chain, we need toString()
* in order to display symbols.
*/
Symbol.prototype.toString = function () {
return "|"+this.name+"|";
};
Object.freeze(Symbol.prototype);
Enum = function (obj) {
if (arguments.length === 1 && obj !== null && typeof obj === "object") {
Object.keys(obj).forEach(function (name) {
this[name] = new Symbol(name, obj[name]);
}, this);
} else {
Array.prototype.forEach.call(arguments, function (name) {
this[name] = new Symbol(name);
}, this);
}
Object.freeze(this);
}
Enum.prototype.symbols = function() {
return Object.keys(this).map(
function(key) {
return this[key];
}, this
);
}
Enum.prototype.contains = function(sym) {
if (! sym instanceof Symbol) return false;
return this[sym.name] === sym;
}
exports.Enum = Enum;
exports.Symbol = Symbol;
}(typeof exports === "undefined" ? this.enums = {} : exports));
// Explanation of this pattern: http://www.2ality.com/2011/08/universal-modules.html
/modules/range/range.class.js
(function (exports) {
Range = function (start_, end_, step_) {
var range;
var typeofrange;
var typeofStart;
var typeofEnd;
var largerange = 100;
var rangelow,rangehigh;
Array.prototype.contains = function(k) {
for(var p in this)
if(this[p] === k)
return true;
return false;
}
var init = function(start, end, step) {
range = [];
typeofStart = typeof start;
typeofEnd = typeof end;
if (typeof(start) == "object")
{
if (start instanceof Array) {
range = start;
typeofrange = "array";
}
// TODO: Hash?
else { // assume an enum if it isn't an array.
range = start;
typeofrange = "enum";
}
return;
}
if (step === 0) {
throw TypeError("Step cannot be zero.");
}
if (typeofStart == "undefined" || typeofEnd == "undefined") {
throw TypeError("Must pass start and end arguments.");
} else if (typeofStart != typeofEnd) {
throw TypeError("Start and end arguments must be of same type.");
}
typeof step == "undefined" && (step = 1);
if (end < start) {
step = -step;
}
rangelow=start;
rangehigh=end;
if (typeofStart == "number") {
if ((end-start)/step >= largerange || step == 1) {
typeofrange = "range";
if (step != 1){
throw TypeError("Step size must be 1 for ranges larger than "+largerange+".");
}
}
else {
typeofrange = typeofStart;
while (step > 0 ? end >= start : end <= start) {
range.push(start);
start += step;
}
}
} else if (typeofStart == "string") {
typeofrange = typeofStart;
if (start.length != 1 || end.length != 1) {
throw TypeError("Only strings with one character are supported.");
}
start = start.charCodeAt(0);
end = end.charCodeAt(0);
while (step > 0 ? end >= start : end <= start) {
range.push(String.fromCharCode(start));
start += step;
}
} else {
throw TypeError("Only string and number types are supported");
}
};
var getRange = function() { if (typeofrange=="range") return getLow()+".."+getHigh();
else return range; };
var getLow = function () { return rangelow; };
var getHigh = function () { return rangehigh; };
var contains = function (value) {
if (typeofrange == "range") {
return value >= rangelow && value <= rangehigh;
}
return range.contains(value)
/*if (typeofrange == "enum") {
return range.contains(value)
}
for(var p in range)
if(this[p] === value)
return true;
return false;
*/
}
init(start_, end_, step_);
return {
getRange:getRange,
getLow:getLow,
getHigh:getHigh,
contains:contains
};
};
exports.Range = Range;
}(typeof exports === "undefined" ? this.range = {} : exports));
//exports.Range = Range;
The text was updated successfully, but these errors were encountered:
The rule engine has trouble parsing rules with constructs like:
but this works:
Here range is a class "Range" that encapsulates the "contains" function that determines if the value is in range.
The pv doesn't seem to be considered a valid symbol by the parser when parsing the "contains(pv)" function call and returns the error that "pv is not defined" (I have tried p.value here also). Pulling off the "isTrue" parses, but the rule no longer functions correctly (it always fires).
Simple models without functions work as seen in the following:
Is there a fix for this? Allowing function calls here is a step up in the expressive range of the language.
Full Code below:
the dsl: /rules/routebroken.nools
the program: routedslbroken.js
/modules/enum/enum.js
/modules/range/range.class.js
The text was updated successfully, but these errors were encountered: