@@ -0,0 +1,939 @@
1+{-# OPTIONS_GHC -Wno-unused-do-bind #-}
2+{-# LANGUAGE BangPatterns #-}
14+import Control.Concurrent (forkIO)
15+import Control.Concurrent.MVar
16+import Control.Monad (filterM, mapM_, sequence_)
17+import qualified Data.Char as Char
18+import qualified Data.Either as Either
19+import qualified Data.Graph as Graph
20+import qualified Data.List as List
21+import qualified Data.Map.Utils as Map
22+import qualified Data.Map.Strict as Map
23+import Data.Map.Strict ((!))
24+import qualified Data.Maybe as Maybe
25+import qualified Data.Name as Name
26+import qualified Data.NonEmptyList as NE
27+import qualified Data.OneOrMore as OneOrMore
28+import qualified System.Directory as Dir
29+import qualified System.FilePath as FP
30+import System.FilePath ((</>), (<.>))
32+import qualified AST.Source as Src
33+import qualified AST.Optimized as Opt
34+import qualified Compile
35+import qualified Elm.Details as Details
36+import qualified Elm.Interface as I
37+import qualified Elm.ModuleName as ModuleName
38+import qualified Elm.Outline as Outline
39+import qualified Elm.Package as Pkg
41+import qualified Parse.Module as Parse
42+import qualified Reporting
43+import qualified Reporting.Annotation as A
44+import qualified Reporting.Exit as Exit
45+import qualified Reporting.Problem as Problem
46+import qualified Reporting.Render.Type.Localizer as Localizer
47+import qualified Stuff
56+ { _key :: Reporting.BKey
59+ , _srcDirs :: [FilePath]
60+ , _locals :: Map.Map ModuleName.Raw Details.Local
61+ , _foreigns :: Map.Map ModuleName.Raw Details.Foreign
65+makeEnv :: Reporting.BKey -> FilePath -> Details.Details -> Env
66+makeEnv key root (Details.Details _ validOutline locals foreigns) =
68+ Details.ValidApp (Outline.AppOutline _ srcDirs _ _ _ _) ->
69+ Env key root Pkg.dummyName srcDirs locals foreigns
71+ Details.ValidPkg (Outline.PkgOutline pkg _ _ _ _ _ _ _) _ ->
72+ Env key root pkg ["src"] locals foreigns
79+fork :: IO a -> IO (MVar a)
81+ do mvar <- newEmptyMVar
82+ _ <- forkIO $ putMVar mvar =<< work
86+{-# INLINE forkWithKey #-}
87+forkWithKey :: (k -> a -> IO b) -> Map.Map k a -> IO (Map.Map k (MVar b))
88+forkWithKey func dict =
89+ Map.traverseWithKey (\k v -> fork (func k v)) dict
96+fromExposed :: Reporting.Style -> FilePath -> Details.Details -> NE.List ModuleName.Raw -> IO (Either Exit.BuildProblem ())
97+fromExposed style root details (NE.List e es) =
98+ Reporting.trackBuild style $ \key ->
99+ do let env = makeEnv key root details
100+ dmvar <- Details.loadInterfaces root details
103+ mvar <- newEmptyMVar
104+ roots <- Map.fromKeysA (fork . crawlModule env mvar) (e:es)
106+ mapM_ readMVar roots
107+ statuses <- traverse readMVar =<< readMVar mvar
110+ midpoint <- checkExposedMidpoint dmvar statuses
113+ return (Left (Exit.BuildProjectProblem problem))
116+ do rmvar <- newEmptyMVar
117+ resultMVars <- forkWithKey (checkModule env foreigns rmvar) statuses
118+ putMVar rmvar resultMVars
119+ results <- traverse readMVar resultMVars
120+ writeDetails root details results
121+ return (detectProblems results)
131+ , _deps :: Dependencies
132+ , _mains :: NE.List Main
133+ , _modules :: [Module]
138+ = Fresh ModuleName.Raw I.Interface Opt.LocalGraph
139+ | Cached ModuleName.Raw Bool (MVar CachedInterface)
143+ Map.Map ModuleName.Canonical I.DependencyInterface
146+fromMains :: Reporting.Style -> FilePath -> Details.Details -> NE.List FilePath -> IO (Either Exit.BuildProblem Artifacts)
147+fromMains style root details paths =
148+ Reporting.trackBuild style $ \key ->
149+ do let env = makeEnv key root details
151+ elmains <- findMains env paths
154+ return (Left (Exit.BuildProjectProblem problem))
158+ dmvar <- Details.loadInterfaces root details
159+ smvar <- newMVar Map.empty
160+ smainMVars <- traverse (fork . crawlMain env smvar) lmains
161+ smains <- traverse readMVar smainMVars
162+ statuses <- traverse readMVar =<< readMVar smvar
164+ midpoint <- checkMainsMidpoint dmvar statuses smains
167+ return (Left (Exit.BuildProjectProblem problem))
171+ rmvar <- newEmptyMVar
172+ resultsMVars <- forkWithKey (checkModule env foreigns rmvar) statuses
173+ putMVar rmvar resultsMVars
174+ rmainMVars <- traverse (fork . checkMain env resultsMVars) smains
175+ results <- traverse readMVar resultsMVars
176+ writeDetails root details results
177+ toArtifacts env foreigns results <$> traverse readMVar rmainMVars
185+ Map.Map ModuleName.Raw (MVar Status)
189+ = SCached Details.Local
190+ | SChanged Details.Local Src.Module
191+ | SNotFound Problem.Find
192+ | SNotValid Problem.Syntax
197+crawlDeps :: Env -> MVar StatusDict -> [ModuleName.Raw] -> a -> IO a
198+crawlDeps env mvar deps blockedValue =
199+ do statusDict <- takeMVar mvar
200+ let depsDict = Map.fromKeys (\_ -> ()) deps
201+ let newsDict = Map.difference depsDict statusDict
202+ statuses <- Map.traverseWithKey crawlNew newsDict
203+ putMVar mvar (Map.union statuses statusDict)
204+ mapM_ readMVar statuses
207+ crawlNew name () = fork (crawlModule env mvar name)
210+crawlModule :: Env -> MVar StatusDict -> ModuleName.Raw -> IO Status
211+crawlModule env@(Env _ root pkg srcDirs locals foreigns) mvar name =
212+ do let fileName = ModuleName.toFilePath name <.> "elm"
213+ let inRoot path = File.exists (root </> path)
215+ paths <- filterM inRoot (map (</> fileName) srcDirs)
219+ case Map.lookup name foreigns of
220+ Just (Details.Foreign dep deps) ->
221+ return $ SNotFound $ Problem.Ambiguous path [] dep deps
224+ case Map.lookup name locals of
226+ crawlFile env mvar name path
228+ Just local@(Details.Local oldPath oldTime deps _) ->
230+ then crawlFile env mvar name path
232+ do newTime <- File.getTime path
233+ if oldTime < newTime
234+ then crawlFile env mvar name path
235+ else crawlDeps env mvar deps (SCached local)
238+ return $ SNotFound $ Problem.AmbiguousLocal p1 p2 ps
241+ case Map.lookup name foreigns of
242+ Just (Details.Foreign dep deps) ->
245+ return $ SForeign dep
248+ return $ SNotFound $ Problem.AmbiguousForeign dep d ds
251+ if Name.isKernel name && Pkg.isKernel pkg then
252+ do exists <- File.exists ("src" </> ModuleName.toFilePath name <.> "js")
253+ return $ if exists then SKernel else SNotFound Problem.NotFound
255+ return $ SNotFound Problem.NotFound
258+crawlFile :: Env -> MVar StatusDict -> ModuleName.Raw -> FilePath -> IO Status
259+crawlFile env@(Env _ root pkg _ _ _) mvar expectedName path =
260+ do time <- File.getTime path
261+ result <- Parse.fromFile pkg (root </> path)
264+ Right modul@(Src.Module maybeActualName _ imports values _ _ _ _) ->
265+ case maybeActualName of
267+ if expectedName == actualName then
269+ deps = map Src.getImportName imports
270+ local = Details.Local path time deps (any isMain values)
272+ crawlDeps env mvar deps (SChanged local modul)
274+ return $ SNotValid $ Problem.BadModuleName_Mismatch expectedName actualName
277+ return $ SNotValid $ Problem.BadModuleName_Unspecified expectedName
280+ return $ SNotValid $ Problem.SyntaxProblem path time syntaxError
283+isMain :: A.Located Src.Value -> Bool
284+isMain (A.At _ (Src.Value (A.At _ name) _ _ _)) =
293+ Map.Map ModuleName.Raw (MVar Result)
297+ = RNew Details.Local I.Interface Opt.LocalGraph
298+ | RSame Details.Local I.Interface Opt.LocalGraph
299+ | RCached Bool (MVar CachedInterface)
300+ | RProblem Problem.Problem
302+ | RForeign I.Interface
308+ | Loaded I.Interface
312+checkModule :: Env -> Dependencies -> MVar ResultDict -> ModuleName.Raw -> Status -> IO Result
313+checkModule env@(Env _ root pkg _ _ _) foreigns resultsMVar name status =
315+ SCached local@(Details.Local path time deps hasMain) ->
316+ do results <- readMVar resultsMVar
317+ depsStatus <- checkDeps root results deps
319+ DepsChange ifaces ->
320+ do result <- Parse.fromFile pkg path
322+ Right modul -> compile env local ifaces modul
324+ return $ RProblem $ Problem.BadSyntax $
325+ Problem.SyntaxProblem path time syntaxError
328+ do mvar <- newMVar Unneeded
329+ return (RCached hasMain mvar)
334+ SChanged local@(Details.Local _ _ deps _) modul ->
335+ do results <- readMVar resultsMVar
336+ depsStatus <- checkDeps root results deps
338+ DepsChange ifaces ->
339+ compile env local ifaces modul
341+ DepsSame same cached ->
342+ do maybeLoaded <- checkCachedInterfaces root cached
348+ do let ifaces = Map.union loaded (Map.fromList same)
349+ compile env local ifaces modul
354+ SNotFound findProblem ->
355+ return (RProblem (Problem.BadFind findProblem))
357+ SNotValid syntaxProblem ->
358+ return (RProblem (Problem.BadSyntax syntaxProblem))
361+ case foreigns ! ModuleName.Canonical home name of
362+ I.Public iface -> return (RForeign iface)
363+ I.Private _ _ _ -> error "loading private interface in Build"
374+ = DepsChange (Map.Map ModuleName.Raw I.Interface)
375+ | DepsSame [Dep] [CDep]
379+checkDeps :: FilePath -> ResultDict -> [ModuleName.Raw] -> IO DepsStatus
380+checkDeps root results deps =
381+ checkDepsHelp root results deps [] [] []
384+type Dep = (ModuleName.Raw, I.Interface)
385+type CDep = (ModuleName.Raw, MVar CachedInterface)
388+checkDepsHelp :: FilePath -> ResultDict -> [ModuleName.Raw] -> [Dep] -> [Dep] -> [CDep] -> IO DepsStatus
389+checkDepsHelp root results deps new same cached =
393+ then return (DepsSame same cached)
395+ do maybeLoaded <- checkCachedInterfaces root cached
401+ return $ DepsChange $
402+ Map.union loaded (Map.union (Map.fromList new) (Map.fromList same))
405+ do result <- readMVar (results ! dep)
408+ checkDepsHelp root results otherDeps ((dep,iface) : new) same cached
411+ checkDepsHelp root results otherDeps new ((dep,iface) : same) cached
414+ checkDepsHelp root results otherDeps new same ((dep,mvar) : cached)
423+ checkDepsHelp root results otherDeps new ((dep,iface) : same) cached
426+ checkDepsHelp root results otherDeps new same cached
433+checkCachedInterfaces :: FilePath -> [(ModuleName.Raw, MVar CachedInterface)] -> IO (Maybe (Map.Map ModuleName.Raw I.Interface))
434+checkCachedInterfaces root deps =
435+ do loading <- traverse (fork . checkCache root) deps
436+ loaded <- traverse readMVar loading
437+ return $ Map.fromList <$> sequence loaded
440+checkCache :: FilePath -> (ModuleName.Raw, MVar CachedInterface) -> IO (Maybe Dep)
441+checkCache root (name, ciMvar) =
442+ do cachedInterface <- takeMVar ciMvar
443+ case cachedInterface of
445+ do putMVar ciMvar cachedInterface
449+ do putMVar ciMvar cachedInterface
450+ return (Just (name, iface))
453+ do maybeIface <- File.readBinary (Stuff.elmi root name)
456+ do putMVar ciMvar Corrupted
460+ do putMVar ciMvar (Loaded iface)
461+ return (Just (name, iface))
468+checkExposedMidpoint :: MVar (Maybe Dependencies) -> Map.Map ModuleName.Raw Status -> IO (Either Exit.BuildProjectProblem Dependencies)
469+checkExposedMidpoint dmvar statuses =
470+ case checkForCycles statuses of
472+ do maybeForeigns <- readMVar dmvar
473+ case maybeForeigns of
474+ Nothing -> return (Left Exit.BP_CannotLoadDependencies)
475+ Just fs -> return (Right fs)
477+ Just (NE.List name names) ->
478+ do _ <- readMVar dmvar
479+ return (Left (Exit.BP_Cycle name names))
482+checkMainsMidpoint :: MVar (Maybe Dependencies) -> Map.Map ModuleName.Raw Status -> NE.List MainStatus -> IO (Either Exit.BuildProjectProblem Dependencies)
483+checkMainsMidpoint dmvar statuses smains =
484+ case checkForCycles statuses of
486+ case checkUniqueMains statuses smains of
488+ do maybeForeigns <- readMVar dmvar
489+ case maybeForeigns of
490+ Nothing -> return (Left Exit.BP_CannotLoadDependencies)
491+ Just fs -> return (Right fs)
494+ do _ <- readMVar dmvar
495+ return (Left problem)
497+ Just (NE.List name names) ->
498+ do _ <- readMVar dmvar
499+ return (Left (Exit.BP_Cycle name names))
506+checkForCycles :: Map.Map ModuleName.Raw Status -> Maybe (NE.List ModuleName.Raw)
507+checkForCycles modules =
509+ !graph = Map.foldrWithKey addToGraph [] modules
510+ !sccs = Graph.stronglyConnComp graph
512+ checkForCyclesHelp sccs
515+checkForCyclesHelp :: [Graph.SCC ModuleName.Raw] -> Maybe (NE.List ModuleName.Raw)
516+checkForCyclesHelp sccs =
523+ Graph.AcyclicSCC _ -> checkForCyclesHelp otherSccs
524+ Graph.CyclicSCC [] -> checkForCyclesHelp otherSccs
525+ Graph.CyclicSCC (m:ms) -> Just (NE.List m ms)
529+ ( ModuleName.Raw, ModuleName.Raw, [ModuleName.Raw] )
532+addToGraph :: ModuleName.Raw -> Status -> [Node] -> [Node]
533+addToGraph name status graph =
537+ SCached (Details.Local _ _ deps _) -> deps
538+ SChanged (Details.Local _ _ deps _) _ -> deps
544+ (name, name, dependencies) : graph
548+-- CHECK UNIQUE MAINS
551+checkUniqueMains :: Map.Map ModuleName.Raw Status -> NE.List MainStatus -> Maybe Exit.BuildProjectProblem
552+checkUniqueMains insides smains =
555+ Map.fromListWith OneOrMore.more (Maybe.mapMaybe mainStatusToNamePathPair (NE.toList smains))
557+ case Map.traverseWithKey checkOutside outsidesDict of
562+ case sequence_ (Map.intersectionWithKey checkInside outsides insides) of
564+ Left problem -> Just problem
567+mainStatusToNamePathPair :: MainStatus -> Maybe (ModuleName.Raw, OneOrMore.OneOrMore FilePath)
568+mainStatusToNamePathPair smain =
570+ SInside _ -> Nothing
571+ SOutsideOk (Details.Local path _ _ _) modul -> Just (Src.getName modul, OneOrMore.one path)
572+ SOutsideErr _ -> Nothing
575+checkOutside :: ModuleName.Raw -> OneOrMore.OneOrMore FilePath -> Either Exit.BuildProjectProblem FilePath
576+checkOutside name paths =
577+ case OneOrMore.destruct NE.List paths of
578+ NE.List p [] -> Right p
579+ NE.List p1 (p2:_) -> Left (Exit.BP_MainNameDuplicate name p1 p2)
582+checkInside :: ModuleName.Raw -> FilePath -> Status -> Either Exit.BuildProjectProblem ()
583+checkInside name p1 status =
585+ SCached (Details.Local p2 _ _ _) -> Left (Exit.BP_MainNameDuplicate name p1 p2)
586+ SChanged (Details.Local p2 _ _ _) _ -> Left (Exit.BP_MainNameDuplicate name p1 p2)
587+ SNotFound _ -> Right ()
588+ SNotValid _ -> Right ()
589+ SForeign _ -> Right ()
597+compile :: Env -> Details.Local -> Map.Map ModuleName.Raw I.Interface -> Src.Module -> IO Result
598+compile (Env key root pkg _ _ _) local@(Details.Local path time _ _) ifaces modul =
599+ case Compile.compile pkg ifaces modul of
600+ Right (Compile.Artifacts canonical annotations objects) ->
601+ do let name = Src.getName modul
602+ let iface = I.fromModule pkg canonical annotations
603+ File.writeBinary (Stuff.elmo root name) objects
604+ maybeOldi <- File.readBinary (Stuff.elmi root name)
606+ Just oldi | oldi == iface ->
607+ do -- iface should be fully forced by equality check
608+ Reporting.report key Reporting.BDone
609+ return (RSame local iface objects)
612+ do -- iface may be lazy still
613+ -- TODO try adding forkIO here
614+ File.writeBinary (Stuff.elmi root name) iface
615+ Reporting.report key Reporting.BDone
616+ return (RNew local iface objects)
619+ do Reporting.report key Reporting.BDone
620+ return $ RProblem $ Problem.BadContent $
621+ Problem.Module (Src.getName modul) path time errors (Localizer.fromModule modul)
628+writeDetails :: FilePath -> Details.Details -> Map.Map ModuleName.Raw Result -> IO ()
629+writeDetails root (Details.Details time outline locals foreigns) results =
630+ File.writeBinary (Stuff.details root) $
631+ Details.Details time outline (Map.foldrWithKey addNewLocal locals results) foreigns
634+addNewLocal :: ModuleName.Raw -> Result -> Map.Map ModuleName.Raw Details.Local -> Map.Map ModuleName.Raw Details.Local
635+addNewLocal name result locals =
637+ RNew local _ _ -> Map.insert name local locals
638+ RSame local _ _ -> Map.insert name local locals
639+ RCached _ _ -> locals
640+ RProblem _ -> locals
642+ RForeign _ -> locals
650+detectProblems :: Map.Map ModuleName.Raw Result -> Either Exit.BuildProblem ()
651+detectProblems results =
652+ case Map.foldr addProblem [] results of
654+ p:ps -> Left (Exit.BuildModuleProblems p ps)
657+addProblem :: Result -> [Problem.Problem] -> [Problem.Problem]
658+addProblem result problems =
660+ RNew _ _ _ -> problems
661+ RSame _ _ _ -> problems
662+ RCached _ _ -> problems
663+ RProblem p -> p:problems
664+ RBlocked -> problems
665+ RForeign _ -> problems
670+--------------------------------------------------------------------------------
671+--------------------------------------------------------------------------------
672+------ AFTER THIS, EVERYTHING IS ABOUT HANDLING MODULES GIVEN BY FILEPATH ------
673+--------------------------------------------------------------------------------
674+--------------------------------------------------------------------------------
682+ = LInside ModuleName.Raw
686+findMains :: Env -> NE.List FilePath -> IO (Either Exit.BuildProjectProblem (NE.List MainLocation))
687+findMains env paths =
688+ do mvars <- traverse (fork . findLocation env) paths
689+ elocs <- traverse readMVar mvars
690+ return $ checkLocations =<< sequence elocs
693+checkLocations :: NE.List Location -> Either Exit.BuildProjectProblem (NE.List MainLocation)
694+checkLocations locations =
696+ toOneOrMore loc@(Location absolute _ _) =
697+ (absolute, OneOrMore.one loc)
699+ fromOneOrMore loc locs =
702+ loc2:_ -> Left (Exit.BP_MainPathDuplicate (_relative loc) (_relative loc2))
704+ fmap (\_ -> fmap _location locations) $
705+ traverse (OneOrMore.destruct fromOneOrMore) $
706+ Map.fromListWith OneOrMore.more $ map toOneOrMore (NE.toList locations)
715+ { _absolute :: FilePath
716+ , _relative :: FilePath
717+ , _location :: MainLocation
721+findLocation :: Env -> FilePath -> IO (Either Exit.BuildProjectProblem Location)
722+findLocation env path =
723+ do exists <- File.exists path
725+ then isInsideSrcDirs env path <$> Dir.canonicalizePath path
726+ else return (Left (Exit.BP_PathUnknown path))
729+isInsideSrcDirs :: Env -> FilePath -> FilePath -> Either Exit.BuildProjectProblem Location
730+isInsideSrcDirs (Env _ root _ srcDirs _ _) path absolutePath =
732+ (dirs, file) = FP.splitFileName absolutePath
733+ (final, ext) = break (=='.') file
736+ then Left (Exit.BP_WithBadExtension path)
739+ roots = FP.splitDirectories root
740+ segments = FP.splitDirectories dirs ++ [final]
742+ case dropPrefix roots segments of
744+ Right (Location absolutePath path (LOutside path))
746+ Just relativeSegments ->
749+ Either.partitionEithers (map (isInsideSrcDirsHelp relativeSegments) srcDirs)
751+ case (exits, Maybe.catMaybes maybes) of
752+ (_, [(_,name)]) -> Right (Location absolutePath path (LInside name))
753+ ([], []) -> Right (Location absolutePath path (LOutside path))
754+ (_, (s1,_):(s2,_):_) -> Left (Exit.BP_WithAmbiguousSrcDir s1 s2)
755+ (exit:_, _) -> Left exit
758+isInsideSrcDirsHelp :: [String] -> FilePath -> Either Exit.BuildProjectProblem (Maybe (FilePath, ModuleName.Raw))
759+isInsideSrcDirsHelp segments srcDir =
760+ case dropPrefix (FP.splitDirectories srcDir) segments of
765+ if all isGoodName names
766+ then Right (Just (srcDir, Name.fromChars (List.intercalate "." names)))
767+ else Left (error "Exit.MakeWithInvalidModuleName" srcDir segments)
770+isGoodName :: [Char] -> Bool
777+ Char.isUpper char && all (\c -> Char.isAlphaNum c || c == '_') chars
780+dropPrefix :: [FilePath] -> [FilePath] -> Maybe [FilePath]
781+dropPrefix roots paths =
789+ p:ps -> if r == p then dropPrefix rs ps else Nothing
797+ = SInside ModuleName.Raw
798+ | SOutsideOk Details.Local Src.Module
799+ | SOutsideErr Problem.Syntax
802+crawlMain :: Env -> MVar StatusDict -> MainLocation -> IO MainStatus
803+crawlMain env@(Env _ _ pkg _ _ _) mvar given =
806+ do statusMVar <- newEmptyMVar
807+ statusDict <- takeMVar mvar
808+ putMVar mvar (Map.insert name statusMVar statusDict)
809+ putMVar statusMVar =<< crawlModule env mvar name
810+ return (SInside name)
813+ do time <- File.getTime path
814+ result <- Parse.fromFile pkg path
816+ Right modul@(Src.Module _ _ imports values _ _ _ _) ->
817+ do let deps = map Src.getImportName imports
818+ let local = Details.Local path time deps (any isMain values)
819+ crawlDeps env mvar deps (SOutsideOk local modul)
822+ return (SOutsideErr (Problem.SyntaxProblem path time syntaxError))
830+ = RInside ModuleName.Raw
831+ | ROutsideOk ModuleName.Raw I.Interface Opt.LocalGraph
832+ | ROutsideErr Problem.Problem
836+checkMain :: Env -> ResultDict -> MainStatus -> IO MainResult
837+checkMain env@(Env _ root _ _ _ _) results pendingMain =
840+ return (RInside name)
842+ SOutsideErr syntaxProblem ->
843+ return (ROutsideErr (Problem.BadSyntax syntaxProblem))
845+ SOutsideOk local@(Details.Local _ _ deps _) modul ->
846+ do depsStatus <- checkDeps root results deps
848+ DepsChange ifaces ->
849+ return $ compileOutside env local ifaces modul
851+ DepsSame same cached ->
852+ do maybeLoaded <- checkCachedInterfaces root cached
855+ return ROutsideBlocked
858+ do let ifaces = Map.union loaded (Map.fromList same)
859+ return $ compileOutside env local ifaces modul
862+ return ROutsideBlocked
865+compileOutside :: Env -> Details.Local -> Map.Map ModuleName.Raw I.Interface -> Src.Module -> MainResult
866+compileOutside (Env _ _ pkg _ _ _) (Details.Local path time _ _) ifaces modul =
868+ name = Src.getName modul
870+ case Compile.compile pkg ifaces modul of
871+ Right (Compile.Artifacts canonical annotations objects) ->
872+ ROutsideOk name (I.fromModule pkg canonical annotations) objects
875+ ROutsideErr $ Problem.BadContent $
876+ Problem.Module name path time errors (Localizer.fromModule modul)
884+ = Inside ModuleName.Raw
885+ | Outside ModuleName.Raw I.Interface Opt.LocalGraph
888+toArtifacts :: Env -> Dependencies -> Map.Map ModuleName.Raw Result -> NE.List MainResult -> Either Exit.BuildProblem Artifacts
889+toArtifacts (Env _ _ pkg _ _ _) foreigns results mainResults =
890+ case gatherProblemsOrMains results mainResults of
891+ Left (NE.List p ps) ->
892+ Left (Exit.BuildModuleProblems p ps)
895+ Right $ Artifacts pkg foreigns mains $
896+ Map.foldrWithKey addInside (foldr addOutside [] mainResults) results
899+gatherProblemsOrMains :: Map.Map ModuleName.Raw Result -> NE.List MainResult -> Either (NE.List Problem.Problem) (NE.List Main)
900+gatherProblemsOrMains results (NE.List mainResult mainResults) =
902+ sortMain result (ps, mains) =
904+ RInside n -> ( ps, Inside n : mains)
905+ ROutsideOk n i o -> ( ps, Outside n i o : mains)
906+ ROutsideErr p -> (p:ps, mains)
907+ ROutsideBlocked -> ( ps, mains)
909+ problems = Map.foldr addProblem [] results
911+ case (mainResult, foldr sortMain (problems, []) mainResults) of
912+ (RInside n , ( [], ms)) -> Right (NE.List (Inside n) ms)
913+ (RInside _ , (p:ps, _ )) -> Left (NE.List p ps)
914+ (ROutsideOk n i o, ( [], ms)) -> Right (NE.List (Outside n i o) ms)
915+ (ROutsideOk _ _ _, (p:ps, _ )) -> Left (NE.List p ps)
916+ (ROutsideErr p , ( ps, _ )) -> Left (NE.List p ps)
917+ (ROutsideBlocked , ( [], _ )) -> error "seems like elm-stuff/ is corrupted"
918+ (ROutsideBlocked , (p:ps, _ )) -> Left (NE.List p ps)
921+addInside :: ModuleName.Raw -> Result -> [Module] -> [Module]
922+addInside name result modules =
924+ RNew _ iface objs -> Fresh name iface objs : modules
925+ RSame _ iface objs -> Fresh name iface objs : modules
926+ RCached main mvar -> Cached name main mvar : modules
927+ RProblem _ -> error ("I missed the error in `" ++ Name.toChars name ++ "` module.")
928+ RBlocked -> error ("I missed the error in `" ++ Name.toChars name ++ "` module.")
929+ RForeign _ -> modules
933+addOutside :: MainResult -> [Module] -> [Module]
934+addOutside main modules =
936+ RInside _ -> modules
937+ ROutsideOk name iface objs -> Fresh name iface objs : modules
938+ ROutsideErr _ -> modules
939+ ROutsideBlocked -> modules