cb914d91ff
Does not actually work, undefined is used in some places as a stopgap measure.
88 lines
2.9 KiB
Haskell
88 lines
2.9 KiB
Haskell
module Initialize (buildFromSource, getSortedModuleNames) where
|
|
|
|
import Control.Applicative ((<$>))
|
|
import Control.Monad.Error
|
|
import Data.List (lookup,nub)
|
|
import qualified Data.Map as Map
|
|
import Data.Data
|
|
import SourceSyntax.Everything
|
|
import Data.List (intercalate,partition)
|
|
import Parse.Parser (parseProgram, parseDependencies)
|
|
import qualified Metadata.Libraries as Libs
|
|
import Transform.Optimize
|
|
import System.Exit
|
|
import System.FilePath
|
|
|
|
|
|
{-- TODO: replace with new stuff
|
|
import Types.Hints (hints)
|
|
import Types.Unify (unify)
|
|
import Types.Alias (dealias, mistakes)
|
|
--}
|
|
mistakes = undefined
|
|
unify = undefined
|
|
hints = undefined
|
|
|
|
|
|
checkMistakes :: (Data t, Data v) => Module t v -> Either String (Module t v)
|
|
checkMistakes modul@(Module name ex im stmts) =
|
|
case mistakes stmts of
|
|
m:ms -> Left (unlines (m:ms))
|
|
[] -> return modul
|
|
|
|
checkTypes :: (Data t, Data v) => Module t v -> Either String (Module t v)
|
|
checkTypes modul =
|
|
do subs <- unify hints modul
|
|
subs `seq` return (optimize (renameModule modul))
|
|
|
|
check :: (Data t, Data v) => Module t v -> Either String (Module t v)
|
|
check = checkMistakes >=> checkTypes
|
|
|
|
buildFromSource :: (Data t, Data v) => Bool -> String -> Either String (Module t v)
|
|
buildFromSource noPrelude src =
|
|
let add = if noPrelude then id else Libs.addPrelude in
|
|
(check . add) =<< (parseProgram src)
|
|
|
|
getSortedModuleNames :: FilePath -> IO [String]
|
|
getSortedModuleNames root =
|
|
sortDeps =<< readDeps [] root
|
|
|
|
type Deps = (String, [String])
|
|
|
|
sortDeps :: [Deps] -> IO [String]
|
|
sortDeps deps = go [] (nub deps)
|
|
where
|
|
msg = "A cyclical or missing module dependency or was detected in: "
|
|
|
|
go :: [String] -> [Deps] -> IO [String]
|
|
go sorted [] = return (map toFilePath sorted)
|
|
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"
|