Skip to content

Commit b3bb653

Browse files
committed
Fix purescript#1297, reduce memory usage from WriterT
1 parent 2c7f092 commit b3bb653

File tree

5 files changed

+87
-11
lines changed

5 files changed

+87
-11
lines changed

psc/Main.hs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,14 @@ compile (PSCMakeOptions inputGlob inputForeignGlob outputDir opts usePrefix) = d
7171
hPutStrLn stderr (P.prettyPrintMultipleWarnings (P.optionsVerboseErrors opts) warnings)
7272
let filePathMap = M.fromList $ map (\(fp, P.Module _ _ mn _ _) -> (mn, fp)) ms
7373
makeActions = buildMakeActions outputDir filePathMap foreigns usePrefix
74-
e <- runMake opts $ P.make makeActions (map snd ms)
74+
(e, warnings') <- runMake opts $ P.make makeActions (map snd ms)
75+
when (P.nonEmpty warnings') $
76+
hPutStrLn stderr (P.prettyPrintMultipleWarnings (P.optionsVerboseErrors opts) warnings')
7577
case e of
7678
Left errs -> do
7779
hPutStrLn stderr (P.prettyPrintMultipleErrors (P.optionsVerboseErrors opts) errs)
7880
exitFailure
79-
Right (_, warnings') -> do
80-
when (P.nonEmpty warnings') $
81-
hPutStrLn stderr (P.prettyPrintMultipleWarnings (P.optionsVerboseErrors opts) warnings')
82-
exitSuccess
81+
Right _ -> exitSuccess
8382

8483
warnFileTypeNotFound :: String -> IO ()
8584
warnFileTypeNotFound = hPutStrLn stderr . ("psc: No files found using pattern: " ++)

psci/PSCi.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ modulesDir = ".psci_modules" ++ pathSeparator : "node_modules"
254254
-- | This is different than the runMake in 'Language.PureScript.Make' in that it specifies the
255255
-- options and ignores the warning messages.
256256
runMake :: P.Make a -> IO (Either P.MultipleErrors a)
257-
runMake mk = fmap (fmap fst) $ P.runMake P.defaultOptions mk
257+
runMake mk = fmap fst $ P.runMake P.defaultOptions mk
258258

259259
makeIO :: (IOError -> P.ErrorMessage) -> IO a -> P.Make a
260260
makeIO f io = do

purescript.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ library
170170
Language.PureScript.Publish.ErrorsWarnings
171171
Language.PureScript.Publish.BoxesHelpers
172172

173+
Control.Monad.Logger
173174
Control.Monad.Unify
174175
Control.Monad.Supply
175176
Control.Monad.Supply.Class

src/Control/Monad/Logger.hs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
-----------------------------------------------------------------------------
2+
--
3+
-- Module : Control.Monad.Logger
4+
-- Author : Phil Freeman
5+
-- License : MIT (http://opensource.org/licenses/MIT)
6+
--
7+
-- Maintainer : Phil Freeman <paf31@cantab.net>
8+
-- Stability : experimental
9+
-- Portability :
10+
--
11+
-- | A replacement for WriterT IO which uses mutable references.
12+
--
13+
-----------------------------------------------------------------------------
14+
15+
{-# LANGUAGE CPP #-}
16+
{-# LANGUAGE FlexibleInstances #-}
17+
{-# LANGUAGE MultiParamTypeClasses #-}
18+
{-# LANGUAGE TypeFamilies #-}
19+
20+
module Control.Monad.Logger where
21+
22+
import Data.IORef
23+
24+
#if __GLASGOW_HASKELL__ < 710
25+
import Control.Applicative
26+
#endif
27+
import Control.Monad (ap)
28+
import Control.Monad.IO.Class
29+
import Control.Monad.Writer.Class
30+
import Control.Monad.Base (MonadBase(..))
31+
import Control.Monad.Trans.Control (MonadBaseControl(..))
32+
33+
-- | A replacement for WriterT IO which uses mutable references.
34+
data Logger w a = Logger { runLogger :: IORef w -> IO a }
35+
36+
-- | Run a Logger computation, starting with an empty log.
37+
runLogger' :: (Monoid w) => Logger w a -> IO (a, w)
38+
runLogger' l = do
39+
r <- newIORef mempty
40+
a <- runLogger l r
41+
w <- readIORef r
42+
return (a, w)
43+
44+
instance Functor (Logger w) where
45+
fmap f (Logger l) = Logger $ \r -> fmap f (l r)
46+
47+
instance (Monoid w) => Applicative (Logger w) where
48+
pure = Logger . const . pure
49+
(<*>) = ap
50+
51+
instance (Monoid w) => Monad (Logger w) where
52+
return = pure
53+
Logger l >>= f = Logger $ \r -> l r >>= \a -> runLogger (f a) r
54+
55+
instance (Monoid w) => MonadIO (Logger w) where
56+
liftIO = Logger . const
57+
58+
instance (Monoid w) => MonadWriter w (Logger w) where
59+
tell w = Logger $ \r -> modifyIORef' r (mappend w)
60+
listen l = Logger $ \r -> do
61+
(a, w) <- liftIO (runLogger' l)
62+
modifyIORef' r (mappend w)
63+
return (a, w)
64+
pass l = Logger $ \r -> do
65+
((a, f), w) <- liftIO (runLogger' l)
66+
modifyIORef' r (mappend (f w))
67+
return a
68+
69+
instance (Monoid w) => MonadBase IO (Logger w) where
70+
liftBase = liftIO
71+
72+
instance (Monoid w) => MonadBaseControl IO (Logger w) where
73+
type StM (Logger w) a = a
74+
liftBaseWith f = Logger $ \r -> liftBaseWith $ \q -> f (q . flip runLogger r)
75+
restoreM = return

src/Language/PureScript/Make.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,10 @@ import Control.Applicative
4343
#endif
4444
import Control.Monad
4545
import Control.Monad.Error.Class (MonadError(..))
46+
import Control.Monad.Writer.Class (MonadWriter(..))
4647
import Control.Monad.Trans.Except
4748
import Control.Monad.Reader
48-
import Control.Monad.Writer.Strict
49+
import Control.Monad.Logger
4950
import Control.Monad.Supply
5051
import Control.Monad.Base (MonadBase(..))
5152
import Control.Monad.Trans.Control (MonadBaseControl(..))
@@ -284,22 +285,22 @@ importPrim = addDefaultImport (ModuleName [ProperName C.prim])
284285
-- |
285286
-- A monad for running make actions
286287
--
287-
newtype Make a = Make { unMake :: ReaderT Options (WriterT MultipleErrors (ExceptT MultipleErrors IO)) a }
288+
newtype Make a = Make { unMake :: ReaderT Options (ExceptT MultipleErrors (Logger MultipleErrors)) a }
288289
deriving (Functor, Applicative, Monad, MonadIO, MonadError MultipleErrors, MonadWriter MultipleErrors, MonadReader Options)
289290

290291
instance MonadBase IO Make where
291292
liftBase = liftIO
292293

293294
instance MonadBaseControl IO Make where
294-
type StM Make a = Either MultipleErrors (a, MultipleErrors)
295+
type StM Make a = Either MultipleErrors a
295296
liftBaseWith f = Make $ liftBaseWith $ \q -> f (q . unMake)
296297
restoreM = Make . restoreM
297298

298299
-- |
299300
-- Execute a 'Make' monad, returning either errors, or the result of the compile plus any warnings.
300301
--
301-
runMake :: Options -> Make a -> IO (Either MultipleErrors (a, MultipleErrors))
302-
runMake opts = runExceptT . runWriterT . flip runReaderT opts . unMake
302+
runMake :: Options -> Make a -> IO (Either MultipleErrors a, MultipleErrors)
303+
runMake opts = runLogger' . runExceptT . flip runReaderT opts . unMake
303304

304305
makeIO :: (IOError -> ErrorMessage) -> IO a -> Make a
305306
makeIO f io = do

0 commit comments

Comments
 (0)