This commit is contained in:
Tony Garnock-Jones 2016-05-08 11:34:45 -04:00
parent 6afac6d21a
commit 7138568e3f
14 changed files with 839 additions and 1072 deletions

1667
dist/syndicate.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -124,24 +124,8 @@ var modifiedSourceActions = {
var label = maybeLabel.numChildren === 1
? maybeLabel.children[0].interval.contents
: JSON.stringify(typeName.interval.contents);
var fragments = [];
fragments.push(
'var ' + typeName.asES5 + ' = (function() {',
' var $SyndicateMeta$ = {',
' label: ' + label + ',',
' arguments: ' + JSON.stringify(formals),
' };',
' return function ' + typeName.asES5 + '(' + formalsRaw.asES5 + ') {',
' return {');
formals.forEach(function(f) {
fragments.push(' ' + JSON.stringify(f) + ': ' + f + ',');
});
fragments.push(
' "$SyndicateMeta$": $SyndicateMeta$',
' };',
' };',
'})();');
return fragments.join('\n');
return 'var ' + typeName.asES5 + ' = Syndicate.Struct.makeStructureConstructor(' +
label + ', ' + JSON.stringify(formals) + ');';
},
SendMessageStatement: function(_colons, expr, sc) {

File diff suppressed because one or more lines are too long

View File

@ -1,32 +1,6 @@
"use strict";
var DOM = (function() {
var $SyndicateMeta$ = {
label: "DOM",
arguments: ["containerSelector","fragmentClass","spec"]
};
return function DOM(containerSelector, fragmentClass, spec) {
return {
"containerSelector": containerSelector,
"fragmentClass": fragmentClass,
"spec": spec,
"$SyndicateMeta$": $SyndicateMeta$
};
};
})();
var jQuery = (function() {
var $SyndicateMeta$ = {
label: "jQuery",
arguments: ["selector","eventType","event"]
};
return function jQuery(selector, eventType, event) {
return {
"selector": selector,
"eventType": eventType,
"event": event,
"$SyndicateMeta$": $SyndicateMeta$
};
};
})();
var DOM = Syndicate.DOM.DOM;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
$(document).ready(function() {
new Syndicate.Ground(function () {
@ -37,7 +11,7 @@ $(document).ready(function() {
this.counter = 0;
Syndicate.Actor.createFacet()
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(DOM('#button-label','',Syndicate.seal(this.counter)), 0); }))
.onEvent(false, "message", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(jQuery('#counter','click',_), 0); }), (function() { var _ = Syndicate.__; return { assertion: jQuery('#counter','click',_), metalevel: 0 }; }), (function() {
.onEvent(false, "message", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(jQueryEvent('#counter','click',_), 0); }), (function() { var _ = Syndicate.__; return { assertion: jQueryEvent('#counter','click',_), metalevel: 0 }; }), (function() {
this.counter++;
})).completeBuild();
});

View File

@ -3,7 +3,6 @@
<head>
<title>Syndicate: Button Example</title>
<meta charset="utf-8">
<link href="style.css" rel="stylesheet">
<script src="../../third-party/jquery-2.2.0.min.js"></script>
<script src="../../dist/syndicatecompiler.js"></script>
<script src="../../dist/syndicate.js"></script>

View File

@ -1,5 +1,5 @@
assertion type DOM(containerSelector, fragmentClass, spec);
assertion type jQuery(selector, eventType, event);
var DOM = Syndicate.DOM.DOM;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
$(document).ready(function() {
ground dataspace {
@ -10,7 +10,7 @@ $(document).ready(function() {
this.counter = 0;
forever {
assert DOM('#button-label', '', Syndicate.seal(this.counter));
on message jQuery('#counter', 'click', _) {
on message jQueryEvent('#counter', 'click', _) {
this.counter++;
}
}

View File

@ -12,15 +12,18 @@ $(document).ready(function () {
console.log('starting ground boot');
Syndicate.DOM.spawnDOMDriver();
var DOM = Syndicate.DOM.DOM;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
Dataspace.spawn({
boot: function () {
return assert(["DOM", "#clicker-holder", "clicker",
seal(["button", ["span", [["style", "font-style: italic"]], "Click me!"]])])
.andThen(sub(["jQuery", "button.clicker", "click", __]));
return assert(DOM("#clicker-holder", "clicker",
seal(["button", ["span", [["style", "font-style: italic"]],
"Click me!"]])))
.andThen(sub(jQueryEvent("button.clicker", "click", __)));
},
handleEvent: function (e) {
if (e.type === "message" && e.message[0] === "jQuery") {
if (e.type === "message" && jQueryEvent.isClassOf(e.message)) {
Dataspace.send("bump_count");
}
}
@ -33,11 +36,11 @@ $(document).ready(function () {
return sub("bump_count");
},
updateState: function () {
Dataspace.stateChange(retract(["DOM", __, __, __])
.andThen(assert(["DOM", "#counter-holder", "counter",
seal(["div",
["p", "The current count is: ",
this.counter]])])));
Dataspace.stateChange(retract(DOM.pattern)
.andThen(assert(DOM("#counter-holder", "counter",
seal(["div",
["p", "The current count is: ",
this.counter]])))));
},
handleEvent: function (e) {
if (e.type === "message" && e.message === "bump_count") {

View File

@ -6,8 +6,8 @@ assertion type tvAlert(text);
assertion type switchAction(on);
assertion type componentPresent(name);
assertion type DOM(containerSelector, fragmentClass, spec);
assertion type jQuery(selector, eventType, event);
var DOM = Syndicate.DOM.DOM;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
///////////////////////////////////////////////////////////////////////////
// TV
@ -48,7 +48,7 @@ function spawnRemoteControl() {
actor {
forever {
assert componentPresent('remote control');
on message jQuery('#remote-control', 'click', _) {
on message jQueryEvent('#remote-control', 'click', _) {
:: remoteClick();
}
}
@ -92,14 +92,14 @@ function spawnStoveSwitch() {
"img/stove-coil-element-" +
(this.powerOn ? "hot" : "cold") + ".jpg"]]]));
on message jQuery('#stove-switch-on', 'click', _) { this.powerOn = true; }
on message jQuery('#stove-switch-off', 'click', _) { this.powerOn = false; }
on message jQueryEvent('#stove-switch-on', 'click', _) { this.powerOn = true; }
on message jQueryEvent('#stove-switch-off', 'click', _) { this.powerOn = false; }
on message switchAction($newState) {
this.powerOn = newState;
}
} until {
case message jQuery('#kill-stove-switch', 'click', _);
case message jQueryEvent('#kill-stove-switch', 'click', _);
}
}
}
@ -120,7 +120,7 @@ function spawnPowerDrawMonitor() {
this.watts = on ? 1500 : 0;
}
} until {
case message jQuery('#kill-power-draw-monitor', 'click', _);
case message jQueryEvent('#kill-power-draw-monitor', 'click', _);
}
}
}
@ -187,10 +187,10 @@ function spawnFailureMonitor() {
function spawnChaosMonkey() {
actor {
forever {
on message jQuery('#spawn-power-draw-monitor', 'click', _) {
on message jQueryEvent('#spawn-power-draw-monitor', 'click', _) {
spawnPowerDrawMonitor();
}
on message jQuery('#spawn-stove-switch', 'click', _) {
on message jQueryEvent('#spawn-stove-switch', 'click', _) {
spawnStoveSwitch();
}
}

View File

@ -14,10 +14,13 @@ $(document).ready(function () {
Dataspace.spawn({
boot: function () {
return sub(['jQuery', '#clicker', 'click', __]);
return sub(Syndicate.JQuery.jQueryEvent('#clicker', 'click', __));
},
handleEvent: function (e) {
if (e.type === 'message' && e.message[0] === 'jQuery' && e.message[1] === '#clicker') {
if (e.type === 'message'
&& Syndicate.JQuery.jQueryEvent.isClassOf(e.message)
&& e.message.selector === '#clicker')
{
var r = $('#result');
r.html(Number(r.html()) + 1);
}

View File

@ -23,8 +23,8 @@ ground dataspace {
actor {
forever {
on message $m {
console.log("Got message:", m);
on message beep($counter) {
console.log("beep!", counter);
}
}
}

View File

@ -1,5 +1,7 @@
"use strict";
var beep = Syndicate.Struct.makeStructureConstructor('beep', ['counter']);
var G;
$(document).ready(function () {
var Dataspace = Syndicate.Dataspace;
@ -15,16 +17,16 @@ $(document).ready(function () {
boot: function () {},
handleEvent: function (e) {},
step: function () {
Dataspace.send(["beep", this.counter++]);
Dataspace.send(beep(this.counter++));
return this.counter <= 10;
}
});
Dataspace.spawn({
boot: function () { return sub(["beep", __]); },
boot: function () { return sub(beep.pattern); },
handleEvent: function (e) {
if (e.type === 'message') {
console.log("beep!", e.message[1]);
console.log("beep!", e.message.counter);
}
}
});

View File

@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////
// GUI
assertion type jQuery(selector, eventType, event);
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
assertion type fieldCommand(detail);
assertion type fieldContents(text, pos);
assertion type highlight(state);
@ -34,8 +34,8 @@ function spawnGui() {
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;
var hLeft = highlight ? highlight[0] : 0;
var hRight = highlight ? highlight[1] : 0;
$("#fieldContents")[0].innerHTML = highlight
? piece(text, pos, 0, hLeft, "normal") +
piece(text, pos, hLeft, hRight, "highlight") +
@ -44,7 +44,7 @@ function spawnGui() {
};
forever {
on message jQuery("#inputRow", "+keypress", $event) {
on message jQueryEvent("#inputRow", "+keypress", $event) {
var keycode = event.keyCode;
var character = String.fromCharCode(event.charCode);
if (keycode === 37 /* left */) {
@ -79,11 +79,11 @@ function spawnGui() {
function spawnModel() {
actor {
this.fieldContents = "initial";
this.cursorPos = this.fieldContents.length; /* positions address gaps between characters */
this.fieldValue = "initial";
this.cursorPos = this.fieldValue.length; /* positions address gaps between characters */
forever {
assert fieldContents(this.fieldContents, this.cursorPos);
assert fieldContents(this.fieldValue, this.cursorPos);
on message fieldCommand("cursorLeft") {
this.cursorPos--;
@ -93,24 +93,24 @@ function spawnModel() {
on message fieldCommand("cursorRight") {
this.cursorPos++;
if (this.cursorPos > this.fieldContents.length)
this.cursorPos = this.fieldContents.length;
if (this.cursorPos > this.fieldValue.length)
this.cursorPos = this.fieldValue.length;
}
on message fieldCommand("backspace") {
if (this.cursorPos > 0) {
this.fieldContents =
this.fieldContents.substring(0, this.cursorPos - 1) +
this.fieldContents.substring(this.cursorPos);
this.fieldValue =
this.fieldValue.substring(0, this.cursorPos - 1) +
this.fieldValue.substring(this.cursorPos);
this.cursorPos--;
}
}
on message fieldCommand(["insert", $newText]) {
this.fieldContents =
this.fieldContents.substring(0, this.cursorPos) +
this.fieldValue =
this.fieldValue.substring(0, this.cursorPos) +
newText +
this.fieldContents.substring(this.cursorPos);
this.fieldValue.substring(this.cursorPos);
this.cursorPos += newText.length;
}
}
@ -122,13 +122,13 @@ function spawnModel() {
function spawnSearch() {
actor {
this.fieldContents = "";
this.fieldValue = "";
this.highlight = false;
this.search = function () {
var searchtext = $("#searchBox")[0].value;
if (searchtext) {
var pos = this.fieldContents.indexOf(searchtext);
var pos = this.fieldValue.indexOf(searchtext);
this.highlight = (pos !== -1) && [pos, pos + searchtext.length];
} else {
this.highlight = false;
@ -138,12 +138,12 @@ function spawnSearch() {
forever {
assert highlight(this.highlight);
on message jQuery("#searchBox", "input", $event) {
on message jQueryEvent("#searchBox", "input", $event) {
this.search();
}
on asserted fieldContents($text, _) {
this.fieldContents = text;
this.fieldValue = text;
this.search();
}
}

View File

@ -2,11 +2,16 @@
// GUI
var Dataspace = Syndicate.Dataspace;
var Route = Syndicate.Route;
var Trie = Syndicate.Trie;
var Patch = Syndicate.Patch;
var __ = Syndicate.__;
var _$ = Syndicate._$;
var jQueryEvent = Syndicate.JQuery.jQueryEvent;
var fieldContents = Syndicate.Struct.makeStructureConstructor('fieldContents', ['text', 'pos']);
var highlight = Syndicate.Struct.makeStructureConstructor('highlight', ['state']);
var fieldCommand = Syndicate.Struct.makeStructureConstructor('fieldCommand', ['detail']);
function escapeText(text) {
text = text.replace(/&/g, '&amp;');
text = text.replace(/</g, '&lt;');
@ -31,37 +36,37 @@ function spawnGui() {
highlight: { state: false },
boot: function () {
return Patch.sub(["jQuery", "#inputRow", "+keypress", __])
.andThen(Patch.sub(["fieldContents", __, __]))
.andThen(Patch.sub(["highlight", __]));
return Patch.sub(jQueryEvent("#inputRow", "+keypress", __))
.andThen(Patch.sub(fieldContents.pattern))
.andThen(Patch.sub(highlight.pattern));
},
fieldContentsProjection: Route.compileProjection(["fieldContents", _$("text"), _$("pos")]),
highlightProjection: Route.compileProjection(["highlight", _$("state")]),
fieldContentsProjection: fieldContents(_$("text"), _$("pos")),
highlightProjection: highlight(_$("state")),
handleEvent: function (e) {
var self = this;
switch (e.type) {
case "message":
var event = e.message[3];
var event = e.message.eventValue;
var keycode = event.keyCode;
var character = String.fromCharCode(event.charCode);
if (keycode === 37 /* left */) {
Dataspace.send(["fieldCommand", "cursorLeft"]);
Dataspace.send(fieldCommand("cursorLeft"));
} else if (keycode === 39 /* right */) {
Dataspace.send(["fieldCommand", "cursorRight"]);
Dataspace.send(fieldCommand("cursorRight"));
} else if (keycode === 9 /* tab */) {
// ignore
} else if (keycode === 8 /* backspace */) {
Dataspace.send(["fieldCommand", "backspace"]);
Dataspace.send(fieldCommand("backspace"));
} else if (character) {
Dataspace.send(["fieldCommand", ["insert", character]]);
Dataspace.send(fieldCommand(["insert", character]));
}
break;
case "stateChange":
Route.projectObjects(e.patch.added, this.fieldContentsProjection).forEach(function (c) {
Trie.projectObjects(e.patch.added, this.fieldContentsProjection).forEach(function (c) {
self.field = c;
});
Route.projectObjects(e.patch.added, this.highlightProjection).forEach(function (c) {
Trie.projectObjects(e.patch.added, this.highlightProjection).forEach(function (c) {
self.highlight = c;
});
this.updateDisplay();
@ -73,8 +78,8 @@ function spawnGui() {
var text = this.field ? this.field.text : "";
var pos = this.field ? this.field.pos : 0;
var highlight = this.highlight ? this.highlight.state : false;
var hLeft = highlight ? highlight.get(0) : 0;
var hRight = highlight ? highlight.get(1) : 0;
var hLeft = highlight ? highlight[0] : 0;
var hRight = highlight ? highlight[1] : 0;
$("#fieldContents")[0].innerHTML = highlight
? piece(text, pos, 0, hLeft, "normal") +
piece(text, pos, hLeft, hRight, "highlight") +
@ -90,36 +95,36 @@ function spawnGui() {
function spawnModel() {
var initialContents = "initial";
Dataspace.spawn({
fieldContents: initialContents,
fieldValue: initialContents,
cursorPos: initialContents.length, /* positions address gaps between characters */
boot: function () {
this.publishState();
return Patch.sub(["fieldCommand", __]);
return Patch.sub(fieldCommand.pattern);
},
handleEvent: function (e) {
if (e.type === "message" && e.message[0] === "fieldCommand") {
var command = e.message[1];
if (e.type === "message" && fieldCommand.isClassOf(e.message)) {
var command = e.message.detail;
if (command === "cursorLeft") {
this.cursorPos--;
if (this.cursorPos < 0)
this.cursorPos = 0;
} else if (command === "cursorRight") {
this.cursorPos++;
if (this.cursorPos > this.fieldContents.length)
this.cursorPos = this.fieldContents.length;
if (this.cursorPos > this.fieldValue.length)
this.cursorPos = this.fieldValue.length;
} else if (command === "backspace" && this.cursorPos > 0) {
this.fieldContents =
this.fieldContents.substring(0, this.cursorPos - 1) +
this.fieldContents.substring(this.cursorPos);
this.fieldValue =
this.fieldValue.substring(0, this.cursorPos - 1) +
this.fieldValue.substring(this.cursorPos);
this.cursorPos--;
} else if (command.constructor === Array && command[0] === "insert") {
var newText = command[1];
this.fieldContents =
this.fieldContents.substring(0, this.cursorPos) +
this.fieldValue =
this.fieldValue.substring(0, this.cursorPos) +
newText +
this.fieldContents.substring(this.cursorPos);
this.fieldValue.substring(this.cursorPos);
this.cursorPos += newText.length;
}
this.publishState();
@ -128,8 +133,8 @@ function spawnModel() {
publishState: function () {
Dataspace.stateChange(
Patch.retract(["fieldContents", __, __])
.andThen(Patch.assert(["fieldContents", this.fieldContents, this.cursorPos])));
Patch.retract(fieldContents.pattern)
.andThen(Patch.assert(fieldContents(this.fieldValue, this.cursorPos))));
}
});
}
@ -139,24 +144,24 @@ function spawnModel() {
function spawnSearch() {
Dataspace.spawn({
fieldContents: "",
fieldValue: "",
highlight: false,
boot: function () {
this.publishState();
return Patch.sub(["jQuery", "#searchBox", "input", __])
.andThen(Patch.sub(["fieldContents", __, __]));
return Patch.sub(jQueryEvent("#searchBox", "input", __))
.andThen(Patch.sub(fieldContents.pattern));
},
fieldContentsProjection: Route.compileProjection(["fieldContents", _$("text"), _$("pos")]),
fieldContentsProjection: fieldContents(_$("text"), _$("pos")),
handleEvent: function (e) {
var self = this;
if (e.type === "message" && e.message[0] === "jQuery") {
if (jQueryEvent.isClassOf(e.message)) {
this.search();
}
if (e.type === "stateChange") {
Route.projectObjects(e.patch.added, this.fieldContentsProjection).forEach(function (c) {
self.fieldContents = c.text;
Trie.projectObjects(e.patch.added, this.fieldContentsProjection).forEach(function (c) {
self.fieldValue = c.text;
});
this.search();
}
@ -164,15 +169,15 @@ function spawnSearch() {
publishState: function () {
Dataspace.stateChange(
Patch.retract(["highlight", __])
.andThen(Patch.assert(["highlight", this.highlight])));
Patch.retract(highlight.pattern)
.andThen(Patch.assert(highlight(this.highlight))));
},
search: function () {
var searchtext = $("#searchBox")[0].value;
var oldHighlight = this.highlight;
if (searchtext) {
var pos = this.fieldContents.indexOf(searchtext);
var pos = this.fieldValue.indexOf(searchtext);
this.highlight = (pos !== -1) && [pos, pos + searchtext.length];
} else {
this.highlight = false;