@@ -13,17 +13,16 @@
14-----------------------------------------------------------------------------
14-----------------------------------------------------------------------------
16−{-# LANGUAGE DoAndIfThenElse #-}
16+{-# LANGUAGE GADTs, DoAndIfThenElse #-}
18module Language.PureScript.CodeGen.JS (
18module Language.PureScript.CodeGen.JS (
19 module AST,
19 module AST,
22 moduleToJs,
21 moduleToJs,
23 identNeedsEscaping
22 identNeedsEscaping
26−import Data.Maybe (catMaybes, fromJust)
25+import Data.Maybe (catMaybes)
27import Data.Function (on)
26import Data.Function (on)
28import Data.List (nub, (\\), delete, sortBy)
27import Data.List (nub, (\\), delete, sortBy)
@@ -42,40 +41,36 @@ import Language.PureScript.Supply
42import Language.PureScript.Traversals (sndM)
41import Language.PureScript.Traversals (sndM)
43import qualified Language.PureScript.Constants as C
42import qualified Language.PureScript.Constants as C
46−-- Different types of modules which are supported
48−data ModuleType = CommonJS | Globals
51-- Generate code in the simplified Javascript intermediate representation for all declarations in a
45-- Generate code in the simplified Javascript intermediate representation for all declarations in a
54−moduleToJs :: (Functor m, Applicative m, Monad m) => ModuleType -> Options -> Module -> Environment -> SupplyT m [JS]
48+moduleToJs :: (Functor m, Applicative m, Monad m) => Options mode -> Module -> Environment -> SupplyT m [JS]
55−moduleToJs mt opts (Module name decls (Just exps)) env = do
49+moduleToJs opts (Module name decls (Just exps)) env = do
56− let jsImports = map (importToJs mt opts) . delete (ModuleName [ProperName C.prim]) . (\\ [name]) . nub $ concatMap imports decls
50+ let jsImports = map (importToJs opts) . delete (ModuleName [ProperName C.prim]) . (\\ [name]) . nub $ concatMap imports decls
57 jsDecls <- mapM (\decl -> declToJs opts name decl env) decls
51 jsDecls <- mapM (\decl -> declToJs opts name decl env) decls
58 let optimized = concat $ map (map $ optimize opts) $ catMaybes jsDecls
52 let optimized = concat $ map (map $ optimize opts) $ catMaybes jsDecls
59 let isModuleEmpty = null exps
53 let isModuleEmpty = null exps
60 let moduleBody = JSStringLiteral "use strict" : jsImports ++ optimized
54 let moduleBody = JSStringLiteral "use strict" : jsImports ++ optimized
61 let moduleExports = JSObjectLiteral $ concatMap exportToJs exps
55 let moduleExports = JSObjectLiteral $ concatMap exportToJs exps
62− return $ case mt of
56+ return $ case optionsAdditional opts of
63− CommonJS -> moduleBody ++ [JSAssignment (JSAccessor "exports" (JSVar "module")) moduleExports]
57+ MakeOptions -> moduleBody ++ [JSAssignment (JSAccessor "exports" (JSVar "module")) moduleExports]
64− Globals | not isModuleEmpty ->
58+ CompileOptions ns _ _ | not isModuleEmpty ->
65− [ JSVariableIntroduction (fromJust (optionsBrowserNamespace opts))
59+ [ JSVariableIntroduction ns
66− (Just (JSBinary Or (JSVar (fromJust (optionsBrowserNamespace opts))) (JSObjectLiteral [])) )
60+ (Just (JSBinary Or (JSVar ns) (JSObjectLiteral [])) )
67− , JSAssignment (JSAccessor (moduleNameToJs name) (JSVar (fromJust (optionsBrowserNamespace opts))))
61+ , JSAssignment (JSAccessor (moduleNameToJs name) (JSVar ns))
68 (JSApp (JSFunction Nothing [] (JSBlock (moduleBody ++ [JSReturn moduleExports]))) [])
62 (JSApp (JSFunction Nothing [] (JSBlock (moduleBody ++ [JSReturn moduleExports]))) [])
71−moduleToJs _ _ _ _ = error "Exports should have been elaborated in name desugaring"
65+moduleToJs _ _ _ = error "Exports should have been elaborated in name desugaring"
73−importToJs :: ModuleType -> Options -> ModuleName -> JS
67+importToJs :: Options mode -> ModuleName -> JS
74−importToJs mt opts mn = JSVariableIntroduction (moduleNameToJs mn) (Just moduleBody)
69+ JSVariableIntroduction (moduleNameToJs mn) (Just moduleBody)
76− moduleBody = case mt of
71+ moduleBody = case optionsAdditional opts of
77− CommonJS -> JSApp (JSVar "require") [JSStringLiteral (runModuleName mn)]
72+ MakeOptions -> JSApp (JSVar "require") [JSStringLiteral (runModuleName mn)]
78− Globals -> JSAccessor (moduleNameToJs mn) (JSVar (fromJust (optionsBrowserNamespace opts)))
73+ CompileOptions ns _ _ -> JSAccessor (moduleNameToJs mn) (JSVar ns)
80imports :: Declaration -> [ModuleName]
75imports :: Declaration -> [ModuleName]
81imports (ImportDeclaration mn _ _) = [mn]
76imports (ImportDeclaration mn _ _) = [mn]
@@ -95,7 +90,7 @@ imports other =
96-- Generate code in the simplified Javascript intermediate representation for a declaration
91-- Generate code in the simplified Javascript intermediate representation for a declaration
98−declToJs :: (Functor m, Applicative m, Monad m) => Options -> ModuleName -> Declaration -> Environment -> SupplyT m (Maybe [JS])
93+declToJs :: (Functor m, Applicative m, Monad m) => Options mode -> ModuleName -> Declaration -> Environment -> SupplyT m (Maybe [JS])
99declToJs opts mp (ValueDeclaration ident _ _ _ val) e = do
94declToJs opts mp (ValueDeclaration ident _ _ _ val) e = do
100 js <- valueToJs opts mp e val
95 js <- valueToJs opts mp e val
101 return $ Just [JSVariableIntroduction (identToJs ident) (Just js)]
96 return $ Just [JSVariableIntroduction (identToJs ident) (Just js)]
@@ -190,7 +185,7 @@ accessorString prop | identNeedsEscaping prop = JSIndexer (JSStringLiteral prop)
191-- Generate code in the simplified Javascript intermediate representation for a value or expression.
186-- Generate code in the simplified Javascript intermediate representation for a value or expression.
193−valueToJs :: (Functor m, Applicative m, Monad m) => Options -> ModuleName -> Environment -> Expr -> SupplyT m JS
188+valueToJs :: (Functor m, Applicative m, Monad m) => Options mode -> ModuleName -> Environment -> Expr -> SupplyT m JS
194valueToJs _ _ _ (NumericLiteral n) = return $ JSNumericLiteral n
189valueToJs _ _ _ (NumericLiteral n) = return $ JSNumericLiteral n
195valueToJs _ _ _ (StringLiteral s) = return $ JSStringLiteral s
190valueToJs _ _ _ (StringLiteral s) = return $ JSStringLiteral s
196valueToJs _ _ _ (BooleanLiteral b) = return $ JSBooleanLiteral b
191valueToJs _ _ _ (BooleanLiteral b) = return $ JSBooleanLiteral b
@@ -315,7 +310,7 @@ qualifiedToJS _ f (Qualified _ a) = JSVar $ identToJs (f a)
315-- Generate code in the simplified Javascript intermediate representation for pattern match binders
310-- Generate code in the simplified Javascript intermediate representation for pattern match binders
316-- and guards.
311-- and guards.
318−bindersToJs :: (Functor m, Applicative m, Monad m) => Options -> ModuleName -> Environment -> [CaseAlternative] -> [JS] -> SupplyT m JS
313+bindersToJs :: (Functor m, Applicative m, Monad m) => Options mode -> ModuleName -> Environment -> [CaseAlternative] -> [JS] -> SupplyT m JS
319bindersToJs opts m e binders vals = do
314bindersToJs opts m e binders vals = do
320 valNames <- replicateM (length vals) freshName
315 valNames <- replicateM (length vals) freshName
321 let assignments = zipWith JSVariableIntroduction valNames (map Just vals)
316 let assignments = zipWith JSVariableIntroduction valNames (map Just vals)
@@ -405,7 +400,7 @@ binderToJs m e varName done binder@(ConsBinder _ _) = do
405 ( JSVariableIntroduction tailVar (Just (JSApp (JSAccessor "slice" (JSVar varName)) [JSNumericLiteral (Left numberOfHeadBinders)])) :
400 ( JSVariableIntroduction tailVar (Just (JSApp (JSAccessor "slice" (JSVar varName)) [JSNumericLiteral (Left numberOfHeadBinders)])) :
407 )) Nothing]
402 )) Nothing]
409 uncons :: [Binder] -> Binder -> ([Binder], Binder)
404 uncons :: [Binder] -> Binder -> ([Binder], Binder)
410 uncons acc (ConsBinder h t) = uncons (h : acc) t
405 uncons acc (ConsBinder h t) = uncons (h : acc) t
411 uncons acc (PositionedBinder _ b) = uncons acc b
406 uncons acc (PositionedBinder _ b) = uncons acc b
@@ -416,3 +411,4 @@ binderToJs m e varName done (NamedBinder ident binder) = do
416binderToJs m e varName done (PositionedBinder _ binder) =
411binderToJs m e varName done (PositionedBinder _ binder) =
417 binderToJs m e varName done binder
412 binderToJs m e varName done binder