1{-# OPTIONS_GHC -Wno-unused-do-bind #-}
2{-# LANGUAGE BangPatterns, OverloadedStrings #-}
14import Control.Concurrent (forkIO)
15import Control.Concurrent.MVar
16import Control.Monad (filterM, mapM_, sequence_)
17import qualified Data.ByteString as B
18import qualified Data.Char as Char
19import qualified Data.Either as Either
20import qualified Data.Graph as Graph
21import qualified Data.List as List
22import qualified Data.Map.Utils as Map
23import qualified Data.Map.Strict as Map
24import Data.Map.Strict ((!))
25import qualified Data.Maybe as Maybe
26import qualified Data.Name as Name
27import qualified Data.NonEmptyList as NE
28import qualified Data.OneOrMore as OneOrMore
29import qualified Data.Set as Set
30import qualified System.Directory as Dir
31import qualified System.FilePath as FP
32import System.FilePath ((</>), (<.>))
34import qualified AST.Source as Src
35import qualified AST.Optimized as Opt
36import qualified Compile
37import qualified Elm.Details as Details
38import qualified Elm.Interface as I
39import qualified Elm.ModuleName as ModuleName
40import qualified Elm.Outline as Outline
41import qualified Elm.Package as Pkg
43import qualified Parse.Module as Parse
44import qualified Reporting
45import qualified Reporting.Annotation as A
46import qualified Reporting.Error as Error
47import qualified Reporting.Error.Syntax as Syntax
48import qualified Reporting.Error.Import as Import
49import qualified Reporting.Exit as Exit
59 { _key :: Reporting.BKey
62 , _srcDirs :: [FilePath]
63 , _locals :: Map.Map ModuleName.Raw Details.Local
64 , _foreigns :: Map.Map ModuleName.Raw Details.Foreign
68makeEnv :: Reporting.BKey -> FilePath -> Details.Details -> Env
69makeEnv key root (Details.Details _ validOutline locals foreigns _) =
71 Details.ValidApp (Outline.AppOutline _ srcDirs _ _ _ _) ->
72 Env key root Pkg.dummyName (NE.toList srcDirs) locals foreigns
74 Details.ValidPkg (Outline.PkgOutline pkg _ _ _ _ _ _ _) _ ->
75 Env key root pkg ["src"] locals foreigns
82fork :: IO a -> IO (MVar a)
84 do mvar <- newEmptyMVar
85 _ <- forkIO $ putMVar mvar =<< work
89{-# INLINE forkWithKey #-}
90forkWithKey :: (k -> a -> IO b) -> Map.Map k a -> IO (Map.Map k (MVar b))
91forkWithKey func dict =
92 Map.traverseWithKey (\k v -> fork (func k v)) dict
99fromExposed :: Reporting.Style -> FilePath -> Details.Details -> NE.List ModuleName.Raw -> IO (Either Exit.BuildProblem ())
100fromExposed style root details (NE.List e es) =
101 Reporting.trackBuild style $ \key ->
102 do let env = makeEnv key root details
103 dmvar <- Details.loadInterfaces root details
107 roots <- Map.fromKeysA (fork . crawlModule env mvar) (e:es)
110 statuses <- traverse readMVar =<< readMVar mvar
113 midpoint <- checkExposedMidpoint dmvar statuses
116 return (Left (Exit.BuildProjectProblem problem))
119 do rmvar <- newEmptyMVar
120 resultMVars <- forkWithKey (checkModule env foreigns rmvar) statuses
121 putMVar rmvar resultMVars
122 results <- traverse readMVar resultMVars
123 writeDetails root details results
124 return (detectProblems results) -- TODO error if "exposed-modules" are not found
134 , _deps :: Dependencies
135 , _mains :: NE.List Main
136 , _modules :: [Module]
141 = Fresh ModuleName.Raw I.Interface Opt.LocalGraph
142 | Cached ModuleName.Raw Bool (MVar CachedInterface)
146 Map.Map ModuleName.Canonical I.DependencyInterface
149fromMains :: Reporting.Style -> FilePath -> Details.Details -> NE.List FilePath -> IO (Either Exit.BuildProblem Artifacts)
150fromMains style root details paths =
151 Reporting.trackBuild style $ \key ->
152 do let env = makeEnv key root details
154 elmains <- findMains env paths
157 return (Left (Exit.BuildProjectProblem problem))
161 dmvar <- Details.loadInterfaces root details
162 smvar <- newMVar Map.empty
163 smainMVars <- traverse (fork . crawlMain env smvar) lmains
164 smains <- traverse readMVar smainMVars
165 statuses <- traverse readMVar =<< readMVar smvar
167 midpoint <- checkMainsMidpoint dmvar statuses smains
170 return (Left (Exit.BuildProjectProblem problem))
174 rmvar <- newEmptyMVar
175 resultsMVars <- forkWithKey (checkModule env foreigns rmvar) statuses
176 putMVar rmvar resultsMVars
177 rmainMVars <- traverse (fork . checkMain env resultsMVars) smains
178 results <- traverse readMVar resultsMVars
179 writeDetails root details results
180 toArtifacts env foreigns results <$> traverse readMVar rmainMVars
188 Map.Map ModuleName.Raw (MVar Status)
192 = SCached Details.Local
193 | SChanged Details.Local B.ByteString Src.Module
194 | SBadImport Import.Problem
195 | SBadSyntax FilePath File.Time B.ByteString Syntax.Error
200crawlDeps :: Env -> MVar StatusDict -> [ModuleName.Raw] -> a -> IO a
201crawlDeps env mvar deps blockedValue =
202 do statusDict <- takeMVar mvar
203 let depsDict = Map.fromKeys (\_ -> ()) deps
204 let newsDict = Map.difference depsDict statusDict
205 statuses <- Map.traverseWithKey crawlNew newsDict
206 putMVar mvar (Map.union statuses statusDict)
207 mapM_ readMVar statuses
210 crawlNew name () = fork (crawlModule env mvar name)
213crawlModule :: Env -> MVar StatusDict -> ModuleName.Raw -> IO Status
214crawlModule env@(Env _ root pkg srcDirs locals foreigns) mvar name =
215 do let fileName = ModuleName.toFilePath name <.> "elm"
216 let inRoot path = File.exists (root </> path)
218 paths <- filterM inRoot (map (</> fileName) srcDirs)
222 case Map.lookup name foreigns of
223 Just (Details.Foreign dep deps) ->
224 return $ SBadImport $ Import.Ambiguous path [] dep deps
227 case Map.lookup name locals of
229 crawlFile env mvar name path
231 Just local@(Details.Local oldPath oldTime deps _) ->
233 then crawlFile env mvar name path
235 do newTime <- File.getTime path
237 then crawlFile env mvar name path
238 else crawlDeps env mvar deps (SCached local)
241 return $ SBadImport $ Import.AmbiguousLocal p1 p2 ps
244 case Map.lookup name foreigns of
245 Just (Details.Foreign dep deps) ->
248 return $ SForeign dep
251 return $ SBadImport $ Import.AmbiguousForeign dep d ds
254 if Name.isKernel name && Pkg.isKernel pkg then
255 do exists <- File.exists ("src" </> ModuleName.toFilePath name <.> "js")
256 return $ if exists then SKernel else SBadImport Import.NotFound
258 return $ SBadImport Import.NotFound
261crawlFile :: Env -> MVar StatusDict -> ModuleName.Raw -> FilePath -> IO Status
262crawlFile env@(Env _ root pkg _ _ _) mvar expectedName path =
263 do time <- File.getTime path
264 source <- File.readUtf8 (root </> path)
266 case Parse.fromByteString pkg source of
268 return $ SBadSyntax path time source err
270 Right modul@(Src.Module maybeActualName _ imports values _ _ _ _) ->
271 case maybeActualName of
273 return $ SBadSyntax path time source (Syntax.ModuleNameUnspecified expectedName)
275 Just name@(A.At _ actualName) ->
276 if expectedName == actualName then
278 deps = map Src.getImportName imports
279 local = Details.Local path time deps (any isMain values)
281 crawlDeps env mvar deps (SChanged local source modul)
283 return $ SBadSyntax path time source (Syntax.ModuleNameMismatch expectedName name)
286isMain :: A.Located Src.Value -> Bool
287isMain (A.At _ (Src.Value (A.At _ name) _ _ _)) =
296 Map.Map ModuleName.Raw (MVar Result)
300 = RNew Details.Local I.Interface Opt.LocalGraph
301 | RSame Details.Local I.Interface Opt.LocalGraph
302 | RCached Bool (MVar CachedInterface)
303 | RNotFound Import.Problem
304 | RProblem Error.Module
306 | RForeign I.Interface
316checkModule :: Env -> Dependencies -> MVar ResultDict -> ModuleName.Raw -> Status -> IO Result
317checkModule env@(Env _ root pkg _ _ _) foreigns resultsMVar name status =
319 SCached local@(Details.Local path time deps hasMain) ->
320 do results <- readMVar resultsMVar
321 depsStatus <- checkDeps root results deps
324 do source <- File.readUtf8 path
325 case Parse.fromByteString pkg source of
326 Right modul -> compile env local source ifaces modul
329 Error.Module name path time source (Error.BadSyntax err)
332 do mvar <- newMVar Unneeded
333 return (RCached hasMain mvar)
338 DepsNotFound problems ->
339 do source <- File.readUtf8 path
340 return $ RProblem $ Error.Module name path time source $
341 case Parse.fromByteString pkg source of
342 Right (Src.Module _ _ imports _ _ _ _ _) ->
343 Error.BadImports (toImportErrors env results imports problems)
348 SChanged local@(Details.Local path time deps _) source modul@(Src.Module _ _ imports _ _ _ _ _) ->
349 do results <- readMVar resultsMVar
350 depsStatus <- checkDeps root results deps
353 compile env local source ifaces modul
355 DepsSame same cached ->
356 do maybeLoaded <- checkCachedInterfaces root cached
362 do let ifaces = Map.union loaded (Map.fromList same)
363 compile env local source ifaces modul
368 DepsNotFound problems ->
369 return $ RProblem $ Error.Module name path time source $
370 Error.BadImports (toImportErrors env results imports problems)
372 SBadImport importProblem ->
373 return (RNotFound importProblem)
375 SBadSyntax path time source err ->
376 return $ RProblem $ Error.Module name path time source $
380 case foreigns ! ModuleName.Canonical home name of
381 I.Public iface -> return (RForeign iface)
382 I.Private _ _ _ -> error "loading private interface in Build"
393 = DepsChange (Map.Map ModuleName.Raw I.Interface)
394 | DepsSame [Dep] [CDep]
396 | DepsNotFound (NE.List (ModuleName.Raw, Import.Problem))
399checkDeps :: FilePath -> ResultDict -> [ModuleName.Raw] -> IO DepsStatus
400checkDeps root results deps =
401 checkDepsHelp root results deps [] [] [] [] False
404type Dep = (ModuleName.Raw, I.Interface)
405type CDep = (ModuleName.Raw, MVar CachedInterface)
408checkDepsHelp :: FilePath -> ResultDict -> [ModuleName.Raw] -> [Dep] -> [Dep] -> [CDep] -> [(ModuleName.Raw,Import.Problem)] -> Bool -> IO DepsStatus
409checkDepsHelp root results deps new same cached importProblems isBlocked =
412 do result <- readMVar (results ! dep)
414 RNew _ iface _ -> checkDepsHelp root results otherDeps ((dep,iface) : new) same cached importProblems isBlocked
415 RSame _ iface _ -> checkDepsHelp root results otherDeps new ((dep,iface) : same) cached importProblems isBlocked
416 RCached _ mvar -> checkDepsHelp root results otherDeps new same ((dep,mvar) : cached) importProblems isBlocked
417 RNotFound prob -> checkDepsHelp root results otherDeps new same cached ((dep,prob) : importProblems) True
418 RProblem _ -> checkDepsHelp root results otherDeps new same cached importProblems True
419 RBlocked -> checkDepsHelp root results otherDeps new same cached importProblems True
420 RForeign iface -> checkDepsHelp root results otherDeps new ((dep,iface) : same) cached importProblems isBlocked
421 RKernel -> checkDepsHelp root results otherDeps new same cached importProblems isBlocked
424 case importProblems of
426 return $ DepsNotFound (NE.List p ps)
432 else if null new then
433 return $ DepsSame same cached
436 do maybeLoaded <- checkCachedInterfaces root cached
442 return $ DepsChange $
443 Map.union loaded (Map.union (Map.fromList new) (Map.fromList same))
450toImportErrors :: Env -> ResultDict -> [Src.Import] -> NE.List (ModuleName.Raw, Import.Problem) -> NE.List Import.Error
451toImportErrors (Env _ _ _ _ locals foreigns) results imports problems =
455 [ Map.keysSet foreigns
457 , Map.keysSet results
461 Set.difference knownModules (Set.fromList (map Src.getImportName imports))
464 Map.fromList (map (\(Src.Import (A.At region name) _ _) -> (name, region)) imports)
466 toError (name, problem) =
467 Import.Error (regionDict ! name) name unimportedModules problem
469 fmap toError problems
476checkCachedInterfaces :: FilePath -> [(ModuleName.Raw, MVar CachedInterface)] -> IO (Maybe (Map.Map ModuleName.Raw I.Interface))
477checkCachedInterfaces root deps =
478 do loading <- traverse (fork . checkCache root) deps
479 loaded <- traverse readMVar loading
480 return $ Map.fromList <$> sequence loaded
483checkCache :: FilePath -> (ModuleName.Raw, MVar CachedInterface) -> IO (Maybe Dep)
484checkCache root (name, ciMvar) =
485 do cachedInterface <- takeMVar ciMvar
486 case cachedInterface of
488 do putMVar ciMvar cachedInterface
492 do putMVar ciMvar cachedInterface
493 return (Just (name, iface))
496 do maybeIface <- File.readBinary (Stuff.elmi root name)
499 do putMVar ciMvar Corrupted
503 do putMVar ciMvar (Loaded iface)
504 return (Just (name, iface))
511checkExposedMidpoint :: MVar (Maybe Dependencies) -> Map.Map ModuleName.Raw Status -> IO (Either Exit.BuildProjectProblem Dependencies)
512checkExposedMidpoint dmvar statuses =
513 case checkForCycles statuses of
515 do maybeForeigns <- readMVar dmvar
516 case maybeForeigns of
517 Nothing -> return (Left Exit.BP_CannotLoadDependencies)
518 Just fs -> return (Right fs)
520 Just (NE.List name names) ->
521 do _ <- readMVar dmvar
522 return (Left (Exit.BP_Cycle name names))
525checkMainsMidpoint :: MVar (Maybe Dependencies) -> Map.Map ModuleName.Raw Status -> NE.List MainStatus -> IO (Either Exit.BuildProjectProblem Dependencies)
526checkMainsMidpoint dmvar statuses smains =
527 case checkForCycles statuses of
529 case checkUniqueMains statuses smains of
531 do maybeForeigns <- readMVar dmvar
532 case maybeForeigns of
533 Nothing -> return (Left Exit.BP_CannotLoadDependencies)
534 Just fs -> return (Right fs)
537 do _ <- readMVar dmvar
538 return (Left problem)
540 Just (NE.List name names) ->
541 do _ <- readMVar dmvar
542 return (Left (Exit.BP_Cycle name names))
549checkForCycles :: Map.Map ModuleName.Raw Status -> Maybe (NE.List ModuleName.Raw)
550checkForCycles modules =
552 !graph = Map.foldrWithKey addToGraph [] modules
553 !sccs = Graph.stronglyConnComp graph
555 checkForCyclesHelp sccs
558checkForCyclesHelp :: [Graph.SCC ModuleName.Raw] -> Maybe (NE.List ModuleName.Raw)
559checkForCyclesHelp sccs =
566 Graph.AcyclicSCC _ -> checkForCyclesHelp otherSccs
567 Graph.CyclicSCC [] -> checkForCyclesHelp otherSccs
568 Graph.CyclicSCC (m:ms) -> Just (NE.List m ms)
572 ( ModuleName.Raw, ModuleName.Raw, [ModuleName.Raw] )
575addToGraph :: ModuleName.Raw -> Status -> [Node] -> [Node]
576addToGraph name status graph =
580 SCached (Details.Local _ _ deps _) -> deps
581 SChanged (Details.Local _ _ deps _) _ _ -> deps
583 SBadSyntax _ _ _ _ -> []
587 (name, name, dependencies) : graph
594checkUniqueMains :: Map.Map ModuleName.Raw Status -> NE.List MainStatus -> Maybe Exit.BuildProjectProblem
595checkUniqueMains insides smains =
598 Map.fromListWith OneOrMore.more (Maybe.mapMaybe mainStatusToNamePathPair (NE.toList smains))
600 case Map.traverseWithKey checkOutside outsidesDict of
605 case sequence_ (Map.intersectionWithKey checkInside outsides insides) of
607 Left problem -> Just problem
610mainStatusToNamePathPair :: MainStatus -> Maybe (ModuleName.Raw, OneOrMore.OneOrMore FilePath)
611mainStatusToNamePathPair smain =
614 SOutsideOk (Details.Local path _ _ _) _ modul -> Just (Src.getName modul, OneOrMore.one path)
615 SOutsideErr _ -> Nothing
618checkOutside :: ModuleName.Raw -> OneOrMore.OneOrMore FilePath -> Either Exit.BuildProjectProblem FilePath
619checkOutside name paths =
620 case OneOrMore.destruct NE.List paths of
621 NE.List p [] -> Right p
622 NE.List p1 (p2:_) -> Left (Exit.BP_MainNameDuplicate name p1 p2)
625checkInside :: ModuleName.Raw -> FilePath -> Status -> Either Exit.BuildProjectProblem ()
626checkInside name p1 status =
628 SCached (Details.Local p2 _ _ _) -> Left (Exit.BP_MainNameDuplicate name p1 p2)
629 SChanged (Details.Local p2 _ _ _) _ _ -> Left (Exit.BP_MainNameDuplicate name p1 p2)
630 SBadImport _ -> Right ()
631 SBadSyntax _ _ _ _ -> Right ()
632 SForeign _ -> Right ()
640compile :: Env -> Details.Local -> B.ByteString -> Map.Map ModuleName.Raw I.Interface -> Src.Module -> IO Result
641compile (Env key root pkg _ _ _) local@(Details.Local path time _ _) source ifaces modul =
642 case Compile.compile pkg ifaces modul of
643 Right (Compile.Artifacts canonical annotations objects) ->
644 do let name = Src.getName modul
645 let iface = I.fromModule pkg canonical annotations
646 File.writeBinary (Stuff.elmo root name) objects
647 maybeOldi <- File.readBinary (Stuff.elmi root name)
649 Just oldi | oldi == iface ->
650 do -- iface should be fully forced by equality check
651 Reporting.report key Reporting.BDone
652 return (RSame local iface objects)
655 do -- iface may be lazy still
656 -- TODO try adding forkIO here
657 File.writeBinary (Stuff.elmi root name) iface
658 Reporting.report key Reporting.BDone
659 return (RNew local iface objects)
662 do Reporting.report key Reporting.BDone
664 Error.Module (Src.getName modul) path time source err
671writeDetails :: FilePath -> Details.Details -> Map.Map ModuleName.Raw Result -> IO ()
672writeDetails root (Details.Details time outline locals foreigns extras) results =
673 File.writeBinary (Stuff.details root) $
674 Details.Details time outline (Map.foldrWithKey addNewLocal locals results) foreigns extras
677addNewLocal :: ModuleName.Raw -> Result -> Map.Map ModuleName.Raw Details.Local -> Map.Map ModuleName.Raw Details.Local
678addNewLocal name result locals =
680 RNew local _ _ -> Map.insert name local locals
681 RSame local _ _ -> Map.insert name local locals
682 RCached _ _ -> locals
683 RNotFound _ -> locals
694detectProblems :: Map.Map ModuleName.Raw Result -> Either Exit.BuildProblem ()
695detectProblems results =
696 case Map.foldr addErrors [] results of
698 e:es -> Left (Exit.BuildModuleProblems e es)
701addErrors :: Result -> [Error.Module] -> [Error.Module]
702addErrors result errors =
705 RSame _ _ _ -> errors
706 RCached _ _ -> errors
707 RNotFound _ -> errors
708 RProblem e -> e:errors
715--------------------------------------------------------------------------------
716--------------------------------------------------------------------------------
717------ AFTER THIS, EVERYTHING IS ABOUT HANDLING MODULES GIVEN BY FILEPATH ------
718--------------------------------------------------------------------------------
719--------------------------------------------------------------------------------
727 = LInside ModuleName.Raw
731findMains :: Env -> NE.List FilePath -> IO (Either Exit.BuildProjectProblem (NE.List MainLocation))
733 do mvars <- traverse (fork . findLocation env) paths
734 elocs <- traverse readMVar mvars
735 return $ checkLocations =<< sequence elocs
738checkLocations :: NE.List Location -> Either Exit.BuildProjectProblem (NE.List MainLocation)
739checkLocations locations =
741 toOneOrMore loc@(Location absolute _ _) =
742 (absolute, OneOrMore.one loc)
744 fromOneOrMore loc locs =
747 loc2:_ -> Left (Exit.BP_MainPathDuplicate (_relative loc) (_relative loc2))
749 fmap (\_ -> fmap _location locations) $
750 traverse (OneOrMore.destruct fromOneOrMore) $
751 Map.fromListWith OneOrMore.more $ map toOneOrMore (NE.toList locations)
760 { _absolute :: FilePath
761 , _relative :: FilePath
762 , _location :: MainLocation
766findLocation :: Env -> FilePath -> IO (Either Exit.BuildProjectProblem Location)
767findLocation env path =
768 do exists <- File.exists path
770 then isInsideSrcDirs env path <$> Dir.canonicalizePath path
771 else return (Left (Exit.BP_PathUnknown path))
774isInsideSrcDirs :: Env -> FilePath -> FilePath -> Either Exit.BuildProjectProblem Location
775isInsideSrcDirs (Env _ root _ srcDirs _ _) path absolutePath =
777 (dirs, file) = FP.splitFileName absolutePath
778 (final, ext) = break (=='.') file
781 then Left (Exit.BP_WithBadExtension path)
784 roots = FP.splitDirectories root
785 segments = FP.splitDirectories dirs ++ [final]
787 case dropPrefix roots segments of
789 Right (Location absolutePath path (LOutside path))
791 Just relativeSegments ->
794 Either.partitionEithers (map (isInsideSrcDirsHelp relativeSegments) srcDirs)
796 -- TODO make sure this is all correct
797 case (exits, Maybe.catMaybes maybes) of
798 (_, [(_,name)]) -> Right (Location absolutePath path (LInside name))
799 ([], []) -> Right (Location absolutePath path (LOutside path))
800 (_, (s1,_):(s2,_):_) -> Left (Exit.BP_WithAmbiguousSrcDir s1 s2)
801 (exit:_, _) -> Left exit
804isInsideSrcDirsHelp :: [String] -> FilePath -> Either Exit.BuildProjectProblem (Maybe (FilePath, ModuleName.Raw))
805isInsideSrcDirsHelp segments srcDir =
806 case dropPrefix (FP.splitDirectories srcDir) segments of
811 if all isGoodName names
812 then Right (Just (srcDir, Name.fromChars (List.intercalate "." names)))
813 else Left (error "Exit.MakeWithInvalidModuleName" srcDir segments)
816isGoodName :: [Char] -> Bool
823 Char.isUpper char && all (\c -> Char.isAlphaNum c || c == '_') chars
826dropPrefix :: [FilePath] -> [FilePath] -> Maybe [FilePath]
827dropPrefix roots paths =
835 p:ps -> if r == p then dropPrefix rs ps else Nothing
843 = SInside ModuleName.Raw
844 | SOutsideOk Details.Local B.ByteString Src.Module
845 | SOutsideErr Error.Module
848crawlMain :: Env -> MVar StatusDict -> MainLocation -> IO MainStatus
849crawlMain env@(Env _ _ pkg _ _ _) mvar given =
852 do statusMVar <- newEmptyMVar
853 statusDict <- takeMVar mvar
854 putMVar mvar (Map.insert name statusMVar statusDict)
855 putMVar statusMVar =<< crawlModule env mvar name
856 return (SInside name)
859 do time <- File.getTime path
860 source <- File.readUtf8 path
861 case Parse.fromByteString pkg source of
862 Right modul@(Src.Module _ _ imports values _ _ _ _) ->
863 do let deps = map Src.getImportName imports
864 let local = Details.Local path time deps (any isMain values)
865 crawlDeps env mvar deps (SOutsideOk local source modul)
868 return $ SOutsideErr $
869 Error.Module "???" path time source (Error.BadSyntax syntaxError)
877 = RInside ModuleName.Raw
878 | ROutsideOk ModuleName.Raw I.Interface Opt.LocalGraph
879 | ROutsideErr Error.Module
883checkMain :: Env -> ResultDict -> MainStatus -> IO MainResult
884checkMain env@(Env _ root _ _ _ _) results pendingMain =
887 return (RInside name)
890 return (ROutsideErr err)
892 SOutsideOk local@(Details.Local path time deps _) source modul@(Src.Module _ _ imports _ _ _ _ _) ->
893 do depsStatus <- checkDeps root results deps
896 return $ compileOutside env local source ifaces modul
898 DepsSame same cached ->
899 do maybeLoaded <- checkCachedInterfaces root cached
902 return ROutsideBlocked
905 do let ifaces = Map.union loaded (Map.fromList same)
906 return $ compileOutside env local source ifaces modul
909 return ROutsideBlocked
911 DepsNotFound problems ->
912 return $ ROutsideErr $ Error.Module (Src.getName modul) path time source $
913 Error.BadImports (toImportErrors env results imports problems)
916compileOutside :: Env -> Details.Local -> B.ByteString -> Map.Map ModuleName.Raw I.Interface -> Src.Module -> MainResult
917compileOutside (Env _ _ pkg _ _ _) (Details.Local path time _ _) source ifaces modul =
919 name = Src.getName modul
921 case Compile.compile pkg ifaces modul of
922 Right (Compile.Artifacts canonical annotations objects) ->
923 ROutsideOk name (I.fromModule pkg canonical annotations) objects
927 Error.Module name path time source errors
935 = Inside ModuleName.Raw
936 | Outside ModuleName.Raw I.Interface Opt.LocalGraph
939toArtifacts :: Env -> Dependencies -> Map.Map ModuleName.Raw Result -> NE.List MainResult -> Either Exit.BuildProblem Artifacts
940toArtifacts (Env _ _ pkg _ _ _) foreigns results mainResults =
941 case gatherProblemsOrMains results mainResults of
942 Left (NE.List e es) ->
943 Left (Exit.BuildModuleProblems e es)
946 Right $ Artifacts pkg foreigns mains $
947 Map.foldrWithKey addInside (foldr addOutside [] mainResults) results
950gatherProblemsOrMains :: Map.Map ModuleName.Raw Result -> NE.List MainResult -> Either (NE.List Error.Module) (NE.List Main)
951gatherProblemsOrMains results (NE.List mainResult mainResults) =
953 sortMain result (es, mains) =
955 RInside n -> ( es, Inside n : mains)
956 ROutsideOk n i o -> ( es, Outside n i o : mains)
957 ROutsideErr e -> (e:es, mains)
958 ROutsideBlocked -> ( es, mains)
960 errors = Map.foldr addErrors [] results
962 case (mainResult, foldr sortMain (errors, []) mainResults) of
963 (RInside n , ( [], ms)) -> Right (NE.List (Inside n) ms)
964 (RInside _ , (e:es, _ )) -> Left (NE.List e es)
965 (ROutsideOk n i o, ( [], ms)) -> Right (NE.List (Outside n i o) ms)
966 (ROutsideOk _ _ _, (e:es, _ )) -> Left (NE.List e es)
967 (ROutsideErr e , ( es, _ )) -> Left (NE.List e es)
968 (ROutsideBlocked , ( [], _ )) -> error "seems like elm-stuff/ is corrupted"
969 (ROutsideBlocked , (e:es, _ )) -> Left (NE.List e es)
972addInside :: ModuleName.Raw -> Result -> [Module] -> [Module]
973addInside name result modules =
975 RNew _ iface objs -> Fresh name iface objs : modules
976 RSame _ iface objs -> Fresh name iface objs : modules
977 RCached main mvar -> Cached name main mvar : modules
978 RNotFound _ -> error (badInside name)
979 RProblem _ -> error (badInside name)
980 RBlocked -> error (badInside name)
981 RForeign _ -> modules
985badInside :: ModuleName.Raw -> [Char]
987 "Error from `" ++ Name.toChars name ++ "` should have been reported already."
990addOutside :: MainResult -> [Module] -> [Module]
991addOutside main modules =
994 ROutsideOk name iface objs -> Fresh name iface objs : modules
995 ROutsideErr _ -> modules
996 ROutsideBlocked -> modules
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list