packages feed

forml-0.1.1: src/hs/Forml/Javascript/Utils.hs

{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverlappingInstances #-}

{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecordWildCards #-}

module Forml.Javascript.Utils where


import Text.InterpolatedString.Perl6
import Language.Javascript.JMacro
import Data.Monoid
import Data.String.Utils

import Prelude hiding (curry, (++), error)


prelude :: String
prelude = show $ renderJs 
          [jmacro| function !is_array(x) { 
                       return `(InfixExpr "instanceof" x (ref "Array"))`;
                   }

                   var !__undefined__ = "undefined";

                   function !run(x) { return x(); }

                   function !error(x) { throw x; }

                   function !exhaust() { error("Pattern Match Exhausted"); }

                   function !__check(x, y) {
                       return x.hasOwnProperty(y);
                   } |]

instance (ToStat a) => ToStat [a] where
    toStat [] = mempty
    toStat x = foldl1 mappend . map toStat $ x

--------------------------------------------------------------------------------
----
---- Metadata


--------------------------------------------------------------------------------
----
---- Utilities

(++) :: Monoid a => a -> a -> a
(++) = mappend

end :: forall a. [a] -> [a]
end (reverse -> x : xs) = x : reverse xs
end _ = fail "End is not defined for empty lists"

ref :: String -> JExpr
ref name    = ValExpr (JVar (StrI name))

func :: String -> JStat -> JStat
func var ex = ReturnStat (ValExpr (JFunc [StrI var] (BlockStat [ex])))

declare_this :: forall a. ToJExpr a => [Char] -> a -> JStat
declare_this name expr =

    [jmacro| `(declare (replace " " "_" name) expr)`;
             this[`(replace " " "_" name)`] = `(ref (replace " " "_" name))`; |]

declare_window :: forall a. ToJExpr a => [Char] -> a -> JStat
declare_window name expr =

    [jmacro| `(declare (replace " " "_" name) expr)`;
             (typeof global == "undefined" ? window : global)[`((replace " " "_" name))`] = `(ref (replace " " "_" name))`; |]
declare :: forall a. ToJExpr a => [Char] -> a -> JStat

declare name expr = 
     [jmacro| `(DeclStat (StrI (replace " " "_" name)) Nothing)`;
              `(ref (replace " " "_" name))` = `(expr)`; |]
             
declare_scope :: String -> JExpr -> JStat -> JStat
declare_scope name expr stat =

    BlockStat [ReturnStat (ApplExpr (ValExpr (JFunc [StrI name] stat)) [expr])]

curry :: Int -> (String -> String) -> JStat -> JStat
curry 0 _ jexpr = jexpr
curry n f jexpr = func (f $ local_pool $ n - 1) (curry (n - 1) f jexpr)

local_pool :: Int -> String
local_pool n = [qq|__{ "abcdefghijklmnopqrstuvqxyz" !! n }__|]

scope :: forall a. ToStat a => a -> JExpr
scope x = [jmacroE| (function() { `(x)`; })() |]