Permalink
Browse files

Merge pull request #95 from doug-martin/index-work

v0.2.3
  • Loading branch information...
2 parents 4b515ac + 8dd364c commit 3ca6e7279a5c02d4d403594bc0eb97fa9d3f0579 @doug-martin doug-martin committed Dec 17, 2013
Showing with 2,274 additions and 3,028 deletions.
  1. +31 −1 Gruntfile.js
  2. +1 −1 benchmark/manners/benchmark.js
  3. +2 −1 bin/nools
  4. +10 −0 docs/History.html
  5. +12 −12 docs/examples/browser/rules/diagnosis.nools
  6. +1 −3 docs/examples/browser/src/conway_3d.js
  7. +0 −2 docs/examples/browser/waltzDb.html
  8. +43 −12 docs/index.html
  9. +9 −9 docs/nools.js
  10. +12 −12 examples/browser/rules/diagnosis.nools
  11. +1 −3 examples/browser/src/conway_3d.js
  12. +0 −2 examples/browser/waltzDb.html
  13. +1 −1 examples/counter/index.js
  14. +1 −1 examples/sudoku/index.js
  15. +9 −0 history.md
  16. +2 −1 lib/agenda.js
  17. +1 −1 lib/compile/common.js
  18. +2 −1 lib/compile/index.js
  19. +15 −5 lib/compile/transpile.js
  20. +5 −1 lib/constraint.js
  21. +20 −5 lib/constraintMatcher.js
  22. +75 −41 lib/context.js
  23. +3 −3 lib/executionStrategy.js
  24. +40 −0 lib/extended.js
  25. +11 −1 lib/flow.js
  26. +2 −3 lib/nodes/adapterNode.js
  27. +35 −14 lib/nodes/betaNode.js
  28. +1 −1 lib/nodes/existsFromNode.js
  29. +1 −1 lib/nodes/fromNode.js
  30. +30 −3 lib/nodes/joinReferenceNode.js
  31. +151 −0 lib/nodes/misc/helpers.js
  32. +35 −116 lib/nodes/misc/memory.js
  33. +174 −0 lib/nodes/misc/table.js
  34. +46 −0 lib/nodes/misc/tupleEntry.js
  35. +16 −18 lib/nodes/notNode.js
  36. +22 −14 lib/workingMemory.js
  37. +980 −2,615 nools.js
  38. +9 −9 nools.min.js
  39. +1 −1 package.json
  40. +61 −12 readme.md
  41. +38 −20 test/constraintMatcher.test.js
  42. +64 −0 test/flow.compiled.test.js
  43. +130 −34 test/flow.dsl.test.js
  44. 0 test/flow.test.js
  45. +6 −6 test/flow/exists.test.js
  46. +49 −0 test/flow/facts.test.js
  47. +1 −0 test/flow/index.js
  48. +28 −3 test/flow/leftMemory.test.js
  49. +10 −11 test/flow/not.test.js
  50. +26 −1 test/flow/rightMemory.test.js
  51. +1 −1 test/rules/agenda-group-compiled.js
  52. +1 −1 test/rules/auto-focus-compiled.js
  53. +1 −0 test/rules/comments-compiled.js
  54. +1 −1 test/rules/diagnosis-compiled.js
  55. +1 −1 test/rules/fibonacci-compiled.js
  56. +1 −0 test/rules/getFacts-compiled.js
  57. +36 −0 test/rules/getFacts.nools
  58. +1 −0 test/rules/global-compiled.js
  59. +1 −0 test/rules/import-compiled.js
  60. +1 −1 test/rules/notRule-compiled.js
  61. +1 −1 test/rules/orRule-compiled.js
  62. +1 −19 test/rules/orRule-notConditions-compiled.js
  63. +1 −0 test/rules/provided-scope-compiled.js
  64. +1 −1 test/rules/scope-compiled.js
  65. +1 −1 test/rules/simple-compiled.js
  66. +1 −0 test/rules/simple-external-defined-compiled.js
