1module Build.File (build) where
3import Control.Applicative ((<$>))
4import Control.Monad (when)
5import Control.Monad.RWS.Strict
6import qualified Data.Binary as Binary
7import qualified Data.List as List
8import qualified Data.Maybe as Maybe
9import Data.Monoid (Last(..))
10import qualified Data.Map as Map
11import System.Directory
16import qualified Transform.Canonicalize as Canonical
17import qualified Data.ByteString.Lazy as L
19import qualified Build.Utils as Utils
20import qualified Build.Flags as Flag
21import qualified Build.Source as Source
22import qualified Build.Print as Print
23import qualified Generate.JavaScript as JS
24import qualified InterfaceSerialization as IS
25import qualified Parse.Module as Parser
26import qualified SourceSyntax.Module as M
28-- Reader: Runtime flags, always accessible
29-- Writer: Remember the last module to be accessed
30-- State: Build up a map of the module interfaces
31type BuildT m a = RWST Flag.Flags (Last String) M.Interfaces m a
32type Build a = BuildT IO a
34evalBuild :: Flag.Flags -> M.Interfaces -> Build () -> IO (Maybe String)
36 (_, s) <- evalRWST b fs is
39-- Builds a list of files, returning the moduleName of the last one.
40-- Returns "" if the list is empty
41build :: Flag.Flags -> M.Interfaces -> [FilePath] -> IO String
42build flags is = fmap (Maybe.fromMaybe "") . evalBuild flags is . buildAll
44buildAll :: [FilePath] -> Build ()
45buildAll fs = mapM_ build1 (zip [1..] fs)
46 where build1 (num, fname) = do
47 compiled <- alreadyCompiled filePath
50 let number = join ["[", show num, " of ", show total, "]"]
51 compile number filePath
52 True -> retrieve filePath
55alreadyCompiled :: FilePath -> Build Bool
56alreadyCompiled filePath = do
59 existsi <- doesFileExist (Utils.elmi flags filePath)
60 existso <- doesFileExist (Utils.elmo flags filePath)
61 if not existsi || not existso
63 else do tsrc <- getModificationTime filePath
64 tint <- getModificationTime (Utils.elmo flags filePath)
67retrieve :: FilePath -> Build ()
70 let elmi = Utils.elmi flags filePath
71 bytes <- liftIO $ IS.loadInterface elmi
72 let binary = IS.interfaceDecode elmi =<< bytes
73 case IS.validVersion filePath =<< binary of
74 Right (name, interface) ->
76 liftIO $ when (Flag.print_types flags) (Print.interfaceTypes interfaces interface)
80 liftIO $ hPutStrLn stderr err >> exitFailure
82compile :: String -> FilePath -> Build ()
83compile number filePath =
86 source <- liftIO $ readFile filePath
87 let name = getName source
90 createDirectoryIfMissing True (Flag.cache_dir flags)
91 createDirectoryIfMissing True (Flag.build_dir flags)
94 liftIO $ case Source.build (Flag.no_prelude flags) interfaces source of
95 Right modul -> return modul
96 Left errors -> do Print.errors errors
99 liftIO $ when (Flag.print_types flags) $ Print.metaTypes interfaces metaModule
101 let intermediate = (name, Canonical.interface name $ M.metaToInterface metaModule)
102 generateCache intermediate metaModule
103 uncurry update intermediate
106 getName source = case Parser.getModuleName source of
111 hPutStrLn stdout $ concat [ number, " Compiling ", name
112 , replicate (max 1 (20 - length name)) ' '
113 , "( " ++ filePath ++ " )" ]
115 generateCache intermediate metaModule = do
118 createDirectoryIfMissing True . dropFileName $ Utils.elmi flags filePath
119 writeFile (Utils.elmo flags filePath) (JS.generate metaModule)
120 withBinaryFile (Utils.elmi flags filePath) WriteMode $ \handle ->
121 L.hPut handle (Binary.encode intermediate)
123update :: String -> M.ModuleInterface -> Build ()
124update name inter = modify (Map.insert name inter)
125 >> tell (Last . Just $ name)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list