@@ -4,6 +4,7 @@ module Main where
4import Control.Monad
4import Control.Monad
5import qualified Data.Map as Map
5import qualified Data.Map as Map
6import qualified Data.List as List
6import qualified Data.List as List
7+import Data.Binary (encodeFile, decodeFile)
7import Data.Version (showVersion)
8import Data.Version (showVersion)
8import System.Console.CmdArgs
9import System.Console.CmdArgs
9import System.Directory
10import System.Directory
@@ -23,13 +24,15 @@ import Paths_Elm
24import Text.PrettyPrint as P
25import Text.PrettyPrint as P
25import qualified Type.Type as Type
26import qualified Type.Type as Type
26−
27+import qualified Parse.Type as Parse
28+import qualified Data.Traversable as Traverse
28data Flags =
30data Flags =
29 Flags { make :: Bool
31 Flags { make :: Bool
30 , files :: [FilePath]
32 , files :: [FilePath]
31 , runtime :: Maybe FilePath
33 , runtime :: Maybe FilePath
32 , only_js :: Bool
34 , only_js :: Bool
35+ , print_types :: Bool
33 , scripts :: [FilePath]
36 , scripts :: [FilePath]
34 , no_prelude :: Bool
37 , no_prelude :: Bool
35 , minify :: Bool
38 , minify :: Bool
@@ -45,6 +48,8 @@ flags = Flags
45 &= help "Specify a custom location for Elm's runtime system."
48 &= help "Specify a custom location for Elm's runtime system."
46 , only_js = False
49 , only_js = False
47 &= help "Compile only to JavaScript."
50 &= help "Compile only to JavaScript."
51+ , print_types = False
52+ &= help "Print out infered types of top-level definitions."
48 , scripts = [] &= typFile
53 , scripts = [] &= typFile
49 &= help "Load JavaScript files in generated HTML. Files will be included in the given order."
54 &= help "Load JavaScript files in generated HTML. Files will be included in the given order."
50 , no_prelude = False
55 , no_prelude = False
@@ -66,8 +71,6 @@ compileArgs flags =
66 fs -> mapM_ (build flags) fs
71 fs -> mapM_ (build flags) fs
69−type Interface = String
71file :: Flags -> FilePath -> String -> FilePath
74file :: Flags -> FilePath -> String -> FilePath
72file flags filePath ext = output_directory flags </> replaceExtension filePath ext
75file flags filePath ext = output_directory flags </> replaceExtension filePath ext
@@ -76,10 +79,10 @@ elmo flags filePath = file flags filePath "elmo"
76elmi flags filePath = file flags filePath "elmi"
79elmi flags filePath = file flags filePath "elmi"
79−buildFile :: Flags -> Int -> Int -> FilePath -> IO Interface
82+buildFile :: Flags -> Int -> Int -> FilePath -> IO ModuleInterface
80buildFile flags moduleNum numModules filePath =
83buildFile flags moduleNum numModules filePath =
81 do compiled <- alreadyCompiled
84 do compiled <- alreadyCompiled
82− if compiled then readFile (elmo flags filePath) else compile
85+ if compiled then decodeFile (elmi flags filePath) else compile
85 alreadyCompiled :: IO Bool
88 alreadyCompiled :: IO Bool
@@ -96,30 +99,35 @@ buildFile flags moduleNum numModules filePath =
96 name :: String
99 name :: String
97 name = List.intercalate "." (splitDirectories (dropExtensions filePath))
100 name = List.intercalate "." (splitDirectories (dropExtensions filePath))
99− compile :: IO Interface
102+ compile :: IO ModuleInterface
100 compile = do
103 compile = do
101 putStrLn (number ++ " Compiling " ++ name)
104 putStrLn (number ++ " Compiling " ++ name)
102 source <- readFile filePath
105 source <- readFile filePath
103− (js, maybeModule) <-
104− if takeExtension filePath == ".js" then return (source, Nothing) else
105− case buildFromSource (no_prelude flags) source of
106− Left err -> mapM print err >> exitFailure
107− Right modul -> return (jsModule modul, Just modul)
108 createDirectoryIfMissing True (output_directory flags)
106 createDirectoryIfMissing True (output_directory flags)
108+ case buildFromSource Map.empty source of
109+ Left err -> mapM print err >> exitFailure
110+ Right modul -> return (modul :: MetadataModule () ())
111+ if print_types flags then printTypes metaModule else return ()
112+ tipes <- toSrcTypes (types metaModule)
113+ let fmt (name, tvars, ctors) = (name, (length tvars, map fst ctors))
114+ interface = ModuleInterface {
116+ iAdts = Map.fromList . map fmt $ datatypes metaModule
118+ encodeFile (elmi flags filePath) interface
119+ let js = jsModule metaModule
109 writeFile (elmo flags filePath) js
120 writeFile (elmo flags filePath) js
110− writeTypes maybeModule
111− return js
121+ return interface
113− writeTypes :: Maybe (MetadataModule () ()) -> IO ()
123+toSrcTypes tipes = Traverse.traverse convert tipes
114− writeTypes maybeModule =
124+ where
116− Nothing -> return ()
117− Just metaModule -> do
118− tipes <- forM (Map.toList (types metaModule)) $ \(n,t) -> do
119− pt <- Type.extraPretty t
125+ convert t = fmap (Parse.readType . P.render) (Type.extraPretty t)
120− return $ P.text n <+> P.text ":" <+> pt
121− writeFile (elmi flags filePath) (P.render $ P.vcat tipes)
127+printTypes metaModule =
128+ forM_ (Map.toList $ types metaModule) $ \(n,t) -> do
129+ pt <- Type.extraPretty t
130+ print $ P.text n <+> P.text ":" <+> pt
125getRuntime :: Flags -> IO FilePath
133getRuntime :: Flags -> IO FilePath
@@ -157,7 +165,7 @@ build flags rootFile = do
157 [ Source (if minify flags then Minified else Readable) js ]
165 [ Source (if minify flags then Minified else Readable) js ]
160−buildFiles :: Flags -> Int -> Map.Map String Interface -> [FilePath] -> IO ()
168+buildFiles :: Flags -> Int -> Map.Map String ModuleInterface -> [FilePath] -> IO ()
161buildFiles _ _ _ [] = return ()
169buildFiles _ _ _ [] = return ()
162buildFiles flags numModules interfaces (filePath:rest) = do
170buildFiles flags numModules interfaces (filePath:rest) = do
163 interface <- buildFile flags (numModules - length rest) numModules filePath
171 interface <- buildFile flags (numModules - length rest) numModules filePath