elm/compiler/Initialize.hs

106 lines
3.8 KiB
Haskell
Raw Normal View History

module Initialize (build, buildFromSource) where
import Control.Applicative ((<$>))
import Control.Monad.Error
import Data.List (lookup,nub)
import Ast
2013-02-08 09:33:21 +00:00
import Data.Either (lefts,rights)
import Data.List (intercalate,partition)
import Parse.Parser (parseProgram, preParse)
import Rename
import Types.Types ((-:))
import Types.Hints (hints)
import Types.Unify
import Types.Alias
import Optimize
import CompileToJS (jsModule)
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-02-08 09:33:21 +00:00
checkTypes (Module name ex im stmts) =
let stmts' = dealias stmts
modul = Module name ex im stmts'
in do subs <- unify hints modul
let --im' | any ((=="Prelude") . fst) im = im
-- | otherwise = ("Prelude", Importing []) : im
modul' = optimize . renameModule $ Module name ex im stmts'
subs `seq` return 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
buildFromSource :: String -> Either String Module
buildFromSource src = check =<< parseProgram src
2013-02-08 09:33:21 +00:00
build :: FilePath -> IO (Either String [Module])
build root = do
names <- getSortedModuleNames root
case names of
2013-02-08 09:33:21 +00:00
Left err -> return (Left err)
Right ns -> do srcs <- zipWithM buildFile' [1..] ns
return (sequence srcs)
where
buildFile' n name = putStrLn (msg n name) >> buildFile name
msg n name = "["++show n++" of "++show (length ns)++"] Compiling "++name
2013-02-08 09:33:21 +00:00
buildFile :: String -> IO (Either String Module)
buildFile moduleName =
let filePath = toFilePath moduleName in
case isNative moduleName of
True -> return (Right $ Module [moduleName] [] [] [])
--return (Left "Can't do that yet")
--Right `liftM` readFile filePath
False -> do txt <- readFile filePath
return $ buildFromSource txt
2013-02-08 09:33:21 +00:00
getSortedModuleNames :: FilePath -> IO (Either String [String])
getSortedModuleNames root = do
deps <- readDeps [] root
return (sortDeps =<< deps)
2013-02-08 09:33:21 +00:00
type Deps = (String, [String])
sortDeps :: [Deps] -> Either String [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] -> Either String [String]
2013-02-08 09:33:21 +00:00
go sorted [] = Right sorted
go sorted unsorted =
case partition (all (`elem` sorted) . snd) unsorted of
([],m:ms) -> Left (msg ++ intercalate ", " (map fst (m:ms)) ++ show sorted ++ show unsorted)
(srtd,unsrtd) -> go (sorted ++ map fst srtd) unsrtd
readDeps :: [FilePath] -> FilePath -> IO (Either String [Deps])
readDeps seen root = do
txt <- readFile root
case preParse txt of
Left err -> return (Left err)
Right (name,deps) -> do rest <- mapM (readDeps seen' . toFilePath) newDeps
return $ do rs <- sequence rest
return ((name, realDeps) : concat rs)
where realDeps = filter (`notElem` builtIns) deps
newDeps = filter (`notElem` seen) realDeps
seen' = root : seen ++ newDeps
builtIns = [] {--
["List","Char","Either","Maybe","Dict","Set","Date",
"Signal","Mouse","Keyboard.Raw","Keyboard","Touch",
"WebSocket","Window","Time","HTTP","Input","Random",
"Graphics","Text","Color","JavaScript","Automaton",
"JavaScript.Experimental","Prelude","JSON"]
--}
isNative name = takeWhile (/='.') name == "Native"
toFilePath name = map swapDots name ++ ext
where swapDots '.' = '/'
swapDots c = c
ext = if isNative name then ".js" else ".elm"