@@ -13,7 +13,10 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−{-# LANGUAGE GADTs, ViewPatterns, FlexibleContexts #-}
16+{-# LANGUAGE GADTs #-}
17+{-# LANGUAGE ViewPatterns #-}
18+{-# LANGUAGE FlexibleContexts #-}
19+{-# LANGUAGE ScopedTypeVariables #-}
1720
1821module Language.PureScript.CodeGen.JS (
1922 module AST,
@@ -28,8 +31,7 @@ import qualified Data.Traversable as T (traverse)
2831import Control.Applicative
2932import Control.Arrow ((&&&))
3033import Control.Monad (foldM, replicateM, forM)
31−import Control.Monad.Reader (MonadReader, asks, lift)
32−import Control.Monad.Supply
34+import Control.Monad.Reader (MonadReader, asks)
3335import Control.Monad.Supply.Class
3436
3537import Language.PureScript.CodeGen.JS.AST as AST
@@ -45,14 +47,14 @@ import qualified Language.PureScript.Constants as C
4547-- Generate code in the simplified Javascript intermediate representation for all declarations in a
4648-- module.
4749--
48−moduleToJs :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
49− => Module Ann -> SupplyT m [JS]
50+moduleToJs :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m, MonadSupply m)
51+ => Module Ann -> m [JS]
5052moduleToJs (Module name imps exps foreigns decls) = do
51− additional <- lift $ asks optionsAdditional
52− jsImports <- lift . T.traverse importToJs . delete (ModuleName [ProperName C.prim]) . (\\ [name]) $ imps
53+ additional <- asks optionsAdditional
54+ jsImports <- T.traverse importToJs . delete (ModuleName [ProperName C.prim]) . (\\ [name]) $ imps
5355 let foreigns' = mapMaybe (\(_, js, _) -> js) foreigns
5456 jsDecls <- mapM (bindToJs name) decls
55− optimized <- lift $ T.traverse (T.traverse optimize) jsDecls
57+ optimized <- T.traverse (T.traverse optimize) jsDecls
5658 let isModuleEmpty = null exps
5759 let moduleBody = JSStringLiteral "use strict" : jsImports ++ foreigns' ++ concat optimized
5860 let exps' = JSObjectLiteral $ map (runIdent &&& JSVar . identToJs) exps
@@ -80,8 +82,8 @@ importToJs mn = do
8082-- |
8183-- Generate code in the simplified Javascript intermediate representation for a declaration
8284--
83−bindToJs :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
84− => ModuleName -> Bind Ann -> SupplyT m [JS]
85+bindToJs :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m, MonadSupply m)
86+ => ModuleName -> Bind Ann -> m [JS]
8587bindToJs mp (NonRec ident val) = return <$> nonRecToJS mp ident val
8688bindToJs mp (Rec vals) = forM vals (uncurry (nonRecToJS mp))
8789
@@ -91,10 +93,10 @@ bindToJs mp (Rec vals) = forM vals (uncurry (nonRecToJS mp))
9193--
9294-- The main purpose of this function is to handle code generation for comments.
9395--
94−nonRecToJS :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
95− => ModuleName -> Ident -> Expr Ann -> SupplyT m JS
96+nonRecToJS :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m, MonadSupply m)
97+ => ModuleName -> Ident -> Expr Ann -> m JS
9698nonRecToJS m i e@(extractAnn -> (_, com, _, _)) | not (null com) = do
97− withoutComment <- lift $ asks optionsNoComments
99+ withoutComment <- asks optionsNoComments
98100 if withoutComment
99101 then nonRecToJS m i (modifyAnn removeComments e)
100102 else JSComment com <$> nonRecToJS m i (modifyAnn removeComments e)
@@ -126,8 +128,8 @@ accessorString prop | identNeedsEscaping prop = JSIndexer (JSStringLiteral prop)
126128-- |
127129-- Generate code in the simplified Javascript intermediate representation for a value or expression.
128130--
129−valueToJs :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
130− => ModuleName -> Expr Ann -> SupplyT m JS
131+valueToJs :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m, MonadSupply m)
132+ => ModuleName -> Expr Ann -> m JS
131133valueToJs m (Literal _ l) =
132134 literalToValueJS m l
133135valueToJs m (Var (_, _, _, Just (IsConstructor _ [])) name) =
@@ -195,11 +197,12 @@ valueToJs _ (Constructor _ _ (ProperName ctor) fields) =
195197 in return $ iife ctor [ constructor
196198 , JSAssignment (JSAccessor "create" (JSVar ctor)) createFn
197199 ]
200+
198201iife :: String -> [JS] -> JS
199202iife v exprs = JSApp (JSFunction Nothing [] (JSBlock $ exprs ++ [JSReturn $ JSVar v])) []
200203
201−literalToValueJS :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
202− => ModuleName -> Literal (Expr Ann) -> SupplyT m JS
204+literalToValueJS :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m, MonadSupply m)
205+ => ModuleName -> Literal (Expr Ann) -> m JS
203206literalToValueJS _ (NumericLiteral n) = return $ JSNumericLiteral n
204207literalToValueJS _ (StringLiteral s) = return $ JSStringLiteral s
205208literalToValueJS _ (BooleanLiteral b) = return $ JSBooleanLiteral b
@@ -209,7 +212,7 @@ literalToValueJS m (ObjectLiteral ps) = JSObjectLiteral <$> mapM (sndM (valueToJ
209212-- |
210213-- Shallow copy an object.
211214--
212−extendObj :: (Functor m, Applicative m, Monad m) => JS -> [(String, JS)] -> SupplyT m JS
215+extendObj :: (Applicative m, Monad m, MonadSupply m) => JS -> [(String, JS)] -> m JS
213216extendObj obj sts = do
214217 newObj <- freshName
215218 key <- freshName
@@ -246,8 +249,8 @@ qualifiedToJS _ f (Qualified _ a) = JSVar $ identToJs (f a)
246249-- Generate code in the simplified Javascript intermediate representation for pattern match binders
247250-- and guards.
248251--
249−bindersToJs :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
250− => ModuleName -> [CaseAlternative Ann] -> [JS] -> SupplyT m JS
252+bindersToJs :: forall m mode. (Functor m, Applicative m, Monad m, MonadReader (Options mode) m, MonadSupply m)
253+ => ModuleName -> [CaseAlternative Ann] -> [JS] -> m JS
251254bindersToJs m binders vals = do
252255 valNames <- replicateM (length vals) freshName
253256 let assignments = zipWith JSVariableIntroduction valNames (map Just vals)
@@ -257,16 +260,14 @@ bindersToJs m binders vals = do
257260 return $ JSApp (JSFunction Nothing [] (JSBlock (assignments ++ concat jss ++ [JSThrow $ JSUnary JSNew $ JSApp (JSVar "Error") [JSStringLiteral "Failed pattern match"]])))
258261 []
259262 where
260− go :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
261− => [String] -> [JS] -> [Binder Ann] -> SupplyT m [JS]
263+ go :: [String] -> [JS] -> [Binder Ann] -> m [JS]
262264 go _ done [] = return done
263265 go (v:vs) done' (b:bs) = do
264266 done'' <- go vs done' bs
265267 binderToJs m v done'' b
266268 go _ _ _ = error "Invalid arguments to bindersToJs"
267269
268− guardsToJs :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
269− => Either [(Guard Ann, Expr Ann)] (Expr Ann) -> SupplyT m [JS]
270+ guardsToJs :: Either [(Guard Ann, Expr Ann)] (Expr Ann) -> m [JS]
270271 guardsToJs (Left gs) = forM gs $ \(cond, val) -> do
271272 cond' <- valueToJs m cond
272273 done <- valueToJs m val
@@ -277,8 +278,8 @@ bindersToJs m binders vals = do
277278-- Generate code in the simplified Javascript intermediate representation for a pattern match
278279-- binder.
279280--
280−binderToJs :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
281− => ModuleName -> String -> [JS] -> Binder Ann -> SupplyT m [JS]
281+binderToJs :: forall m mode. (Functor m, Applicative m, Monad m, MonadReader (Options mode) m, MonadSupply m)
282+ => ModuleName -> String -> [JS] -> Binder Ann -> m [JS]
282283binderToJs _ _ done (NullBinder{}) = return done
283284binderToJs m varName done (LiteralBinder _ l) =
284285 literalToBinderJS m varName done l
@@ -295,8 +296,7 @@ binderToJs m varName done (ConstructorBinder (_, _, _, Just (IsConstructor ctorT
295296 (JSBlock js)
296297 Nothing]
297298 where
298− go :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
299− => [(Ident, Binder Ann)] -> [JS] -> SupplyT m [JS]
299+ go :: [(Ident, Binder Ann)] -> [JS] -> m [JS]
300300 go [] done' = return done'
301301 go ((field, binder) : remain) done' = do
302302 argVar <- freshName
@@ -326,8 +326,8 @@ binderToJs m varName done (NamedBinder _ ident binder) = do
326326 js <- binderToJs m varName done binder
327327 return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : js)
328328
329−literalToBinderJS :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
330− => ModuleName -> String -> [JS] -> Literal (Binder Ann) -> SupplyT m [JS]
329+literalToBinderJS :: forall m mode. (Functor m, Applicative m, Monad m, MonadReader (Options mode) m, MonadSupply m)
330+ => ModuleName -> String -> [JS] -> Literal (Binder Ann) -> m [JS]
331331literalToBinderJS _ varName done (NumericLiteral num) =
332332 return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSNumericLiteral num)) (JSBlock done) Nothing]
333333literalToBinderJS _ varName done (StringLiteral str) =
@@ -338,8 +338,7 @@ literalToBinderJS _ varName done (BooleanLiteral False) =
338338 return [JSIfElse (JSUnary Not (JSVar varName)) (JSBlock done) Nothing]
339339literalToBinderJS m varName done (ObjectLiteral bs) = go done bs
340340 where
341− go :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
342− => [JS] -> [(String, Binder Ann)] -> SupplyT m [JS]
341+ go :: [JS] -> [(String, Binder Ann)] -> m [JS]
343342 go done' [] = return done'
344343 go done' ((prop, binder):bs') = do
345344 propVar <- freshName
@@ -350,8 +349,7 @@ literalToBinderJS m varName done (ArrayLiteral bs) = do
350349 js <- go done 0 bs
351350 return [JSIfElse (JSBinary EqualTo (JSAccessor "length" (JSVar varName)) (JSNumericLiteral (Left (fromIntegral $ length bs)))) (JSBlock js) Nothing]
352351 where
353− go :: (Functor m, Applicative m, Monad m, MonadReader (Options mode) m)
354− => [JS] -> Integer -> [Binder Ann] -> SupplyT m [JS]
352+ go :: [JS] -> Integer -> [Binder Ann] -> m [JS]
355353 go done' _ [] = return done'
356354 go done' index (binder:bs') = do
357355 elVar <- freshName