@@ -1,49 +1,83 @@
1+{-# LANGUAGE DeriveDataTypeable #-}
12module Main where
23
3−import Data.List (isPrefixOf)
4+import Data.Either (lefts, rights)
5+import Data.List (intersect, intercalate)
6+import Data.Maybe (fromMaybe)
7+import System.Console.CmdArgs
8+import Text.Blaze.Html.Renderer.String (renderHtml)
9+
10+import Ast
11+import Initialize
412import CompileToJS
513import GenerateHtml
6−import System.Environment
7−import Text.Blaze.Html.Renderer.String (renderHtml)
14+import Paths_Elm
15+
16+
17+data 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)
26+
27+elm = 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"
837
9−main :: IO ()
10−main = getArgs >>= parse
11−
12−parse :: [String] -> IO ()
13−parse ("--help":_) = putStrLn usage
14−parse ("--version":_) = putStrLn "The Elm Compiler 0.2.0.1"
15−parse [loc,file]
16− | "--runtime-location=" `isPrefixOf` loc =
17− produceHtml (tail $ dropWhile (/='=') loc) file
18− | otherwise = putStrLn usageMini
19−parse [file] = produceHtml "elm-mini.js" file
20−parse _ = putStrLn usageMini
21−
22−produceHtml :: String -> FilePath -> IO ()
23−produceHtml libLoc file = do
38+main = do
39+ args <- cmdArgs elm
40+ mini <- getDataFileName "elm-runtime-0.3.0.js"
41+ compileArgs mini args
42+
43+compileArgs mini (ELM _ [] _) =
44+ putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
45+compileArgs mini (ELM make files rtLoc) =
46+ mapM_ (fileToHtml $ fromMaybe mini rtLoc) files
47+
48+fileToHtml rtLoc file = do
49+ ems <- getModules [] file
50+ case ems of
51+ Left err -> putStrLn $ "Error while compiling " ++ file ++ ":\n" ++ err
52+ Right ms ->
53+ let name = reverse . tail . dropWhile (/='.') $ reverse file in
54+ writeFile (name ++ ".html") . renderHtml $
55+ modulesToHtml rtLoc ms
56+
57+
58+getModules :: [String] -> FilePath -> IO (Either String [Module])
59+getModules uses file = do
2460 code <- readFile file
25− let name = takeWhile (/='.') file
26− case compile code of
27− Left err -> putStrLn err
28− Right jsCode -> writeFile (name ++ ".html") . renderHtml $
29− generateHtml libLoc name code
30−
31−usageMini :: String
32−usageMini =
33− "Usage: elm [OPTIONS] FILE\n\
34− \Try `elm --help' for more information."
35−
36−usage :: String
37−usage =
38− "Usage: elm [OPTIONS] FILE\n\
39− \Compile .elm files to .html files.\n\
40− \Example: elm --runtime-location=../elm-mini.js main.elm\n\
41− \\n\
42− \Resource Locations:\n\
43− \ --runtime-location set the location of the Elm runtime (elm-mini.js)\n\
44− \\n\
45− \Compiler Information:\n\
46− \ --version print the version information and exit\n\
47− \ --help display this help and exit\n\
48− \\n\
49− \Elm home page: <http://elm-lang.org>"
61+ case initialize code of
62+ Left err -> return . Left $ "Error in " ++ file ++ ":\n" ++ err
63+ Right modul@(Module _ _ imports _) ->
64+ let imps = filter (`notElem` builtInModules) $ map fst imports in
65+ case intersect uses imps of
66+ x:_ -> return . Left $ "Error: Cyclic dependency. Module " ++
67+ x ++ " depends on itself."
68+ [] -> do
69+ ems <- mapM (getModules (uses ++ imps) . toFilePath) imps
70+ return $ case lefts ems of
71+ [] -> Right $ concat (rights ems) ++ [modul]
72+ errs -> Left $ intercalate "\n" errs
73+
74+toFilePath :: String -> FilePath
75+toFilePath modul = map (\c -> if c == '.' then '/' else c) modul ++ ".elm"
76+
77+builtInModules =
78+ concat [ map ("Data."++) [ "List", "Char", "Maybe" ]
79+ , map ("Signal."++) [ "Mouse", "Keyboard.Raw"
80+ , "Window", "Time", "HTTP", "Input", "Random" ]
81+ , [ "Element", "Text", "Color", "Line" ]
82+ , [ "Prelude" ]
83+ ]