fay 0.5.0.0 → 0.5.1.0
raw patch · 9 files changed
+384/−239 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Language.Fay: compileRecConstr :: QName -> [FieldUpdate] -> Compile JsExp
+ Language.Fay: printTestCompile :: String -> IO ()
+ Language.Fay.Types: JsLookup :: JsExp -> JsExp -> JsExp
Files
- docs/home.js +272/−200
- docs/snippets/ffi.hs +5/−5
- examples/dom.hs +1/−0
- fay.cabal +2/−2
- src/Language/Fay.hs +85/−29
- src/Language/Fay/Print.hs +2/−0
- src/Language/Fay/Types.hs +1/−0
- tests/16 +3/−0
- tests/16.hs +13/−3
docs/home.js view
@@ -5,15 +5,15 @@ var False = false; /*******************************************************************************-* Thunks.-*/+ * Thunks.+ */ // Force a thunk (if it is a thunk) until WHNF. function _(thunkish,nocache){- while (thunkish instanceof $) {- thunkish = thunkish.force(nocache);- }- return thunkish;+ while (thunkish instanceof $) {+ thunkish = thunkish.force(nocache);+ }+ return thunkish; } // Apply a function to arguments (see method2 in Fay.hs).@@ -27,344 +27,415 @@ // Thunk object. function $(value){- this.forced = false;- this.value = value;+ this.forced = false;+ this.value = value; } // Force the thunk. $.prototype.force = function(nocache){- return nocache- ? this.value()- : this.forced- ? this.value- : (this.forced = true, this.value = this.value());+ return nocache+ ? this.value()+ : this.forced+ ? this.value+ : (this.forced = true, this.value = this.value()); }; /*******************************************************************************-* Constructors.-*/+ * Constructors.+ */ // A constructor. function Fay$$Constructor(){- this.name = arguments[0];- this.fields = Array.prototype.slice.call(arguments,1);+ this.name = arguments[0];+ this.fields = Array.prototype.slice.call(arguments,1); } // Eval in the context of the Haskell bindings. function Fay$$eval(str){- return eval(str);+ return eval(str); } /*******************************************************************************-* Monad.-*/+ * Monad.+ */ function Fay$$Monad(value){- this.value = value;+ this.value = value; } // >> function Fay$$then(a){- return function(b){- return new $(function(){- _(a,true);- return b;- });- };+ return function(b){+ return new $(function(){+ _(a,true);+ return b;+ });+ }; } // >>= function Fay$$bind(m){- return function(f){- return new $(function(){- var monad = _(m,true);- return f(monad.value);- });- };+ return function(f){+ return new $(function(){+ var monad = _(m,true);+ return f(monad.value);+ });+ }; } var Fay$$unit = null; // return function Fay$$return(a){- return new Fay$$Monad(a);+ return new Fay$$Monad(a); } /*******************************************************************************-* FFI.-*/+ * FFI.+ */ // Serialize a Fay object to JS.-function Fay$$serialize(type,obj){- type = _(type);- if(type) type = type[0].name;- if(type == "JsType"){- return function(){- return _(obj,true).value;- };- } else {- obj = _(obj);- if(type == "StringType" ||- (obj instanceof Fay$$Cons && typeof obj.car == 'string')){- var str = "";- while(obj instanceof Fay$$Cons) {- str += obj.car;- obj = _(obj.cdr);- }- return str;- } else if(type == "FunctionType" || typeof obj == 'function'){- return function(){- var out = obj;- for (var len = arguments.length, i = 0; i < len; i++){- if(typeof out != 'function') {- throw "Wrong number of arguments for callback: " + arguments.toString();- }- out = out(arguments[i]);+function Fay$$serialize(type,fayObj){+ var base = type[0];+ var args = type[1];+ var jsObj;+ switch(base){+ case "action": {+ // A nullary monadic action. Should become a nullary JS function.+ // Fay () -> function(){ return ... }+ jsObj = function(){+ return Fay$$serialize(args[0],_(fayObj,true).value);+ };+ break;+ }+ case "function": {+ // A proper function.+ jsObj = function(){+ var return_type = args[args.length-1];+ var len = args.length;+ // If some arguments.+ if (len > 1) {+ // Apply to all the arguments.+ fayObj = _(fayObj,true);+ for (var i = 0, len = len; i < len - 1; i++) {+ // Unserialize the JS values to Fay for the Fay callback.+ fayObj = _(fayObj(Fay$$unserialize(args[i],arguments[i])),true);+ }+ // Finally, serialize the Fay return value back to JS.+ var return_base = return_type[0];+ var return_args = return_type[1];+ // If it's a monadic return value, get the value instead.+ if(return_base == "action") {+ return Fay$$serialize(return_args[0],fayObj.value);+ }+ // Otherwise just serialize the value direct.+ else {+ return Fay$$serialize(return_type,fayObj);+ }+ } else {+ throw new Error("Nullary function?");+ }+ };+ break;+ }+ case "string": {+ // Serialize Fay string to JavaScript string.+ var str = "";+ fayObj = _(fayObj);+ while(fayObj instanceof Fay$$Cons) {+ str += fayObj.car;+ fayObj = _(fayObj.cdr); }- return _(out,true);- };- } else if(type == "ListType" || (obj instanceof Fay$$Cons)){- var arr = [];- while(obj instanceof Fay$$Cons) {- arr.push(Fay$$serialize(null,obj.car));- obj = _(obj.cdr);- }- return arr;- } // else if(type == "BoolType || obj == _(True) || obj == _(False)) {- // return obj == _(True);- // }- else {- return obj;+ jsObj = str;+ break; }- }+ case "list": {+ // Serialize Fay list to JavaScript array.+ var arr = [];+ fayObj = _(fayObj);+ while(fayObj instanceof Fay$$Cons) {+ arr.push(Fay$$serialize(args[0],fayObj.car));+ fayObj = _(fayObj.cdr);+ }+ jsObj = arr;+ break;+ }+ case "double": {+ // Serialize double, just force the argument. Doubles are unboxed.+ jsObj = _(fayObj);+ break;+ }+ case "unknown": {+ // Just force unknown values to WHNF.+ jsObj = _(fayObj);+ break;+ }+ case "bool": {+ // Bools are unboxed.+ jsObj = fayObj;+ break;+ }+ default: throw new Error("Unhandled serialize type: " + base);+ }+ return jsObj; } +// Unserialize an object from JS to Fay.+function Fay$$unserialize(type,jsObj){+ var base = type[0];+ var args = type[1];+ var fayObj;+ switch(base){+ case "action": {+ // Unserialize a "monadic" JavaScript return value into a monadic value.+ fayObj = Fay$$return(Fay$$unserialize(args[0],jsObj));+ break;+ }+ case "string": {+ // Unserialize a JS string into Fay list (String).+ fayObj = Fay$$list(jsObj);+ break;+ }+ case "list": {+ // Unserialize a JS array into a Fay list ([a]).+ var serializedList = [];+ for (var i = 0, len = jsObj.length; i < len; i++) {+ // Unserialize each JS value into a Fay value, too.+ serializedList.push(Fay$$unserialize(args[0],jsObj[i]));+ }+ // Pop it all in a Fay list.+ fayObj = Fay$$list(serializedList);+ break;+ }+ case "double": {+ // Doubles are unboxed, so there's nothing to do.+ fayObj = jsObj;+ break;+ }+ case "unknown": {+ // Any unknown values can be left as-is.+ fayObj = jsObj;+ break;+ }+ default: throw new Error("Unhandled unserialize type: " + base);+ }+ return fayObj;+}+ // Encode a value to a Show representation function Fay$$encodeShow(x){- if (x instanceof $) x = _(x);- if (x instanceof Array) {- if (x.length == 0) {- return "[]";- } else {- if (x[0] instanceof Fay$$Constructor) {- if(x[0].fields.length > 0) {- var args = x.slice(1);- var fieldNames = x[0].fields;- return "(" + x[0].name + " { " + args.map(function(x,i){- return fieldNames[i] + ' = ' + Fay$$encodeShow(x);- }).join(", ") + " })";+ if (x instanceof $) x = _(x);+ if (x instanceof Array) {+ if (x.length == 0) {+ return "[]"; } else {- var args = x.slice(1);- return "(" + [x[0].name].concat(args.map(Fay$$encodeShow)).join(" ") + ")";+ if (x[0] instanceof Fay$$Constructor) {+ if(x[0].fields.length > 0) {+ var args = x.slice(1);+ var fieldNames = x[0].fields;+ return "(" + x[0].name + " { " + args.map(function(x,i){+ return fieldNames[i] + ' = ' + Fay$$encodeShow(x);+ }).join(", ") + " })";+ } else {+ var args = x.slice(1);+ return "(" + [x[0].name].concat(args.map(Fay$$encodeShow)).join(" ") + ")";+ }+ } else {+ return "[" + x.map(Fay$$encodeShow).join(",") + "]";+ } }- } else {- return "[" + x.map(Fay$$encodeShow).join(",") + "]";- }+ } else if (typeof x == 'string') {+ return JSON.stringify(x);+ } else if(x instanceof Fay$$Cons) {+ return Fay$$encodeShow(Fay$$serialize(["list",[["unknown"]]],x));+ } else if(x == null) {+ return '[]';+ } else {+ return x.toString(); }- } else if (typeof x == 'string') {- return JSON.stringify(x);- } else if(x instanceof Fay$$Cons) {- return Fay$$encodeShow(Fay$$serialize(ListType,x));- } else if(x == null) {- return '[]';- } else {- return x.toString();- } } -// Unserialize an object from JS to Fay.-function Fay$$unserialize(typ,obj){- if(typ == 'string' || typ == 'array' || typ == 'list')- return Fay$$list(obj);- else if(typ == 'bool')- return obj? True : False;- else if(typ == 'data') {- alert('Time to unserialize a data record!');- }- else return obj;-}- /*******************************************************************************-* Lists.-*/+ * Lists.+ */ // Cons object. function Fay$$Cons(car,cdr){- this.car = car;- this.cdr = cdr;+ this.car = car;+ this.cdr = cdr; } // Make a list. function Fay$$list(xs){- var out = null;- for(var i=xs.length-1; i>=0;i--)- out = new Fay$$Cons(xs[i],out);- return out;+ var out = null;+ for(var i=xs.length-1; i>=0;i--)+ out = new Fay$$Cons(xs[i],out);+ return out; } // Built-in list cons. function Fay$$cons(x){- return function(y){- return new Fay$$Cons(x,y);- };+ return function(y){+ return new Fay$$Cons(x,y);+ }; } // List index. function Fay$$index(index){- return function(list){- for(var i = 0; i < index; i++) {- list = _(list).cdr;- }- return list.car;- };+ return function(list){+ for(var i = 0; i < index; i++) {+ list = _(list).cdr;+ }+ return list.car;+ }; } /*******************************************************************************-* Numbers.-*/+ * Numbers.+ */ // Built-in *. function Fay$$mult(x){- return function(y){- return _(x) * _(y);- };+ return function(y){+ return _(x) * _(y);+ }; } // Built-in +. function Fay$$add(x){- return function(y){- return _(x) + _(y);- };+ return function(y){+ return _(x) + _(y);+ }; } // Built-in -. function Fay$$sub(x){- return function(y){- return _(x) - _(y);- };+ return function(y){+ return _(x) - _(y);+ }; } // Built-in /. function Fay$$div(x){- return function(y){- return _(x) / _(y);- };+ return function(y){+ return _(x) / _(y);+ }; } /*******************************************************************************-* Booleans.-*/+ * Booleans.+ */ // Are two values equal? function Fay$$equal(lit1,lit2){- // Simple case- lit1 = _(lit1);- lit2 = _(lit2);- if(lit1 === lit2) {- return true;- }- // General case- if(lit1 instanceof Array) {- if(lit1.length!=lit2.length) return false;- for(var len = lit1.length, i = 0; i < len; i++) {- if(!Fay$$equal(lit1[i],lit2[i]))- return false;+ // Simple case+ lit1 = _(lit1);+ lit2 = _(lit2);+ if(lit1 === lit2) {+ return true; }- return true;- } else if (lit1 instanceof Fay$$Cons) {- while(lit1 instanceof Fay$$Cons && lit2 instanceof Fay$$Cons && Fay$$equal(lit1.car,lit2.car))- lit1 = lit1.cdr, lit2 = lit2.cdr;- return (lit1 === null && lit2 === null);- } else return false;+ // General case+ if(lit1 instanceof Array) {+ if(lit1.length!=lit2.length) return false;+ for(var len = lit1.length, i = 0; i < len; i++) {+ if(!Fay$$equal(lit1[i],lit2[i]))+ return false;+ }+ return true;+ } else if (lit1 instanceof Fay$$Cons) {+ while(lit1 instanceof Fay$$Cons && lit2 instanceof Fay$$Cons && Fay$$equal(lit1.car,lit2.car))+ lit1 = lit1.cdr, lit2 = lit2.cdr;+ return (lit1 === null && lit2 === null);+ } else return false; } // Built-in ==. function Fay$$eq(x){- return function(y){- return Fay$$equal(x,y);- };+ return function(y){+ return Fay$$equal(x,y);+ }; } // Built-in /=. function Fay$$neq(x){- return function(y){- return !(Fay$$equal(x,y));- };+ return function(y){+ return !(Fay$$equal(x,y));+ }; } // Built-in >. function Fay$$gt(x){- return function(y){- return _(x) > _(y);- };+ return function(y){+ return _(x) > _(y);+ }; } // Built-in <. function Fay$$lt(x){- return function(y){- return _(x) < _(y);- };+ return function(y){+ return _(x) < _(y);+ }; } // Built-in >=. function Fay$$gte(x){- return function(y){- return _(x) >= _(y);- };+ return function(y){+ return _(x) >= _(y);+ }; } // Built-in <=. function Fay$$lte(x){- return function(y){- return _(x) <= _(y);- };+ return function(y){+ return _(x) <= _(y);+ }; } // Built-in &&. function Fay$$and(x){- return function(y){- return _(x) && _(y);- };+ return function(y){+ return _(x) && _(y);+ }; } // Built-in ||. function Fay$$or(x){- return function(y){- return _(x) || _(y);- };+ return function(y){+ return _(x) || _(y);+ }; } /*******************************************************************************-* Mutable references.-*/+ * Mutable references.+ */ // Make a new mutable reference. function Fay$$Ref(x){- this.value = x;+ this.value = x; } // Write to the ref. function Fay$$writeRef(ref,x){- ref.value = x;+ ref.value = x; } // Get the value from the ref. function Fay$$readRef(ref,x){- return ref.value;+ return ref.value; } /*******************************************************************************-* Dates.-*/+ * Dates.+ */ function Fay$$date(str){- return window.Date.parse(str);+ return window.Date.parse(str); } /*******************************************************************************-* Application code.-*/+ * Application code.+ */ -var main = new $(function(){return _(_($36$)(_(ready)(_(wrap)(thedocument))))(_(_(Fay$$then)(indentAndHighlight))(_(_(Fay$$then)(setupExpanders))(_(_(Fay$$then)(setupTableOfContents))(_(_(Fay$$bind)(_(query)(Fay$$list(".subheadline"))))(function($_a){var body = $_a;return _(_(Fay$$then)(_(_(addClassWith)(function($_a){var i = $_a;return function($_b){var f = $_b;return _(_(Fay$$then)(_(alert)(_(show)(i))))(_(_(Fay$$then)(_(alert)(f)))(_(Fay$$return)(f)));};}))(body)))(_(Fay$$return)(Fay$$unit));})))));});var addClassWith = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_b).addClass(function(x,i){ return Fay$$serialize(FunctionType,$_a)(x,Fay$$list(i)); })));});};};var indentAndHighlight = new $(function(){return _(_(Fay$$bind)(_(query)(Fay$$list(".language-javascript"))))(function($_a){var samples = $_a;return _(_(Fay$$then)(_(_($36$)(_(each)(samples)))(function($_a){var i = $_a;return function($_b){var _$this = $_b;return (function(){var sample = new $(function(){return _(wrap)(_$this);});return _(_(Fay$$bind)(_(getText)(sample)))(function($_a){var text = $_a;return _(_(setText)(sample))(_(_(beautify)(text))(2));});})();};})))(_(_(Fay$$then)(_(_(setTabReplace)(hljs))(Fay$$list(" "))))(_(initHighlightingOnLoad)(hljs)));});});var setupExpanders = new $(function(){return _(_(Fay$$bind)(_(_(Fay$$bind)(_(query)(Fay$$list(".wrap"))))(getWidth)))(function($_a){var wrapwidth = $_a;return _(_(Fay$$bind)(_(query)(Fay$$list(".example"))))(function($_a){var examples = $_a;return _(_($36$)(_(each)(examples)))(function($_a){var i = $_a;return function($_b){var _$this = $_b;return _(_(Fay$$bind)(_(_(getFind)(_(wrap)(_$this)))(Fay$$list("tr"))))(function($_a){var tr = $_a;return _(_(Fay$$bind)(_(_(Fay$$bind)(_(_(getFind)(tr))(Fay$$list("td"))))(getFirst)))(function($_a){var left = $_a;return _(_(Fay$$then)(_(_(addClass)(left))(Fay$$list("left"))))(_(_(Fay$$bind)(_(getNext)(left)))(function($_a){var right = $_a;return _(_(Fay$$bind)(_(makeElement)(Fay$$list("<a class='toggle' href='javascript:'>Show JavaScript</a>"))))(function($_a){var toggle = $_a;return _(_(Fay$$bind)(_(_($36$)(Fay$$return))(_(_(Fay$$bind)(_(_(getIs)(right))(Fay$$list(":visible"))))(function($_a){var visible = $_a;return _(visible) ? _(_(Fay$$then)(_(_(setText)(toggle))(Fay$$list("Hide JavaScript"))))(_(_(_(swapClasses)(toggle))(Fay$$list("toggle-hide")))(Fay$$list("toggle-show"))) : _(_(Fay$$then)(_(_(setText)(toggle))(Fay$$list("Show JavaScript"))))(_(_(_(swapClasses)(toggle))(Fay$$list("toggle-show")))(Fay$$list("toggle-hide")));}))))(function($_a){var toggleButton = $_a;return _(_(Fay$$then)(_(_($36$)(_(setClick)(toggle)))(_(_($36$)(_(fadeToggle)(right)))(toggleButton))))(_(_(Fay$$bind)(_(getWidth)(tr)))(function($_a){var width = $_a;return _(_(Fay$$then)(_(_($36$)(_(when)(_(width) > _(_(wrapwidth) + _(_(20 * _(wrapwidth)) / 100)))))(_(hide)(right))))(_(_(Fay$$then)(toggleButton))(_(_(Fay$$bind)(_(_(getFind)(left))(Fay$$list(".panel"))))(function($_a){var panel = $_a;return _(_(Fay$$then)(_(_(prepend)(panel))(toggle)))(_(Fay$$return)(Fay$$unit));})));}));});});}));});});};});});});});var setupTableOfContents = new $(function(){return _(_(Fay$$bind)(_(makeElement)(Fay$$list("<div class='table-of-contents'><p>Table of Contents</p></div>"))))(function($_a){var toc = $_a;return _(_(Fay$$then)(_(_(Fay$$bind)(_(query)(Fay$$list(".subheadline"))))(_(after)(toc))))(_(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<ul></ul>"))))(_(appendTo)(toc))))(function($_a){var ul = $_a;return _(_(Fay$$bind)(_(query)(Fay$$list("h2"))))(function($_a){var headings = $_a;return _(_($36$)(_(each)(headings)))(function($_a){var i = $_a;return function($_b){var heading = $_b;return (function(){var anchor = new $(function(){return _(_($43$$43$)(Fay$$list("section-")))(_(show)(i));});var h = new $(function(){return _(wrap)(heading);});return _(_(Fay$$then)(_(_(_(attr)(h))(Fay$$list("id")))(anchor)))(_(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<li></li>"))))(_(appendTo)(ul))))(function($_a){var li = $_a;return _(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<a></a>"))))(_(appendTo)(li))))(function($_a){var a = $_a;return _(_(Fay$$then)(_(_(Fay$$bind)(_(getText)(h)))(_(setText)(a))))(_(_(Fay$$then)(_(_(_(attr)(a))(Fay$$list("href")))(_(_($43$$43$)(Fay$$list("#")))(anchor))))(_(_(Fay$$bind)(_(getTagName)(heading)))(_(addClass)(li))));});}));})();};});});}));});});var print = new $(function(){return _(_($46$)(consolelog))(show);});var consolelog = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",console.log(Fay$$serialize(StringType,$_a))));});};var alert = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",window.alert(Fay$$serialize(StringType,$_a))));});};var thedocument = new $(function(){return Fay$$unserialize("",window.document);});var getTagName = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("string",Fay$$serialize(UnknownType,$_a)['tagName']));});};var wrap = function($_a){return new $(function(){return Fay$$unserialize("",window['jQuery'](Fay$$serialize(UnknownType,$_a)));});};var ready = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['ready'](Fay$$serialize(JsType,$_b))));});};};var each = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['each'](Fay$$serialize(FunctionType,$_b))));});};};var query = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",window['jQuery'](Fay$$serialize(StringType,$_a))));});};var setText = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['text'](Fay$$serialize(StringType,$_b))));});};};var attr = function($_a){return function($_b){return function($_c){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['attr'](Fay$$serialize(StringType,$_b),Fay$$serialize(StringType,$_c))));});};};};var setClick = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['click'](Fay$$serialize(JsType,$_b))));});};};var fadeToggle = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['fadeToggle'](Fay$$serialize(JsType,$_b))));});};};var hide = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['hide']()));});};var addClass = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['addClass'](Fay$$serialize(StringType,$_b))));});};};var removeClass = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['removeClass'](Fay$$serialize(StringType,$_b))));});};};var swapClasses = function($_a){return function($_b){return function($_c){return new $(function(){var removeme = $_c;var addme = $_b;var obj = $_a;return _(_(Fay$$then)(_(_(addClass)(obj))(addme)))(_(_(removeClass)(obj))(removeme));});};};};var getText = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("string",Fay$$serialize(UnknownType,$_a)['text']()));});};var getIs = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("bool",Fay$$serialize(UnknownType,$_a)['is'](Fay$$serialize(StringType,$_b))));});};};var getSize = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['length']));});};var getNext = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['next']()));});};var getFirst = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['first']()));});};var getFind = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['find'](Fay$$serialize(StringType,$_b))));});};};var prepend = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['prepend'](Fay$$serialize(UnknownType,$_b))));});};};var after = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_b)['after'](Fay$$serialize(UnknownType,$_a))));});};};var append = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['append'](Fay$$serialize(UnknownType,$_b))));});};};var appendTo = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_b)['appendTo'](Fay$$serialize(UnknownType,$_a))));});};};var makeElement = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",window['jQuery'](Fay$$serialize(StringType,$_a))));});};var getWidth = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['width']()));});};var beautify = function($_a){return function($_b){return new $(function(){return Fay$$unserialize("string",$jsBeautify(Fay$$serialize(StringType,$_a),Fay$$serialize(DoubleType,$_b)));});};};var hljs = new $(function(){return Fay$$unserialize("",window['hljs']);});var initHighlightingOnLoad = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['initHighlightingOnLoad']()));});};var setTabReplace = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",Fay$$serialize(UnknownType,$_a)['tabReplace']=Fay$$serialize(StringType,$_b)));});};};var DateType = new $(function(){return [new Fay$$Constructor("DateType")];});var FunctionType = new $(function(){return [new Fay$$Constructor("FunctionType")];});var JsType = new $(function(){return [new Fay$$Constructor("JsType")];});var StringType = new $(function(){return [new Fay$$Constructor("StringType")];});var DoubleType = new $(function(){return [new Fay$$Constructor("DoubleType")];});var ListType = new $(function(){return [new Fay$$Constructor("ListType")];});var BoolType = new $(function(){return [new Fay$$Constructor("BoolType")];});var UnknownType = new $(function(){return [new Fay$$Constructor("UnknownType")];});var Just = function(slot1){return new $(function(){return [new Fay$$Constructor("Just"),slot1];});};var Nothing = new $(function(){return [new Fay$$Constructor("Nothing")];});var show = function($_a){return new $(function(){return Fay$$unserialize("string",Fay$$encodeShow(Fay$$serialize(UnknownType,$_a)));});};var fromInteger = function($_a){return new $(function(){var x = $_a;return x;});};var fromRational = function($_a){return new $(function(){var x = $_a;return x;});};var snd = function($_a){return new $(function(){var x = Fay$$index(1)(_($_a));return x;throw ["unhandled case in Ident \"snd\"",[$_a]];});};var fst = function($_a){return new $(function(){var x = Fay$$index(0)(_($_a));return x;throw ["unhandled case in Ident \"fst\"",[$_a]];});};var find = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var p = $_a;return _(_(p)(x)) ? _(Just)(x) : _(_(find)(p))(xs);}if (_($_b) === null) {var p = $_a;return Nothing;}throw ["unhandled case in Ident \"find\"",[$_a,$_b]];});};};var any = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var p = $_a;return _(_(p)(x)) ? true : _(_(any)(p))(xs);}if (_($_b) === null) {var p = $_a;return false;}throw ["unhandled case in Ident \"any\"",[$_a,$_b]];});};};var filter = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var p = $_a;return _(_(p)(x)) ? _(_(Fay$$cons)(x))(_(_(filter)(p))(xs)) : _(_(filter)(p))(xs);}if (_($_b) === null) {return null;}throw ["unhandled case in Ident \"filter\"",[$_a,$_b]];});};};var not = function($_a){return new $(function(){var p = $_a;return _(p) ? false : true;});};var _$null = function($_a){return new $(function(){if (_($_a) === null) {return true;}return false;});};var map = function($_a){return function($_b){return new $(function(){if (_($_b) === null) {return null;}var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var f = $_a;return _(_(Fay$$cons)(_(f)(x)))(_(_(map)(f))(xs));}throw ["unhandled case in Ident \"map\"",[$_a,$_b]];});};};var nub = function($_a){return new $(function(){var ls = $_a;return _(_(nub$39$)(ls))(null);});};var nub$39$ = function($_a){return function($_b){return new $(function(){if (_($_a) === null) {return null;}var ls = $_b;var $_$_a = _($_a);if ($_$_a instanceof Fay$$Cons) {var x = $_$_a.car;var xs = $_$_a.cdr;return _(_(_(elem)(x))(ls)) ? _(_(nub$39$)(xs))(ls) : _(_(Fay$$cons)(x))(_(_(nub$39$)(xs))(_(_(Fay$$cons)(x))(ls)));}throw ["unhandled case in Ident \"nub'\"",[$_a,$_b]];});};};var elem = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var y = $_$_b.car;var ys = $_$_b.cdr;var x = $_a;return _(_(_(Fay$$eq)(x))(y)) || _(_(_(elem)(x))(ys));}if (_($_b) === null) {return false;}throw ["unhandled case in Ident \"elem\"",[$_a,$_b]];});};};var GT = new $(function(){return [new Fay$$Constructor("GT")];});var LT = new $(function(){return [new Fay$$Constructor("LT")];});var EQ = new $(function(){return [new Fay$$Constructor("EQ")];});var sort = new $(function(){return _(sortBy)(compare);});var compare = function($_a){return function($_b){return new $(function(){var y = $_b;var x = $_a;return _(_(x) > _(y)) ? GT : _(_(x) < _(y)) ? LT : EQ;});};};var sortBy = function($_a){return new $(function(){var cmp = $_a;return _(_(foldr)(_(insertBy)(cmp)))(null);});};var insertBy = function($_a){return function($_b){return function($_c){return new $(function(){if (_($_c) === null) {var x = $_b;return Fay$$list([x]);}var ys = $_c;var x = $_b;var cmp = $_a;return (function($_ys){var $_$_ys = _($_ys);if ($_$_ys instanceof Fay$$Cons) {var y = $_$_ys.car;var ys$39$ = $_$_ys.cdr;return (function($tmp){if ((_($tmp))[0].name === "GT") {return _(_(Fay$$cons)(y))(_(_(_(insertBy)(cmp))(x))(ys$39$));}return _(_(Fay$$cons)(x))(ys);})(_(_(cmp)(x))(y));}return (function(){ throw (["unhandled case",$_ys]); })();})(ys);});};};};var when = function($_a){return function($_b){return new $(function(){var m = $_b;var p = $_a;return _(p) ? _(_(Fay$$then)(m))(_(Fay$$return)(Fay$$unit)) : _(Fay$$return)(Fay$$unit);});};};var enumFrom = function($_a){return new $(function(){var i = $_a;return _(_(Fay$$cons)(i))(_(enumFrom)(_(i) + 1));});};var enumFromTo = function($_a){return function($_b){return new $(function(){var n = $_b;var i = $_a;return _(_(_(Fay$$eq)(i))(n)) ? Fay$$list([i]) : _(_(Fay$$cons)(i))(_(_(enumFromTo)(_(i) + 1))(n));});};};var zipWith = function($_a){return function($_b){return function($_c){return new $(function(){var $_$_c = _($_c);if ($_$_c instanceof Fay$$Cons) {var b = $_$_c.car;var bs = $_$_c.cdr;var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var a = $_$_b.car;var as = $_$_b.cdr;var f = $_a;return _(_(Fay$$cons)(_(_(f)(a))(b)))(_(_(_(zipWith)(f))(as))(bs));}}return null;});};};};var zip = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var b = $_$_b.car;var bs = $_$_b.cdr;var $_$_a = _($_a);if ($_$_a instanceof Fay$$Cons) {var a = $_$_a.car;var as = $_$_a.cdr;return _(_(Fay$$cons)(Fay$$list([a,b])))(_(_(zip)(as))(bs));}}return null;});};};var flip = function($_a){return function($_b){return function($_c){return new $(function(){var y = $_c;var x = $_b;var f = $_a;return _(_(f)(y))(x);});};};};var maybe = function($_a){return function($_b){return function($_c){return new $(function(){if ((_($_c))[0].name === "Nothing") {var f = $_b;var m = $_a;return m;}if ((_($_c))[0].name === "Just") {var x = (_($_c))[1];var f = $_b;var m = $_a;return _(f)(x);}throw ["unhandled case in Ident \"maybe\"",[$_a,$_b,$_c]];});};};};var $46$ = function($_a){return function($_b){return function($_c){return new $(function(){var x = $_c;var g = $_b;var f = $_a;return _(f)(_(g)(x));});};};};var $43$$43$ = function($_a){return function($_b){return new $(function(){var y = $_b;var x = $_a;return _(_(conc)(x))(y);});};};var $36$ = function($_a){return function($_b){return new $(function(){var x = $_b;var f = $_a;return _(f)(x);});};};var conc = function($_a){return function($_b){return new $(function(){var ys = $_b;var $_$_a = _($_a);if ($_$_a instanceof Fay$$Cons) {var x = $_$_a.car;var xs = $_$_a.cdr;return _(_(Fay$$cons)(x))(_(_(conc)(xs))(ys));}var ys = $_b;if (_($_a) === null) {return ys;}throw ["unhandled case in Ident \"conc\"",[$_a,$_b]];});};};var concat = new $(function(){return _(_(foldr)(conc))(null);});var foldr = function($_a){return function($_b){return function($_c){return new $(function(){if (_($_c) === null) {var z = $_b;var f = $_a;return z;}var $_$_c = _($_c);if ($_$_c instanceof Fay$$Cons) {var x = $_$_c.car;var xs = $_$_c.cdr;var z = $_b;var f = $_a;return _(_(f)(x))(_(_(_(foldr)(f))(z))(xs));}throw ["unhandled case in Ident \"foldr\"",[$_a,$_b,$_c]];});};};};var foldl = function($_a){return function($_b){return function($_c){return new $(function(){if (_($_c) === null) {var z = $_b;var f = $_a;return z;}var $_$_c = _($_c);if ($_$_c instanceof Fay$$Cons) {var x = $_$_c.car;var xs = $_$_c.cdr;var z = $_b;var f = $_a;return _(_(_(foldl)(f))(_(_(f)(z))(x)))(xs);}throw ["unhandled case in Ident \"foldl\"",[$_a,$_b,$_c]];});};};};var lookup = function($_a){return function($_b){return new $(function(){if (_($_b) === null) {var _key = $_a;return Nothing;}var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = Fay$$index(0)(_($_$_b.car));var y = Fay$$index(1)(_($_$_b.car));var xys = $_$_b.cdr;var key = $_a;return _(_(_(Fay$$eq)(key))(x)) ? _(Just)(y) : _(_(lookup)(key))(xys);}throw ["unhandled case in Ident \"lookup\"",[$_a,$_b]];});};};var intersperse = function($_a){return function($_b){return new $(function(){if (_($_b) === null) {return null;}var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var sep = $_a;return _(_(Fay$$cons)(x))(_(_(prependToAll)(sep))(xs));}throw ["unhandled case in Ident \"intersperse\"",[$_a,$_b]];});};};var prependToAll = function($_a){return function($_b){return new $(function(){if (_($_b) === null) {return null;}var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var sep = $_a;return _(_(Fay$$cons)(sep))(_(_(Fay$$cons)(x))(_(_(prependToAll)(sep))(xs)));}throw ["unhandled case in Ident \"prependToAll\"",[$_a,$_b]];});};};var intercalate = function($_a){return function($_b){return new $(function(){var xss = $_b;var xs = $_a;return _(concat)(_(_(intersperse)(xs))(xss));});};};var forM_ = function($_a){return function($_b){return new $(function(){var m = $_b;var $_$_a = _($_a);if ($_$_a instanceof Fay$$Cons) {var x = $_$_a.car;var xs = $_$_a.cdr;return _(_(Fay$$then)(_(m)(x)))(_(_(forM_)(xs))(m));}if (_($_a) === null) {return _(Fay$$return)(Fay$$unit);}throw ["unhandled case in Ident \"forM_\"",[$_a,$_b]];});};};var mapM_ = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var m = $_a;return _(_(Fay$$then)(_(m)(x)))(_(_(mapM_)(m))(xs));}if (_($_b) === null) {return _(Fay$$return)(Fay$$unit);}throw ["unhandled case in Ident \"mapM_\"",[$_a,$_b]];});};};+var main = new $(function(){return _(_($36$)(_(ready)(_(wrap)(thedocument))))(_(_(Fay$$then)(indentAndHighlight))(_(_(Fay$$then)(setupExpanders))(setupTableOfContents)));});var indentAndHighlight = new $(function(){return _(_(Fay$$bind)(_(query)(Fay$$list(".language-javascript"))))(function($_a){var samples = $_a;return _(_(Fay$$then)(_(_($36$)(_(each)(samples)))(function($_a){var i = $_a;return function($_b){var _$this = $_b;return (function(){var sample = new $(function(){return _(wrap)(_$this);});return _(_(Fay$$bind)(_(getText)(sample)))(function($_a){var text = $_a;return _(_(setText)(sample))(_(_(beautify)(text))(2));});})();};})))(_(_(Fay$$then)(_(_(setTabReplace)(hljs))(Fay$$list(" "))))(_(initHighlightingOnLoad)(hljs)));});});var setupExpanders = new $(function(){return _(_(Fay$$bind)(_(_(Fay$$bind)(_(query)(Fay$$list(".wrap"))))(getWidth)))(function($_a){var wrapwidth = $_a;return _(_(Fay$$bind)(_(query)(Fay$$list(".example"))))(function($_a){var examples = $_a;return _(_($36$)(_(each)(examples)))(function($_a){var i = $_a;return function($_b){var _$this = $_b;return _(_(Fay$$bind)(_(_(getFind)(_(wrap)(_$this)))(Fay$$list("tr"))))(function($_a){var tr = $_a;return _(_(Fay$$bind)(_(_(Fay$$bind)(_(_(getFind)(tr))(Fay$$list("td"))))(getFirst)))(function($_a){var left = $_a;return _(_(Fay$$then)(_(_(addClass)(left))(Fay$$list("left"))))(_(_(Fay$$bind)(_(getNext)(left)))(function($_a){var right = $_a;return _(_(Fay$$bind)(_(makeElement)(Fay$$list("<a class='toggle' href='javascript:'>Show JavaScript</a>"))))(function($_a){var toggle = $_a;return _(_(Fay$$bind)(_(_($36$)(Fay$$return))(_(_(Fay$$bind)(_(_(getIs)(right))(Fay$$list(":visible"))))(function($_a){var visible = $_a;return _(visible) ? _(_(Fay$$then)(_(_(setText)(toggle))(Fay$$list("Hide JavaScript"))))(_(_(_(swapClasses)(toggle))(Fay$$list("toggle-hide")))(Fay$$list("toggle-show"))) : _(_(Fay$$then)(_(_(setText)(toggle))(Fay$$list("Show JavaScript"))))(_(_(_(swapClasses)(toggle))(Fay$$list("toggle-show")))(Fay$$list("toggle-hide")));}))))(function($_a){var toggleButton = $_a;return _(_(Fay$$then)(_(_($36$)(_(setClick)(toggle)))(_(_($36$)(_(fadeToggle)(right)))(toggleButton))))(_(_(Fay$$bind)(_(getWidth)(tr)))(function($_a){var width = $_a;return _(_(Fay$$then)(_(_($36$)(_(when)(_(width) > _(_(wrapwidth) + _(_(20 * _(wrapwidth)) / 100)))))(_(hide)(right))))(_(_(Fay$$then)(toggleButton))(_(_(Fay$$bind)(_(_(getFind)(left))(Fay$$list(".panel"))))(function($_a){var panel = $_a;return _(_(Fay$$then)(_(_(prepend)(panel))(toggle)))(_(Fay$$return)(Fay$$unit));})));}));});});}));});});};});});});});var setupTableOfContents = new $(function(){return _(_(Fay$$bind)(_(makeElement)(Fay$$list("<div class='table-of-contents'><p>Table of Contents</p></div>"))))(function($_a){var toc = $_a;return _(_(Fay$$then)(_(_(Fay$$bind)(_(query)(Fay$$list(".subheadline"))))(_(after)(toc))))(_(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<ul></ul>"))))(_(appendTo)(toc))))(function($_a){var ul = $_a;return _(_(Fay$$bind)(_(query)(Fay$$list("h2"))))(function($_a){var headings = $_a;return _(_($36$)(_(each)(headings)))(function($_a){var i = $_a;return function($_b){var heading = $_b;return (function(){var anchor = new $(function(){return _(_($43$$43$)(Fay$$list("section-")))(_(show)(i));});var h = new $(function(){return _(wrap)(heading);});return _(_(Fay$$then)(_(_(_(attr)(h))(Fay$$list("id")))(anchor)))(_(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<li></li>"))))(_(appendTo)(ul))))(function($_a){var li = $_a;return _(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<a></a>"))))(_(appendTo)(li))))(function($_a){var a = $_a;return _(_(Fay$$then)(_(_(Fay$$bind)(_(getText)(h)))(_(setText)(a))))(_(_(Fay$$then)(_(_(_(attr)(a))(Fay$$list("href")))(_(_($43$$43$)(Fay$$list("#")))(anchor))))(_(_(Fay$$bind)(_(getTagName)(heading)))(_(addClass)(li))));});}));})();};});});}));});});var print = new $(function(){return _(_($46$)(consolelog))(show);});var consolelog = new $(function(){return _(_(ffi)(Fay$$list("console.log(%1)")))(FayNone);});var alert = new $(function(){return _(_(ffi)(Fay$$list("window.alert(%1)")))(FayNone);});var thedocument = new $(function(){return _(_(ffi)(Fay$$list("window.document")))(FayNone);});var getTagName = new $(function(){return _(_(ffi)(Fay$$list("%1['tagName']")))(FayString);});var wrap = new $(function(){return _(_(ffi)(Fay$$list("window['jQuery'](%1)")))(FayNone);});var ready = new $(function(){return _(_(ffi)(Fay$$list("%1['ready'](%2)")))(FayNone);});var each = new $(function(){return _(_(ffi)(Fay$$list("%1['each'](%2)")))(FayNone);});var query = new $(function(){return _(_(ffi)(Fay$$list("window['jQuery'](%1)")))(FayNone);});var setText = new $(function(){return _(_(ffi)(Fay$$list("%1['text'](%2)")))(FayNone);});var attr = new $(function(){return _(_(ffi)(Fay$$list("%1['attr'](%2,%3)")))(FayNone);});var setClick = new $(function(){return _(_(ffi)(Fay$$list("%1['click'](%2)")))(FayNone);});var fadeToggle = new $(function(){return _(_(ffi)(Fay$$list("%1['fadeToggle'](%2)")))(FayNone);});var hide = new $(function(){return _(_(ffi)(Fay$$list("%1['hide']()")))(FayNone);});var addClass = new $(function(){return _(_(ffi)(Fay$$list("%1['addClass'](%2)")))(FayNone);});var removeClass = new $(function(){return _(_(ffi)(Fay$$list("%1['removeClass'](%2)")))(FayNone);});var swapClasses = function($_a){return function($_b){return function($_c){return new $(function(){var removeme = $_c;var addme = $_b;var obj = $_a;return _(_(Fay$$then)(_(_(addClass)(obj))(addme)))(_(_(removeClass)(obj))(removeme));});};};};var getText = new $(function(){return _(_(ffi)(Fay$$list("%1['text']()")))(FayString);});var getIs = new $(function(){return _(_(ffi)(Fay$$list("%1['is'](%2)")))(FayBool);});var getSize = new $(function(){return _(_(ffi)(Fay$$list("%1['length']")))(FayNone);});var getNext = new $(function(){return _(_(ffi)(Fay$$list("%1['next']()")))(FayNone);});var getFirst = new $(function(){return _(_(ffi)(Fay$$list("%1['first']()")))(FayNone);});var getFind = new $(function(){return _(_(ffi)(Fay$$list("%1['find'](%2)")))(FayNone);});var prepend = new $(function(){return _(_(ffi)(Fay$$list("%1['prepend'](%2)")))(FayNone);});var after = new $(function(){return _(_(ffi)(Fay$$list("%2['after'](%1)")))(FayNone);});var append = new $(function(){return _(_(ffi)(Fay$$list("%1['append'](%2)")))(FayNone);});var appendTo = new $(function(){return _(_(ffi)(Fay$$list("%2['appendTo'](%1)")))(FayNone);});var makeElement = new $(function(){return _(_(ffi)(Fay$$list("window['jQuery'](%1)")))(FayNone);});var getWidth = new $(function(){return _(_(ffi)(Fay$$list("%1['width']()")))(FayNone);});var beautify = new $(function(){return _(_(ffi)(Fay$$list("$jsBeautify(%1,%2)")))(FayString);});var hljs = new $(function(){return _(_(ffi)(Fay$$list("window['hljs']")))(FayNone);});var initHighlightingOnLoad = new $(function(){return _(_(ffi)(Fay$$list("%1['initHighlightingOnLoad']()")))(FayNone);});var setTabReplace = new $(function(){return _(_(ffi)(Fay$$list("%1['tabReplace']=%2")))(FayNone);});var Just = function(slot1){return new $(function(){return [new Fay$$Constructor("Just"),slot1];});};var Nothing = new $(function(){return [new Fay$$Constructor("Nothing")];});var show = function($_a){return new $(function(){return Fay$$unserialize(["string"],Fay$$encodeShow(Fay$$serialize(["unknown"],$_a)));});};var fromInteger = function($_a){return new $(function(){var x = $_a;return x;});};var fromRational = function($_a){return new $(function(){var x = $_a;return x;});};var snd = function($_a){return new $(function(){var x = Fay$$index(1)(_($_a));return x;throw ["unhandled case in Ident \"snd\"",[$_a]];});};var fst = function($_a){return new $(function(){var x = Fay$$index(0)(_($_a));return x;throw ["unhandled case in Ident \"fst\"",[$_a]];});};var find = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var p = $_a;return _(_(p)(x)) ? _(Just)(x) : _(_(find)(p))(xs);}if (_($_b) === null) {var p = $_a;return Nothing;}throw ["unhandled case in Ident \"find\"",[$_a,$_b]];});};};var any = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var p = $_a;return _(_(p)(x)) ? true : _(_(any)(p))(xs);}if (_($_b) === null) {var p = $_a;return false;}throw ["unhandled case in Ident \"any\"",[$_a,$_b]];});};};var filter = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var p = $_a;return _(_(p)(x)) ? _(_(Fay$$cons)(x))(_(_(filter)(p))(xs)) : _(_(filter)(p))(xs);}if (_($_b) === null) {return null;}throw ["unhandled case in Ident \"filter\"",[$_a,$_b]];});};};var not = function($_a){return new $(function(){var p = $_a;return _(p) ? false : true;});};var _$null = function($_a){return new $(function(){if (_($_a) === null) {return true;}return false;});};var map = function($_a){return function($_b){return new $(function(){if (_($_b) === null) {return null;}var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var f = $_a;return _(_(Fay$$cons)(_(f)(x)))(_(_(map)(f))(xs));}throw ["unhandled case in Ident \"map\"",[$_a,$_b]];});};};var nub = function($_a){return new $(function(){var ls = $_a;return _(_(nub$39$)(ls))(null);});};var nub$39$ = function($_a){return function($_b){return new $(function(){if (_($_a) === null) {return null;}var ls = $_b;var $_$_a = _($_a);if ($_$_a instanceof Fay$$Cons) {var x = $_$_a.car;var xs = $_$_a.cdr;return _(_(_(elem)(x))(ls)) ? _(_(nub$39$)(xs))(ls) : _(_(Fay$$cons)(x))(_(_(nub$39$)(xs))(_(_(Fay$$cons)(x))(ls)));}throw ["unhandled case in Ident \"nub'\"",[$_a,$_b]];});};};var elem = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var y = $_$_b.car;var ys = $_$_b.cdr;var x = $_a;return _(_(_(Fay$$eq)(x))(y)) || _(_(_(elem)(x))(ys));}if (_($_b) === null) {return false;}throw ["unhandled case in Ident \"elem\"",[$_a,$_b]];});};};var GT = new $(function(){return [new Fay$$Constructor("GT")];});var LT = new $(function(){return [new Fay$$Constructor("LT")];});var EQ = new $(function(){return [new Fay$$Constructor("EQ")];});var sort = new $(function(){return _(sortBy)(compare);});var compare = function($_a){return function($_b){return new $(function(){var y = $_b;var x = $_a;return _(_(x) > _(y)) ? GT : _(_(x) < _(y)) ? LT : EQ;});};};var sortBy = function($_a){return new $(function(){var cmp = $_a;return _(_(foldr)(_(insertBy)(cmp)))(null);});};var insertBy = function($_a){return function($_b){return function($_c){return new $(function(){if (_($_c) === null) {var x = $_b;return Fay$$list([x]);}var ys = $_c;var x = $_b;var cmp = $_a;return (function($_ys){var $_$_ys = _($_ys);if ($_$_ys instanceof Fay$$Cons) {var y = $_$_ys.car;var ys$39$ = $_$_ys.cdr;return (function($tmp){if ((_($tmp))[0].name === "GT") {return _(_(Fay$$cons)(y))(_(_(_(insertBy)(cmp))(x))(ys$39$));}return _(_(Fay$$cons)(x))(ys);})(_(_(cmp)(x))(y));}return (function(){ throw (["unhandled case",$_ys]); })();})(ys);});};};};var when = function($_a){return function($_b){return new $(function(){var m = $_b;var p = $_a;return _(p) ? _(_(Fay$$then)(m))(_(Fay$$return)(Fay$$unit)) : _(Fay$$return)(Fay$$unit);});};};var enumFrom = function($_a){return new $(function(){var i = $_a;return _(_(Fay$$cons)(i))(_(enumFrom)(_(i) + 1));});};var enumFromTo = function($_a){return function($_b){return new $(function(){var n = $_b;var i = $_a;return _(_(_(Fay$$eq)(i))(n)) ? Fay$$list([i]) : _(_(Fay$$cons)(i))(_(_(enumFromTo)(_(i) + 1))(n));});};};var zipWith = function($_a){return function($_b){return function($_c){return new $(function(){var $_$_c = _($_c);if ($_$_c instanceof Fay$$Cons) {var b = $_$_c.car;var bs = $_$_c.cdr;var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var a = $_$_b.car;var as = $_$_b.cdr;var f = $_a;return _(_(Fay$$cons)(_(_(f)(a))(b)))(_(_(_(zipWith)(f))(as))(bs));}}return null;});};};};var zip = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var b = $_$_b.car;var bs = $_$_b.cdr;var $_$_a = _($_a);if ($_$_a instanceof Fay$$Cons) {var a = $_$_a.car;var as = $_$_a.cdr;return _(_(Fay$$cons)(Fay$$list([a,b])))(_(_(zip)(as))(bs));}}return null;});};};var flip = function($_a){return function($_b){return function($_c){return new $(function(){var y = $_c;var x = $_b;var f = $_a;return _(_(f)(y))(x);});};};};var maybe = function($_a){return function($_b){return function($_c){return new $(function(){if ((_($_c))[0].name === "Nothing") {var f = $_b;var m = $_a;return m;}if ((_($_c))[0].name === "Just") {var x = (_($_c))[1];var f = $_b;var m = $_a;return _(f)(x);}throw ["unhandled case in Ident \"maybe\"",[$_a,$_b,$_c]];});};};};var $46$ = function($_a){return function($_b){return function($_c){return new $(function(){var x = $_c;var g = $_b;var f = $_a;return _(f)(_(g)(x));});};};};var $43$$43$ = function($_a){return function($_b){return new $(function(){var y = $_b;var x = $_a;return _(_(conc)(x))(y);});};};var $36$ = function($_a){return function($_b){return new $(function(){var x = $_b;var f = $_a;return _(f)(x);});};};var conc = function($_a){return function($_b){return new $(function(){var ys = $_b;var $_$_a = _($_a);if ($_$_a instanceof Fay$$Cons) {var x = $_$_a.car;var xs = $_$_a.cdr;return _(_(Fay$$cons)(x))(_(_(conc)(xs))(ys));}var ys = $_b;if (_($_a) === null) {return ys;}throw ["unhandled case in Ident \"conc\"",[$_a,$_b]];});};};var concat = new $(function(){return _(_(foldr)(conc))(null);});var foldr = function($_a){return function($_b){return function($_c){return new $(function(){if (_($_c) === null) {var z = $_b;var f = $_a;return z;}var $_$_c = _($_c);if ($_$_c instanceof Fay$$Cons) {var x = $_$_c.car;var xs = $_$_c.cdr;var z = $_b;var f = $_a;return _(_(f)(x))(_(_(_(foldr)(f))(z))(xs));}throw ["unhandled case in Ident \"foldr\"",[$_a,$_b,$_c]];});};};};var foldl = function($_a){return function($_b){return function($_c){return new $(function(){if (_($_c) === null) {var z = $_b;var f = $_a;return z;}var $_$_c = _($_c);if ($_$_c instanceof Fay$$Cons) {var x = $_$_c.car;var xs = $_$_c.cdr;var z = $_b;var f = $_a;return _(_(_(foldl)(f))(_(_(f)(z))(x)))(xs);}throw ["unhandled case in Ident \"foldl\"",[$_a,$_b,$_c]];});};};};var lookup = function($_a){return function($_b){return new $(function(){if (_($_b) === null) {var _key = $_a;return Nothing;}var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = Fay$$index(0)(_($_$_b.car));var y = Fay$$index(1)(_($_$_b.car));var xys = $_$_b.cdr;var key = $_a;return _(_(_(Fay$$eq)(key))(x)) ? _(Just)(y) : _(_(lookup)(key))(xys);}throw ["unhandled case in Ident \"lookup\"",[$_a,$_b]];});};};var intersperse = function($_a){return function($_b){return new $(function(){if (_($_b) === null) {return null;}var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var sep = $_a;return _(_(Fay$$cons)(x))(_(_(prependToAll)(sep))(xs));}throw ["unhandled case in Ident \"intersperse\"",[$_a,$_b]];});};};var prependToAll = function($_a){return function($_b){return new $(function(){if (_($_b) === null) {return null;}var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var sep = $_a;return _(_(Fay$$cons)(sep))(_(_(Fay$$cons)(x))(_(_(prependToAll)(sep))(xs)));}throw ["unhandled case in Ident \"prependToAll\"",[$_a,$_b]];});};};var intercalate = function($_a){return function($_b){return new $(function(){var xss = $_b;var xs = $_a;return _(concat)(_(_(intersperse)(xs))(xss));});};};var forM_ = function($_a){return function($_b){return new $(function(){var m = $_b;var $_$_a = _($_a);if ($_$_a instanceof Fay$$Cons) {var x = $_$_a.car;var xs = $_$_a.cdr;return _(_(Fay$$then)(_(m)(x)))(_(_(forM_)(xs))(m));}if (_($_a) === null) {return _(Fay$$return)(Fay$$unit);}throw ["unhandled case in Ident \"forM_\"",[$_a,$_b]];});};};var mapM_ = function($_a){return function($_b){return new $(function(){var $_$_b = _($_b);if ($_$_b instanceof Fay$$Cons) {var x = $_$_b.car;var xs = $_$_b.cdr;var m = $_a;return _(_(Fay$$then)(_(m)(x)))(_(_(mapM_)(m))(xs));}if (_($_b) === null) {return _(Fay$$return)(Fay$$unit);}throw ["unhandled case in Ident \"mapM_\"",[$_a,$_b]];});};}; // Exports this.main = main; @@ -374,6 +445,7 @@ this.$list = Fay$$list; this.$encodeShow = Fay$$encodeShow; this.$eval = Fay$$eval;+this.$serialize = Fay$$serialize; }; ;
docs/snippets/ffi.hs view
@@ -1,17 +1,17 @@ print :: Foreign a => a -> Fay ()-print = ffi "window.console.log(%1)" ""+print = ffi "window.console.log(%1)" alert :: Foreign a => a -> Fay ()-alert = ffi "window.alert(%1)" ""+alert = ffi "window.alert(%1)" getInnerHtml :: Element -> Fay String-getInnerHtml = ffi "%1.innerHTML" FayString+getInnerHtml = ffi "%1.innerHTML" setInnerHtml :: Element -> String -> Fay () setInnerHtml = ffi "%1.innerHTML=%2" thedocument :: Element-thedocument = ffi "window.document" FayNone+thedocument = ffi "window.document" jquery :: Element -> JQuery-jquery = ffi "window.jQuery(%1)" FayNone+jquery = ffi "window.jQuery(%1)"
examples/dom.hs view
@@ -19,6 +19,7 @@ data Element instance Foreign Element+instance Show (Element) documentGetElements :: String -> Fay [Element] documentGetElements = ffi "document.getElementsByTagName(%1)"
fay.cabal view
@@ -1,5 +1,5 @@ name: fay-version: 0.5.0.0+version: 0.5.1.0 synopsis: A compiler for Fay, a Haskell subset that compiles to JavaScript. description: Fay is a proper subset of Haskell which can be compiled (type-checked) with GHC, and compiled to JavaScript. It is lazy, pure, with a Fay monad,@@ -22,7 +22,7 @@ . /Release Notes/ .- * MAJOR FFI RESTRUCTURING. Please see commit d6c346c320245762432928bc83aa8ca98a426138.+ * New representation for records and support for RecDecl (closes #43) . See full history at: <https://github.com/chrisdone/fay/commits> homepage: http://fay-lang.org/
src/Language/Fay.hs view
@@ -22,6 +22,7 @@ import Control.Monad.IO import Control.Monad.State import Data.Char+import Data.Default (def) import Data.List import Data.Maybe import Data.String@@ -90,6 +91,11 @@ Right (ok,_) -> do writeFile "/tmp/x.js" ok prettyPrintFile "/tmp/x.js" >>= putStr +-- | Compile a String of Fay and print it as beautified JavaScript.+printTestCompile :: String -> IO ()+printTestCompile = printCompile def compileModule++ -------------------------------------------------------------------------------- -- Compilers @@ -116,7 +122,7 @@ cfg <- config id result <- liftIO $ compileToAst cfg compileModule contents case result of- Right (stmts,state) -> return stmts+ Right (stmts,_) -> return stmts Left err -> throwError err where replace c r = map (\x -> if x == c then r else x) compileImport i =@@ -163,6 +169,8 @@ Just sig -> compileFFI ident formatstr sig Nothing -> throwError (FfiNeedsTypeSig pat) _ -> compileNormalPatBind toplevel ident rhs+ PatBind _ (PVar ident) Nothing (UnGuardedRhs rhs) bdecls ->+ compileNormalPatBind toplevel ident (Let bdecls rhs) _ -> throwError (UnsupportedDeclaration pat) where ffiExp (App (Var (UnQual (Ident "ffi"))) (Lit (String formatstr))) = Just formatstr@@ -288,33 +296,59 @@ fmap concat $ forM constructors $ \(QualConDecl _ _ _ condecl) -> case condecl of- ConDecl (UnQual -> name) types -> fmap return (makeDataCons name types [])+ ConDecl (UnQual -> name) types -> do+ cons <- makeConstructor name (slots types)+ func <- makeFunc name (slots types)+ return [cons, func] RecDecl (UnQual -> name) fields -> do- cons <- makeDataCons name (map snd fields) (map fst fields)- funs <- makeAccessors (zip [1..] (map fst fields))- return (cons : funs)+ cons <- makeConstructor name $ map (head . fst) fields+ func <- makeFunc name $ map (head . fst) fields+ funs <- makeAccessors (map fst fields)+ return (cons : func : funs) _ -> throwError (UnsupportedDeclaration decl) - where makeDataCons name types fields = do- let slots = (map (fromString . ("slot"++) . show . fst)- (zip [1 :: Integer ..] types))+ where+ slots :: [a] -> [Name]+ slots = map (Ident . ("slot"++) . show . fst) . zip [1 :: Integer ..]++ constructorName = fromString . (++ "_RecConstr") . qname++ -- Creates a constructor R_RecConstr for a Record+ makeConstructor name fields = do+ let fieldParams = map (fromString . unname) fields+ -- this._fields = [fieldName1, fieldName2, ..]+ let setFields = JsSetProp (fromString ":this") (fromString "_fields")+ (JsList . flip map fields $ \(Ident field) -> JsLit . JsStr $ field)+ return $- JsVar name- (foldr (\slot inner -> JsFun [slot] [] (Just inner))- (thunk (JsList ((JsNew (hjIdent "Constructor")- (JsLit (JsStr (qname name)) :- concat (map (map (JsLit . JsStr . unname)) fields)))- : map JsName slots)))- slots)- makeAccessors fields = do+ JsVar (constructorName name) $+ JsFun fieldParams+ (setFields :+ (flip map fields $+ \field@(Ident s) ->+ JsSetProp (fromString ":this") (UnQual field) (JsName (fromString s))))+ Nothing++ -- Creates a function to initialize the record by regular application+ makeFunc name fields = do+ let fieldParams = map (\(Ident s) -> fromString s) fields+ let fieldExps = map (JsName . UnQual) fields+ return $+ JsVar name $+ foldr (\slot inner -> JsFun [slot] [] (Just inner))+ (thunk $ JsNew (constructorName name) fieldExps)+ fieldParams++ -- Creates getters for a RecDecl's values+ makeAccessors fields = do fmap concat $- forM fields $ \(i,field) ->- forM field $ \name ->+ forM fields $ \field ->+ forM field $ \name@(Ident nameStr) -> bindToplevel toplevel (UnQual name) (JsFun ["x"] []- (Just (thunk (JsIndex i (force (JsName "x"))))))+ (Just (thunk (JsGetProp (force (JsName "x")) (UnQual (Ident nameStr)))))) -- | Extract the string from a qname. qname :: QName -> String@@ -395,9 +429,14 @@ fmap concat (mapM flatten xs) expand _ = Nothing --- -- | Run a JS file.+-- | Format a JS file using "js-beautify", or return the JS as-is if+-- "js-beautify" is unavailable prettyPrintFile :: String -> IO String-prettyPrintFile file = fmap (either id id) (readAllFromProcess "js-beautify" file)+prettyPrintFile file =+ (readAllFromProcess "js-beautify" file)+ >>= (either+ (\_ -> (readFile file) >>= (\js -> return $ js ++ "\n"))+ return) -- | Compile a right-hand-side expression. compileRhs :: Rhs -> Compile JsExp@@ -461,12 +500,14 @@ t <- compileExp i' return (JsApp (JsApp (JsName "enumFromTo") [f]) [t])+ RecConstr name fieldUpdates -> compileRecConstr name fieldUpdates ExpTypeSig _ e _ -> compileExp e exp -> throwError (UnsupportedExpression exp) instance CompilesTo Exp JsExp where compileTo = compileExp + -- | Compile simple application. compileApp :: Exp -> Exp -> Compile JsExp compileApp exp1 exp2 = do@@ -518,6 +559,7 @@ exps <- mapM compileExp xs return (makeList exps) +makeList :: [JsExp] -> JsExp makeList exps = (JsApp (JsName (hjIdent "list")) [JsList exps]) -- | Compile an if.@@ -619,11 +661,24 @@ body []] +-- | Compile as binding in pattern match compilePAsPat :: JsExp -> Name -> Pat -> [JsStmt] -> Compile [JsStmt] compilePAsPat exp name pat body = do- x <- compilePat exp pat body;+ x <- compilePat exp pat body return ([JsVar (UnQual name) exp] ++ x ++ body) +-- | Compile a record construction with named fields+-- | GHC will warn on uninitialized fields, they will be undefined in JS.+compileRecConstr :: QName -> [FieldUpdate] -> Compile JsExp+compileRecConstr name fieldUpdates = do+ let o = UnQual (Ident (map toLower (qname name)))+ -- var obj = new Type_RecConstr()+ let record = JsVar o (JsNew (UnQual (Ident ((qname name) ++ "_RecConstr"))) [])+ setFields <- forM fieldUpdates $+ -- obj.field = value+ \(FieldUpdate (UnQual field) value) -> JsSetProp o (UnQual field) <$> compileExp value+ return $ JsApp (JsFun [] (record:setFields) (Just (JsName o))) []+ -- | Equality test for two expressions, with some optimizations. equalExps :: JsExp -> JsExp -> JsExp equalExps a b@@ -642,18 +697,19 @@ compilePApp :: QName -> [Pat] -> JsExp -> [JsStmt] -> Compile [JsStmt] compilePApp cons pats exp body = do let forcedExp = force exp- substmts <- foldM (\body (i,pat) -> compilePat (JsIndex i forcedExp) pat body)+ substmts <- foldM (\body (fieldIndex,pat) ->+ -- r[r._fields[N]]+ compilePat (JsLookup forcedExp+ (JsIndex fieldIndex+ (JsGetProp forcedExp "_fields"))) pat body) body- (reverse (zip [1..] pats))- let constructor = JsIndex 0 forcedExp- compareConstructorNames+ (reverse (zip [0..] pats))+ let compareConstructorNames -- Special-casing on the booleans. | cons == "True" = JsEq forcedExp (JsLit (JsBool True)) | cons == "False" = JsEq forcedExp (JsLit (JsBool False)) -- Everything else, generic:- | otherwise =- JsEq (JsGetProp constructor "name")- (JsLit (JsStr (qname cons)))+ | otherwise = forcedExp `JsInstanceOf` (UnQual (Ident ((qname cons) ++ "_RecConstr"))) return [JsIf compareConstructorNames substmts []]
src/Language/Fay/Print.hs view
@@ -148,6 +148,8 @@ printJS exp1 ++ " === " ++ printJS exp2 printJS (JsGetProp exp prop) = printJS exp ++ "." ++ printJS prop+ printJS (JsLookup exp1 exp2) =+ printJS exp1 ++ "[" ++ printJS exp2 ++ "]" printJS (JsUpdateProp name prop expr) = (concat ["(",printJS name,".",printJS prop," = ",printJS expr,")"]) printJS (JsInfix op x y) =
src/Language/Fay/Types.hs view
@@ -136,6 +136,7 @@ | JsSequence [JsExp] | JsParen JsExp | JsGetProp JsExp JsName+ | JsLookup JsExp JsExp | JsUpdateProp JsExp JsName JsExp | JsGetPropExtern JsExp JsName | JsUpdatePropExtern JsExp JsName JsExp
tests/16 view
@@ -1,1 +1,4 @@ Hello!+Hello!+Hello!+Hello!
tests/16.hs view
@@ -1,7 +1,17 @@-data Person = Person String String Int+data Person1 = Person1 String String Int+data Person2 = Person2 { fname :: String, sname :: String, age :: Int }+data Person3 = Person3 { slot3 :: String, slot2 :: String, slot1 :: Int } -main = print (case Person "Chris" "Done" 13 of- Person "Chris" "Done" 13 -> "Hello!")+p1 = Person1 "Chris" "Done" 13+p2 = Person2 "Chris" "Done" 13+p2a = Person2 { fname = "Chris", sname = "Done", age = 13 }+p3 = Person3 "Chris" "Done" 13++main = do+ print (case p1 of Person1 "Chris" "Done" 13 -> "Hello!")+ print (case p2 of Person2 "Chris" "Done" 13 -> "Hello!")+ print (case p2a of Person2 "Chris" "Done" 13 -> "Hello!")+ print (case p3 of Person3 "Chris" "Done" 13 -> "Hello!") print :: String -> Fay () print = ffi "console.log(%1)"