on master help sign in
Try to purge everything that's moving to elm-package or elm-make
commitf476ba76a9e85b5bf597afb1c8b7894b9629200e authorEvan Czaplicki <info@elm-lang.org> dateTue 7 Oct 2014, 21:34 (12 years ago) parent89ba043
16 files changed+119−726
Elm.cabal+8−13 compiler/AST/Module.hs+3−3 compiler/Build/Dependencies.hs−158 compiler/Build/File.hs−176 compiler/Build/Flags.hs+4−3 compiler/Build/Interface.hs+6−4 compiler/Build/Utils.hs+9 compiler/Compiler.hs+9−21 compiler/Elm/Compiler.hs+69 compiler/Elm/Compiler/Version.hs+10 compiler/Elm/Internal/Dependencies.hs−156 compiler/Elm/Internal/Name.hs−51 compiler/Elm/Internal/Paths.hs−24 compiler/Elm/Internal/Utils.hs−35 compiler/Elm/Internal/Version.hs−73 compiler/Parse/Parse.hs+1−9
Elm.cabal+8−13
@@ -30,14 +30,11 @@ source-repository head
3030 location: git://github.com/elm-lang/Elm.git
3131
3232Library
33− exposed-modules: Elm.Internal.Dependencies,
34− Elm.Internal.Documentation,
35− Elm.Internal.Name,
36− Elm.Internal.Paths,
37− Elm.Internal.Utils,
38− Elm.Internal.Version
33+ exposed-modules: Elm.Compiler,
34+ Elm.Internal.Documentation
3935 Hs-Source-Dirs: compiler
40− other-modules: AST.Annotation,
36+ other-modules: Elm.Compiler.Version,
37+ AST.Annotation,
4138 AST.Declaration,
4239 AST.Expression.General,
4340 AST.Expression.Source,
@@ -91,8 +88,6 @@ Library
9188 Type.State,
9289 Type.Type,
9390 Type.Unify,
94− Build.Dependencies,
95− Build.File,
9691 Build.Flags,
9792 Build.Interface,
9893 Build.Print,
@@ -128,7 +123,8 @@ Executable elm
128123 Main-is: Compiler.hs
129124 ghc-options: -threaded -O2
130125 Hs-Source-Dirs: compiler
131− other-modules: AST.Annotation,
126+ other-modules: Elm.Compiler.Version,
127+ AST.Annotation,
132128 AST.Declaration,
133129 AST.Expression.General,
134130 AST.Expression.Source,
@@ -182,8 +178,6 @@ Executable elm
182178 Type.State,
183179 Type.Type,
184180 Type.Unify,
185− Build.Dependencies,
186− Build.File,
187181 Build.Flags,
188182 Build.Interface,
189183 Build.Print,
@@ -218,7 +212,8 @@ Executable elm
218212Executable elm-doc
219213 Main-is: Docs.hs
220214 Hs-Source-Dirs: compiler
221− other-modules: AST.Annotation,
215+ other-modules: Elm.Compiler.Version,
216+ AST.Annotation,
222217 AST.Declaration,
223218 AST.Expression.General,
224219 AST.Helpers,
compiler/AST/Module.hs+3−3
@@ -11,8 +11,8 @@ import qualified AST.Declaration as Decl
1111import qualified AST.Type as Type
1212import qualified AST.Variable as Var
1313import AST.PrettyPrint
14+import qualified Elm.Compiler.Version as Compiler
1415import Text.PrettyPrint as P
15−import qualified Elm.Internal.Version as Version
1616
1717
1818-- HELPFUL TYPE ALIASES
@@ -79,7 +79,7 @@ nameToString = List.intercalate "."
7979
8080{-| Key facts about a module, used when reading info from .elmi files. -}
8181data Interface = Interface
82− { iVersion :: Version.Version
82+ { iVersion :: String
8383 , iExports :: [Var.Value]
8484 , iTypes :: Types
8585 , iImports :: [(String, ImportMethod)]
@@ -93,7 +93,7 @@ toInterface :: CanonicalModule -> Interface
9393toInterface modul =
9494 let body' = body modul in
9595 Interface
96− { iVersion = Version.elmVersion
96+ { iVersion = Compiler.version
9797 , iExports = exports modul
9898 , iTypes = types body'
9999 , iImports = imports modul
compiler/Build/Dependencies.hsdeleted−158
@@ -1,158 +0,0 @@
1−{-# OPTIONS_GHC -W #-}
2−module Build.Dependencies (Recipe(..), getBuildRecipe, readDeps) where
3−
4−import Control.Monad.Error
5−import qualified Control.Monad.State as State
6−import qualified Data.Graph as Graph
7−import qualified Data.List as List
8−import qualified Data.Map as Map
9−import qualified Data.Set as Set
10−import System.Directory
11−import System.FilePath as FP
12−
13−import qualified AST.Module as Module
14−import qualified Parse.Parse as Parse
15−import qualified Elm.Internal.Paths as Path
16−import qualified Elm.Internal.Name as N
17−import qualified Elm.Internal.Version as V
18−import qualified Elm.Internal.Dependencies as Deps
19−
20−data Recipe = Recipe
21− { _elmFiles :: [FilePath]
22− , _jsFiles :: [FilePath]
23− }
24−
25−getBuildRecipe :: [FilePath] -> Module.Interfaces -> FilePath -> ErrorT String IO Recipe
26−getBuildRecipe srcDirs builtIns root =
27− do directories <- getDependencies
28− jsFiles <- nativeFiles ("." : directories)
29− let allSrcDirs = srcDirs ++ directories
30− nodes <- collectDependencies allSrcDirs builtIns root
31− elmFiles <- sortElmFiles nodes
32− return (Recipe elmFiles jsFiles)
33−
34−-- | Based on the projects elm_dependencies.json, find all of the paths and
35−-- dependency information we might need.
36−getDependencies :: ErrorT String IO [FilePath]
37−getDependencies =
38− do exists <- liftIO $ doesFileExist Path.dependencyFile
39− if not exists then return [] else getPaths
40− where
41− getPaths :: ErrorT String IO [FilePath]
42− getPaths =
43− Deps.withDeps Path.dependencyFile $ \deps ->
44− mapM getPath (Deps.dependencies deps)
45−
46− getPath :: (N.Name, V.Version) -> ErrorT String IO FilePath
47− getPath (name,version) = do
48− let path = Path.dependencyDirectory </> N.toFilePath name </> show version
49− exists <- liftIO $ doesDirectoryExist path
50− if exists
51− then return path
52− else throwError (notFound name version)
53−
54− notFound :: N.Name -> V.Version -> String
55− notFound name version =
56− unlines
57− [ "Your " ++ Path.dependencyFile ++ " file says you depend on library"
58− , show name ++ " " ++ show version ++ " but it was not found."
59− , "You may need to install it with:"
60− , ""
61− , " elm-get install " ++ show name ++ " " ++ show version ]
62−
63−nativeFiles :: [FilePath] -> ErrorT String IO [FilePath]
64−nativeFiles directories =
65− do exists <- liftIO $ doesFileExist Path.dependencyFile
66− if not exists
67− then return []
68− else concat `fmap` mapM getNativeFiles directories
69− where
70− getNativeFiles dir =
71− Deps.withDeps (dir </> Path.dependencyFile) $ \deps ->
72− return (map (toPath dir) (Deps.native deps))
73−
74− toPath dir moduleName =
75− dir </> joinPath (split moduleName) <.> "js"
76−
77−split :: String -> [String]
78−split moduleName = go [] moduleName
79− where
80− go paths str =
81− case break (=='.') str of
82− (path, _:rest) -> go (paths ++ [path]) rest
83− (path, []) -> paths ++ [path]
84−
85−type DependencyNode = (FilePath, String, [String])
86−
87−sortElmFiles :: [DependencyNode] -> ErrorT String IO [FilePath]
88−sortElmFiles depends =
89− if null mistakes
90− then return (concat sccs)
91− else throwError $ msg ++ unlines (map show mistakes)
92− where
93− sccs = map Graph.flattenSCC $ Graph.stronglyConnComp depends
94−
95− mistakes = filter (\scc -> length scc > 1) sccs
96− msg = "A cyclical module dependency or was detected in:\n"
97−
98−collectDependencies :: [FilePath] -> Module.Interfaces -> FilePath
99− -> ErrorT String IO [DependencyNode]
100−collectDependencies srcDirs rawBuiltIns filePath =
101− State.evalStateT (go Nothing filePath) Set.empty
102− where
103− builtIns :: Set.Set String
104− builtIns = Set.fromList $ Map.keys rawBuiltIns
105−
106− go :: Maybe String -> FilePath -> State.StateT (Set.Set String) (ErrorT String IO) [DependencyNode]
107− go parentModuleName filePath = do
108− filePath' <- lift $ findSrcFile parentModuleName srcDirs filePath
109− (moduleName, deps) <- lift $ readDeps filePath'
110− seen <- State.get
111− let realDeps = Set.difference (Set.fromList deps) builtIns
112− newDeps = Set.difference (Set.filter (not . isNative) realDeps) seen
113− State.put (Set.insert moduleName (Set.union newDeps seen))
114− rest <- mapM (go (Just moduleName) . toFilePath) (Set.toList newDeps)
115− return ((makeRelative "." filePath', moduleName, Set.toList realDeps) : concat rest)
116−
117−readDeps :: FilePath -> ErrorT String IO (String, [String])
118−readDeps path = do
119− txt <- lift $ readFile path
120− case Parse.dependencies txt of
121− Right o -> return o
122− Left err -> throwError $ msg ++ show err
123− where msg = "Error resolving dependencies in " ++ path ++ ":\n"
124−
125−findSrcFile :: Maybe String -> [FilePath] -> FilePath -> ErrorT String IO FilePath
126−findSrcFile parentModuleName dirs path =
127− foldr tryDir notFound dirs
128− where
129− tryDir dir next = do
130− let path' = dir </> path
131− exists <- liftIO $ doesFileExist path'
132− if exists
133− then return path'
134− else next
135−
136− parentModuleName' =
137− case parentModuleName of
138− Just name -> "module '" ++ name ++ "'"
139− Nothing -> "the main module"
140−
141− notFound = throwError $ unlines
142− [ "When finding the imports declared in " ++ parentModuleName' ++ ", could not find file: " ++ path
143− , " If you created this module, but it is in a subdirectory that does not"
144− , " exactly match the module name, you may need to use the --src-dir flag."
145− , ""
146− , " If it is part of a 3rd party library, it needs to be declared"
147− , " as a dependency in your project's " ++ Path.dependencyFile ++ " file."
148− ]
149−
150−isNative :: String -> Bool
151−isNative name = List.isPrefixOf "Native." name
152−
153−toFilePath :: String -> FilePath
154−toFilePath name = map swapDots name ++ ext
155− where
156− swapDots '.' = '/'
157− swapDots c = c
158− ext = if isNative name then ".js" else ".elm"
compiler/Build/File.hsdeleted−176
@@ -1,176 +0,0 @@
1−{-# OPTIONS_GHC -W #-}
2−module Build.File (build) where
3−
4−import Control.Applicative ((<$>))
5−import Control.Monad.Error (runErrorT)
6−import Control.Monad.RWS.Strict
7−import System.Directory
8−import System.Exit
9−import System.FilePath
10−import System.IO
11−
12−import qualified Data.Binary as Binary
13−import qualified Data.List as List
14−import qualified Data.Maybe as Maybe
15−import qualified Data.Map as Map
16−import qualified Data.ByteString.Lazy as L
17−
18−import qualified Build.Dependencies as Deps
19−import qualified Build.Flags as Flag
20−import qualified Build.Interface as Interface
21−import qualified Build.Print as Print
22−import qualified Build.Source as Source
23−import qualified Build.Utils as Utils
24−import qualified Generate.JavaScript as JS
25−import qualified Parse.Module as Parser
26−import qualified AST.Module as Module
27−
28−-- Reader: Runtime flags, always accessible
29−-- Writer: Remember the last module to be accessed
30−-- State: Build up a map of the module interfaces
31−type BuildT m a = RWST Flag.Flags (Last String) BInterfaces m a
32−type Build a = BuildT IO a
33−
34−-- Interfaces, remembering if something was recompiled
35−type BInterfaces = Map.Map String (Bool, Module.Interface)
36−
37−evalBuild :: Flag.Flags -> Module.Interfaces -> Build ()
38− -> IO (Map.Map String Module.Interface, Maybe String)
39−evalBuild flags interfaces build =
40− do (ifaces, moduleNames) <- execRWST build flags (fmap notUpdated interfaces)
41− return (fmap snd ifaces, getLast moduleNames)
42− where
43− notUpdated iface = (False, iface)
44−
45−-- | Builds a list of files, returning the moduleName of the last one.
46−-- Returns \"\" if the list is empty
47−build :: Flag.Flags -> Module.Interfaces -> [FilePath] -> IO String
48−build flags interfaces files =
49− do (ifaces, topName) <- evalBuild flags interfaces (buildAll files)
50− let removeTopName = Maybe.maybe id Map.delete topName
51− mapM_ (checkPorts topName) (Map.toList $ removeTopName ifaces)
52− return $ Maybe.fromMaybe "" topName
53− where
54− checkPorts topName (name,iface)
55− | null ports = return ()
56− | otherwise = Print.failure msg
57− where
58− ports = Module.iPorts iface
59− msg = concat
60− [ "Port Error: ports may only appear in the main module, but\n"
61− , " sub-module ", name, " declares the following port"
62− , if length ports == 1 then "" else "s", ": "
63− , List.intercalate ", " ports
64− , case topName of
65− Nothing -> ""
66− Just tname -> "\n All ports must appear in module " ++ tname
67− ]
68−
69−buildAll :: [FilePath] -> Build ()
70−buildAll fs = mapM_ (uncurry build1) (zip [1..] fs)
71− where build1 :: Integer -> FilePath -> Build ()
72− build1 num fname = do
73− shouldCompile <- shouldBeCompiled fname
74− if shouldCompile
75− then compile number fname
76− else retrieve fname
77−
78− where number = join ["[", show num, " of ", show total, "]"]
79−
80− total = length fs
81−
82−shouldBeCompiled :: FilePath -> Build Bool
83−shouldBeCompiled filePath = do
84− flags <- ask
85− let alreadyCompiled = liftIO $ do
86− existsi <- doesFileExist (Utils.elmi flags filePath)
87− existso <- doesFileExist (Utils.elmo flags filePath)
88− return $ existsi && existso
89−
90− outDated = liftIO $ do
91− tsrc <- getModificationTime filePath
92− tint <- getModificationTime (Utils.elmo flags filePath)
93− return (tsrc > tint)
94−
95− dependenciesUpdated = do
96− eDeps <- liftIO . runErrorT $ Deps.readDeps filePath
97− case eDeps of
98− -- Should never actually reach here
99− Left err -> liftIO $ Print.failure err
100− Right (_, deps) -> anyM wasCompiled deps
101−
102−
103− in (not <$> alreadyCompiled) `orM` outDated `orM` dependenciesUpdated
104−
105−wasCompiled :: String -> Build Bool
106−wasCompiled modul = maybe False fst . Map.lookup modul <$> get
107−
108−-- Short-circuiting monadic (||)
109−infixr 2 `orM`
110−orM :: (Monad m) => m Bool -> m Bool -> m Bool
111−orM m1 m2 = do b1 <- m1
112− if b1
113− then return b1
114− else m2
115−
116−anyM :: (Monad m) => (a -> m Bool) -> [a] -> m Bool
117−anyM f = foldr (orM . f) (return False)
118−
119−retrieve :: FilePath -> Build ()
120−retrieve filePath = do
121− flags <- ask
122− iface <- liftIO $ Interface.load (Utils.elmi flags filePath)
123− case Interface.isValid filePath iface of
124− Right (name, interface) ->
125− do liftIO $ when (Flag.print_types flags) (Print.types (Module.iTypes interface))
126− update name interface False
127−
128− Left err -> liftIO $ Print.failure err
129−
130−compile :: String -> FilePath -> Build ()
131−compile number filePath =
132− do flags <- ask
133− binterfaces <- get
134− source <- liftIO $ readFile filePath
135− let interfaces = snd <$> binterfaces
136− name = getName source
137− liftIO $ do
138− printStatus name
139− createDirectoryIfMissing True (Flag.cache_dir flags)
140− createDirectoryIfMissing True (Flag.build_dir flags)
141−
142− canonicalModule <-
143− liftIO $ case Source.build (Flag.no_prelude flags) interfaces source of
144− Right modul -> return modul
145− Left errors -> do Print.errors errors
146− exitFailure
147−
148− liftIO $ when (Flag.print_types flags) $ do
149− Print.types (Module.types (Module.body canonicalModule))
150−
151− let newInters = Module.toInterface canonicalModule
152− generateCache name newInters canonicalModule
153− update name newInters True
154−
155− where
156− getName source = case Parser.getModuleName source of
157− Just n -> n
158− Nothing -> "Main"
159−
160− printStatus name =
161− hPutStrLn stdout $ concat [ number, " Compiling ", name
162− , replicate (max 1 (20 - length name)) ' '
163− , "( " ++ filePath ++ " )" ]
164−
165− generateCache name interfs canonicalModule = do
166− flags <- ask
167− liftIO $ do
168− createDirectoryIfMissing True . dropFileName $ Utils.elmi flags filePath
169− writeFile (Utils.elmo flags filePath) (JS.generate canonicalModule)
170− withBinaryFile (Utils.elmi flags filePath) WriteMode $ \handle ->
171− L.hPut handle (Binary.encode (name, interfs))
172−
173−update :: String -> Module.Interface -> Bool -> Build ()
174−update name inter wasUpdated =
175− do modify (Map.insert name (wasUpdated, inter))
176− tell (Last . Just $ name)
compiler/Build/Flags.hs+4−3
@@ -1,9 +1,10 @@
11{-# LANGUAGE DeriveDataTypeable #-}
22module Build.Flags where
33
4−import qualified Elm.Internal.Version as Version
4+import qualified Elm.Compiler.Version as Compiler
55import System.Console.CmdArgs
66
7+
78data Flags = Flags
89 { make :: Bool
910 , files :: [FilePath]
@@ -59,5 +60,5 @@ flags = Flags
5960
6061 } &= help "Compile Elm programs to HTML, CSS, and JavaScript."
6162 &= helpArg [explicit, name "help", name "h"]
62− &= versionArg [explicit, name "version", name "v", summary (show Version.elmVersion)]
63− &= summary ("The Elm Compiler " ++ show Version.elmVersion ++ ", (c) Evan Czaplicki 2011-2014")
63+ &= versionArg [explicit, name "version", name "v", summary Compiler.version]
64+ &= summary ("The Elm Compiler " ++ Compiler.version ++ ", (c) Evan Czaplicki 2011-2014")
compiler/Build/Interface.hs+6−4
@@ -5,10 +5,11 @@ import qualified Data.ByteString.Lazy as L
55import qualified Data.Binary as Binary
66
77import qualified Build.Print as Print
8−import qualified Elm.Internal.Version as Version
8+import qualified Elm.Compiler.Version as Compiler
99import System.Directory (doesFileExist)
1010import AST.Module as Module
1111
12+
1213load :: Binary.Binary a => FilePath -> IO a
1314load filePath =
1415 do exists <- doesFileExist filePath
@@ -28,14 +29,15 @@ load filePath =
2829 , " Please remove the file and try again."
2930 ]
3031
32+
3133isValid :: FilePath -> (String, Module.Interface) -> Either String (String, Module.Interface)
3234isValid filePath (name, interface) =
3335 let version = iVersion interface in
34− if version == Version.elmVersion
36+ if version == Compiler.version
3537 then Right (name, interface)
3638 else Left $ concat
3739 [ "Error reading build artifact: ", filePath, "\n"
38− , " It was generated by version ", show version, " of the compiler,\n"
39− , " but you are using version ", show Version.elmVersion, "\n"
40+ , " It was generated by version ", version, " of the compiler,\n"
41+ , " but you are using version ", Compiler.version, "\n"
4042 , " Please remove the file and try again.\n"
4143 ]
compiler/Build/Utils.hs+9
@@ -6,6 +6,7 @@ import System.Directory (doesFileExist)
66import System.Environment (getEnv)
77import System.FilePath ((</>), replaceExtension)
88import System.IO.Error (tryIOError)
9+import System.IO.Unsafe (unsafePerformIO)
910import qualified Build.Flags as Flag
1011import qualified Build.Print as Print
1112import qualified Paths_Elm as This
@@ -26,6 +27,14 @@ elmi :: Flag.Flags -> FilePath -> FilePath
2627elmi flags filePath =
2728 cachePath flags filePath "elmi"
2829
30+
31+{-# NOINLINE runtime #-}
32+-- |The absolute path to Elm's runtime system.
33+runtime :: FilePath
34+runtime =
35+ unsafePerformIO $ getDataFile "elm-runtime.js"
36+
37+
2938-- |The absolute path to a data file
3039getDataFile :: FilePath -> IO FilePath
3140getDataFile name = do
compiler/Compiler.hs+9−21
@@ -1,32 +1,19 @@
1−{-# OPTIONS_GHC -W #-}
1+{-# OPTIONS_GHC -Wall #-}
22module Main where
33
4−import Control.Monad (foldM, when)
5−import qualified Data.Maybe as Maybe
6−import Text.Blaze.Html.Renderer.String (renderHtml)
7−import qualified Data.ByteString.Lazy.Char8 as BS
8−import qualified System.Console.CmdArgs as CmdArgs
9−import System.Directory
10−import System.Exit (exitSuccess)
11−import System.FilePath
12−import GHC.Conc
4+import GHC.Conc (getNumProcessors, setNumCapabilities)
135
14−import Build.Dependencies (getBuildRecipe, Recipe(..))
15−import qualified Generate.Html as Html
16−import qualified Metadata.Prelude as Prelude
17−import qualified Build.Utils as Utils
18−import qualified Build.Flags as Flag
19−import qualified Build.File as File
20−import qualified Elm.Internal.Paths as Path
216
227main :: IO ()
23−main = do setNumCapabilities =<< getNumProcessors
24− compileArgs =<< CmdArgs.cmdArgs Flag.flags
8+main =
9+ do setNumCapabilities =<< getNumProcessors
10+ error "currently out of order"
2511
12+{--
2613compileArgs :: Flag.Flags -> IO ()
2714compileArgs flags =
2815 do when (Flag.get_runtime flags) $ do
29− putStrLn Path.runtime
16+ putStrLn Utils.runtime
3017 exitSuccess
3118 case Flag.files flags of
3219 [] -> putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
@@ -67,7 +54,7 @@ build flags rootFile =
6754
6855 getRuntime :: IO Html.JSSource
6956 getRuntime =
70− let runtimePath = Maybe.fromMaybe Path.runtime (Flag.set_runtime flags) in
57+ let runtimePath = Maybe.fromMaybe Utils.runtime (Flag.set_runtime flags) in
7158 case Flag.bundle_runtime flags of
7259 False -> return (Html.Link runtimePath)
7360 True -> Html.Source `fmap` BS.readFile runtimePath
@@ -87,3 +74,4 @@ build flags rootFile =
8774 sources js = map Html.Link (Flag.scripts flags) ++ [ Html.Source js ]
8875 html runtime =
8976 Html.generate runtime (takeBaseName rootFile) (sources js) moduleName ""
77+--}
compiler/Elm/Compiler.hsnew file+69
@@ -0,0 +1,69 @@
1+{-# OPTIONS_GHC -Wall #-}
2+{-# LANGUAGE FlexibleContexts #-}
3+module Elm.Compiler (version, moduleNameToPath, moduleNameToString, parseDependencies, elmToJs) where
4+
5+import Control.Monad.Error (MonadError, MonadIO, liftIO, throwError)
6+import qualified Data.List as List
7+import System.FilePath ((</>))
8+import System.IO.Unsafe (unsafePerformIO)
9+
10+import qualified AST.Module as Module
11+import qualified Elm.Compiler.Version as Version
12+import qualified Metadata.Prelude as Prelude
13+import qualified Parse.Helpers as Help
14+import qualified Parse.Module as Parse
15+
16+
17+-- VERSION
18+
19+version :: String
20+version =
21+ Version.version
22+
23+
24+-- MODULE NAMES
25+
26+newtype ModuleName =
27+ ModuleName [String]
28+
29+
30+moduleNameToPath :: ModuleName -> FilePath
31+moduleNameToPath (ModuleName names) =
32+ List.foldl1 (</>) names
33+
34+
35+moduleNameToString :: ModuleName -> String
36+moduleNameToString (ModuleName names) =
37+ List.intercalate "." names
38+
39+
40+-- DEPENDENCIES
41+
42+parseDependencies :: (MonadIO m, MonadError String m) => FilePath -> m (ModuleName, [ModuleName])
43+parseDependencies filePath =
44+ do src <- liftIO (readFile filePath)
45+ case Help.iParse Parse.headerAndImports src of
46+ Left msg ->
47+ throwError (show msg)
48+
49+ Right (Module.HeaderAndImports names _exports imports) ->
50+ return ( ModuleName names, map (ModuleName . fst) imports )
51+
52+
53+-- COMPILATION
54+
55+{-| Compiles Elm source code to JavaScript. -}
56+elmToJs :: String -> Either String String
57+elmToJs source =
58+ error "elmToJs is not working yet"
59+{-
60+ case Source.build False interfaces source of
61+ Left docs -> Left . unlines . List.intersperse "" $ map P.render docs
62+ Right modul -> Right $ JS.generate modul
63+-}
64+
65+{-# NOINLINE interfaces #-}
66+interfaces :: Module.Interfaces
67+interfaces =
68+ unsafePerformIO $ Prelude.interfaces False
69+
compiler/Elm/Compiler/Version.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# OPTIONS_GHC -Wall #-}
2+module Elm.Compiler.Version (version) where
3+
4+import qualified Data.Version as Version
5+import qualified Paths_Elm as This
6+
7+
8+version :: String
9+version =
10+ Version.showVersion This.version
compiler/Elm/Internal/Dependencies.hsdeleted−156
@@ -1,156 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−module Elm.Internal.Dependencies where
3−
4−import Control.Applicative
5−import Control.Arrow (first)
6−import Control.Monad.Error
7−import qualified Control.Exception as E
8−import Data.Aeson
9−import Data.Aeson.Types (Parser)
10−import Data.Aeson.Encode.Pretty
11−import Data.Maybe (fromMaybe)
12−import qualified Data.List as List
13−import qualified Data.ByteString.Lazy as BS
14−import qualified Data.HashMap.Strict as Map
15−import qualified Data.Text as T
16−
17−import qualified Elm.Internal.Name as N
18−import qualified Elm.Internal.Version as V
19−import qualified Elm.Internal.Paths as Path
20−
21−data Deps = Deps
22− { name :: N.Name
23− , version :: V.Version
24− , summary :: String
25− , description :: String
26− , license :: String
27− , repo :: String
28− , exposed :: [String]
29− , native :: [String]
30− , elmVersion :: V.Version
31− , dependencies :: [(N.Name,V.Version)]
32− } deriving (Show, Eq, Ord)
33−
34−instance ToJSON Deps where
35− toJSON d =
36− object $
37− [ "version" .= version d
38− , "summary" .= summary d
39− , "description" .= description d
40− , "license" .= license d
41− , "repository" .= repo d
42− , "exposed-modules" .= exposed d
43− , "elm-version" .= elmVersion d
44− , "dependencies" .= (jsonDeps . dependencies $ d)
45− ] ++ nativeModules
46− where
47− jsonDeps = Map.fromList . map (first (T.pack . show))
48− nativeModules
49− | null (native d) = []
50− | otherwise = [ "native-modules" .= native d ]
51−
52−instance FromJSON Deps where
53− parseJSON (Object obj) =
54− do version <- get obj "version" "your projects version number"
55−
56− summary <- get obj "summary" "a short summary of your project"
57− when (length summary >= 80) $
58− fail "'summary' must be less than 80 characters"
59−
60− desc <- get obj "description" "an extended description of your project \
61− \and how to get started with it."
62− license <- get obj "license" "license information (BSD3 is recommended)"
63−
64− repo <- get obj "repository" "a link to the project's GitHub repo"
65− name <- case repoToName repo of
66− Left err -> fail err
67− Right nm -> return nm
68−
69− exposed <- get obj "exposed-modules" "a list of modules exposed to users"
70−
71− native <- fromMaybe [] <$> (obj .:? "native-modules")
72−
73− elmVersion <- get obj "elm-version" "the version of the Elm compiler you are using"
74−
75− deps <- getDependencies obj
76−
77− return $ Deps name version summary desc license repo exposed native elmVersion deps
78−
79− parseJSON _ = mzero
80−
81−getDependencies :: Object -> Parser [(N.Name, V.Version)]
82−getDependencies obj =
83− toDeps =<< get obj "dependencies" "a listing of your project's dependencies"
84− where
85− toDeps deps =
86− forM (Map.toList deps) $ \(f,v) ->
87− case (N.fromString f, V.fromString v) of
88− (Just name, Just version) -> return (name,version)
89− (Nothing, _) -> fail $ N.errorMsg f
90− (_, Nothing) -> fail $ "invalid version number " ++ v
91−
92−get :: FromJSON a => Object -> T.Text -> String -> Parser a
93−get obj field desc =
94− do maybe <- obj .:? field
95− case maybe of
96− Just value -> return value
97− Nothing -> fail $ "Missing field " ++ show field ++ ", " ++ desc ++ ".\n" ++
98− " Check out an example " ++ Path.dependencyFile ++ " file here:" ++
99− " <https://github.com/evancz/automaton/blob/master/elm_dependencies.json>"
100−
101−repoToName :: String -> Either String N.Name
102−repoToName repo
103− | not (end `List.isSuffixOf` repo) = Left msg
104− | otherwise =
105− do path <- getPath
106− let raw = take (length path - length end) path
107− case N.fromString raw of
108− Nothing -> Left msg
109− Just name -> Right name
110− where
111− getPath | http `List.isPrefixOf` repo = Right $ drop (length http ) repo
112− | https `List.isPrefixOf` repo = Right $ drop (length https) repo
113− | otherwise = Left msg
114− http = "http://github.com/"
115− https = "https://github.com/"
116− end = ".git"
117− msg = "the 'repository' field must point to a GitHub project for now, something\n\
118− \like <https://github.com/USER/PROJECT.git> where USER is your GitHub name\n\
119− \and PROJECT is the repo you want to upload."
120−
121−withDeps :: FilePath -> (Deps -> ErrorT String IO a) -> ErrorT String IO a
122−withDeps path handle =
123− do json <- readPath
124− case eitherDecode json of
125− Left err -> throwError $ "Error reading file " ++ path ++ ":\n " ++ err
126− Right ds -> handle ds
127− where
128− readPath :: ErrorT String IO BS.ByteString
129− readPath = do
130− result <- liftIO $ E.catch (Right <$> BS.readFile path)
131− (\err -> return $ Left (err :: IOError))
132− case result of
133− Right bytes -> return bytes
134− Left _ -> throwError $
135− "could not find " ++ path ++ " file. You may need to create one.\n" ++
136− " For an example of how to fill in the dependencies file, check out\n" ++
137− " <https://github.com/evancz/automaton/blob/master/elm_dependencies.json>"
138−
139−depsAt :: FilePath -> ErrorT String IO Deps
140−depsAt filePath = withDeps filePath return
141−
142−-- | Encode dependencies in a canonical JSON format
143−prettyJSON :: Deps -> BS.ByteString
144−prettyJSON = encodePretty' config
145− where config = defConfig { confCompare = order }
146− order = keyOrder [ "name"
147− , "version"
148− , "summary"
149− , "description"
150− , "license"
151− , "repo"
152− , "exposed-modules"
153− , "native-modules"
154− , "elm-version"
155− , "dependencies"
156− ]
compiler/Elm/Internal/Name.hsdeleted−51
@@ -1,51 +0,0 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
2−module Elm.Internal.Name where
3−
4−import Control.Applicative
5−import Control.Monad.Error
6−import Data.Aeson
7−import Data.Binary
8−import qualified Data.Text as T
9−import qualified Data.Maybe as Maybe
10−import Data.Typeable
11−
12−data Name = Name { user :: String, project :: String }
13− deriving (Typeable,Eq, Ord)
14−
15−instance Binary Name where
16− get = Name <$> get <*> get
17− put (Name user project) =
18− put user >> put project
19−
20−instance Show Name where
21− show name = user name ++ "/" ++ project name
22−
23−toFilePath :: Name -> FilePath
24−toFilePath name = user name ++ "-" ++ project name
25−
26−fromString :: String -> Maybe Name
27−fromString string =
28− case break (=='/') string of
29− ( user@(_:_), '/' : project@(_:_) )
30− | all (/='/') project -> Just (Name user project)
31− _ -> Nothing
32−
33−fromString' :: String -> ErrorT String IO Name
34−fromString' string =
35− Maybe.maybe (throwError $ errorMsg string) return (fromString string)
36−
37−instance FromJSON Name where
38− parseJSON (String text) =
39− let string = T.unpack text in
40− Maybe.maybe (fail $ errorMsg string) return (fromString string)
41−
42− parseJSON _ = fail "Project name must be a string."
43−
44−instance ToJSON Name where
45− toJSON name = toJSON (show name)
46−
47−errorMsg string =
48− unlines
49− [ "Dependency file has an invalid name: " ++ string
50− , "Must have format user/project and match a public github project."
51− ]
compiler/Elm/Internal/Paths.hsdeleted−24
@@ -1,24 +0,0 @@
1−{-# OPTIONS_GHC -Wall #-}
2−module Elm.Internal.Paths where
3−
4−import Build.Utils (getDataFile)
5−import System.IO.Unsafe (unsafePerformIO)
6−
7−-- |Name of directory for all of a project's dependencies.
8−dependencyDirectory :: FilePath
9−dependencyDirectory = "elm_dependencies"
10−
11−-- |Name of the dependency file, specifying dependencies and
12−-- other metadata for building and sharing projects.
13−dependencyFile :: FilePath
14−dependencyFile = "elm_dependencies.json"
15−
16−{-# NOINLINE runtime #-}
17−-- |The absolute path to Elm's runtime system.
18−runtime :: FilePath
19−runtime = unsafePerformIO $ getDataFile "elm-runtime.js"
20−
21−{-# NOINLINE docs #-}
22−-- |The absolute path to Elm's core library documentation.
23−docs :: FilePath
24−docs = unsafePerformIO $ getDataFile "docs.json"
compiler/Elm/Internal/Utils.hsdeleted−35
@@ -1,35 +0,0 @@
1−{- | This module exports functions for compiling Elm to JS.
2−-}
3−module Elm.Internal.Utils (compile, moduleName, nameAndImports) where
4−
5−import qualified Data.List as List
6−import qualified Generate.JavaScript as JS
7−import qualified Build.Source as Source
8−import qualified Parse.Module as Parser
9−import qualified AST.Module as M
10−import Parse.Parse (dependencies)
11−import qualified Text.PrettyPrint as P
12−import qualified Metadata.Prelude as Prelude
13−import System.IO.Unsafe
14−
15−-- |This function compiles Elm code to JavaScript. It will return either
16−-- an error message or the compiled JS code.
17−compile :: String -> Either String String
18−compile source =
19− case Source.build False interfaces source of
20− Left docs -> Left . unlines . List.intersperse "" $ map P.render docs
21− Right modul -> Right $ JS.generate modul
22−
23−{-# NOINLINE interfaces #-}
24−interfaces :: M.Interfaces
25−interfaces = unsafePerformIO $ Prelude.interfaces False
26−
27−-- |This function extracts the module name of a given source program.
28−moduleName :: String -> Maybe String
29−moduleName = Parser.getModuleName
30−
31−-- |This function extracts the module name and imported modules from a given
32−-- source program.
33−nameAndImports :: String -> Maybe (String, [String])
34−nameAndImports src =
35− either (const Nothing) Just (dependencies src)
compiler/Elm/Internal/Version.hsdeleted−73
@@ -1,73 +0,0 @@
1−{-# LANGUAGE DeriveDataTypeable, TemplateHaskell #-}
2−module Elm.Internal.Version where
3−
4−import Control.Applicative
5−import Data.Aeson
6−import Data.Binary
7−import Data.Char (isDigit)
8−import qualified Data.List as List
9−import Data.Typeable
10−import qualified Data.Text as T
11−import qualified Paths_Elm as This
12−import qualified Data.Version as Version
13−
14−elmVersion :: Version
15−elmVersion = V ns ""
16− where (Version.Version ns _) = This.version
17−
18−-- Data representation
19−
20−data Version = V [Int] String
21− deriving (Typeable,Eq)
22−
23−instance Ord Version where
24− compare (V ns tag) (V ns' tag') =
25− case compare ns ns' of
26− EQ -> compare tag' tag -- reverse comparison to favor ""
27− cmp -> cmp
28−
29−instance Show Version where
30− show (V ns tag) =
31− List.intercalate "." (map show ns) ++ if null tag then "" else "-" ++ tag
32−
33−instance Binary Version where
34− get = V <$> get <*> get
35− put (V ns tag) = do put ns
36− put tag
37−
38−tagless :: Version -> Bool
39−tagless (V _ tag) = null tag
40−
41−fromString :: String -> Maybe Version
42−fromString version = V <$> splitNumbers possibleNumbers <*> tag
43− where
44− (possibleNumbers, possibleTag) = break (=='-') version
45−
46− tag = case possibleTag of
47− "" -> Just ""
48− '-':rest -> Just rest
49− _ -> Nothing
50−
51− splitNumbers :: String -> Maybe [Int]
52− splitNumbers ns =
53− case span isDigit ns of
54− ("", _) -> Nothing
55− (number, []) -> Just [read number]
56− (number, '.':rest) -> (read number :) <$> splitNumbers rest
57− _ -> Nothing
58−
59−instance FromJSON Version where
60− parseJSON (String text) =
61− let string = T.unpack text in
62− case fromString string of
63− Just v -> return v
64− Nothing -> fail $ unlines
65− [ "Dependency file has an invalid version number: " ++ string
66− , "Must have format 0.1.2 or 0.1.2-tag"
67− ]
68−
69− parseJSON _ = fail "Version number must be stored as a string."
70−
71−instance ToJSON Version where
72− toJSON version = toJSON (show version)
73−
compiler/Parse/Parse.hs+1−9
@@ -1,5 +1,5 @@
11{-# OPTIONS_GHC -W #-}
2−module Parse.Parse (program, dependencies) where
2+module Parse.Parse (program) where
33
44import Control.Applicative ((<$>))
55import Control.Arrow (first)
@@ -40,14 +40,6 @@ programParser =
4040 let stringyImports = map (first M.nameToString) imports
4141 return $ M.Module names "" exports stringyImports declarations
4242
43−dependencies :: String -> Either [P.Doc] (String, [String])
44−dependencies =
45− setupParser $ do
46− header <- Module.headerAndImports
47− return ( M.nameToString (M._names header)
48− , map (M.nameToString . fst) (M._imports header)
49− )
50−
5143setupParserWithTable :: OpTable -> IParser a -> String -> Either [P.Doc] a
5244setupParserWithTable table p source =
5345 do localTable <- setupParser parseFixities source