2013-08-02 00:22:44 +00:00
|
|
|
module Initialize (buildFromSource, getSortedDependencies) where
|
2012-05-29 18:25:43 +00:00
|
|
|
|
2013-06-15 02:23:58 +00:00
|
|
|
import Data.Data
|
2013-07-26 14:38:40 +00:00
|
|
|
import Control.Monad.State
|
2013-07-19 16:05:31 +00:00
|
|
|
import qualified Data.Graph as Graph
|
|
|
|
import qualified Data.List as List
|
2013-07-26 14:38:40 +00:00
|
|
|
import qualified Data.Map as Map
|
|
|
|
import qualified Data.Set as Set
|
2013-07-16 12:52:50 +00:00
|
|
|
import System.Exit
|
2013-07-16 19:43:56 +00:00
|
|
|
import System.FilePath as FP
|
2013-07-20 16:52:43 +00:00
|
|
|
import Text.PrettyPrint (Doc)
|
2013-07-16 12:52:50 +00:00
|
|
|
|
|
|
|
import SourceSyntax.Everything
|
2013-08-22 19:16:39 +00:00
|
|
|
import qualified SourceSyntax.Type as Type
|
2013-07-16 19:43:56 +00:00
|
|
|
import qualified Parse.Parse as Parse
|
2013-07-25 18:53:22 +00:00
|
|
|
import qualified Metadata.Prelude as Prelude
|
2013-07-14 23:06:00 +00:00
|
|
|
import qualified Transform.Check as Check
|
2013-07-16 19:43:56 +00:00
|
|
|
import qualified Transform.SortDefinitions as SD
|
2013-07-16 12:52:50 +00:00
|
|
|
import qualified Type.Inference as TI
|
2013-07-16 19:43:56 +00:00
|
|
|
import qualified Type.Constrain.Declaration as TcDecl
|
2013-07-29 09:59:55 +00:00
|
|
|
import qualified Transform.Canonicalize as Canonical
|
2012-05-29 18:25:43 +00:00
|
|
|
|
2013-07-29 09:59:55 +00:00
|
|
|
buildFromSource :: Bool -> Interfaces -> String -> Either [Doc] (MetadataModule () ())
|
|
|
|
buildFromSource noPrelude interfaces source =
|
|
|
|
do let add = if noPrelude then id else Prelude.add
|
2013-08-29 09:53:20 +00:00
|
|
|
infixes = Map.fromList . map (\(assoc,lvl,op) -> (op,(lvl,assoc)))
|
|
|
|
. concatMap iFixities $ Map.elems interfaces
|
|
|
|
|
|
|
|
modul@(Module _ _ _ decls') <- add `fmap` Parse.program infixes source
|
2013-07-11 10:48:37 +00:00
|
|
|
|
2013-07-16 19:43:56 +00:00
|
|
|
-- check for structural errors
|
2013-07-20 16:52:43 +00:00
|
|
|
Module names exs ims decls <-
|
2013-07-20 22:15:35 +00:00
|
|
|
case Check.mistakes decls' of
|
2013-07-20 16:52:43 +00:00
|
|
|
[] -> return modul
|
|
|
|
ms -> Left ms
|
2013-07-29 09:59:55 +00:00
|
|
|
|
2013-08-02 05:48:05 +00:00
|
|
|
let exports'
|
|
|
|
| null exs =
|
|
|
|
let get = Set.toList . SD.boundVars in
|
|
|
|
concat [ get pattern | Definition (Def pattern _) <- decls ] ++
|
2013-08-22 19:16:39 +00:00
|
|
|
concat [ map fst ctors | Datatype _ _ ctors <- decls ] ++
|
|
|
|
[ name | TypeAlias name _ (Type.Record _ _) <- decls ]
|
2013-08-02 05:48:05 +00:00
|
|
|
| otherwise = exs
|
|
|
|
|
2013-07-29 09:59:55 +00:00
|
|
|
metaModule <- Canonical.metadataModule interfaces $ MetadataModule {
|
2013-07-16 19:43:56 +00:00
|
|
|
names = names,
|
|
|
|
path = FP.joinPath names,
|
2013-08-02 05:48:05 +00:00
|
|
|
exports = exports',
|
2013-07-16 19:43:56 +00:00
|
|
|
imports = ims,
|
2013-07-19 16:05:31 +00:00
|
|
|
-- reorder AST into strongly connected components
|
|
|
|
program = SD.sortDefs . dummyLet $ TcDecl.toExpr decls,
|
2013-07-16 19:43:56 +00:00
|
|
|
types = Map.empty,
|
2013-07-25 18:19:50 +00:00
|
|
|
datatypes = [ (name,vars,ctors) | Datatype name vars ctors <- decls ],
|
2013-07-16 19:43:56 +00:00
|
|
|
fixities = [ (assoc,level,op) | Fixity assoc level op <- decls ],
|
|
|
|
aliases = [ (name,tvs,tipe) | TypeAlias name tvs tipe <- decls ],
|
|
|
|
foreignImports = [ (evt,v,name,typ) | ImportEvent evt v name typ <- decls ],
|
|
|
|
foreignExports = [ (evt,name,typ) | ExportEvent evt name typ <- decls ]
|
|
|
|
}
|
2013-02-08 09:33:21 +00:00
|
|
|
|
2013-07-21 20:50:48 +00:00
|
|
|
types <- TI.infer interfaces metaModule
|
2013-07-19 16:05:31 +00:00
|
|
|
|
2013-08-02 05:48:05 +00:00
|
|
|
return $ metaModule { types = types }
|
2013-02-08 09:33:21 +00:00
|
|
|
|
|
|
|
|
2013-08-02 00:22:44 +00:00
|
|
|
getSortedDependencies :: Bool -> FilePath -> IO [String]
|
|
|
|
getSortedDependencies noPrelude root =
|
2013-07-28 00:24:17 +00:00
|
|
|
sortDeps =<< readDeps noPrelude root
|
2013-02-08 09:33:21 +00:00
|
|
|
|
2013-08-02 00:22:44 +00:00
|
|
|
type Deps = (FilePath, String, [String])
|
2013-02-27 07:33:47 +00:00
|
|
|
|
2013-06-05 07:44:04 +00:00
|
|
|
sortDeps :: [Deps] -> IO [String]
|
2013-07-19 16:05:31 +00:00
|
|
|
sortDeps depends =
|
|
|
|
if null mistakes
|
|
|
|
then return (concat sccs)
|
2013-07-20 22:15:35 +00:00
|
|
|
else print msg >> mapM print mistakes >> exitFailure
|
2013-07-19 16:05:31 +00:00
|
|
|
where
|
2013-08-02 00:22:44 +00:00
|
|
|
sccs = map Graph.flattenSCC $ Graph.stronglyConnComp depends
|
2013-07-19 16:05:31 +00:00
|
|
|
|
|
|
|
mistakes = filter (\scc -> length scc > 1) sccs
|
|
|
|
msg = "A cyclical module dependency or was detected in: "
|
2013-02-27 07:33:47 +00:00
|
|
|
|
2013-07-28 00:24:17 +00:00
|
|
|
readDeps :: Bool -> FilePath -> IO [Deps]
|
|
|
|
readDeps noPrelude root = evalStateT (go root) Set.empty
|
2013-07-26 14:38:40 +00:00
|
|
|
where
|
2013-07-28 00:24:17 +00:00
|
|
|
builtIns = if noPrelude then Set.empty
|
|
|
|
else Set.fromList (Map.keys Prelude.interfaces)
|
2013-07-26 14:38:40 +00:00
|
|
|
|
|
|
|
go :: FilePath -> StateT (Set.Set String) IO [Deps]
|
|
|
|
go root = do
|
|
|
|
txt <- liftIO $ readFile root
|
|
|
|
case Parse.dependencies txt of
|
|
|
|
Left err -> liftIO (putStrLn msg >> print err >> exitFailure)
|
|
|
|
where msg = "Error resolving dependencies in " ++ root ++ ":"
|
2013-07-16 19:43:56 +00:00
|
|
|
|
2013-07-26 14:38:40 +00:00
|
|
|
Right (name,deps) ->
|
|
|
|
do seen <- get
|
|
|
|
let realDeps = Set.difference (Set.fromList deps) builtIns
|
|
|
|
newDeps = Set.difference (Set.filter (not . isNative) realDeps) seen
|
|
|
|
put (Set.insert name (Set.union newDeps seen))
|
|
|
|
rest <- mapM (go . toFilePath) (Set.toList newDeps)
|
2013-08-02 00:22:44 +00:00
|
|
|
return ((makeRelative "." root, name, Set.toList realDeps) : concat rest)
|
2013-06-05 07:44:04 +00:00
|
|
|
|
2013-02-27 07:33:47 +00:00
|
|
|
|
2013-07-19 16:05:31 +00:00
|
|
|
isNative name = List.isPrefixOf "Native." name
|
2013-06-05 07:44:04 +00:00
|
|
|
|
|
|
|
toFilePath :: String -> FilePath
|
2013-02-27 07:33:47 +00:00
|
|
|
toFilePath name = map swapDots name ++ ext
|
|
|
|
where swapDots '.' = '/'
|
|
|
|
swapDots c = c
|
|
|
|
ext = if isNative name then ".js" else ".elm"
|