From 761f5652afb5cd2c48e57de661d65239f754fffc Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Sat, 19 Mar 2016 15:06:23 -0400 Subject: [PATCH] Two simple in-browser examples --- js/examples/smoketest-dsl/index.html | 14 +++ js/examples/smoketest-dsl/index.js | 31 +++++ js/examples/textfield-dsl/index.html | 23 ++++ js/examples/textfield-dsl/index.js | 169 +++++++++++++++++++++++++++ js/examples/textfield-dsl/style.css | 12 ++ 5 files changed, 249 insertions(+) create mode 100644 js/examples/smoketest-dsl/index.html create mode 100644 js/examples/smoketest-dsl/index.js create mode 100644 js/examples/textfield-dsl/index.html create mode 100644 js/examples/textfield-dsl/index.js create mode 100644 js/examples/textfield-dsl/style.css diff --git a/js/examples/smoketest-dsl/index.html b/js/examples/smoketest-dsl/index.html new file mode 100644 index 0000000..b8208b7 --- /dev/null +++ b/js/examples/smoketest-dsl/index.html @@ -0,0 +1,14 @@ + + + + Syndicate: Smoketest with DSL + + + + + + + +

Smoketest

+ + diff --git a/js/examples/smoketest-dsl/index.js b/js/examples/smoketest-dsl/index.js new file mode 100644 index 0000000..3f16981 --- /dev/null +++ b/js/examples/smoketest-dsl/index.js @@ -0,0 +1,31 @@ +assertion type beep(counter); + +ground network { + console.log('starting ground boot'); + + actor { + until { + case asserted Syndicate.observe(beep(_)) { + var counter = 0; + state { + init { + :: beep(counter++); + } + on message beep(_) { + :: beep(counter++); + } + } until { + case (counter >= 10); + } + } + } + } + + actor { + forever { + on message $m { + console.log("Got message:", m); + } + } + } +} diff --git a/js/examples/textfield-dsl/index.html b/js/examples/textfield-dsl/index.html new file mode 100644 index 0000000..9684bd4 --- /dev/null +++ b/js/examples/textfield-dsl/index.html @@ -0,0 +1,23 @@ + + + + Syndicate: Textfield Example (DSL variation) + + + + + + + + +

Textfield Example (DSL variation)

+

+ After Hesam + Samimi's paper. +

+

Field contents:

+

Search

+ +

