-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | QuasiQuotation library for programmatic generation of Javascript code. -- -- Javascript syntax, functional syntax, hygienic names, compile-time -- guarantees of syntactic correctness, limited typechecking. @package jmacro @version 0.3.2 module Language.Javascript.JMacro.Util (.) :: JExpr -> String -> JExpr (<>) :: (ToJExpr a) => JExpr -> a -> JExpr (=:) :: (ToJExpr a) => JExpr -> a -> JStat ($) :: (ToJExpr a, ToJExpr b) => a -> b -> JExpr ($$) :: (ToJExpr a, ToJExpr b) => a -> b -> JStat (!=) :: JExpr -> JExpr -> JExpr (<) :: JExpr -> JExpr -> JExpr (&&) :: JExpr -> JExpr -> JExpr (==) :: JExpr -> JExpr -> JExpr null :: JExpr new :: (ToJExpr a) => a -> JExpr if' :: (ToJExpr a, ToStat b) => a -> b -> JStat ifElse :: (ToJExpr a, ToStat b, ToStat c) => a -> b -> c -> JStat while :: (ToJExpr a) => a -> JStat -> JStat return :: (ToJExpr a) => a -> JStat toJExprList :: (ToJExpr a) => a -> [JExpr] jstr :: String -> JExpr module Language.Javascript.JMacro.Prelude -- | This provides a set of basic functional programming primitives, a few -- utility functions and, more importantly, a decent sample of idiomatic -- jmacro code. View the source for details. jmPrelude :: JStat module Language.Javascript.JMacro.Typed runTypecheck :: (JTypeCheck a) => a -> IO () data JType JTNum :: JType JTStr :: JType JTBool :: JType JTRec :: Int -> JType JTFunc :: [JType] -> JType -> JType JTList :: (Maybe Int) -> (Maybe JType) -> JType JTStat :: JType JTSat :: Int -> JType BotOf :: JType -> JType JTVar :: Int -> JType data JConstr Sub :: JType -> JConstr Super :: JType -> JConstr data TCState TCS :: [Map Ident JType] -> Map Int JType -> Map Int [JConstr] -> Map Int [(Ident, JType)] -> [Set Int] -> Int -> Bool -> Bool -> Bool -> Bool -> TCState tc_env :: TCState -> [Map Ident JType] tc_vars :: TCState -> Map Int JType tc_constrs :: TCState -> Map Int [JConstr] tc_recs :: TCState -> Map Int [(Ident, JType)] tc_scopedSat :: TCState -> [Set Int] tc_varCt :: TCState -> Int tc_strictnull :: TCState -> Bool tc_canextend :: TCState -> Bool tc_debug :: TCState -> Bool tc_expandFree :: TCState -> Bool tcStateEmpty :: TCState type JMonad a = ErrorT String (State TCState) a orElse :: JMonad a -> JMonad a -> JMonad a lookupEnvErr :: Ident -> JMonad JType withLocalScope :: [Ident] -> JMonad a -> JMonad a withLocalScope' :: [Ident] -> JMonad a -> JMonad a inConditional :: JMonad a -> JMonad a addEnv :: Ident -> JType -> JMonad () addTopEnv :: Ident -> JType -> JMonad () newV :: JMonad Int newVar :: JMonad JType newSat :: JMonad JType addNewSat :: Ident -> JMonad () addNewVar :: Ident -> JMonad () newTopSat :: JMonad JType killSats :: JMonad () newSatAtScope :: [Int] -> JMonad JType satInScope :: Int -> JMonad Bool incScope :: Int -> Int -> JMonad () bumpScope :: Int -> JType -> JMonad () getRec :: Int -> JMonad [(Ident, JType)] putRec :: Int -> [(Ident, JType)] -> JMonad () recLookup :: Ident -> JType -> JMonad (Maybe JType) newRec :: JMonad JType unzipConstrs :: [JConstr] -> ([JType], [JType]) zipConstrs :: [JType] -> [JType] -> [JConstr] lookupConstraints :: Int -> JMonad [JConstr] addConstraint :: Int -> JConstr -> JMonad () chkNoNull :: [JType] -> JMonad () showType :: JType -> JMonad String prettyType :: JType -> JMonad String prettyType' :: JType -> JMonad String resolveType :: JType -> JMonad JType resolveState :: JMonad () ifDbg :: JMonad () -> JMonad () traceSats :: JMonad () traceVars :: JMonad () traceConstrs :: JMonad () tyErr1 :: String -> JType -> JMonad a tyErr2 :: String -> JType -> JType -> JMonad a tyErr2l :: String -> [JType] -> [JType] -> JMonad a traceTy :: String -> JType -> JMonad () traceTys :: String -> JType -> JType -> JMonad () (<:) :: JType -> JType -> JMonad () subtype :: JType -> JType -> JMonad () occursCheck :: Int -> JType -> JMonad () (<=.=) :: JType -> JType -> JMonad () (=.=) :: JType -> JType -> JMonad () type JMonadClone a = StateT [(Int, JType)] (ErrorT String (State TCState)) a addSub :: (Int, JType) -> JMonadClone () findSub :: Int -> JMonadClone (Maybe JType) traceSubs :: JMonadClone () traceC :: JConstr -> JMonadClone () clone :: JType -> JMonad JType cloneMany :: [JType] -> JMonad [JType] clone'' :: JType -> JMonadClone JType clone' :: JType -> JMonadClone JType substitute :: JType -> JMonadClone JType resC :: Bool -> JType -> JMonad JType resC' :: Bool -> Bool -> JType -> JMonadClone JType simplifyCs :: [JConstr] -> JMonadClone [JConstr] simplifyC :: JConstr -> JMonadClone [JConstr] (\/) :: JType -> JType -> JMonad JType lub :: JType -> JType -> JMonad JType luball :: [JType] -> JMonad JType (/\) :: JType -> JType -> JMonad JType glb :: JType -> JType -> JMonad JType glball :: [JType] -> JMonad JType class JTypeCheck a typecheck :: (JTypeCheck a) => a -> JMonad JType typecheckLhs :: JExpr -> JMonad JType appFun :: JType -> [JType] -> JMonad JType typecheckAnnotated :: (JMacro a, JsToDoc a, JTypeCheck a) => a -> JMonad JType instance Show TCState instance Show JConstr instance Show JType instance Eq JType instance JTypeCheck [JStat] instance JTypeCheck JVal instance JTypeCheck JExpr instance JTypeCheck JStat -- | Allows for the creation of rpc server/client pairs from monomorphic -- functions. The server portion is a function from a json-encoded list -- of parameters to a json response. A list of server functions are -- expected to be wrapped by a dispatch function in the server framework -- of your choice. -- -- The client portion generated from a function of arity n is a function -- from a string identifying a server or a subdirectory on a server to an -- arity n function from javascript expressions (of type JExpr) to -- a single javascript expression. This expression, when evaluated on the -- client side, will call back to the provided server with -- json-serialized arguments and yield the result (deserialized from -- json). This client function is expected to be embedded via -- antiquotation into a larger block of jmacro code. -- -- Client portions must unfortunately be given explicit type signatures. -- -- The following example is a server/client pair providing an ajax call -- to add integers. -- --
--   testRPCCall :: String -> JExpr -> JExpr -> JExpr
--   (testRPC, testRPCCall) = mkWebRPC "test" $ \x y -> asIO $ return (x + (y::Int))
--   
module Language.Javascript.JMacro.Rpc -- | Produce a pair of (ServerFunction, ClientFunction) from a function in -- IO mkWebRPC :: (ToWebRPC_ a, CallWebRPC_ a b) => String -> a -> (WebRPCDesc, String -> b) -- | id with a helpful type. asIO :: IO a -> IO a -- | A String containing a json representation of function arguments -- encoded as a list of parameters. Generally would be passed as part of -- an HTTP request. type Request = String -- | Either a success or failure (with code). Generally would be turned -- back into a propre HTTP response. data Response GoodResponse :: String -> Response BadResponse :: Int -> String -> Response instance (CallWebRPC_ b c, ToJExpr d) => CallWebRPC_ (a -> b) (d -> c) instance CallWebRPC_ (IO b) JExpr instance (JSON a, ToWebRPC_ b) => ToWebRPC_ (a -> b) instance (JSON b) => ToWebRPC_ (IO b) -- | Simple DSL for lightweight (untyped) programmatic generation of -- Javascript. -- -- A number of examples are available in the source of -- Language.Javascript.JMacro.Prelude. -- -- Functions to generate generic RPC wrappers (using json serialization) -- are available in Language.Javascript.JMacro.Rpc. -- -- usage: -- --
--   renderJs [$jmacro|fun id x -> x|]
--   
-- -- The above produces the id function at the top level. -- --
--   renderJs [$jmacro|var id = \x -> x|]
--   
-- -- So does the above here. However, as id is brought into scope by the -- keyword var, you do not get a variable named id in the generated -- javascript, but a variable with an arbitrary unique identifier. -- --
--   renderJs [$jmacro|var !id = \x -> x|]
--   
-- -- The above, by using the bang special form in a var declaration, -- produces a variable that really is named id. -- --
--   renderJs [$jmacro|function id(x) {return x;}|]
--   
-- -- The above is also id. -- --
--   renderJs [$jmacro|function !id(x) {return x;}|]
--   
-- -- As is the above (with the correct name). -- --
--   renderJs [$jmacro|fun id x {return x;}|]
--   
-- -- As is the above. -- --
--   renderJs [$jmacroE|foo(x,y)|]
--   
-- -- The above is an expression representing the application of foo to x -- and y. -- --
--   renderJs [$jmacroE|foo x y|]]
--   
-- -- As is the above. -- --
--   renderJs [$jmacroE|foo (x,y)|]]
--   
-- -- While the above is an error. (i.e. standard javascript function -- application cannot seperate the leading parenthesis of the argument -- from the function being applied) -- --
--   \x -> [$jmacroE|foo `(x)`|]]
--   
-- -- The above is a haskell expression that provides a function that takes -- an x, and yields an expression representing the application of foo to -- the value of x as transformed to a Javascript expression. -- --
--   [$jmacroE|\x ->`(foo x)`|]]
--   
-- -- Meanwhile, the above lambda is in Javascript, and brings the variable -- into scope both in javascript and in the enclosed antiquotes. The -- expression is a Javascript function that takes an x, and yields an -- expression produced by the application of the Haskell function foo as -- applied to the identifier x (which is of type JExpr -- i.e. a -- Javascript expression). -- -- Other than that, the language is essentially Javascript (1.5). Note -- however that one must use semicolons in a principled fashion -- i.e. -- to end statements consistently. Otherwise, the parser will mistake the -- whitespace for a whitespace application, and odd things will occur. A -- further gotcha exists in regex literals, whicch cannot begin with a -- space. x 5 4 parses as ((x 5) 4). However, -- x 5 4 will parse as x(5 , 4). Such are the -- perils of operators used as delimeters in the presence of whitespace -- application. -- -- Additional datatypes can be marshalled to Javascript by proper -- instance declarations for the ToJExpr class. -- -- An experimental typechecker is available in the -- Language.Javascript.JMacro.Typed module. module Language.Javascript.JMacro -- | QuasiQuoter for a block of JMacro statements. jmacro :: QuasiQuoter -- | QuasiQuoter for a JMacro expression. jmacroE :: QuasiQuoter parseJM :: String -> Either ParseError JStat -- | Statements data JStat DeclStat :: Ident -> JStat ReturnStat :: JExpr -> JStat IfStat :: JExpr -> JStat -> JStat -> JStat WhileStat :: JExpr -> JStat -> JStat ForInStat :: Bool -> Ident -> JExpr -> JStat -> JStat SwitchStat :: JExpr -> [(JExpr, JStat)] -> JStat -> JStat TryStat :: JStat -> Ident -> JStat -> JStat -> JStat BlockStat :: [JStat] -> JStat ApplStat :: JExpr -> [JExpr] -> JStat PostStat :: String -> JExpr -> JStat AssignStat :: JExpr -> JExpr -> JStat UnsatBlock :: (State [Ident] JStat) -> JStat AntiStat :: String -> JStat BreakStat :: JStat -- | Expressions data JExpr ValExpr :: JVal -> JExpr SelExpr :: JExpr -> Ident -> JExpr IdxExpr :: JExpr -> JExpr -> JExpr InfixExpr :: String -> JExpr -> JExpr -> JExpr PostExpr :: String -> JExpr -> JExpr IfExpr :: JExpr -> JExpr -> JExpr -> JExpr NewExpr :: JExpr -> JExpr ApplExpr :: JExpr -> [JExpr] -> JExpr UnsatExpr :: (State [Ident] JExpr) -> JExpr AntiExpr :: String -> JExpr -- | Values data JVal JVar :: Ident -> JVal JList :: [JExpr] -> JVal JDouble :: Double -> JVal JInt :: Integer -> JVal JStr :: String -> JVal JRegEx :: String -> JVal JHash :: (Map String JExpr) -> JVal JFunc :: [Ident] -> JStat -> JVal UnsatVal :: (State [Ident] JVal) -> JVal -- | Identifiers newtype Ident StrI :: String -> Ident -- | Utility class to coerce the ADT into a regular structure. class JMacro a toMC :: (JMacro a) => a -> MultiComp fromMC :: (JMacro a) => MultiComp -> a -- | Union type to allow regular traversal by compos. data MultiComp MStat :: JStat -> MultiComp MExpr :: JExpr -> MultiComp MVal :: JVal -> MultiComp MIdent :: Ident -> MultiComp -- | Compos and ops for generic traversal as defined over the JMacro ADT. class Compos t compos :: (Compos t) => (forall a. a -> m a) -> (forall a b. m (a -> b) -> m a -> m b) -> (t -> m t) -> t -> m t composOp :: (Compos t) => (t -> t) -> t -> t composOpM :: (Compos t, Monad m) => (t -> m t) -> t -> m t composOpM_ :: (Compos t, Monad m) => (t -> m ()) -> t -> m () composOpFold :: (Compos t) => b -> (b -> b -> b) -> (t -> b) -> t -> b -- | Apply a transformation to a fully saturated syntax tree, taking care -- to return any free variables back to their free state following the -- transformation. As the transformation preserves free variables, it is -- hygienic. Cannot be used nested. withHygiene :: (JMacro a) => (a -> a) -> a -> a -- | Takes a fully saturated expression and transforms it to use unique -- variables that respect scope. scopify :: JStat -> JStat -- | Render a syntax tree as a pretty-printable document (simply showing -- the resultant doc produces a nice, well formatted String). renderJs :: (JsToDoc a, JMacro a) => a -> Doc class JsToDoc a jsToDoc :: (JsToDoc a) => a -> Doc -- | Things that can be marshalled into javascript values. Instantiate for -- any necessary data structures. class ToJExpr a toJExpr :: (ToJExpr a) => a -> JExpr toJExprFromList :: (ToJExpr a) => [a] -> JExpr jsv :: String -> JExpr -- | Create a new anonymous function. The result is an expression. Usage: -- jLam $ x y -> {JExpr involving x and y} jLam :: (ToSat a) => a -> JExpr -- | Introduce a new variable into scope for the duration of the enclosed -- expression. The result is a block statement. Usage: jVar $ x y -- -> {JExpr involving x and y} jVar :: (ToSat a) => a -> JStat jFor :: (ToJExpr a, ToStat b) => JStat -> a -> JStat -> b -> JStat -- | Create a for in statement. Usage: jForIn {expression} $ x -> -- {block involving x} jForIn :: (ToSat a) => JExpr -> (JExpr -> a) -> JStat -- | As with jForIn but creating a "for each in" statement. jForEachIn :: (ToSat a) => JExpr -> (JExpr -> a) -> JStat jTryCatchFinally :: (ToSat a) => JStat -> a -> JStat -> JStat expr2stat :: JExpr -> JStat class ToStat a toStat :: (ToStat a) => a -> JStat nullStat :: JStat jhEmpty :: Map String JExpr jhSingle :: (ToJExpr a) => String -> a -> Map String JExpr jhAdd :: (ToJExpr a) => String -> a -> Map String JExpr -> Map String JExpr jhFromList :: [(String, JExpr)] -> JVal -- | Given an optional prefix, fills in all free variable names with a -- supply of names generated by the prefix. jsSaturate :: (JMacro a) => Maybe String -> a -> a