fay 0.3.1.1 → 0.4.0.1
raw patch · 44 files changed
+277/−335 lines, 44 filesdep +language-javascriptdep +safePVP ok
version bump matches the API change (PVP)
Dependencies added: language-javascript, safe
API changes (from Hackage documentation)
- Language.Fay: BoolType :: ArgType
- Language.Fay: DoubleType :: ArgType
- Language.Fay: FunctionType :: ArgType
- Language.Fay: JsType :: ArgType
- Language.Fay: ListType :: ArgType
- Language.Fay: StringType :: ArgType
- Language.Fay: UnknownType :: ArgType
- Language.Fay: compileFFIFunc :: Type -> Name -> (String, String, FayReturnType) -> Compile [JsStmt]
- Language.Fay: compileFFIMethod :: Type -> Name -> (String, String, FayReturnType) -> Compile [JsStmt]
- Language.Fay: compileFFISetProp :: Type -> Name -> (String, String, FayReturnType) -> Compile [JsStmt]
- Language.Fay: data ArgType
- Language.Fay: instance Eq ArgType
- Language.Fay: instance Show ArgType
- Language.Fay.FFI: foreignFay :: Foreign a => String -> FayReturnType -> a
- Language.Fay.FFI: foreignMethod :: Foreign a => String -> FayReturnType -> a
- Language.Fay.FFI: foreignMethodFay :: Foreign a => String -> FayReturnType -> a
- Language.Fay.FFI: foreignProp :: Foreign a => String -> FayReturnType -> a
- Language.Fay.FFI: foreignPropFay :: Foreign a => String -> FayReturnType -> a
- Language.Fay.FFI: foreignPure :: Foreign a => String -> FayReturnType -> a
- Language.Fay.FFI: foreignSetProp :: (Foreign object, Foreign value) => String -> object -> value -> Fay ()
- Language.Fay.FFI: foreignValue :: Foreign a => String -> FayReturnType -> a
- Language.Fay.Types: JsRawName :: String -> JsExp
+ Language.Fay: argType :: Type -> ArgType
+ Language.Fay: formatFFI :: String -> [(JsParam, ArgType)] -> Compile String
+ Language.Fay.FFI: ffi :: Foreign a => String -> FayReturnType -> a
+ Language.Fay.Types: BoolType :: ArgType
+ Language.Fay.Types: DoubleType :: ArgType
+ Language.Fay.Types: FfiFormatBadChars :: String -> CompileError
+ Language.Fay.Types: FfiFormatIncompleteArg :: CompileError
+ Language.Fay.Types: FfiFormatInvalidJavaScript :: String -> String -> CompileError
+ Language.Fay.Types: FfiFormatNoSuchArg :: Int -> CompileError
+ Language.Fay.Types: FunctionType :: ArgType
+ Language.Fay.Types: JsRawExp :: String -> JsExp
+ Language.Fay.Types: JsType :: ArgType
+ Language.Fay.Types: ListType :: ArgType
+ Language.Fay.Types: StringType :: ArgType
+ Language.Fay.Types: UnknownType :: ArgType
+ Language.Fay.Types: data ArgType
+ Language.Fay.Types: instance Eq ArgType
+ Language.Fay.Types: instance Show ArgType
- Language.Fay: compileFFI :: Type -> Name -> (String, String, FayReturnType) -> JsExp -> [JsName] -> [JsName] -> Compile [JsStmt]
+ Language.Fay: compileFFI :: Name -> String -> FayReturnType -> Type -> Compile [JsStmt]
- Language.Fay: typeArity :: Type -> Integer
+ Language.Fay: typeArity :: Type -> Int
Files
- docs/home.hs +37/−33
- docs/home.js +1/−1
- docs/snippets/ffi.hs +6/−6
- examples/alert.hs +1/−1
- examples/canvas.water.html +0/−10
- examples/canvaswater.hs +17/−17
- examples/canvaswater.html +10/−0
- examples/console.hs +1/−1
- examples/data.hs +1/−1
- examples/dom.hs +4/−7
- examples/ref.hs +8/−7
- fay.cabal +15/−6
- hs/stdlib.hs +1/−1
- src/Language/Fay.hs +98/−123
- src/Language/Fay/FFI.hs +4/−61
- src/Language/Fay/Print.hs +1/−1
- src/Language/Fay/Types.hs +15/−2
- tests/10.hs +2/−2
- tests/11 +1/−1
- tests/11.hs +3/−3
- tests/12.hs +5/−5
- tests/13.hs +2/−2
- tests/14.hs +2/−2
- tests/15.hs +2/−2
- tests/16.hs +2/−2
- tests/17.hs +2/−2
- tests/18.hs +2/−2
- tests/19.hs +2/−2
- tests/20.hs +2/−2
- tests/21.hs +2/−2
- tests/22.hs +2/−2
- tests/23.hs +2/−2
- tests/24.hs +2/−2
- tests/25.hs +2/−2
- tests/26.hs +2/−2
- tests/27.hs +2/−2
- tests/28.hs +2/−2
- tests/3.hs +2/−2
- tests/4.hs +2/−2
- tests/5.hs +2/−2
- tests/6.hs +2/−2
- tests/7.hs +2/−2
- tests/8.hs +2/−2
- tests/9.hs +2/−2
docs/home.hs view
@@ -88,13 +88,17 @@ -------------------------------------------------------------------------------- -- Window object +-- | Print something.+print :: Show a => a -> Fay ()+print = consolelog . show+ -- | Console log.-print :: (Show a,Foreign a) => a -> Fay ()-print = foreignFay "console.log" FayNone+consolelog :: String -> Fay ()+consolelog = ffi "console.log(%1)" FayNone -- | Pop-up an alert. alert :: String -> Fay ()-alert = foreignFay "window.alert" FayNone+alert = ffi "window.alert(%1)" FayNone -------------------------------------------------------------------------------- -- DOM@@ -105,12 +109,12 @@ -- | The document. thedocument :: Element-thedocument = foreignValue "window.document" FayNone+thedocument = ffi "window.document" FayNone -- | Get the size of the given jquery array. getTagName :: Element -> Fay String-getTagName = foreignPropFay "tagName" FayString- +getTagName = ffi "%1['tagName']" FayString+ -------------------------------------------------------------------------------- -- jQuery @@ -120,47 +124,47 @@ -- | Make a jQuery object out of an element. wrap :: [Element] -> JQuery-wrap = foreignPure "window['jQuery']" FayNone+wrap = ffi "window['jQuery'](%1)" FayNone -- | Bind a handler for when the element is ready. ready :: JQuery -> Fay () -> Fay ()-ready = foreignMethodFay "ready" FayNone+ready = ffi "%1['ready'](%2)" FayNone -- | Bind a handler for when the element is ready. each :: JQuery -> (Double -> Element -> Fay ()) -> Fay ()-each = foreignMethodFay "each" FayNone+each = ffi "%1['each'](%2)" FayNone -- | Query for elements. query :: String -> Fay JQuery-query = foreignFay "window['jQuery']" FayNone+query = ffi "window['jQuery'](%1)" FayNone -- | Set the text of the given object. setText :: JQuery -> String -> Fay ()-setText = foreignMethodFay "text" FayNone+setText = ffi "%1['text'](%2)" FayNone -- | Set the text of the given object. attr :: JQuery -> String -> String -> Fay ()-attr = foreignMethodFay "attr" FayNone+attr = ffi "%1['attr'](%2,%3)" FayNone -- | Set the click of the given object. setClick :: JQuery -> Fay () -> Fay ()-setClick = foreignMethodFay "click" FayNone+setClick = ffi "%1['click'](%2)" FayNone -- | Toggle the visibility of an element, faded. fadeToggle :: JQuery -> Fay () -> Fay ()-fadeToggle = foreignMethodFay "fadeToggle" FayNone+fadeToggle = ffi "%1['fadeToggle'](%2)" FayNone -- | Hide an element. hide :: JQuery -> Fay ()-hide = foreignMethodFay "hide" FayNone+hide = ffi "%1['hide']()" FayNone -- | Add a class to the given object. addClass :: JQuery -> String -> Fay ()-addClass = foreignMethodFay "addClass" FayNone+addClass = ffi "%1['addClass'](%2)" FayNone -- | Remove a class from the given object. removeClass :: JQuery -> String -> Fay ()-removeClass = foreignMethodFay "removeClass" FayNone+removeClass = ffi "%1['removeClass'](%2)" FayNone -- | Swap the given classes on the object. swapClasses :: JQuery -> String -> String -> Fay ()@@ -170,51 +174,51 @@ -- | Get the text of the given object. getText :: JQuery -> Fay String-getText = foreignMethodFay "text" FayString+getText = ffi "%1['text']()" FayString -- | Get the text of the given object. getIs :: JQuery -> String -> Fay Bool-getIs = foreignMethodFay "is" FayBool+getIs = ffi "%1['is'](%2)" FayBool -- | Get the size of the given jquery array. getSize :: JQuery -> Fay Double-getSize = foreignPropFay "length" FayNone+getSize = ffi "%1['length']" FayNone -- | Get the next of the given object. getNext :: JQuery -> Fay JQuery-getNext = foreignMethodFay "next" FayNone+getNext = ffi "%1['next']()" FayNone -- | Get the first of the given object. getFirst :: JQuery -> Fay JQuery-getFirst = foreignMethodFay "first" FayNone+getFirst = ffi "%1['first']()" FayNone -- | Get the find of the given object. getFind :: JQuery -> String -> Fay JQuery-getFind = foreignMethodFay "find" FayNone+getFind = ffi "%1['find'](%2)" FayNone -- | Prepend an element to this one. prepend :: JQuery -> JQuery -> Fay JQuery-prepend = foreignMethodFay "prepend" FayNone+prepend = ffi "%1['prepend'](%2)" FayNone -- | Append an element /after/ this one. after :: JQuery -> JQuery -> Fay JQuery-after = foreignMethodFay "after" FayNone+after = ffi "%1['after'](%2)" FayNone -- | Append an element to this one. append :: JQuery -> JQuery -> Fay JQuery-append = foreignMethodFay "append" FayNone+append = ffi "%1['append'](%2)" FayNone -- | Append this to an element. appendTo :: JQuery -> JQuery -> Fay JQuery-appendTo = foreignMethodFay "appendTo" FayNone+appendTo = ffi "%1['appendTo'](%2)" FayNone -- | Make a new element. makeElement :: String -> Fay JQuery-makeElement = foreignFay "window['jQuery']" FayNone+makeElement = ffi "window['jQuery'](%1)" FayNone -- | Get the width of the given object. getWidth :: JQuery -> Fay Double-getWidth = foreignMethodFay "width" FayNone+getWidth = ffi "%1['width']()" FayNone -------------------------------------------------------------------------------- -- Pretty printing / highlighting@@ -223,19 +227,19 @@ beautify :: String -- ^ The JS code. -> Double -- ^ The indentation level. -> String -- ^ The reformatted JS code.-beautify = foreignPure "$jsBeautify" FayString+beautify = ffi "$jsBeautify(%1,%2)" FayString data Highlighter instance Foreign Highlighter -- | Get the highlighter. hljs :: Highlighter-hljs = foreignValue "window['hljs']" FayNone+hljs = ffi "window['hljs']" FayNone -- | Init syntax highlighting on load. initHighlightingOnLoad :: Highlighter -> Fay ()-initHighlightingOnLoad = foreignMethodFay "initHighlightingOnLoad" FayNone+initHighlightingOnLoad = ffi "%1['initHighlightingOnLoad']()" FayNone -- | Init syntax highlighting on load. setTabReplace :: Highlighter -> String -> Fay ()-setTabReplace = foreignSetProp "tabReplace"+setTabReplace = ffi "%1['tabReplace']=%2" FayNone
docs/home.js view
@@ -365,7 +365,7 @@ */ -var main = new $(function(){return _(_($36$)(_(ready)(_(wrap)(Fay$$list([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)(Fay$$list([_$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)(Fay$$list([_$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"))))(_(_(flip)(after))(toc))))(_(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<ul></ul>"))))(_(_(flip)(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)(Fay$$list([heading]));});return _(_(Fay$$then)(_(_(_(attr)(h))(Fay$$list("id")))(anchor)))(_(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<li></li>"))))(_(_(flip)(appendTo))(ul))))(function($_a){var li = $_a;return _(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<a></a>"))))(_(_(flip)(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 = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",console.log(Fay$$serialize(UnknownType,$_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",_($_a)['tagName']));});};var wrap = function($_a){return new $(function(){return Fay$$unserialize("",window['jQuery'](Fay$$serialize(ListType,$_a)));});};var ready = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['ready'](Fay$$serialize(JsType,$_b))));});};};var each = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['each'](Fay$$serialize(UnknownType,$_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("",_($_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("",_($_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("",_($_a)['click'](Fay$$serialize(JsType,$_b))));});};};var fadeToggle = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['fadeToggle'](Fay$$serialize(JsType,$_b))));});};};var hide = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['hide']()));});};var addClass = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['addClass'](Fay$$serialize(StringType,$_b))));});};};var removeClass = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_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",_($_a)['text']()));});};var getIs = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("bool",_($_a)['is'](Fay$$serialize(StringType,$_b))));});};};var getSize = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['length']));});};var getNext = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['next']()));});};var getFirst = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['first']()));});};var getFind = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['find'](Fay$$serialize(StringType,$_b))));});};};var prepend = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['prepend'](Fay$$serialize(UnknownType,$_b))));});};};var after = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['after'](Fay$$serialize(UnknownType,$_b))));});};};var append = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['append'](Fay$$serialize(UnknownType,$_b))));});};};var appendTo = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['appendTo'](Fay$$serialize(UnknownType,$_b))));});};};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("",_($_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("",_($_a)['initHighlightingOnLoad']()));});};var setTabReplace = function($_a){return function($_b){return new $(function(){return new Fay$$Monad((_($_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)(Fay$$list([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)(Fay$$list([_$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)(Fay$$list([_$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"))))(_(_(flip)(after))(toc))))(_(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<ul></ul>"))))(_(_(flip)(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)(Fay$$list([heading]));});return _(_(Fay$$then)(_(_(_(attr)(h))(Fay$$list("id")))(anchor)))(_(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<li></li>"))))(_(_(flip)(appendTo))(ul))))(function($_a){var li = $_a;return _(_(Fay$$bind)(_(_(Fay$$bind)(_(makeElement)(Fay$$list("<a></a>"))))(_(_(flip)(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",_($_a)['tagName']));});};var wrap = function($_a){return new $(function(){return Fay$$unserialize("",window['jQuery'](Fay$$serialize(ListType,$_a)));});};var ready = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['ready'](Fay$$serialize(JsType,$_b))));});};};var each = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_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("",_($_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("",_($_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("",_($_a)['click'](Fay$$serialize(JsType,$_b))));});};};var fadeToggle = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['fadeToggle'](Fay$$serialize(JsType,$_b))));});};};var hide = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['hide']()));});};var addClass = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['addClass'](Fay$$serialize(StringType,$_b))));});};};var removeClass = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_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",_($_a)['text']()));});};var getIs = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("bool",_($_a)['is'](Fay$$serialize(StringType,$_b))));});};};var getSize = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['length']));});};var getNext = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['next']()));});};var getFirst = function($_a){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['first']()));});};var getFind = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['find'](Fay$$serialize(StringType,$_b))));});};};var prepend = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['prepend'](_($_b))));});};};var after = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['after'](_($_b))));});};};var append = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['append'](_($_b))));});};};var appendTo = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_a)['appendTo'](_($_b))));});};};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("",_($_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("",_($_a)['initHighlightingOnLoad']()));});};var setTabReplace = function($_a){return function($_b){return new $(function(){return new Fay$$Monad(Fay$$unserialize("",_($_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(_($_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;
docs/snippets/ffi.hs view
@@ -1,17 +1,17 @@ print :: Foreign a => a -> Fay ()-print = foreignFay "window.console.log" ""+print = ffi "window.console.log(%1)" "" alert :: Foreign a => a -> Fay ()-alert = foreignFay "window.alert" ""+alert = ffi "window.alert(%1)" "" getInnerHtml :: Element -> Fay String-getInnerHtml = foreignMethodFay "innerHTML" FayString+getInnerHtml = ffi "%1.innerHTML(%2)" FayString setInnerHtml :: Element -> String -> Fay ()-setInnerHtml = foreignSetProp "innerHTML"+setInnerHtml = ffi "%1.innerHTML=%2" thedocument :: Element-thedocument = foreignValue "window.document" FayNone+thedocument = ffi "window.document" FayNone jquery :: Element -> JQuery-jquery = foreignPure "window.jQuery" FayNone+jquery = ffi "window.jQuery(%1)" FayNone
examples/alert.hs view
@@ -10,4 +10,4 @@ -- | Alert using window.alert. alert :: Foreign a => a -> Fay ()-alert = foreignFay "window.alert" FayNone+alert = ffi "window.alert(%1)" FayNone
− examples/canvas.water.html
@@ -1,10 +0,0 @@-<!doctype html>-<html>- <head>- <title>Canvas demo -- water effect</title> - <script src="canvaswater.js"></script>- </head>- <body style="margin:0;padding:0">- <canvas width="230" height="230" id="can"></canvas>- </body>-</html>
examples/canvaswater.hs view
@@ -55,11 +55,11 @@ -- | Add an event listener to an element. addEventListener :: (Foreign a,Eventable a) => a -> String -> Fay () -> Bool -> Fay ()-addEventListener = foreignMethodFay "addEventListener" FayNone+addEventListener = ffi "%1['addEventListener'](%2,%3,%4)" FayNone -- | Get an element by its ID. getElementById :: String -> Fay Element-getElementById = foreignFay "document.getElementById" FayNone+getElementById = ffi "document['getElementById'](%1)" FayNone -------------------------------------------------------------------------------- -- Images@@ -70,11 +70,11 @@ -- | Make a new image. newImage :: Fay Image-newImage = foreignFay "new Image" FayNone+newImage = ffi "new Image()" FayNone -- | Make a new image. setSrc :: Image -> String -> Fay ()-setSrc = foreignSetProp "src"+setSrc = ffi "%1['src'] = %2" FayNone -------------------------------------------------------------------------------- -- Canvas@@ -85,11 +85,11 @@ -- | Get an element by its ID. getContext :: Element -> String -> Fay Context-getContext = foreignMethodFay "getContext" FayNone+getContext = ffi "%1['getContext'](%2)" FayNone -- | Draw an image onto a canvas rendering context. drawImage :: Context -> Image -> Double -> Double -> Fay ()-drawImage = foreignMethodFay "drawImage" FayNone+drawImage = ffi "%1['drawImage'](%2,%3,%4)" FayNone -- | Draw an image onto a canvas rendering context. --@@ -101,15 +101,15 @@ drawImageSpecific :: Context -> Image -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Fay ()-drawImageSpecific = foreignMethodFay "drawImage" FayNone+drawImageSpecific = ffi "%1['drawImage'](%2,%3,%4,%5,%6,%7,%8,%9,%10)" FayNone -- | Set the fill style. setFillStyle :: Context -> String -> Fay ()-setFillStyle = foreignSetProp "fillStyle"+setFillStyle = ffi "%1['fillStyle']=%2" FayNone -- | Set the fill style. setFillRect :: Context -> Double -> Double -> Double -> Double -> Fay ()-setFillRect = foreignMethodFay "fillRect" FayNone+setFillRect = ffi "%1['fillRect'](%2,%3,%4,%5)" FayNone -------------------------------------------------------------------------------- -- Ref@@ -120,35 +120,35 @@ -- | Make a new mutable reference. newRef :: Foreign a => a -> Fay (Ref a)-newRef = foreignFay "new Fay$$Ref" FayNone+newRef = ffi "new Fay$$Ref(%1)" FayNone -- | Replace the value in the mutable reference. writeRef :: Foreign a => Ref a -> a -> Fay ()-writeRef = foreignFay "Fay$$writeRef" FayNone+writeRef = ffi "Fay$$writeRef(%1,%2)" FayNone -- | Get the referred value from the mutable value. readRef :: Foreign a => Ref a -> Fay a-readRef = foreignFay "Fay$$readRef" FayNone+readRef = ffi "Fay$$readRef(%1)" FayNone -------------------------------------------------------------------------------- -- Misc -- | Alert using window.alert. alert :: Foreign a => a -> Fay ()-alert = foreignFay "window.alert" FayNone+alert = ffi "window['alert'](%1)" FayNone -- | Alert using window.alert. print :: Double -> Fay ()-print = foreignFay "console.log" FayNone+print = ffi "console['log'](%1)" FayNone -- | Alert using window.alert. log :: String -> Fay ()-log = foreignFay "console.log" FayNone+log = ffi "console['log'](%1)" FayNone -- | Alert using window.alert. sin :: Double -> Double-sin = foreignPure "Math.sin" FayNone+sin = ffi "window.Math['sin'](%1)" FayNone -- | Alert using window.alert. setInterval :: Fay () -> Double -> Fay ()-setInterval = foreignFay "window.setInterval" FayNone+setInterval = ffi "window['setInterval'](%1,%2)" FayNone
+ examples/canvaswater.html view
@@ -0,0 +1,10 @@+<!doctype html>+<html>+ <head>+ <title>Canvas demo -- water effect</title> + <script src="canvaswater.js"></script>+ </head>+ <body style="margin:0;padding:0">+ <canvas width="230" height="230" id="can"></canvas>+ </body>+</html>
examples/console.hs view
@@ -9,4 +9,4 @@ -- | Print using console.log. print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print = ffi "console.log(%1)" FayNone
examples/data.hs view
@@ -18,4 +18,4 @@ main = print (show (Foo 123 "abc" Bar)) print :: String -> Fay ()-print = foreignFay "console.log" FayNone+print = ffi "console.log(%1)" FayNone
examples/dom.hs view
@@ -14,17 +14,14 @@ result <- documentGetElements "body" print result -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone data Element instance Foreign Element documentGetElements :: String -> Fay [Element]-documentGetElements =- foreignFay "document.getElementsByTagName"- FayArray+documentGetElements = ffi "document.getElementsByTagName(%1)" FayArray addEventListener :: String -> Fay () -> Bool -> Fay ()-addEventListener =- foreignFay "window.addEventListener" FayNone+addEventListener = ffi "window['addEventListener'](%1,%2,%3)" FayNone
examples/ref.hs view
@@ -11,21 +11,22 @@ main :: Fay () main = do ref <- newRef "Hello, World!"- readRef ref >>= print+ x <- readRef ref writeRef ref "Hai!" readRef ref >>= print -print :: String -> Fay ()-print = foreignFay "console.log" ""- data Ref a+instance Show (Ref a) instance Foreign a => Foreign (Ref a) newRef :: Foreign a => a -> Fay (Ref a)-newRef = foreignFay "new Fay$$Ref" FayNone+newRef = ffi "new Fay$$Ref(%1)" FayNone writeRef :: Foreign a => Ref a -> a -> Fay ()-writeRef = foreignFay "Fay$$writeRef" FayNone+writeRef = ffi "Fay$$writeRef(%1,%2)" FayNone readRef :: Foreign a => Ref a -> Fay a-readRef = foreignFay "Fay$$readRef" FayNone+readRef = ffi "Fay$$readRef(%1)" FayNone++print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
fay.cabal view
@@ -1,5 +1,5 @@ name: fay-version: 0.3.1.1+version: 0.4.0.1 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,8 @@ . /Release Notes/ .- * Fix FFI detection.+ * Collapse all the FFI types by using the type signature instead using UHC+ approach. Check the docs and examples. . See full history at: <https://github.com/chrisdone/fay/commits> homepage: http://fay-lang.org/@@ -39,7 +40,7 @@ src/Language/Fay/Stdlib.hs extra-source-files: examples/ref.hs examples/alert.hs examples/console.hs examples/dom.hs examples/tailrecursive.hs examples/data.hs examples/canvaswater.hs- examples/canvas.water.html examples/haskell.png+ examples/canvaswater.html examples/haskell.png -- Test cases tests/10 tests/10.hs tests/11 tests/11.hs tests/12 tests/12.hs tests/13 tests/13.hs tests/14 tests/14.hs tests/15 tests/15.hs tests/16 tests/16.hs@@ -78,6 +79,8 @@ json, pretty-show, data-default,+ safe,+ language-javascript, -- Requirements for the executables which -- `cabal-dev ghci' needs.@@ -99,7 +102,9 @@ haskell-src-exts, json, process,- data-default+ data-default,+ safe,+ language-javascript executable fay-tests hs-source-dirs: src@@ -114,7 +119,9 @@ process, filepath, directory,- data-default+ data-default,+ safe,+ language-javascript executable fay-docs hs-source-dirs: src@@ -133,4 +140,6 @@ blaze-markup, bytestring, time,- data-default+ data-default,+ safe,+ language-javascript
hs/stdlib.hs view
@@ -13,7 +13,7 @@ | Nothing show :: (Foreign a,Show a) => a -> String-show = foreignPure "Fay$$encodeShow" FayString+show = ffi "Fay$$encodeShow(%1)" FayString -- There is only Double in JS. fromInteger x = x
src/Language/Fay.hs view
@@ -14,19 +14,23 @@ where -import Language.Fay.Print ()-import Language.Fay.Types+import Language.Fay.Print ()+import Language.Fay.Types -import Control.Applicative-import Control.Monad.Error-import Control.Monad.IO-import Control.Monad.State-import Data.List-import Data.Maybe-import Data.String-import Language.Haskell.Exts-import System.Process.Extra+import Control.Applicative+import Control.Monad.Error+import Control.Monad.IO+import Control.Monad.State+import Data.Char+import Data.List+import Data.Maybe+import Data.String+import Language.Haskell.Exts+import Safe +import qualified Language.JavaScript.Parser as JS+import System.Process.Extra+ -------------------------------------------------------------------------------- -- Top level entry points @@ -150,120 +154,81 @@ compilePatBind toplevel sig pat = do case pat of PatBind _ (PVar ident) Nothing (UnGuardedRhs rhs) (BDecls []) ->- case ffiExp rhs <|> ffiProp rhs of- Just detail@(binding,_,_) ->- case sig of- Nothing -> compileNormalPatBind toplevel ident rhs- Just sig -> case () of- () | func binding -> compileFFIFunc sig ident detail- | method binding -> compileFFIMethod sig ident detail- | setprop binding -> compileFFISetProp sig ident detail- | otherwise -> throwError (FfiNeedsTypeSig pat)+ case ffiExp rhs of+ Just (formatstr,typ) -> case sig of+ Just sig -> compileFFI ident formatstr typ sig+ Nothing -> throwError (FfiNeedsTypeSig pat) _ -> compileNormalPatBind toplevel ident rhs _ -> throwError (UnsupportedDeclaration pat) - where func = flip elem ["foreignFay","foreignPure","foreignValue"]- method = flip elem ["foreignMethodFay","foreignProp","foreignPropFay","foreignMethod"]- setprop = flip elem ["foreignSetProp"]-- ffiExp (App (App (Var (UnQual (Ident ident)))- (Lit (String name)))+ where ffiExp (App (App (Var (UnQual (Ident "ffi")))+ (Lit (String formatstr))) (Con (UnQual (Ident (reads -> [(typ,"")])))))- | func ident || method ident || setprop ident = Just (ident,name,typ)+ = Just (formatstr,typ) ffiExp _ = Nothing - ffiProp (App (Var (UnQual (Ident ident)))- (Lit (String name)))- | func ident || method ident || setprop ident = Just (ident,name,FayNone)- ffiProp _ = Nothing---- | Compile a normal simple pattern binding.-compileNormalPatBind :: Bool -> Name -> Exp -> Compile [JsStmt]-compileNormalPatBind toplevel ident rhs = do- body <- compileExp rhs- bind <- bindToplevel toplevel (UnQual ident) (thunk body)- return [bind]---- | Compile a foreign function.-compileFFIFunc :: Type -> Name -> (String,String,FayReturnType) -> Compile [JsStmt]-compileFFIFunc sig ident detail@(_,name,_) = do- let args = zipWith const uniqueNames [1..typeArity sig]- compileFFI sig ident detail (JsRawName name) args args---- | Compile a foreign method.-compileFFIMethod :: Type -> Name -> (String,String,FayReturnType) -> Compile [JsStmt]-compileFFIMethod sig ident detail@(_,name,_) = do- let args = zipWith const uniqueNames [1..typeArity sig]- jsargs = drop 1 args- obj = head args- compileFFI sig ident detail (JsGetPropExtern (force (JsName obj)) (fromString name)) args jsargs---- | Compile a foreign method.-compileFFISetProp :: Type -> Name -> (String,String,FayReturnType) -> Compile [JsStmt]-compileFFISetProp sig ident detail@(_,name,_) = do- let args = zipWith const uniqueNames [1..typeArity sig]- jsargs = drop 1 args- obj = head args- compileFFI sig- ident- detail- (JsUpdatePropExtern (force (JsName obj))- (fromString name)- (serialize (head (tail funcTypes))- (JsName (head jsargs))))- args- []- - where funcTypes = functionTypeArgs sig- -- | Compile an FFI call.-compileFFI :: Type- -> Name- -> (String,String,FayReturnType)- -> JsExp- -> [JsName]- -> [JsName]+compileFFI :: Name -- ^ Name of the to-be binding.+ -> String -- ^ The format string.+ -> FayReturnType -- ^ The return type.+ -> Type -- ^ Type signature. -> Compile [JsStmt]-compileFFI sig ident (binding,_,typ) exp params args = do- let innerexp- | length args == 0 && elem binding ["foreignProp","foreignPropFay","foreignValue"] = exp- | binding == "foreignSetProp" = exp- | otherwise = JsApp exp- (map (\(typ,name) -> serialize typ (JsName name))- (zip types args))- bind <- bindToplevel True- (UnQual ident)- (foldr (\name inner -> JsFun [name] [] (Just inner))- (thunk- (maybeMonad- (if binding == "foreignSetProp"- then innerexp- else unserialize typ innerexp)))- params)- return [bind]-- where (maybeMonad,types) | binding == "foreignFay" = (monad,funcTypes)- | binding == "foreignProp" = (id,drop 1 funcTypes)- | binding == "foreignMethodFay" = (monad,drop 1 funcTypes)- | binding == "foreignPropFay" = (monad,drop 1 funcTypes)- | binding == "foreignMethod" = (id,drop 1 funcTypes)- | binding == "foreignSetProp" = (monad,[])- | otherwise = (id,funcTypes)- funcTypes = functionTypeArgs sig+compileFFI name formatstr returnType sig = do+ inner <- formatFFI formatstr (zip params funcArgTypes)+ case JS.parse (printJS (wrapReturn inner)) (prettyPrint name) of+ Left err -> throwError (FfiFormatInvalidJavaScript inner err)+ Right{} -> fmap return (bindToplevel True (UnQual name) (body inner))+ + where body inner = foldr wrapParam (wrapReturn inner) params+ wrapParam name inner = JsFun [name] [] (Just inner)+ params = zipWith const uniqueNames [1..typeArity sig]+ wrapReturn inner = thunk $+ case lastMay funcArgTypes of+ -- Fay action:+ Just JsType -> monad (unserialize returnType (JsRawExp inner))+ -- Returns a “pure” value;+ Just{} -> unserialize returnType (JsRawExp inner)+ -- Base case:+ Nothing -> JsRawExp inner+ funcArgTypes = functionTypeArgs sig --- | These are the data types that are serializable directly to native--- JS data types. Strings, floating points and arrays. The others are:--- actiosn in the JS monad, which are thunks that shouldn't be forced--- when serialized but wrapped up as JS zero-arg functions, and--- unknown types can't be converted but should at least be forced.-data ArgType = FunctionType | JsType | StringType | DoubleType | ListType | BoolType | UnknownType- deriving (Show,Eq)+-- | Format the FFI format string with the given arguments.+formatFFI :: String -- ^ The format string.+ -> [(JsParam,ArgType)] -- ^ Arguments.+ -> Compile String -- ^ The JS code.+formatFFI formatstr args = go formatstr where+ go ('%':'*':xs) = do+ these <- mapM inject (zipWith const [1..] args)+ rest <- go xs+ return (intercalate "," these ++ rest)+ go ('%':'%':xs) = do+ rest <- go xs+ return ('%' : rest)+ go ['%'] = throwError FfiFormatIncompleteArg+ go ('%':(span isDigit -> (op,xs))) = do+ case readMay op of+ Nothing -> throwError (FfiFormatBadChars op)+ Just n -> do+ this <- inject n+ rest <- go xs+ return (this ++ rest)+ go (x:xs) = do rest <- go xs+ return (x : rest)+ go [] = return []+ + inject n =+ case listToMaybe (drop (n-1) args) of+ Nothing -> throwError (FfiFormatNoSuchArg n)+ Just (arg,typ) -> do+ return (printJS (serialize typ (JsName arg))) -- | Serialize a value to native JS, if possible. serialize :: ArgType -> JsExp -> JsExp serialize typ exp =- JsApp (JsName (hjIdent "serialize"))- [JsName (fromString (show typ)),exp]+ case typ of+ UnknownType -> force exp+ _ -> JsApp (JsName (hjIdent "serialize"))+ [JsName (fromString (show typ)),exp] -- | Get arg types of a function type. functionTypeArgs :: Type -> [ArgType]@@ -272,26 +237,36 @@ TyForall _ _ i -> functionTypeArgs i TyFun a b -> argType a : functionTypeArgs b TyParen st -> functionTypeArgs st- _ -> []+ r -> [argType r] - where argType t =- case t of- TyApp (TyCon "Fay") _ -> JsType- TyCon "String" -> StringType- TyCon "Double" -> DoubleType- TyCon "Bool" -> BoolType- TyFun{} -> FunctionType- TyList _ -> ListType- _ -> UnknownType+-- | Convert a Haskell type to an internal FFI representation.+argType :: Type -> ArgType+argType t =+ case t of+ TyApp (TyCon "Fay") _ -> JsType+ TyCon "String" -> StringType+ TyCon "Double" -> DoubleType+ TyCon "Bool" -> BoolType+ TyFun{} -> FunctionType+ TyList _ -> ListType+ TyParen st -> argType st+ _ -> UnknownType -- | Get the arity of a type.-typeArity :: Type -> Integer+typeArity :: Type -> Int typeArity t = case t of TyForall _ _ i -> typeArity i TyFun _ b -> 1 + typeArity b TyParen st -> typeArity st _ -> 0++-- | Compile a normal simple pattern binding.+compileNormalPatBind :: Bool -> Name -> Exp -> Compile [JsStmt]+compileNormalPatBind toplevel ident rhs = do+ body <- compileExp rhs+ bind <- bindToplevel toplevel (UnQual ident) (thunk body)+ return [bind] -- | Compile a data declaration. compileDataDecl :: Bool -> Decl -> [QualConDecl] -> Compile [JsStmt]
src/Language/Fay/FFI.hs view
@@ -37,66 +37,9 @@ instance (Foreign a,Foreign b) => Foreign (a -> b) -- | Declare a foreign action.-foreignFay- :: Foreign a- => String -- ^ The foreign function name.- -> FayReturnType -- ^ JS return type.- -> a -- ^ Bottom.-foreignFay = error "Language.Fay.FFI.foreignFay: Used foreign function not in a JS engine context."---- | Declare a foreign function.-foreignPure- :: Foreign a- => String -- ^ The foreign function name.- -> FayReturnType -- ^ JS return type.- -> a -- ^ Bottom.-foreignPure = error "Language.Fay.FFI.foreign: Used foreign function not in a JS engine context."---- | Declare a foreign function.-foreignValue- :: Foreign a- => String -- ^ The foreign function name.- -> FayReturnType -- ^ JS return type.- -> a -- ^ Bottom.-foreignValue = error "Language.Fay.FFI.foreignValue: Used foreign function not in a JS engine context."---- | Declare a foreign function.-foreignProp- :: Foreign a- => String -- ^ The foreign function name.- -> FayReturnType -- ^ JS return type.- -> a -- ^ Bottom.-foreignProp = error "Language.Fay.FFI.foreignProp: Used foreign function not in a JS engine context."---- | Declare a foreign function.-foreignPropFay- :: Foreign a- => String -- ^ The foreign function name.- -> FayReturnType -- ^ JS return type.- -> a -- ^ Bottom.-foreignPropFay = error "Language.Fay.FFI.foreignProp: Used foreign function not in a JS engine context."---- | Declare a foreign action.-foreignMethodFay- :: Foreign a- => String -- ^ The foreign function name.- -> FayReturnType -- ^ JS return type.- -> a -- ^ Bottom.-foreignMethodFay = error "Language.Fay.FFI.foreignMethodFay: Used foreign function not in a JS engine context."---- | Declare a foreign function.-foreignMethod+ffi :: Foreign a- => String -- ^ The foreign function name.- -> FayReturnType -- ^ JS return type.+ => String -- ^ The foreign value.+ -> FayReturnType -- ^ JS return type (if any). -> a -- ^ Bottom.-foreignMethod = error "Language.Fay.FFI.foreignMethod: Used foreign function not in a JS engine context."---- | Declare a foreign action.-foreignSetProp- :: (Foreign object,Foreign value)- => String -- ^ The property.- -> object -- ^ The object.- -> value -- ^ The value.- -> Fay () -- ^ Bottom.-foreignSetProp = error "Language.Fay.FFI.foreignSetProp: Used foreign function not in a JS engine context."+ffi = error "Language.Fay.FFI.foreignFay: Used foreign function not in a JS engine context."
src/Language/Fay/Print.hs view
@@ -103,7 +103,7 @@ -- | Print an expression. instance Printable JsExp where- printJS (JsRawName name) = name+ printJS (JsRawExp name) = name printJS (JsThrowExp exp) = "(function(){ throw (" ++ printJS exp ++ "); })()" printJS (JsFun params stmts ret) =
src/Language/Fay/Types.hs view
@@ -18,7 +18,8 @@ ,Fay ,CompileConfig(..) ,CompileState(..)- ,FayReturnType(..))+ ,FayReturnType(..)+ ,ArgType(..)) where import Control.Exception@@ -97,6 +98,10 @@ | InvalidDoBlock | RecursiveDoUnsupported | FfiNeedsTypeSig Decl+ | FfiFormatBadChars String+ | FfiFormatNoSuchArg Int+ | FfiFormatIncompleteArg+ | FfiFormatInvalidJavaScript String String deriving (Show,Eq,Data,Typeable) instance Error CompileError instance Exception CompileError@@ -123,7 +128,7 @@ -- | Expression type. data JsExp = JsName JsName- | JsRawName String+ | JsRawExp String | JsFun [JsParam] [JsStmt] (Maybe JsExp) | JsLit JsLit | JsApp JsExp [JsExp]@@ -155,3 +160,11 @@ data FayReturnType = FayArray | FayList | FayString | FayBool | FayNone deriving (Read,Show,Eq)++-- | These are the data types that are serializable directly to native+-- JS data types. Strings, floating points and arrays. The others are:+-- actiosn in the JS monad, which are thunks that shouldn't be forced+-- when serialized but wrapped up as JS zero-arg functions, and+-- unknown types can't be converted but should at least be forced.+data ArgType = FunctionType | JsType | StringType | DoubleType | ListType | BoolType | UnknownType+ deriving (Show,Eq)
tests/10.hs view
@@ -8,5 +8,5 @@ append (x:xs) ys = x : append xs ys append [] ys = ys -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/11 view
@@ -1,1 +1,1 @@-[ 1, 2, 3, 4, 5 ]+[1,2,3,4,5]
tests/11.hs view
@@ -1,4 +1,4 @@-main = print (take 5 (let ns = 1 : map (\x -> x + 1) ns in ns))+main = print (show (take 5 (let ns = 1 : map (\x -> x + 1) ns in ns))) take 0 _ = [] take n (x:xs) = x : take (n - 1) xs@@ -6,5 +6,5 @@ map f [] = [] map f (x:xs) = f x : map f xs -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/12.hs view
@@ -1,8 +1,5 @@ main = print (show (take 5 (let ns = 1 : map (foo 123) ns in ns))) -show :: Foreign a => a -> String-show = foreignPure "JSON.stringify" FayString- foo x y = x * y / 2 take 0 _ = []@@ -11,5 +8,8 @@ map f [] = [] map f (x:xs) = f x : map f xs -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone++show :: String -> String+show = ffi "JSON.stringify(%1)" FayString
tests/13.hs view
@@ -2,5 +2,5 @@ True -> "Hello!" False -> "Ney!") -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/14.hs view
@@ -2,5 +2,5 @@ True -> "Hello!" False -> "Ney!") -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/15.hs view
@@ -2,5 +2,5 @@ True -> "Hello!" _ -> "Ney!") -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/16.hs view
@@ -3,5 +3,5 @@ main = print (case Person "Chris" "Done" 13 of Person "Chris" "Done" 13 -> "Hello!") -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/17.hs view
@@ -4,5 +4,5 @@ Person "Chris" "Done" 13 -> "Hello!" _ -> "World!") -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/18.hs view
@@ -6,5 +6,5 @@ Person "Chris" "Done" 14 -> "Hello!" _ -> "World!") -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/19.hs view
@@ -7,5 +7,5 @@ foo (Person "Chris" "Done" 14) = "Hello!" foo _ = "World!" -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/20.hs view
@@ -1,4 +1,4 @@ main = print "Hello," >> print "World!" -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/21.hs view
@@ -1,4 +1,4 @@ main = do print "Hello,"; print "World!" -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/22.hs view
@@ -2,5 +2,5 @@ x <- return "Hello, World!" >>= return print x -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/23.hs view
@@ -2,5 +2,5 @@ [1,2] <- return [1,2] print "OK." -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/24.hs view
@@ -4,5 +4,5 @@ [1,2,3,4,5] -> "OK." _ -> "Broken.") -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/25.hs view
@@ -1,4 +1,4 @@ main = print ((\a 'a' -> "OK.") 0 'b') -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/26.hs view
@@ -1,4 +1,4 @@ main = print (5 * 3 / 2) -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: Double -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/27.hs view
@@ -16,5 +16,5 @@ getSeconds :: Fay Double getSeconds = foreignFay "new Date" FayNone -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: Double -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/28.hs view
@@ -4,8 +4,8 @@ import Language.Fay.Prelude import Language.Fay.FFI -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone main :: Fay () main = print $ show $ fromInteger 5
tests/3.hs view
@@ -1,4 +1,4 @@ main = print 1 -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: Double -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/4.hs view
@@ -1,4 +1,4 @@ main = print "Hello, World!" -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: String -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/5.hs view
@@ -1,4 +1,4 @@ main = print (2 * 4 / 2) -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: Double -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/6.hs view
@@ -1,4 +1,4 @@ main = print (10 + (2 * (4 / 2))) -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: Double -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/7.hs view
@@ -1,4 +1,4 @@ main = print True -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: Double -> Fay ()+print = ffi "console.log(%1)" FayNone
tests/8.hs view
@@ -2,8 +2,8 @@ main = print (head (fix (\xs -> 123 : xs))) -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: Double -> Fay ()+print = ffi "console.log(%1)" FayNone head (x:xs) = x
tests/9.hs view
@@ -1,7 +1,7 @@ main = print (head (tail (fix (\xs -> 123 : xs)))) -print :: Foreign a => a -> Fay ()-print = foreignFay "console.log" FayNone+print :: Double -> Fay ()+print = ffi "console.log(%1)" FayNone head (x:xs) = x