Permalink
Browse files

first commit

  • Loading branch information...
doug-martin committed Feb 25, 2012
0 parents commit 562b51a09c5bf18ccad8445abb35f1bb011c16b7
Showing with 3,055 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +1 −0 index.js
  3. +137 −0 lib/atoms.js
  4. +132 −0 lib/constraintMatcher.js
  5. +137 −0 lib/index.js
  6. +815 −0 lib/nodes.js
  7. +99 −0 lib/parser.js
  8. +70 −0 lib/pattern.js
  9. +112 −0 lib/rule.js
  10. +83 −0 lib/workingMemory.js
  11. +25 −0 package.json
  12. +138 −0 test/constraintMatcher.test.js
  13. +255 −0 test/flow.test.js
  14. +690 −0 test/parser.test.js
  15. +359 −0 test/rules.test.js
@@ -0,0 +1,2 @@
+node_modules
+nools.iml
@@ -0,0 +1 @@
+module.exports = exports = require("./lib");
@@ -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");
@@ -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);
+};
+
+
+
Oops, something went wrong.

0 comments on commit 562b51a

Please sign in to comment.