diff --git a/js/compiler/compiler.js b/js/compiler/compiler.js index cd65c43..2292d81 100644 --- a/js/compiler/compiler.js +++ b/js/compiler/compiler.js @@ -182,7 +182,7 @@ var modifiedSourceActions = { buildOnEvent(true, 'retracted', pattern.instantiatedSubscription, - 'null', + pattern.instantiatedProjection, [], '{}') + '.completeBuild(); }'); @@ -252,6 +252,12 @@ semantics.addAttribute('instantiatedSubscription', { } }); +semantics.addAttribute('instantiatedProjection', { + _default: function(children) { + return buildSubscription(children, null, 'instantiated'); + } +}); + semantics.addAttribute('projection', { _default: function(children) { return buildSubscription(children, null, 'projection'); diff --git a/js/compiler/demo-bankaccount.js b/js/compiler/demo-bankaccount.js index 897dba4..aa70f37 100644 --- a/js/compiler/demo-bankaccount.js +++ b/js/compiler/demo-bankaccount.js @@ -1,4 +1,4 @@ -// node src/compiler.js src/demo-bankaccount.js | node +// bin/syndicatec compiler/demo-bankaccount.js | node var Syndicate = require('./src/main.js'); diff --git a/js/compiler/demo-filesystem.js b/js/compiler/demo-filesystem.js new file mode 100644 index 0000000..1542209 --- /dev/null +++ b/js/compiler/demo-filesystem.js @@ -0,0 +1,66 @@ +// bin/syndicatec compiler/demo-filesystem.js | node + +var Syndicate = require('./src/main.js'); + +assertion type file(name, content) = "file"; +assertion type saveFile(name, content) = "save"; +assertion type deleteFile(name) = "delete"; + +ground network { + /////////////////////////////////////////////////////////////////////////// + // The file system actor + + actor { + this.files = {}; + forever { + during Syndicate.observe(file($name, _)) { + init { + console.log("At least one reader exists for:", name); + } + assert file(name, this.files[name]); + done { + console.log("No remaining readers exist for:", name); + } + } + on message saveFile($name, $newcontent) { + this.files[name] = newcontent; + } + on message deleteFile($name) { + delete this.files[name]; + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // A simple demo client of the file system + + actor { + state { + on asserted file("hello.txt", $content) { + console.log("hello.txt has content", JSON.stringify(content)); + } + } until { + case asserted file("hello.txt", "quit demo") { + console.log("The hello.txt file contained 'quit demo', so we will quit"); + } + } + + until { + case asserted Syndicate.observe(saveFile(_, _)) { + :: saveFile("hello.txt", "a"); + :: deleteFile("hello.txt"); + :: saveFile("hello.txt", "c"); + :: saveFile("hello.txt", "quit demo"); + :: saveFile("hello.txt", "final contents"); + actor { + until { + case asserted file("hello.txt", $content) { + console.log("second observer sees that hello.txt content is", + JSON.stringify(content)); + } + } + } + } + } + } +} diff --git a/js/src/actor.js b/js/src/actor.js index e2c9de2..3fa192f 100644 --- a/js/src/actor.js +++ b/js/src/actor.js @@ -99,7 +99,7 @@ Facet.prototype.onEvent = function(isTerminal, eventType, subscriptionFn, projec ? e.patch.added : e.patch.removed, compiledSpec); - if (objects) { + if (objects && objects.size > 0) { // console.log(objects.toArray()); if (isTerminal) { facet.terminate(); } objects.forEach(function (o) { Util.kwApply(handlerFn, facet.actor.state, o); }); diff --git a/js/src/route.js b/js/src/route.js index 854a93f..efdb218 100644 --- a/js/src/route.js +++ b/js/src/route.js @@ -17,7 +17,7 @@ function makeStructureConstructor(label, argumentNames) { } function isStructure(s) { - return !!(s.$SyndicateMeta$); + return (s !== null) && (typeof s === 'object') && ("$SyndicateMeta$" in s); } function structureToArray(s) { @@ -138,7 +138,7 @@ function compilePattern(v, p) { return rseq(SOA, acc); } - if (p.$SyndicateMeta$) { + if (isStructure(p)) { var args = p.$SyndicateMeta$.arguments; acc = rseq(EOA, acc); for (var i = args.length - 1; i >= 0; i--) { @@ -538,7 +538,7 @@ function matchValue(r, v) { } else { r = rlookup(r, __); } - } else if (v.$SyndicateMeta$) { + } else if (isStructure(v)) { if (r.has(SOA)) { r = rlookup(r, SOA); stack.push(vs); @@ -735,7 +735,7 @@ function compileProjection(/* projection, projection, ... */) { return; } - if (p.$SyndicateMeta$) { + if (isStructure(p)) { acc.push(SOA); acc.push(p.$SyndicateMeta$.label); var args = p.$SyndicateMeta$.arguments; @@ -768,7 +768,7 @@ function projectionToPattern(p) { return result; } - if (p.$SyndicateMeta$) { + if (isStructure(p)) { var result = {"$SyndicateMeta$": p.$SyndicateMeta$}; var args = p.$SyndicateMeta$.arguments; for (var i = 0; i < args.length; i++) {