elm/compiler/Initialize.hs

84 lines
2.7 KiB
Haskell
Raw Normal View History

module Initialize (buildFromSource, getSortedModuleNames) where
import Control.Applicative ((<$>))
import Control.Monad.Error
import Data.List (lookup,nub)
import qualified Data.Map as Map
import Ast
2013-02-08 09:33:21 +00:00
import Data.Either (lefts,rights)
import Data.List (intercalate,partition)
import Parse.Parser (parseProgram, parseDependencies)
import Rename
2013-04-08 08:48:30 +00:00
import qualified Libraries as Libs
import Types.Types ((-:))
import Types.Hints (hints)
2013-05-28 13:47:36 +00:00
import Types.Unify (unify)
2013-04-05 16:55:30 +00:00
import Types.Alias (dealias, mistakes)
import Optimize
import System.Exit
import System.FilePath
2013-02-08 09:33:21 +00:00
checkMistakes :: Module -> Either String Module
checkMistakes modul@(Module name ex im stmts) =
case mistakes stmts of
m:ms -> Left (unlines (m:ms))
2013-02-08 09:33:21 +00:00
[] -> return modul
checkTypes :: Module -> Either String Module
2013-04-05 16:55:30 +00:00
checkTypes modul =
do subs <- unify hints modul
subs `seq` return (optimize (renameModule modul))
2013-02-08 09:33:21 +00:00
check :: Module -> Either String Module
2013-02-08 09:33:21 +00:00
check = checkMistakes >=> checkTypes
2013-04-08 08:48:30 +00:00
buildFromSource :: Bool -> String -> Either String Module
buildFromSource noPrelude src =
let add = if noPrelude then id else Libs.addPrelude in
(check . add) =<< (parseProgram src)
2013-02-08 09:33:21 +00:00
getSortedModuleNames :: FilePath -> IO [String]
getSortedModuleNames root =
sortDeps =<< readDeps [] root
2013-02-08 09:33:21 +00:00
type Deps = (String, [String])
sortDeps :: [Deps] -> IO [String]
sortDeps deps = go [] (nub deps)
2013-02-08 09:33:21 +00:00
where
msg = "A cyclical or missing module dependency or was detected in: "
go :: [String] -> [Deps] -> IO [String]
go sorted [] = return (map toFilePath sorted)
2013-02-08 09:33:21 +00:00
go sorted unsorted =
case partition (all (`elem` sorted) . snd) unsorted of
([],m:ms) -> do putStrLn (msg ++ intercalate ", " (map fst (m:ms)) ++ show sorted ++ show unsorted)
exitFailure
(srtd,unsrtd) -> go (sorted ++ map fst srtd) unsrtd
readDeps :: [FilePath] -> FilePath -> IO [Deps]
readDeps seen root = do
txt <- readFile root
case parseDependencies txt of
Left err ->
let msg = "Error resolving dependencies in " ++ root ++ ":\n" in
putStrLn (msg ++ err) >> exitFailure
Right (name,deps) ->
do rest <- mapM (readDeps seen' . toFilePath) newDeps
return ((name, realDeps) : concat rest)
where
realDeps = filter (`notElem` builtIns) deps
newDeps = filter (\d -> d `notElem` seen && not (isNative d)) realDeps
seen' = root : seen ++ newDeps
builtIns = Map.keys Libs.libraries
isNative name = takeWhile (/='.') name == "Native"
toFilePath :: String -> FilePath
toFilePath name = map swapDots name ++ ext
where swapDots '.' = '/'
swapDots c = c
ext = if isNative name then ".js" else ".elm"