{-# LANGUAGE TemplateHaskell #-} module Language.Elm.CoreLibs where import Data.FileEmbed import Language.Elm.BuildUtil import Elm.Compiler import Elm.Compiler.Module import qualified Data.Map as Map import qualified Data.Set as Set import qualified Data.List as List import Control.Monad import Data.ByteString.Char8 (unpack) import Data.Maybe (fromJust) import qualified Language.Elm.CoreSources as Sources --The Elm header which we need to append to the top of a linked JS file header :: String header = Sources.header --Pair of the runtime and its name, to be added to a dictionary runtime = (fromJust $ nameFromString "Elm.Native.Runtime", Sources.runtime) --A dictionary mapping names to the JS source code for native modules in the standard library nativeDict = Map.fromList nativePairs where nativePairs = map (\(n,t) -> (fromJust $ nameFromString n, t)) nativeTextPairs nativeTextPairs = Sources.nativeSources --A list of source files for each standard library Elm module sources = Sources.stdlibSources --Dependencies standard lib modules have with each other internalDepsPairs = case (mapM uniqueDeps sources) of Left s -> error $ "Failed parsing stdlib:" ++ s Right pairs -> pairs --The dependency graph of the standard library modules internalDeps :: Dependencies internalDeps = Map.fromList internalDepsPairs --The compiled JavaScript of the entire standard library stdLib :: CompileResult stdLib = case eitherLib of Left s -> error $ "Failed building standard library: " ++ s Right dict -> dict where sourcesDict = Map.fromList $ zip (map fst internalDepsPairs) sources eitherLib = compileAll internalDeps "elm-lang" "core" (Map.empty, Map.empty) sourcesDict --jsSources = --Given a dependency list, return the compile result of the standard library --Omitting unneeded modules stdLibForSources :: Dependencies -> [String] -> Either String CompileResult stdLibForSources deps modules = do let libDeps = Set.filter (importNotNative) $ findStdLibDeps deps let (allJs, allIfaces) = stdLib let js = Map.filterWithKey (\d _ -> Set.member d libDeps ) allJs let ifaces = Map.filterWithKey (\d _ -> Set.member d libDeps ) allIfaces return (js, ifaces) --Find the standard library modules dthat a module depends on moduleStdlibDeps :: String -> Either String [Name] moduleStdlibDeps s = do (name, deps) <- parseDependencies s let stdlibDeps = filter (\d -> Map.member d (fst stdLib)) deps return $ List.nub stdlibDeps --Given a mapping of names to dependencies, expand the dependencies --To inlcude their dependencies, etc. i.e. transitivity findStdLibDeps :: Dependencies -> Set.Set Name findStdLibDeps deps = let depSets = Map.elems deps topWithDefaults = Set.unions $ [Set.fromList defaultImports] ++ depSets --Get dependencies of dependencies in traverseDeps internalDeps topWithDefaults --Given the dependency graph of some sources, find which Native modules it depends on nativesForSources :: Dependencies -> Either String (Map.Map Name String) nativesForSources deps = do let libDeps = findStdLibDeps deps let nativeNames = Set.filter (not . importNotNative ) libDeps return $ Map.filterWithKey (\d _ -> Set.member d nativeNames) nativeDict