Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
doug-martin committed Feb 25, 2012
0 parents commit 562b51a
Show file tree
Hide file tree
Showing 15 changed files with 3,055 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
node_modules
nools.iml
1 change: 1 addition & 0 deletions index.js
@@ -0,0 +1 @@
module.exports = exports = require("./lib");
137 changes: 137 additions & 0 deletions lib/atoms.js
@@ -0,0 +1,137 @@
var comb = require("comb"), constraintMatcher;

var Atom = comb.define(null, {

instance:{
constructor:function (type, constraint) {
!constraintMatcher && (constraintMatcher = require("./constraintMatcher"));
this.type = type;
this.constraint = constraint;
},
assert:function () {
throw "not implemented";
},

getters:{
variables:function () {
return [this.alias];
}
}


}
});

var ObjectAtom = comb.define(Atom, {
instance:{
constructor:function (type) {
this._super(["object", type]);
}
}
}).as(exports, "ObjectAtom");

var EqualityAtom = comb.define(Atom, {

instance:{
constructor:function (constraint) {
this._super(["equality", constraint]);
},

assert:function (hash) {
return constraintMatcher.match(hash, this.constraint);
}
}
}).as(exports, "EqualityAtom");

var TrueAtom = comb.define(Atom, {

instance:{
constructor:function (constraint) {
this._super(["equality", [true]]);
},

assert:function (assertable) {
return true;
}
}
}).as(exports, "TrueAtom");

var ReferenceAtom = comb.define(Atom, {

instance:{
constructor:function (constraint) {
this._super(["reference", constraint]);
},

assert:function (values) {
return constraintMatcher.match(values, this.constraint);
},

getters:{
variables:function () {
return constraintMatcher.getIdentifiers(this.constraint).filter(function (v) {
return v != this.alias;
}, this);
}
}
}

}).as(exports, "ReferenceAtom");


var HashAtom = comb.define(Atom, {
instance:{
constructor:function (hash) {
this._super(["hash", hash]);
},

assert:function (factHash) {
var fact = factHash[this.alias];
Object.keys(this.constraint).forEach(function (k) {
var v = this.constraint[k];
factHash[v] = fact[k];
}, this);
return true;
},

getters:{
variables:function () {
return this.constraint;
}
}

}
}).as(exports, "HashAtom");


var CompositeAtom = comb.define(Atom, {

instance:{

constructor:function (type, atoms) {
this._super(type == "and" ? "and" : "or", atoms);
}

}

});

var AndAtom = comb.define(CompositeAtom, {

instance:{
constructor:function (atoms) {
this._super(["and", atoms]);
}
}

}).as(exports, "AndAtom");

var OrAtom = comb.define(CompositeAtom, {

instance:{
constructor:function (atoms) {
this._super(["or", atoms]);
}
}

}).as(exports, "OrAtom");
132 changes: 132 additions & 0 deletions lib/constraintMatcher.js
@@ -0,0 +1,132 @@
var comb = require("comb"), array = comb.array, removeDups = array.removeDuplicates, intersect = array.intersect, atoms = require("./atoms");

var lang = {

getIdentifiers:function (rule) {
var ret = [];
if (rule[2] == "identifier") {
//its an identifier so stop
return rule[0];
} else if (["string", "number", "boolean", "regexp", "unminus"].indexOf(rule[2]) == -1) {
//its an expression so keep going
if(rule[2] == "prop"){
return ret.concat(this.getIdentifiers(rule[0]));
}
return ret.concat(this.getIdentifiers(rule[0]), this.getIdentifiers(rule[1]));
}
//remove dups and return
return removeDups(ret);
},

toAtoms:function (rule, reference) {
var ret = [];
if (rule[2] == "and") {
ret = ret.concat(this.toAtoms(rule[0],reference)).concat(this.toAtoms(rule[1],reference));
} else if (rule[2] == "or") {
//we probably shouldnt support this right now
ret.push(new atoms.EqualityAtom(rule));
} else if (["lt", "gt", "lte", "gte", "like", "eq", "neq"].indexOf(rule[2]) != -1) {
if (this.getIdentifiers(rule).some(function(i){ return i != reference})) {
ret.push(new atoms.ReferenceAtom(rule));
} else {
ret.push(new atoms.EqualityAtom(rule));
}
}
return ret;
},

parse:function (rule, env) {
return this[rule[2]](rule[0], rule[1], env);
},

and:function (lhs, rhs, env) {
return this.parse(lhs, env) && this.parse(rhs, env);
},
or:function (lhs, rhs, env) {
return this.parse(lhs, env) || this.parse(rhs, env);
},

prop:function (name, prop, env) {
return this.parse(prop, this.parse(name, env));
},

plus:function (lhs, rhs, env) {
return this.parse(lhs, env) + this.parse(rhs, env);
},
minus:function (lhs, rhs, env) {
return this.parse(lhs, env) - this.parse(rhs, env);
},
mult:function (lhs, rhs, env) {
return this.parse(lhs, env) * this.parse(rhs, env);
},

unminus:function (lhs, rhs, env) {
return -1 * this.parse(lhs, env);
},

div:function (lhs, rhs, env) {
return this.parse(lhs, env) / this.parse(rhs, env);
},
lt:function (lhs, rhs, env) {
return this.parse(lhs, env) < this.parse(rhs, env);
},
gt:function (lhs, rhs, env) {
return this.parse(lhs, env) > this.parse(rhs, env);
},
lte:function (lhs, rhs, env) {
return this.parse(lhs, env) <= this.parse(rhs, env);
},
gte:function (lhs, rhs, env) {
return this.parse(lhs, env) >= this.parse(rhs, env);
},
like:function (lhs, rhs, env) {
return ("" + this.parse(lhs, env)).match(this.parse(rhs, env)) != null;
},
eq:function (lhs, rhs, env) {
return this.parse(lhs, env) === this.parse(rhs, env);
},
neq:function (lhs, rhs, env) {
return this.parse(lhs, env) !== this.parse(rhs, env);
},

string:function (lhs, rhs, env) {
return lhs;
},

number:function (lhs, rhs, env) {
return lhs;
},

boolean:function (lhs, rhs, env) {
return lhs;
},

regexp:function (lhs, rhs, env) {
return lhs;
},

identifier:function (lhs, rhs, env) {
return env ? env[lhs] : undefined;
}
};

exports.constraintToAtoms = function (constraint,reference) {
return lang.toAtoms(constraint,reference);
};


exports.match = function (env, constraint) {
env = env || {};
return lang.parse(constraint, env);
};

exports.isDependent = function (keys, constraint) {
return intersect(keys, lang.getIdentifiers(constraint)).length >= 1;
};

exports.getIdentifiers = function (constraint) {
return lang.getIdentifiers(constraint);
};



0 comments on commit 562b51a

Please sign in to comment.