on 482b7ea help sign in
elk/elm/src/Compiler.hs
98 lines 3.6 kB history raw
1{-# LANGUAGE DeriveDataTypeable #-}
2module Main where
4import Data.Either (lefts, rights)
5import Data.List (intersect, intercalate)
6import Data.Maybe (fromMaybe)
7import System.Console.CmdArgs
8import Text.Blaze.Html.Renderer.String (renderHtml)
10import Ast
11import Initialize
12import CompileToJS
13import GenerateHtml
14import Paths_Elm
17data ELM =
18 ELM { make :: Bool
19 , files :: [FilePath]
20 , runtime :: Maybe FilePath
21 , separate_js :: Bool
22 , only_js :: Bool
23-- , verbose_js :: Bool
24 }
25 deriving (Data,Typeable,Show,Eq)
27elm = ELM { make = False &= help "automatically compile dependencies."
28 , files = def &= args &= typ "FILES"
29 , runtime = Nothing &= typ "FILE" &=
30 help "Specify a custom location for Elm's runtime system."
31 , separate_js = False &= help "Compile to separate HTML and JS files."
32 , only_js = False &= help "Compile only to JavaScript."
33-- , verbose_js = False &= help "Produce JavaScript that may be easier to debug."
34 } &=
35 help "Compile Elm programs to HTML, CSS, and JavaScript." &=
36 summary "The Elm Compiler v0.3.0, (c) Evan Czaplicki"
38main = do
39 args <- cmdArgs elm
40 mini <- getDataFileName "elm-runtime-0.3.0.js"
41 compileArgs mini args
43compileArgs mini (ELM _ [] _ _ _) =
44 putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
45compileArgs mini (ELM make files rtLoc split only) =
46 mapM_ (fileTo get what $ fromMaybe mini rtLoc) files
47 where get = if make then getModules [] else getModule
48 what = if only then JS else
49 if split then Split else HTML
51data What = JS | HTML | Split
53fileTo get what rtLoc file = do
54 ems <- get file
55 case ems of
56 Left err -> putStrLn $ "Error while compiling " ++ file ++ ":\n" ++ err
57 Right ms ->
58 let name = reverse . tail . dropWhile (/='.') $ reverse file
59 js = name ++ ".js"
60 html = name ++ ".html"
61 in case what of
62 JS -> writeFile js $ concatMap jsModule ms
63 HTML -> writeFile html . renderHtml $ modulesToHtml rtLoc ms
64 Split -> do
65 writeFile html . renderHtml $ linkedHtml rtLoc js ms
66 writeFile js $ concatMap jsModule ms
68getModules :: [String] -> FilePath -> IO (Either String [Module])
69getModules uses file = do
70 code <- readFile file
71 case initialize code of
72 Left err -> return . Left $ "Error in " ++ file ++ ":\n" ++ err
73 Right modul@(Module _ _ imports _) ->
74 let imps = filter (`notElem` builtInModules) $ map fst imports in
75 case intersect uses imps of
76 x:_ -> return . Left $ "Error: Cyclic dependency. Module " ++
77 x ++ " depends on itself."
78 [] -> do
79 ems <- mapM (getModules (uses ++ imps) . toFilePath) imps
80 return $ case lefts ems of
81 [] -> Right $ concat (rights ems) ++ [modul]
82 errs -> Left $ intercalate "\n" errs
84getModule :: FilePath -> IO (Either String [Module])
85getModule file = do
86 code <- readFile file
87 return . fmap (:[]) $ initialize code
89toFilePath :: String -> FilePath
90toFilePath modul = map (\c -> if c == '.' then '/' else c) modul ++ ".elm"
92builtInModules =
93 concat [ map ("Data."++) [ "List", "Char", "Maybe" ]
94 , map ("Signal."++) [ "Mouse", "Keyboard.Raw"
95 , "Window", "Time", "HTTP", "Input", "Random" ]
96 , [ "Element", "Text", "Color", "Line" ]
97 , [ "Prelude" ]
98 ]