+  
+
diff --git a/js/examples/textfield-dsl/index.js b/js/examples/textfield-dsl/index.js
new file mode 100644
index 0000000..5f33832
--- /dev/null
+++ b/js/examples/textfield-dsl/index.js
@@ -0,0 +1,169 @@
+///////////////////////////////////////////////////////////////////////////
+// GUI
+
+assertion type jQuery(selector, eventType, event);
+assertion type fieldCommand(detail);
+assertion type fieldContents(text, pos);
+assertion type highlight(state);
+
+function escapeText(text) {
+  text = text.replace(/&/g, '&');
+  text = text.replace(//g, '>');
+  text = text.replace(/ /g, ' ');
+  return text;
+}
+
+function piece(text, pos, lo, hi, cls) {
+  return ""+
+    ((pos >= lo && pos < hi)
+     ? (escapeText(text.substring(lo, pos)) +
+	"" +
+	escapeText(text.substring(pos, hi)))
+     : escapeText(text.substring(lo, hi)))
+    + "";
+}
+
+function spawnGui() {
+  actor {
+    this.text = '';
+    this.pos = 0;
+    this.highlightState = false;
+
+    this.updateDisplay = function () {
+      var text = this.text;
+      var pos = this.pos;
+      var highlight = this.highlightState;
+      var hLeft = highlight ? highlight.get(0) : 0;
+      var hRight = highlight ? highlight.get(1) : 0;
+      $("#fieldContents")[0].innerHTML = highlight
+	? piece(text, pos, 0, hLeft, "normal") +
+	piece(text, pos, hLeft, hRight, "highlight") +
+	piece(text, pos, hRight, text.length + 1, "normal")
+	: piece(text, pos, 0, text.length + 1, "normal");
+    };
+
+    forever {
+      on message jQuery("#inputRow", "+keypress", $event) {
+        var keycode = event.keyCode;
+        var character = String.fromCharCode(event.charCode);
+        if (keycode === 37 /* left */) {
+          :: fieldCommand("cursorLeft");
+        } else if (keycode === 39 /* right */) {
+	  :: fieldCommand("cursorRight");
+        } else if (keycode === 9 /* tab */) {
+	  // ignore
+        } else if (keycode === 8 /* backspace */) {
+	  :: fieldCommand("backspace");
+        } else if (character) {
+	  :: fieldCommand(["insert", character]);
+        }
+      }
+
+      on asserted fieldContents($text, $pos) {
+        this.text = text;
+        this.pos = pos;
+        this.updateDisplay();
+      }
+
+      on asserted highlight($state) {
+        this.highlightState = state;
+        this.updateDisplay();
+      }
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Textfield Model
+
+function spawnModel() {
+  actor {
+    this.fieldContents = "initial";
+    this.cursorPos = this.fieldContents.length; /* positions address gaps between characters */
+
+    forever {
+      assert fieldContents(this.fieldContents, this.cursorPos);
+
+      on message fieldCommand("cursorLeft") {
+	this.cursorPos--;
+	if (this.cursorPos < 0)
+	  this.cursorPos = 0;
+      }
+
+      on message fieldCommand("cursorRight") {
+	this.cursorPos++;
+	if (this.cursorPos > this.fieldContents.length)
+	  this.cursorPos = this.fieldContents.length;
+      }
+
+      on message fieldCommand("backspace") {
+        if (this.cursorPos > 0) {
+	  this.fieldContents =
+	    this.fieldContents.substring(0, this.cursorPos - 1) +
+	    this.fieldContents.substring(this.cursorPos);
+	  this.cursorPos--;
+        }
+      }
+
+      on message fieldCommand(["insert", $newText]) {
+	this.fieldContents =
+	  this.fieldContents.substring(0, this.cursorPos) +
+	  newText +
+	  this.fieldContents.substring(this.cursorPos);
+	this.cursorPos += newText.length;
+      }
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Search engine
+
+function spawnSearch() {
+  actor {
+    this.fieldContents = "";
+    this.highlight = false;
+
+    this.search = function () {
+      var searchtext = $("#searchBox")[0].value;
+      if (searchtext) {
+	var pos = this.fieldContents.indexOf(searchtext);
+	this.highlight = (pos !== -1) && [pos, pos + searchtext.length];
+      } else {
+	this.highlight = false;
+      }
+    };
+
+    forever {
+      assert highlight(this.highlight);
+
+      on message jQuery("#searchBox", "input", $event) {
+        this.search();
+      }
+
+      on asserted fieldContents($text, _) {
+        this.fieldContents = text;
+        this.search();
+      }
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Main
+
+$(document).ready(function () {
+  ground network G {
+    Syndicate.JQuery.spawnJQueryDriver();
+    Syndicate.DOM.spawnDOMDriver();
+
+    spawnGui();
+    spawnModel();
+    spawnSearch();
+  }
+
+  G.network.onStateChange = function (mux, patch) {
+    $("#spy-holder").text(Syndicate.prettyTrie(mux.routingTable));
+  };
+});
diff --git a/js/examples/textfield-dsl/style.css b/js/examples/textfield-dsl/style.css
new file mode 100644
index 0000000..d612510
--- /dev/null
+++ b/js/examples/textfield-dsl/style.css
@@ -0,0 +1,12 @@
+#fieldContents {
+    font-family: monospace;
+}
+
+.cursor {
+    border-left: solid red 1px;
+    border-right: solid red 1px;
+}
+
+.highlight {
+    background-color: yellow;
+}