git » hoplite.git » commit ee3c93e

More pred funcs, tests

author Alan Dipert
2021-06-14 14:12:11 UTC
committer Alan Dipert
2021-06-14 14:12:11 UTC
parent 0a5b716b4c4483cb0bab4a9d5fc55ee55281fd7f

More pred funcs, tests

datalog.mjs +21 -4
tests.mjs +57 -19

diff --git a/datalog.mjs b/datalog.mjs
index 27b31f8..785495c 100644
--- a/datalog.mjs
+++ b/datalog.mjs
@@ -216,6 +216,21 @@ function evalPred(predExpr) {
       if (!(args[i] < args[i+1])) return false;
     }
     return true;
+  } else if (op === '<=') {
+    for (let i = 0; i < args.length-1; i += 2) {
+      if (!(args[i] <= args[i+1])) return false;
+    }
+    return true;
+  } else if (op === '>') {
+    for (let i = 0; i < args.length-1; i += 2) {
+      if (!(args[i] > args[i+1])) return false;
+    }
+    return true;
+  } else if (op === '>=') {
+    for (let i = 0; i < args.length-1; i += 2) {
+      if (!(args[i] >= args[i+1])) return false;
+    }
+    return true;
   } else {
     throw new Error(`Unknown predicate: ${op}`);
   }
@@ -223,18 +238,20 @@ function evalPred(predExpr) {
 
 function filterByPredicate(rel, predClause) {
   return [...rel].reduce((xs, x) => {
-    let predExpr = predClause.map(y => {
+    let predExpr = [];
+    for (let y of predClause) {
       if (isBlank(y)) {
         throw new Error("Blanks not allowed in predicates");
       } else if (isVar(y)) {
         if (!x.hasOwnProperty(y.description)) {
           throw new Error("Unknown variable ${y.description} in predicate");
         }
-        return x[y.description];
+        if (x[y.description] === ANY.VALUE) continue;
+        predExpr.push(x[y.description]);
       } else {
-        return y;
+        predExpr.push(y);
       }
-    });
+    };
     if (evalPred(predExpr)) xs.add(x);
     return xs;
   }, new Relation(rel.vars));
diff --git a/tests.mjs b/tests.mjs
index 51bb6bb..5a61927 100644
--- a/tests.mjs
+++ b/tests.mjs
@@ -1,4 +1,4 @@
-import { _, query, StupidTupleSet } from './datalog.mjs';
+import { _, query, StupidTupleSet, ANY } from './datalog.mjs';
 const { module, test } = QUnit;
 
 // QUnit.assert.queryEquals = function(expect, q, ...args) {
@@ -17,42 +17,54 @@ module('datalog', () => {
 
   let db2 = new StupidTupleSet([
     ["ethel", "sex", "female"],
-    ["fred", "sex", "male"]
+    ["fred", "sex", "male"],
+    ["sally", "sex", "female"]
   ]);
 
-  test('simple query', assert => {
+  test('basic query', assert => {
     assert.deepEqual(
       query({
         find: [_.e],
-        use: [[_.db]],
         where: [
-          [_.db, _.e, "age", 42]
+          [_.e, "age", 42]
         ]
       }, db1).toArray(),
-      [["fred"], ["ethel"]]
+      [["fred"], ["ethel"]],
+      "implicit database"
     );
-  });
-  test('implicit database', assert => {
     assert.deepEqual(
       query({
         find: [_.e],
+        use: [[_.db]],
         where: [
-          [_.e, "age", 42]
+          [_.db, _.e, "age", 42]
         ]
       }, db1).toArray(),
-      [["fred"], ["ethel"]]
+      [["fred"], ["ethel"]],
+      "explicit database"
+    );
+    assert.deepEqual(
+      query({
+        find: [_.sex],
+        use: [[_.db1, _.db2], _.age],
+        where: [
+          [_.db1, _.e, "age", _.age],
+          [_.db2, _.e, "sex", _.sex]
+        ]
+      }, db1, db2, 21).toArray(),
+      [["female"]],
+      "multiple databases with variable"
     );
-  })
-  test('partial unify', assert => {
     assert.deepEqual(
       query({
         find: [_.e],
         where: [[_.e]]
       }, db2).toArray(),
-      [["ethel"], ["fred"]]
-    )
-  })
-  test('simple predicate', assert => {
+      [["ethel"], ["fred"], ["sally"]],
+      "partial tuple match"
+    );
+  });
+  test('predicates', assert => {
     assert.deepEqual(
       query({
         find: [_.e],
@@ -61,7 +73,33 @@ module('datalog', () => {
           [['<', _.age, 30]]
         ]
       }, db1).toArray(),
-      [["sally"]]
-    )
-  })
+      [["sally"]],
+      "no variable"
+    );
+    assert.deepEqual(
+      query({
+        find: [_.e],
+        use: [_.maxAge],
+        where: [
+          [_.e, "age", _.age],
+          [['<', _.age, _.maxAge]]
+        ]
+      }, db1, ANY.VALUE).toArray(),
+      [["sally"], ["fred"], ["ethel"]],
+      "ANY.VALUE variable"
+    );
+    assert.deepEqual(
+      query({
+        find: [_.e],
+        use: [_.minAge, _.maxAge],
+        where: [
+          [_.e, "age", _.age],
+          [['>', _.age, _.minAge]],
+          [['<=', _.age, _.maxAge]]
+        ]
+      }, db1, 30, 50).toArray(),
+      [["fred"], ["ethel"]],
+      "multiple variable"
+    );
+  });
 });