git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge pull request #1572 from purescript/1297

Fix #1297, reduce memory usage from WriterT

commit322292cedc073457314c9e97071fc36860f9bb2f authorPhil Freeman <paf31@cantab.net> dateMon 26 Oct 2015, 13:49 (11 years ago) parent2c7f092b6fe164
6 files changed+88−12
psc/Main.hs+4−5 psci/PSCi.hs+1−1 purescript.cabal+1 src/Control/Monad/Logger.hs+75 src/Language/PureScript/Make.hs+6−5 tests/Main.hs+1−1
psc/Main.hs+4−5
@@ -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
8483warnFileTypeNotFound :: String -> IO ()
8584warnFileTypeNotFound = hPutStrLn stderr . ("psc: No files found using pattern: " ++)
psci/PSCi.hs+1−1
@@ -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.
256256runMake :: 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
259259makeIO :: (IOError -> P.ErrorMessage) -> IO a -> P.Make a
260260makeIO f io = do
purescript.cabal+1
@@ -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.hsnew file+75
@@ -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+6−5
@@ -43,9 +43,10 @@ import Control.Applicative
4343#endif
4444import Control.Monad
4545import Control.Monad.Error.Class (MonadError(..))
46+import Control.Monad.Writer.Class (MonadWriter(..))
4647import Control.Monad.Trans.Except
4748import Control.Monad.Reader
48−import Control.Monad.Writer.Strict
49+import Control.Monad.Logger
4950import Control.Monad.Supply
5051import Control.Monad.Base (MonadBase(..))
5152import 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
290291instance MonadBase IO Make where
291292 liftBase = liftIO
292293
293294instance 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
304305makeIO :: (IOError -> ErrorMessage) -> IO a -> Make a
305306makeIO f io = do
tests/Main.hs+1−1
@@ -104,7 +104,7 @@ readInput inputFiles = forM inputFiles $ \inputFile -> do
104104type TestM = WriterT [(FilePath, String)] IO
105105
106106runTest :: P.Make a -> IO (Either P.MultipleErrors a)
107−runTest = fmap (fmap fst) . P.runMake P.defaultOptions
107+runTest = fmap fst . P.runMake P.defaultOptions
108108
109109compile :: [FilePath] -> M.Map P.ModuleName FilePath -> IO (Either P.MultipleErrors P.Environment)
110110compile inputFiles foreigns = runTest $ do