View
@@ -1,6 +1,8 @@
/*global module:false*/
module.exports = function (grunt) {
// Project configuration.
+ var path = require("path"),
+ child = require("child_process");
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
jshint: {
@@ -48,9 +50,37 @@ module.exports = function (grunt) {
});
// Default task.
- grunt.registerTask('default', ['jshint', 'it', 'browserify:nools', 'uglify:min']);
+ grunt.registerTask('default', ['jshint', "compile-tests", 'it', 'browserify:nools', 'uglify:min']);
grunt.loadNpmTasks('grunt-it');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-browserify');
+
+ grunt.registerTask("compile-tests", "compiles all lest files", function () {
+ var files = grunt.file.expand("./test/rules/*.nools"), count = files.length, done = this.async();
+
+ function counter(err) {
+ if (err) {
+ done(err);
+ } else {
+ count--;
+ if (!count) {
+ done();
+ }
+ }
+ }
+
+ files.forEach(function (file) {
+ var base = path.basename(file, ".nools"),
+ out = path.resolve(path.dirname(file), base + "-compiled.js");
+ child.exec(path.resolve(__dirname, "./bin/nools") + " compile " + file + " -l ../../ -n " + base + "-compiled", function (err, output) {
+ if (!err) {
+ grunt.file.write(out, output.toString());
+ }
+ counter(err);
+ });
+ });
+
+
+ });
};
@@ -4,7 +4,7 @@
nools = require("../../index");
var flow = nools.compile(__dirname + "/manners.nools");
- var guests = data.load(flow).manners32;
+ var guests = data.load(flow).manners64;
var session = flow.getSession.apply(flow, guests);
session.assert(new (flow.getDefined("count"))({value: 1}));
var start = new Date();
View
@@ -5,6 +5,7 @@ var nools = require(".."),
path = require("path"),
fs = require("fs"),
path = require("path"),
+ stdout = process.stdout,
template = fs.readFileSync(path.join(__dirname, "assets", "compile_wrapper.tmpl"), "utf8"),
str = require("string-extended"),
uglifyjs = require("uglify-js"),
@@ -42,7 +43,7 @@ program.command("compile")
var noolsLocation = program["nools_location"] || "nools";
files.forEach(function (file) {
var name = program.name || path.basename(file, path.extname(file));
- console.log(uglify(str.format(template, { source: nools.transpile(path.resolve(process.cwd(), file), {name: name}), noolsLocation: noolsLocation}), program));
+ stdout.write(uglify(str.format(template, { source: nools.transpile(path.resolve(process.cwd(), file), {name: name}), noolsLocation: noolsLocation}), program));
});
});
View
@@ -178,6 +178,16 @@
+<h1>0.2.3</h1>
+<ul>
+<li>Added new <code>getFacts</code> method to allow for querying of facts currently in session. <a href="https://github.com/C2FO/nools/issues/52">#52</a>;</li>
+<li>Added indexing on comparison operators (i.e. <code>&gt;, &lt;, &gt;=, &lt;=</code>).</li>
+<li>Updated documentation.<ul>
+<li>Added new section about retrieving facts from a session.</li>
+<li>Created new section for async actions to address <a href="https://github.com/C2FO/nools/issues/94">#94</a></li>
+</ul>
+</li>
+</ul>
<h1>0.2.2</h1>
<ul>
<li>Performance Upgrades<ul>
@@ -22,6 +22,18 @@ define Treatment {
}
+rule Cold {
+ when {
+ p : Patient p.fever in ['mild', 'high'] {name : n};
+ not(d : Diagnosis d.name == n && d.diagnosis == 'flu');
+ }
+ then {
+ var d = new Diagnosis({name : n, diagnosis : "cold"});
+ emit("diagnosis", d);
+ assert(d);
+ }
+}
+
rule Measels {
when {
p : Patient p.fever == 'high' && p.spots == true && p.innoculated == true {name : n};
@@ -68,18 +80,6 @@ rule Flu {
}
}
-rule Cold {
- when {
- p : Patient p.fever in ['mild', 'high'] {name : n};
- not(d : Diagnosis d.name == n && d.diagnosis == 'flu');
- }
- then {
- var d = new Diagnosis({name : n, diagnosis : "cold"});
- emit("diagnosis", d);
- assert(d);
- }
-}
-
rule Healthy {
when {
p: Patient {name : n};
@@ -21,7 +21,7 @@
container.css({width: innerWidth + "px", height: innerHeight + "px"});
var camera = this.camera = new THREE.PerspectiveCamera(100, innerWidth / innerHeight, 1, 10000);
- camera.position.set(0.01,(dimension || this.defaultDimensions) * 25, 0.01);
+ camera.position.set(0.01, (dimension || this.defaultDimensions) * 25, 0.01);
var controls = this.controls = new THREE.OrbitControls(camera, container[0]);
@@ -77,7 +77,6 @@
__disposeAndReset: function () {
this.session.dispose();
if (!this.stopped) {
- console.profileEnd();
this.reset();
this.__matchPromise = null;
return this.run();
@@ -89,7 +88,6 @@
var session;
if (this.stopped && !this.__matchPromise) {
this.stopped = false;
- console.profile();
this.__matchPromise = this.statsListener.listen(this.session = this.flow
.getSession(this.cells))
.focus("populate")
@@ -71,7 +71,6 @@ <h1 class="inline">WaltzDB Benchmark</h1>
function run() {
stop();
- console.profile();
var data = loadData(flow, dataset);
session = statsListener.listen(flow.getSession());
for (var i = 0, l = data.length; i < l; i++) {
@@ -84,7 +83,6 @@ <h1 class="inline">WaltzDB Benchmark</h1>
resultsContainer.scrollTop(resultsContainer.prop("scrollHeight"));
})
.match().then(function () {
- console.profileEnd();
console.log("done");
}, function (e) {
console.log(e.stack);
View
@@ -195,6 +195,7 @@
<li><a href="#facts-assert">Assert</a></li>
<li><a href="#facts-retract">Retract</a></li>
<li><a href="#facts-modify">Modify</a></li>
+<li><a href="#get-facts">Retrieving Facts</a></li>
</ul>
</li>
<li><a href="#firing">Firing</a> </li>
@@ -221,7 +222,10 @@
<li><a href="#exists-constraint">Exists</a></li>
</ul>
</li>
-<li><a href="#action">Actions</a></li>
+<li><a href="#action">Actions</a><ul>
+<li><a href="#action-async">Async Actions</a></li>
+</ul>
+</li>
<li><a href="#globals">Globals</a></li>
<li><a href="#import">Import</a></li>
</ul>
@@ -434,6 +438,23 @@
session.modify(m);</code></pre>
<p><strong>Note</strong> <code>modify</code> is typically used during the execution of the rules.</p>
+<p><a name="get-facts"></a></p>
+<h3>Retrieving Facts</h3>
+<p>To get a list of facts currently in the session you can use the <code>getFacts()</code> method exposed on a session.</p>
+<pre class='prettyprint linenums lang-js'><code class="lang-javascript">session.assert(1);
+session.assert(&quot;A&quot;);
+session.assert(&quot;B&quot;);
+session.assert(2);
+
+session.getFacts(); //[1, &quot;A&quot;, &quot;B&quot;, 2];</code></pre>
+<p>You may also pass in a <code>Type</code> to <code>getFacts</code> which will return facts only of the given type.</p>
+<pre class='prettyprint linenums lang-js'><code class="lang-javascript">session.assert(1);
+session.assert(&quot;A&quot;);
+session.assert(&quot;B&quot;);
+session.assert(2);
+
+session.getFacts(Number); //[1, 2];
+session.getFacts(String); //[&quot;A&quot;, &quot;B&quot;];</code></pre>
<p><a name="firing"></a></p>
<h2>Firing the rules</h2>
<p>When you get a session from a <strong>flow</strong> no rules will be fired until the <strong>match</strong> method is called.</p>
@@ -1250,8 +1271,17 @@
session.modify(f3);
session.retract(f1);
}</code></pre>
-<p>If you have an async action that needs to take place an optional third argument can be passed in which is a function
-to be called when the action is completed.</p>
+<p>To define the actions with the nools DSL</p>
+<pre class='prettyprint linenums lang-js'><code>then {
+ modify(f3, function(){
+ this.value = f1.value + f2.value;
+ });
+ retract(f1);
+}</code></pre>
+<p>For rules defined using the rules language nools will automatically determine what parameters need to be passed in based on what is referenced in the action.</p>
+<p><a name="action-async"></a></p>
+<h3>Async Actions</h3>
+<p>If your action is async you can use the third argument which should called when the action is completed.</p>
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">function (facts, engine, next) {
//some async action
process.nextTick(function(){
@@ -1261,17 +1291,18 @@
engine.modify(f3);
engine.retract(f1);
next();
- })
+ });
}</code></pre>
-<p>If any arguments are passed into next it is assumed there was an error and the session will error out.</p>
-<p>To define the action with the nools DSL</p>
-<pre class='prettyprint linenums lang-js'><code>then {
- modify(f3, function(){
- this.value = f1.value + f2.value;
- });
- retract(f1);
+<p>If an error occurs you can pass the error as the first argument to <code>next</code>.</p>
+<pre class='prettyprint linenums lang-js'><code class="lang-javascript">then{
+ saveToDatabase(user, function(err){
+ next(new Error(&quot;Something went BOOM!&quot;));
+ });
+}</code></pre>
+<p>If you are using a <a href="http://promises-aplus.github.io/promises-spec/"><code>Promises/A+</code></a> compliant library you can just return a promise from your action and <code>nools</code> will wait for the promise to resolve before continuing.</p>
+<pre class='prettyprint linenums lang-js'><code class="lang-javascript">then{
+ return saveToDatabase(user); // assume saveToDatabase returns a promise
}</code></pre>
-<p>For rules defined using the rules language nools will automatically determine what parameters need to be passed in based on what is referenced in the action.</p>
<p><a name="globals"></a></p>
<h3>Globals</h3>
<p>Globals are accessible through the current working scope of rules defined in a <code>dsl</code>, very similar to using the <code>scope</code> option when compiling.</p>
View
Oops, something went wrong.
@@ -22,6 +22,18 @@ define Treatment {
}
+rule Cold {
+ when {
+ p : Patient p.fever in ['mild', 'high'] {name : n};
+ not(d : Diagnosis d.name == n && d.diagnosis == 'flu');
+ }
+ then {
+ var d = new Diagnosis({name : n, diagnosis : "cold"});
+ emit("diagnosis", d);
+ assert(d);
+ }
+}
+
rule Measels {
when {
p : Patient p.fever == 'high' && p.spots == true && p.innoculated == true {name : n};
@@ -68,18 +80,6 @@ rule Flu {
}
}
-rule Cold {
- when {
- p : Patient p.fever in ['mild', 'high'] {name : n};
- not(d : Diagnosis d.name == n && d.diagnosis == 'flu');
- }
- then {
- var d = new Diagnosis({name : n, diagnosis : "cold"});
- emit("diagnosis", d);
- assert(d);
- }
-}
-
rule Healthy {
when {
p: Patient {name : n};
@@ -21,7 +21,7 @@
container.css({width: innerWidth + "px", height: innerHeight + "px"});
var camera = this.camera = new THREE.PerspectiveCamera(100, innerWidth / innerHeight, 1, 10000);
- camera.position.set(0.01,(dimension || this.defaultDimensions) * 25, 0.01);
+ camera.position.set(0.01, (dimension || this.defaultDimensions) * 25, 0.01);
var controls = this.controls = new THREE.OrbitControls(camera, container[0]);
@@ -77,7 +77,6 @@
__disposeAndReset: function () {
this.session.dispose();
if (!this.stopped) {
- console.profileEnd();
this.reset();
this.__matchPromise = null;
return this.run();
@@ -89,7 +88,6 @@
var session;
if (this.stopped && !this.__matchPromise) {
this.stopped = false;
- console.profile();
this.__matchPromise = this.statsListener.listen(this.session = this.flow
.getSession(this.cells))
.focus("populate")
@@ -71,7 +71,6 @@ <h1 class="inline">WaltzDB Benchmark</h1>
function run() {
stop();
- console.profile();
var data = loadData(flow, dataset);
session = statsListener.listen(flow.getSession());
for (var i = 0, l = data.length; i < l; i++) {
@@ -84,7 +83,6 @@ <h1 class="inline">WaltzDB Benchmark</h1>
resultsContainer.scrollTop(resultsContainer.prop("scrollHeight"));
})
.match().then(function () {
- console.profileEnd();
console.log("done");
}, function (e) {
console.log(e.stack);
@@ -5,6 +5,6 @@ var flow = nools.compile(require.resolve("./counter.nools"));
flow.getSession().matchUntilHalt().then(function () {
//halt finally invoked
console.log("done");
-}, function () {
+}, function (err) {
console.log(err);
});
View
@@ -92,7 +92,7 @@ var hard4 = [
var sud = new sudoku.Sudoku(flow);
var repl = require("repl");
-sud.setCellValues(hard4).then(function () {
+sud.setCellValues(hard3).then(function () {
var sudokuRepl = repl.start("sudoku>>");
sudokuRepl.context.print = sud.dumpGrid.bind(sud);
sudokuRepl.context.step = function () {
View
@@ -1,3 +1,12 @@
+#0.2.3
+
+* Added new `getFacts` method to allow for querying of facts currently in session. [#52](https://github.com/C2FO/nools/issues/52);
+* Added indexing on comparison operators (i.e. `>, <, >=, <=`).
+* Updated documentation.
+ * Added new section about retrieving facts from a session.
+ * Created new section for async actions to address [#94](https://github.com/C2FO/nools/issues/94)
+
+
#0.2.2
* Performance Upgrades
View
@@ -3,6 +3,7 @@ var extd = require("./extended"),
declare = extd.declare,
AVLTree = extd.AVLTree,
LinkedList = extd.LinkedList,
+ isPromise = extd.isPromiseLike,
EventEmitter = require("events").EventEmitter;
@@ -110,7 +111,7 @@ module.exports = declare(EventEmitter, {
var activation = this.pop();
this.emit("fire", activation.rule.name, activation.match.factHash);
var fired = activation.rule.fire(this.flow, activation.match);
- if (extd.isPromiseLike(fired)) {
+ if (isPromise(fired)) {
ret = fired.then(function () {
//return true if an activation fired
return true;
View
@@ -4,7 +4,7 @@ var extd = require("../extended"),
forEach = extd.forEach,
isString = extd.isString;
-exports.modifiers = ["assert", "modify", "retract", "emit", "halt", "focus"];
+exports.modifiers = ["assert", "modify", "retract", "emit", "halt", "focus", "getFacts"];
var createFunction = function (body, defined, scope, scopeNames, definedNames) {
var declares = [];
Oops, something went wrong.

0 comments on commit 3ca6e72

Please sign in to comment.