on master help sign in
Merge branch 'dev' into topic/webgl
commit6785c5cec58af621c099ba41a3327900394d5efb authorJohn P Mayer Jr <john.p.mayer.jr@gmail.com> dateWed 18 Dec 2013, 00:40 (13 years ago) parented58c3f16aef1e
32 files changed+935−782
Elm.cabal+28−7 compiler/Build/Dependencies.hs+131 compiler/Build/File.hs+106 compiler/Build/Flags.hs+44 compiler/Build/Print.hs+32 compiler/Build/Source.hs+63 compiler/Build/Utils.hs+20 compiler/Compiler.hs+42−199 compiler/Elm/Internal/Dependencies.hs+119 compiler/Elm/Internal/Documentation.hs+41 compiler/Elm/Internal/Name.hs+51 compiler/Elm/Internal/Paths.hs+23 compiler/Elm/Internal/Utils.hs+28 compiler/Elm/Internal/Version.hs+73 compiler/Generate/Html.hs+3−10 compiler/Generate/JavaScript.hs+17−17 compiler/Generate/Markdown.hs+34−1 compiler/Initialize.hs−123 compiler/InterfaceSerialization.hs+4−4 compiler/Language/Elm.hs−45 compiler/Paths_El.hs → compiler/Paths_Elm.h compiler/SourceSyntax/Module.hs+11−3 libraries/Basics.elm+7−3 libraries/Bitwise.elm+6−6 libraries/Graphics/Element.elm+1−1 libraries/Graphics/Input.elm+1−1 libraries/Lazy.elm−53 libraries/Lazy/Stream.elm−275 libraries/Native/Lazy.js−26 libraries/Signal.elm+3−3 libraries/Transform2D.elm+7−5 libraries/elm_dependencies.json+40
Elm.cabal+28−7
@@ -30,7 +30,12 @@ source-repository head
3030 location: git://github.com/evancz/Elm.git
3131
3232Library
33− exposed-modules: Language.Elm
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
3439 Hs-Source-Dirs: compiler
3540 other-modules: SourceSyntax.Declaration,
3641 SourceSyntax.Expression,
@@ -54,7 +59,6 @@ Library
5459 Transform.Substitute,
5560 Transform.Optimize,
5661 Metadata.Prelude,
57− Initialize,
5862 InterfaceSerialization,
5963 Parse.Binop,
6064 Parse.Declaration,
@@ -79,9 +83,16 @@ Library
7983 Type.State,
8084 Type.Type,
8185 Type.Unify,
86+ Build.Dependencies,
87+ Build.File,
88+ Build.Flags,
89+ Build.Print,
90+ Build.Source,
91+ Build.Utils,
8292 Paths_Elm
8393
84− Build-depends: base >=4.2 && <5,
94+ Build-depends: aeson,
95+ base >=4.2 && <5,
8596 binary >= 0.6.4.0,
8697 blaze-html == 0.5.* || == 0.6.*,
8798 blaze-markup,
@@ -97,9 +108,11 @@ Library
97108 pandoc >= 1.10,
98109 parsec >= 3.1.1,
99110 pretty,
111+ text,
100112 transformers >= 0.2,
101113 union-find,
102− uniplate
114+ uniplate,
115+ unordered-containers
103116
104117Executable elm
105118 Main-is: Compiler.hs
@@ -126,7 +139,6 @@ Executable elm
126139 Transform.Substitute,
127140 Transform.Optimize,
128141 Metadata.Prelude,
129− Initialize,
130142 InterfaceSerialization,
131143 Parse.Binop,
132144 Parse.Declaration,
@@ -151,9 +163,16 @@ Executable elm
151163 Type.State,
152164 Type.Type,
153165 Type.Unify,
166+ Build.Dependencies,
167+ Build.File,
168+ Build.Flags,
169+ Build.Print,
170+ Build.Source,
171+ Build.Utils,
154172 Paths_Elm
155173
156− Build-depends: base >=4.2 && <5,
174+ Build-depends: aeson,
175+ base >=4.2 && <5,
157176 binary >= 0.6.4.0,
158177 blaze-html == 0.5.* || == 0.6.*,
159178 blaze-markup == 0.5.1.*,
@@ -169,9 +188,11 @@ Executable elm
169188 pandoc >= 1.10,
170189 parsec >= 3.1.1,
171190 pretty,
191+ text,
172192 transformers >= 0.2,
173193 union-find,
174− uniplate
194+ uniplate,
195+ unordered-containers
175196
176197Executable elm-doc
177198 Main-is: Docs.hs
compiler/Build/Dependencies.hsnew file+131
@@ -0,0 +1,131 @@
1+module Build.Dependencies (getSortedDependencies) where
2+
3+import Data.Data
4+import Control.Applicative
5+import Control.Monad.Error
6+import qualified Control.Monad.State as State
7+import qualified Data.Aeson as Json
8+import qualified Data.ByteString.Lazy.Char8 as BSC
9+import qualified Data.Char as Char
10+import qualified Data.Graph as Graph
11+import qualified Data.List as List
12+import qualified Data.Map as Map
13+import qualified Data.Maybe as Maybe
14+import qualified Data.Set as Set
15+import System.Directory
16+import System.Exit
17+import System.FilePath as FP
18+import System.IO
19+import Text.PrettyPrint (Doc)
20+
21+import SourceSyntax.Everything
22+import qualified SourceSyntax.Type as Type
23+import qualified Parse.Parse as Parse
24+import qualified Metadata.Prelude as Prelude
25+import qualified Transform.Check as Check
26+import qualified Transform.SortDefinitions as SD
27+import qualified Type.Inference as TI
28+import qualified Type.Constrain.Declaration as TcDecl
29+import qualified Transform.Canonicalize as Canonical
30+import qualified Elm.Internal.Paths as Path
31+import qualified Elm.Internal.Name as N
32+import qualified Elm.Internal.Version as V
33+import qualified Elm.Internal.Dependencies as Deps
34+
35+getSortedDependencies :: [FilePath] -> Interfaces -> FilePath -> IO [String]
36+getSortedDependencies srcDirs builtIns root =
37+ do extras <- extraDependencies
38+ let allSrcDirs = srcDirs ++ Maybe.fromMaybe [] extras
39+ result <- runErrorT $ readDeps allSrcDirs builtIns root
40+ case result of
41+ Right deps -> sortDeps deps
42+ Left err -> failure $ err ++ if Maybe.isJust extras then "" else msg
43+ where msg = "\nYou may need to create a " ++
44+ Path.dependencyFile ++
45+ " file if you\nare trying to use a 3rd party library."
46+
47+failure msg = hPutStrLn stderr msg >> exitFailure
48+
49+extraDependencies :: IO (Maybe [FilePath])
50+extraDependencies =
51+ do exists <- doesFileExist Path.dependencyFile
52+ if not exists then return Nothing else Just <$> getPaths
53+ where
54+ getPaths = do
55+ raw <- BSC.readFile Path.dependencyFile
56+ case Json.eitherDecode raw of
57+ Right (Deps.Mini deps) -> mapM validate deps
58+ Left err ->
59+ failure $ "Error reading the " ++ Path.dependencyFile ++ " file:\n" ++ err
60+
61+ validate (name,version) = do
62+ let path = Path.dependencyDirectory </> toPath name version
63+ exists <- doesDirectoryExist path
64+ if exists then return path else failure (notFound name version)
65+
66+ toPath name version = N.toFilePath name </> show version
67+
68+ notFound name version =
69+ unlines
70+ [ "Your " ++ Path.dependencyFile ++ " file says you depend on library"
71+ , show name ++ " " ++ show version ++ " but it was not found."
72+ , "You may need to install it with:"
73+ , ""
74+ , " elm-get install " ++ show name ++ " " ++ show version ]
75+
76+type Deps = (FilePath, String, [String])
77+
78+sortDeps :: [Deps] -> IO [String]
79+sortDeps depends =
80+ if null mistakes
81+ then return (concat sccs)
82+ else failure $ msg ++ unlines (map show mistakes)
83+ where
84+ sccs = map Graph.flattenSCC $ Graph.stronglyConnComp depends
85+
86+ mistakes = filter (\scc -> length scc > 1) sccs
87+ msg = "A cyclical module dependency or was detected in:\n"
88+
89+readDeps :: [FilePath] -> Interfaces -> FilePath -> ErrorT String IO [Deps]
90+readDeps srcDirs builtIns root = do
91+ let ifaces = (Set.fromList . Map.keys) builtIns
92+ State.evalStateT (go ifaces root) Set.empty
93+ where
94+ go :: Set.Set String -> FilePath -> State.StateT (Set.Set String) (ErrorT String IO) [Deps]
95+ go builtIns root = do
96+ (root', txt) <- lift $ getFile srcDirs root
97+ case Parse.dependencies txt of
98+ Left err -> throwError $ msg ++ show err
99+ where msg = "Error resolving dependencies in " ++ root' ++ ":\n"
100+
101+ Right (name,deps) ->
102+ do seen <- State.get
103+ let realDeps = Set.difference (Set.fromList deps) builtIns
104+ newDeps = Set.difference (Set.filter (not . isNative) realDeps) seen
105+ State.put (Set.insert name (Set.union newDeps seen))
106+ rest <- mapM (go builtIns . toFilePath) (Set.toList newDeps)
107+ return ((makeRelative "." root', name, Set.toList realDeps) : concat rest)
108+
109+getFile :: [FilePath] -> FilePath -> ErrorT String IO (FilePath,String)
110+getFile [] path =
111+ throwError $ unlines
112+ [ "Could not find file: " ++ path
113+ , " If it is not in the root directory of your project, use"
114+ , " --src-dir to declare additional locations for source files."
115+ , " If it is part of a 3rd party library, it needs to be declared"
116+ , " as a dependency in the " ++ Path.dependencyFile ++ " file." ]
117+
118+getFile (dir:dirs) path = do
119+ let path' = dir </> path
120+ exists <- liftIO $ doesFileExist path'
121+ case exists of
122+ True -> (,) path' `fmap` liftIO (readFile path')
123+ False -> getFile dirs path
124+
125+isNative name = List.isPrefixOf "Native." name
126+
127+toFilePath :: String -> FilePath
128+toFilePath name = map swapDots name ++ ext
129+ where swapDots '.' = '/'
130+ swapDots c = c
131+ ext = if isNative name then ".js" else ".elm"
compiler/Build/File.hsnew file+106
@@ -0,0 +1,106 @@
1+module Build.File (build) where
2+
3+import Control.Monad (when)
4+import qualified Data.Binary as Binary
5+import qualified Data.List as List
6+import qualified Data.Map as Map
7+import System.Directory
8+import System.Exit
9+import System.FilePath
10+import System.IO
11+
12+import qualified Transform.Canonicalize as Canonical
13+
14+import qualified Data.ByteString.Lazy as L
15+
16+import qualified Build.Utils as Utils
17+import qualified Build.Flags as Flag
18+import qualified Build.Source as Source
19+import qualified Build.Print as Print
20+import qualified Generate.JavaScript as JS
21+import qualified InterfaceSerialization as IS
22+import qualified Parse.Module as Parser
23+import qualified SourceSyntax.Module as M
24+
25+build :: Flag.Flags -> Int -> M.Interfaces -> String -> [FilePath]
26+ -> IO (String, M.Interfaces)
27+build _ _ interfaces moduleName [] =
28+ return (moduleName, interfaces)
29+build flags numModules interfaces _ (filePath:rest) =
30+ do (name,interface) <-
31+ build1 flags (numModules - length rest) numModules interfaces filePath
32+ let interfaces' = Map.insert name interface interfaces
33+ build flags numModules interfaces' name rest
34+
35+
36+build1 :: Flag.Flags -> Int -> Int -> M.Interfaces -> FilePath
37+ -> IO (String, M.ModuleInterface)
38+build1 flags moduleNum numModules interfaces filePath =
39+ do compiled <- alreadyCompiled flags filePath
40+ case compiled of
41+ False -> compile flags number interfaces filePath
42+ True -> retrieve flags interfaces filePath
43+ where
44+ number = "[" ++ show moduleNum ++ " of " ++ show numModules ++ "]"
45+
46+
47+alreadyCompiled :: Flag.Flags -> FilePath -> IO Bool
48+alreadyCompiled flags filePath = do
49+ existsi <- doesFileExist (Utils.elmi flags filePath)
50+ existso <- doesFileExist (Utils.elmo flags filePath)
51+ if not existsi || not existso
52+ then return False
53+ else do tsrc <- getModificationTime filePath
54+ tint <- getModificationTime (Utils.elmo flags filePath)
55+ return (tsrc <= tint)
56+
57+retrieve :: Flag.Flags -> Map.Map String M.ModuleInterface -> FilePath
58+ -> IO (String, M.ModuleInterface)
59+retrieve flags interfaces filePath = do
60+ bytes <- IS.loadInterface (Utils.elmi flags filePath)
61+ let binary = IS.interfaceDecode (Utils.elmi flags filePath) =<< bytes
62+ case IS.validVersion filePath =<< binary of
63+ Right (name, interface) ->
64+ do when (Flag.print_types flags) (Print.interfaceTypes interfaces interface)
65+ return (name, interface)
66+ Left err ->
67+ do hPutStrLn stderr err
68+ exitFailure
69+
70+compile :: Flag.Flags -> String -> M.Interfaces -> FilePath
71+ -> IO (String, M.ModuleInterface)
72+compile flags number interfaces filePath =
73+ do source <- readFile filePath
74+ let name = getName source
75+ printStatus name
76+
77+ createDirectoryIfMissing True (Flag.cache_dir flags)
78+ createDirectoryIfMissing True (Flag.build_dir flags)
79+
80+ metaModule <-
81+ case Source.build (Flag.no_prelude flags) interfaces source of
82+ Right modul -> return modul
83+ Left errors -> do Print.errors errors
84+ exitFailure
85+
86+ when (Flag.print_types flags) $ Print.metaTypes interfaces metaModule
87+
88+ let intermediate = (name, Canonical.interface name $ M.metaToInterface metaModule)
89+ generateCache intermediate metaModule
90+ return intermediate
91+
92+ where
93+ getName source = case Parser.getModuleName source of
94+ Just n -> n
95+ Nothing -> "Main"
96+
97+ printStatus name =
98+ hPutStrLn stdout $ concat [ number, " Compiling ", name
99+ , replicate (max 1 (20 - length name)) ' '
100+ , "( " ++ filePath ++ " )" ]
101+
102+ generateCache intermediate metaModule = do
103+ createDirectoryIfMissing True . dropFileName $ Utils.elmi flags filePath
104+ writeFile (Utils.elmo flags filePath) (JS.generate metaModule)
105+ withBinaryFile (Utils.elmi flags filePath) WriteMode $ \handle ->
106+ L.hPut handle (Binary.encode intermediate)
compiler/Build/Flags.hsnew file+44
@@ -0,0 +1,44 @@
1+{-# LANGUAGE DeriveDataTypeable #-}
2+module Build.Flags where
3+
4+import qualified Elm.Internal.Version as Version
5+import System.Console.CmdArgs
6+
7+data Flags = Flags
8+ { make :: Bool
9+ , files :: [FilePath]
10+ , runtime :: Maybe FilePath
11+ , only_js :: Bool
12+ , print_types :: Bool
13+ , scripts :: [FilePath]
14+ , no_prelude :: Bool
15+ , cache_dir :: FilePath
16+ , build_dir :: FilePath
17+ , src_dir :: [FilePath]
18+ }
19+ deriving (Data,Typeable,Show,Eq)
20+
21+flags = Flags
22+ { files = def &= args &= typ "FILES"
23+ , make = False
24+ &= help "automatically compile dependencies."
25+ , only_js = False
26+ &= help "Compile only to JavaScript."
27+ , no_prelude = False
28+ &= help "Do not import Prelude by default, used only when compiling standard libraries."
29+ , scripts = [] &= typFile
30+ &= help "Load JavaScript files in generated HTML. Files will be included in the given order."
31+ , runtime = Nothing &= typFile
32+ &= help "Specify a custom location for Elm's runtime system."
33+ , cache_dir = "cache" &= typFile
34+ &= help "Directory for files cached to make builds faster. Defaults to cache/ directory."
35+ , build_dir = "build" &= typFile
36+ &= help "Directory for generated HTML and JS files. Defaults to build/ directory."
37+ , src_dir = ["."] &= typFile
38+ &= help "Additional source directories besides project root. Searched when using --make"
39+ , print_types = False
40+ &= help "Print out infered types of top-level definitions."
41+ } &= help "Compile Elm programs to HTML, CSS, and JavaScript."
42+ &= helpArg [explicit, name "help", name "h"]
43+ &= versionArg [explicit, name "version", name "v", summary (show Version.elmVersion)]
44+ &= summary ("The Elm Compiler " ++ show Version.elmVersion ++ ", (c) Evan Czaplicki 2011-2013")
compiler/Build/Print.hsnew file+32
@@ -0,0 +1,32 @@
1+module Build.Print where
2+
3+import qualified Data.Map as Map
4+import qualified Data.List as List
5+import qualified SourceSyntax.Module as M
6+import qualified SourceSyntax.PrettyPrint as Pretty
7+import qualified Type.Alias as Alias
8+import qualified Text.PrettyPrint as P
9+
10+metaTypes :: Map.Map String M.ModuleInterface -> M.MetadataModule () () -> IO ()
11+metaTypes interfaces meta =
12+ types interfaces (M.types meta) (M.aliases meta) (M.imports meta)
13+
14+interfaceTypes :: Map.Map String M.ModuleInterface -> M.ModuleInterface -> IO ()
15+interfaceTypes interfaces iface =
16+ types interfaces (M.iTypes iface) (M.iAliases iface) (M.iImports iface)
17+
18+types interfaces types' aliases imports =
19+ do putStrLn ""
20+ mapM_ printType (Map.toList types')
21+ putStrLn ""
22+ where
23+ rules = Alias.rules interfaces aliases imports
24+
25+ printType (n,t) = do
26+ print $ P.hsep [ Pretty.variable n
27+ , P.text ":"
28+ , Pretty.pretty (Alias.realias rules t) ]
29+
30+errors :: [P.Doc] -> IO ()
31+errors errs =
32+ mapM_ print (List.intersperse (P.text " ") errs)
compiler/Build/Source.hsnew file+63
@@ -0,0 +1,63 @@
1+module Build.Source (build) where
2+
3+import Data.Data
4+import Control.Monad.State
5+import qualified Data.Graph as Graph
6+import qualified Data.List as List
7+import qualified Data.Map as Map
8+import qualified Data.Set as Set
9+import System.Directory
10+import System.Exit
11+import System.FilePath as FP
12+import Text.PrettyPrint (Doc)
13+
14+import SourceSyntax.Everything
15+import qualified SourceSyntax.Type as Type
16+import qualified Parse.Parse as Parse
17+import qualified Metadata.Prelude as Prelude
18+import qualified Transform.Check as Check
19+import qualified Transform.SortDefinitions as SD
20+import qualified Type.Inference as TI
21+import qualified Type.Constrain.Declaration as TcDecl
22+import qualified Transform.Canonicalize as Canonical
23+
24+build :: Bool -> Interfaces -> String -> Either [Doc] (MetadataModule () ())
25+build noPrelude interfaces source =
26+ do let add = if noPrelude then id else Prelude.add
27+ infixes = Map.fromList . map (\(assoc,lvl,op) -> (op,(lvl,assoc)))
28+ . concatMap iFixities $ Map.elems interfaces
29+
30+ modul@(Module _ _ _ decls') <- add `fmap` Parse.program infixes source
31+
32+ -- check for structural errors
33+ Module names exs ims decls <-
34+ case Check.mistakes decls' of
35+ [] -> return modul
36+ ms -> Left ms
37+
38+ let exports'
39+ | null exs =
40+ let get = Set.toList . SD.boundVars in
41+ concat [ get pattern | Definition (Def pattern _) <- decls ] ++
42+ concat [ map fst ctors | Datatype _ _ ctors <- decls ] ++
43+ [ name | TypeAlias name _ (Type.Record _ _) <- decls ]
44+ | otherwise = exs
45+
46+ metaModule <- Canonical.metadataModule interfaces $ MetadataModule {
47+ names = names,
48+ path = FP.joinPath names,
49+ exports = exports',
50+ imports = ims,
51+ -- reorder AST into strongly connected components
52+ program = SD.sortDefs . dummyLet $ TcDecl.toExpr decls,
53+ types = Map.empty,
54+ datatypes = [ (name,vars,ctors) | Datatype name vars ctors <- decls ],
55+ fixities = [ (assoc,level,op) | Fixity assoc level op <- decls ],
56+ aliases = [ (name,tvs,tipe) | TypeAlias name tvs tipe <- decls ],
57+ foreignImports = [ (evt,v,name,typ) | ImportEvent evt v name typ <- decls ],
58+ foreignExports = [ (evt,name,typ) | ExportEvent evt name typ <- decls ]
59+ }
60+
61+ types <- TI.infer interfaces metaModule
62+
63+ return $ metaModule { types = types }
compiler/Build/Utils.hsnew file+20
@@ -0,0 +1,20 @@
1+module Build.Utils where
2+
3+import System.FilePath ((</>), replaceExtension)
4+import qualified Build.Flags as Flag
5+
6+buildPath :: Flag.Flags -> FilePath -> String -> FilePath
7+buildPath flags filePath ext =
8+ Flag.build_dir flags </> replaceExtension filePath ext
9+
10+cachePath :: Flag.Flags -> FilePath -> String -> FilePath
11+cachePath flags filePath ext =
12+ Flag.cache_dir flags </> replaceExtension filePath ext
13+
14+elmo :: Flag.Flags -> FilePath -> FilePath
15+elmo flags filePath =
16+ cachePath flags filePath "elmo"
17+
18+elmi :: Flag.Flags -> FilePath -> FilePath
19+elmi flags filePath =
20+ cachePath flags filePath "elmi"
compiler/Compiler.hs+42−199
@@ -1,225 +1,68 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
21module Main where
32
4−import Control.Monad
3+import Control.Monad (foldM)
54import qualified Data.Map as Map
6−import qualified Data.List as List
7−import qualified Data.Binary as Binary
8−import Data.Version (showVersion)
9−import System.Console.CmdArgs hiding (program)
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
109import System.Directory
11−import System.Exit
1210import System.FilePath
13−import System.IO
1411import GHC.Conc
1512
16−import Text.Blaze.Html.Renderer.Pretty (renderHtml)
17−import qualified Data.ByteString.Lazy.Char8 as BS
18−import qualified Data.ByteString.Lazy as L
19−
13+import Build.Dependencies (getSortedDependencies)
14+import qualified Generate.Html as Html
2015import qualified Metadata.Prelude as Prelude
21−import qualified Transform.Canonicalize as Canonical
22−import SourceSyntax.Module
23−import Parse.Module (getModuleName)
24−import Initialize (buildFromSource, getSortedDependencies)
25−import Generate.JavaScript (jsModule)
26−import Generate.Html (createHtml, JSSource(..))
27−import qualified InterfaceSerialization as IS
28−import Paths_Elm
29−
30−import SourceSyntax.PrettyPrint (pretty, variable)
31−import Text.PrettyPrint as P
32−import qualified Type.Type as Type
33−import qualified Type.Alias as Alias
34−
35−data Flags =
36− Flags { make :: Bool
37− , files :: [FilePath]
38− , runtime :: Maybe FilePath
39− , only_js :: Bool
40− , print_types :: Bool
41− , scripts :: [FilePath]
42− , no_prelude :: Bool
43− , cache_dir :: FilePath
44− , build_dir :: FilePath
45− , src_dir :: [FilePath]
46− }
47− deriving (Data,Typeable,Show,Eq)
48−
49−flags = Flags
50− { files = def &= args &= typ "FILES"
51− , make = False
52− &= help "automatically compile dependencies."
53− , only_js = False
54− &= help "Compile only to JavaScript."
55− , no_prelude = False
56− &= help "Do not import Prelude by default, used only when compiling standard libraries."
57− , scripts = [] &= typFile
58− &= help "Load JavaScript files in generated HTML. Files will be included in the given order."
59− , runtime = Nothing &= typFile
60− &= help "Specify a custom location for Elm's runtime system."
61− , cache_dir = "cache" &= typFile
62− &= help "Directory for files cached to make builds faster. Defaults to cache/ directory."
63− , build_dir = "build" &= typFile
64− &= help "Directory for generated HTML and JS files. Defaults to build/ directory."
65− , src_dir = ["."] &= typFile
66− &= help "Additional source directories besides project root. Searched when using --make"
67− , print_types = False
68− &= help "Print out infered types of top-level definitions."
69− } &= help "Compile Elm programs to HTML, CSS, and JavaScript."
70− &= helpArg [explicit, name "help", name "h"]
71− &= versionArg [explicit, name "version", name "v", summary (showVersion version)]
72− &= summary ("The Elm Compiler " ++ showVersion version ++ ", (c) Evan Czaplicki 2011-2013")
16+import qualified Build.Utils as Utils
17+import qualified Build.Flags as Flag
18+import qualified Build.File as File
19+import qualified Elm.Internal.Paths as Path
7320
7421main :: IO ()
7522main = do setNumCapabilities =<< getNumProcessors
76− compileArgs =<< cmdArgs flags
23+ compileArgs =<< CmdArgs.cmdArgs Flag.flags
7724
78−compileArgs :: Flags -> IO ()
25+compileArgs :: Flag.Flags -> IO ()
7926compileArgs flags =
80− case files flags of
27+ case Flag.files flags of
8128 [] -> putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
8229 fs -> mapM_ (build flags) fs
8330
31+build :: Flag.Flags -> FilePath -> IO ()
32+build flags rootFile =
33+ do let noPrelude = Flag.no_prelude flags
34+ builtIns <- if noPrelude then return Map.empty else Prelude.interfaces
8435
85−buildPath :: Flags -> FilePath -> String -> FilePath
86−buildPath flags filePath ext = build_dir flags </> replaceExtension filePath ext
87−
88−cachePath :: Flags -> FilePath -> String -> FilePath
89−cachePath flags filePath ext = cache_dir flags </> replaceExtension filePath ext
90−
91−elmo :: Flags -> FilePath -> FilePath
92−elmo flags filePath = cachePath flags filePath "elmo"
93−
94−elmi :: Flags -> FilePath -> FilePath
95−elmi flags filePath = cachePath flags filePath "elmi"
96−
97−buildFile :: Flags -> Int -> Int -> Interfaces -> FilePath -> IO (String, ModuleInterface)
98−buildFile flags moduleNum numModules interfaces filePath = do
99− compiled <- alreadyCompiled
100− if not compiled then compile else do
101− bytes <- IS.loadInterface (elmi flags filePath)
102− let binary = IS.interfaceDecode (elmi flags filePath) =<< bytes
103− case IS.validVersion filePath =<< binary of
104− Left err -> do
105− hPutStrLn stderr err
106− exitFailure
107−
108− Right (name, interface) -> do
109− when (print_types flags) $
110− printTypes interfaces
111− (iTypes interface)
112− (iAliases interface)
113− (iImports interface)
114−
115− return (name, interface)
116−
117− where
118− alreadyCompiled :: IO Bool
119− alreadyCompiled = do
120− existsi <- doesFileExist (elmi flags filePath)
121− existso <- doesFileExist (elmo flags filePath)
122− if not existsi || not existso
123− then return False
124− else do tsrc <- getModificationTime filePath
125− tint <- getModificationTime (elmo flags filePath)
126− return (tsrc <= tint)
127−
128− number :: String
129− number = "[" ++ show moduleNum ++ " of " ++ show numModules ++ "]"
130−
131− compile :: IO (String,ModuleInterface)
132− compile = do
133− source <- readFile filePath
134− let name = case getModuleName source of
135− Just n -> n
136− Nothing -> "Main"
137− putStrLn $ concat [ number, " Compiling ", name
138− , replicate (max 1 (20 - length name)) ' '
139− , "( " ++ filePath ++ " )" ]
140−
141− createDirectoryIfMissing True (cache_dir flags)
142− createDirectoryIfMissing True (build_dir flags)
143−
144− metaModule <-
145− case buildFromSource (no_prelude flags) interfaces source of
146− Left errors -> do
147− mapM print (List.intersperse (P.text " ") errors)
148− exitFailure
149− Right modul -> return modul
150−
151− when (print_types flags)
152− (printTypes interfaces
153− (types metaModule) (aliases metaModule) (imports metaModule))
154−
155− let interface = Canonical.interface name $ ModuleInterface {
156− iVersion = showVersion version,
157− iTypes = types metaModule,
158− iImports = imports metaModule,
159− iAdts = datatypes metaModule,
160− iAliases = aliases metaModule,
161− iFixities = fixities metaModule
162− }
163−
164− createDirectoryIfMissing True . dropFileName $ elmi flags filePath
165− handle <- openBinaryFile (elmi flags filePath) WriteMode
166− L.hPut handle (Binary.encode (name,interface))
167− hClose handle
168− writeFile (elmo flags filePath) (jsModule metaModule)
169− return (name,interface)
170−
171−printTypes interfaces moduleTypes moduleAliases moduleImports = do
172− putStrLn ""
173− let rules = Alias.rules interfaces moduleAliases moduleImports
174− forM_ (Map.toList moduleTypes) $ \(n,t) -> do
175− print $ variable n <+> P.text ":" <+> pretty (Alias.realias rules t)
176− putStrLn ""
177−
178−getRuntime :: Flags -> IO FilePath
179−getRuntime flags =
180− case runtime flags of
181− Just fp -> return fp
182− Nothing -> getDataFileName "elm-runtime.js"
183−
184−build :: Flags -> FilePath -> IO ()
185−build flags rootFile = do
186− let noPrelude = no_prelude flags
187− builtIns <- if noPrelude then return Map.empty else Prelude.interfaces
188−
189− files <- if make flags
190− then getSortedDependencies (src_dir flags) builtIns rootFile
191− else return [rootFile]
36+ files <- if Flag.make flags
37+ then getSortedDependencies (Flag.src_dir flags) builtIns rootFile
38+ else return [rootFile]
19239
193− (moduleName, interfaces) <- buildFiles flags (length files) builtIns "" files
40+ (moduleName, interfaces) <-
41+ File.build flags (length files) builtIns "" files
19442
195− js <- foldM appendToOutput BS.empty files
43+ js <- foldM appendToOutput BS.empty files
19644
197− (extension, code) <- case only_js flags of
198− True -> do
199− putStr "Generating JavaScript ... "
200− return ("js", js)
201− False -> do
202− putStr "Generating HTML ... "
203− rtsPath <- getRuntime flags
204− return ("html", BS.pack . renderHtml $
205− createHtml rtsPath (takeBaseName rootFile) (sources js) moduleName "")
45+ (extension, code) <-
46+ if Flag.only_js flags
47+ then do putStr "Generating JavaScript ... "
48+ return ("js", js)
49+ else do putStr "Generating HTML ... "
50+ return (makeHtml js moduleName)
20651
207− let targetFile = buildPath flags rootFile extension
208− createDirectoryIfMissing True (takeDirectory targetFile)
209− BS.writeFile targetFile code
210− putStrLn "Done"
52+ let targetFile = Utils.buildPath flags rootFile extension
53+ createDirectoryIfMissing True (takeDirectory targetFile)
54+ BS.writeFile targetFile code
55+ putStrLn "Done"
21156
21257 where
21358 appendToOutput :: BS.ByteString -> FilePath -> IO BS.ByteString
214− appendToOutput js filePath =
215− do src <- BS.readFile (elmo flags filePath)
216− return (BS.append src js)
59+ appendToOutput js filePath = do
60+ src <- BS.readFile (Utils.elmo flags filePath)
61+ return (BS.append src js)
21762
218− sources js = map Link (scripts flags) ++ [ Source js ]
63+ sources js = map Html.Link (Flag.scripts flags) ++ [ Html.Source js ]
21964
220−buildFiles :: Flags -> Int -> Interfaces -> String -> [FilePath] -> IO (String, Interfaces)
221−buildFiles _ _ interfaces moduleName [] = return (moduleName, interfaces)
222−buildFiles flags numModules interfaces _ (filePath:rest) = do
223− (name,interface) <- buildFile flags (numModules - length rest) numModules interfaces filePath
224− let interfaces' = Map.insert name interface interfaces
225− buildFiles flags numModules interfaces' name rest
65+ makeHtml js moduleName = ("html", BS.pack $ renderHtml html)
66+ where
67+ rtsPath = Maybe.fromMaybe Path.runtime (Flag.runtime flags)
68+ html = Html.generate rtsPath (takeBaseName rootFile) (sources js) moduleName ""
compiler/Elm/Internal/Dependencies.hsnew file+119
@@ -0,0 +1,119 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Elm.Internal.Dependencies where
3+
4+import Control.Applicative
5+import Control.Monad.Error
6+import qualified Control.Exception as E
7+import Data.Aeson
8+import qualified Data.List as List
9+import qualified Data.ByteString.Lazy as BS
10+import qualified Data.HashMap.Strict as Map
11+import qualified Elm.Internal.Name as N
12+import qualified Elm.Internal.Version as V
13+
14+data Deps = Deps
15+ { name :: N.Name
16+ , version :: V.Version
17+ , summary :: String
18+ , description :: String
19+ , license :: String
20+ , repo :: String
21+ , exposed :: [String]
22+ , elmVersion :: V.Version
23+ , dependencies :: [(N.Name,V.Version)]
24+ } deriving Show
25+
26+data MiniDeps = Mini [(N.Name,V.Version)]
27+
28+instance FromJSON MiniDeps where
29+ parseJSON (Object obj) = Mini <$> getDependencies obj
30+ parseJSON _ = mzero
31+
32+instance FromJSON Deps where
33+ parseJSON (Object obj) =
34+ do version <- get obj "version" "your projects version number"
35+
36+ summary <- get obj "summary" "a short summary of your project"
37+ when (length summary >= 80) $
38+ fail "'summary' must be less than 80 characters"
39+
40+ desc <- get obj "description" "an extended description of your project \
41+ \and how to get started with it."
42+ license <- get obj "license" "license information (BSD3 is recommended)"
43+
44+ repo <- get obj "repository" "a link to the project's GitHub repo"
45+ name <- case repoToName repo of
46+ Left err -> fail err
47+ Right nm -> return nm
48+
49+ exposed <- get obj "exposed-modules" "a list of modules exposed to users"
50+ when (null exposed) $
51+ fail "there are no 'exposed-modules'.\n\
52+ \At least one module must be exposed \
53+ \for anyone to use this library!"
54+
55+ elmVersion <- get obj "elm-version" "the version of the Elm compiler you are using"
56+
57+ deps <- getDependencies obj
58+
59+ return $ Deps name version summary desc license repo exposed elmVersion deps
60+
61+ parseJSON _ = mzero
62+
63+getDependencies obj =
64+ toDeps =<< get obj "dependencies" "a listing of your project's dependencies"
65+ where
66+ toDeps deps =
67+ forM (Map.toList deps) $ \(f,v) ->
68+ case (N.fromString f, V.fromString v) of
69+ (Just name, Just version) -> return (name,version)
70+ (Nothing, _) -> fail $ N.errorMsg f
71+ (_, Nothing) -> fail $ "invalid version number " ++ v
72+
73+
74+get obj field desc =
75+ do maybe <- obj .:? field
76+ case maybe of
77+ Just value -> return value
78+ Nothing -> fail $ "Missing field " ++ show field ++ ", " ++ desc ++ ".\n" ++
79+ " <https://github.com/evancz/rainbow-palette/blob/master/elm_dependencies.json>"
80+
81+repoToName :: String -> Either String N.Name
82+repoToName repo
83+ | not (end `List.isSuffixOf` repo) = Left msg
84+ | otherwise =
85+ do path <- getPath
86+ let raw = take (length path - length end) path
87+ case N.fromString raw of
88+ Nothing -> Left msg
89+ Just name -> Right name
90+ where
91+ getPath | http `List.isPrefixOf` repo = Right $ drop (length http ) repo
92+ | https `List.isPrefixOf` repo = Right $ drop (length https) repo
93+ | otherwise = Left msg
94+ http = "http://github.com/"
95+ https = "https://github.com/"
96+ end = ".git"
97+ msg = "the 'repository' field must point to a GitHub project for now, something\n\
98+ \like <https://github.com/USER/PROJECT.git> where USER is your GitHub name\n\
99+ \and PROJECT is the repo you want to upload."
100+
101+withDeps :: (Deps -> a) -> FilePath -> ErrorT String IO a
102+withDeps handle path =
103+ do json <- readPath
104+ case eitherDecode json of
105+ Left err -> throwError $ "Error reading file " ++ path ++ ":\n " ++ err
106+ Right ds -> return (handle ds)
107+ where
108+ readPath :: ErrorT String IO BS.ByteString
109+ readPath = do
110+ result <- liftIO $ E.catch (Right <$> BS.readFile path)
111+ (\err -> return $ Left (err :: IOError))
112+ case result of
113+ Right bytes -> return bytes
114+ Left _ -> throwError $
115+ "could not find file " ++ path ++
116+ "\n You may need to create a dependency file for your project."
117+
118+depsAt :: FilePath -> ErrorT String IO Deps
119+depsAt = withDeps id
compiler/Elm/Internal/Documentation.hsnew file+41
@@ -0,0 +1,41 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Elm.Internal.Documentation where
3+
4+import Control.Applicative ((<$>),(<*>))
5+import Control.Monad
6+import Data.Aeson
7+
8+data Document = Doc
9+ { moduleName :: String
10+ , structure :: String
11+ , entries :: [Entry]
12+ } deriving (Show)
13+
14+data Entry = Entry
15+ { name :: String
16+ , comment :: String
17+ , raw :: String
18+ , assocPrec :: Maybe (String,Int)
19+ } deriving (Show)
20+
21+instance FromJSON Document where
22+ parseJSON (Object v) =
23+ Doc <$> v .: "name"
24+ <*> v .: "document"
25+ <*> (concat <$> sequence [ v .: "aliases", v .: "datatypes", v .: "values" ])
26+
27+ parseJSON _ = fail "Conversion to Document was expecting an object"
28+
29+instance FromJSON Entry where
30+ parseJSON (Object v) =
31+ Entry <$> v .: "name"
32+ <*> v .: "comment"
33+ <*> v .: "raw"
34+ <*> (liftM2 (,) <$> v .:? "associativity"
35+ <*> v .:? "precedence")
36+
37+ parseJSON _ = fail "Conversion to Entry was expecting an object"
38+
39+data Content = Markdown String | Value String
40+ deriving Show
41+
compiler/Elm/Internal/Name.hsnew file+51
@@ -0,0 +1,51 @@
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)
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.hsnew file+23
@@ -0,0 +1,23 @@
1+module Elm.Internal.Paths where
2+
3+import System.IO.Unsafe
4+import qualified Paths_Elm as This
5+
6+-- |Name of directory for all of a project's dependencies.
7+dependencyDirectory :: FilePath
8+dependencyDirectory = "elm_dependencies"
9+
10+-- |Name of the dependency file, specifying dependencies and
11+-- other metadata for building and sharing projects.
12+dependencyFile :: FilePath
13+dependencyFile = "elm_dependencies.json"
14+
15+{-# NOINLINE runtime #-}
16+-- |The absolute path to Elm's runtime system.
17+runtime :: FilePath
18+runtime = unsafePerformIO $ This.getDataFileName "elm-runtime.js"
19+
20+{-# NOINLINE docs #-}
21+-- |The absolute path to Elm's core library documentation.
22+docs :: FilePath
23+docs = unsafePerformIO $ This.getDataFileName "docs.json"
compiler/Elm/Internal/Utils.hsnew file+28
@@ -0,0 +1,28 @@
1+{- | This module exports functions for compiling Elm to JS.
2+-}
3+module Elm.Internal.Utils (compile, moduleName) 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 SourceSyntax.Module as M
10+import qualified Text.PrettyPrint as P
11+import qualified Metadata.Prelude as Prelude
12+import System.IO.Unsafe
13+
14+-- |This function compiles Elm code to JavaScript. It will return either
15+-- an error message or the compiled JS code.
16+compile :: String -> Either String String
17+compile source =
18+ case Source.build False interfaces source of
19+ Left docs -> Left . unlines . List.intersperse "" $ map P.render docs
20+ Right modul -> Right $ JS.generate modul
21+
22+{-# NOINLINE interfaces #-}
23+interfaces :: M.Interfaces
24+interfaces = unsafePerformIO $ Prelude.interfaces
25+
26+-- |This function extracts the module name of a given source program.
27+moduleName :: String -> Maybe String
28+moduleName = Parser.getModuleName
compiler/Elm/Internal/Version.hsnew file+73
@@ -0,0 +1,73 @@
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/Generate/Html.hs+3−10
@@ -1,8 +1,5 @@
11{-# LANGUAGE OverloadedStrings #-}
2−module Generate.Html
3− (createHtml,
4− JSSource (..)
5− ) where
2+module Generate.Html (generate, JSSource(..)) where
63
74import Text.Blaze (preEscapedToMarkup)
85import qualified Text.Blaze.Html5 as H
@@ -10,10 +7,6 @@ import Text.Blaze.Html5 ((!))
107import qualified Text.Blaze.Html5.Attributes as A
118import qualified Data.ByteString.Lazy.Char8 as BS
129
13−import Initialize (buildFromSource)
14−import Generate.JavaScript
15−import Generate.Noscript
16−
1710data JSSource = Link String | Source BS.ByteString
1811
1912makeScript :: JSSource -> H.Html
@@ -24,8 +17,8 @@ makeScript source =
2417 H.script ! A.type_ "text/javascript" $
2518 preEscapedToMarkup $ BS.unpack src
2619
27−createHtml :: FilePath -> String -> [JSSource] -> String -> String -> H.Html
28−createHtml libLoc title scripts moduleName noscript =
20+generate :: FilePath -> String -> [JSSource] -> String -> String -> H.Html
21+generate libLoc title scripts moduleName noscript =
2922 H.docTypeHtml $ do
3023 H.head $ do
3124 H.meta ! A.charset "UTF-8"
compiler/Generate/JavaScript.hs+17−17
@@ -52,7 +52,7 @@ varDecl x expr =
5252 VarDecl () (var x) (Just expr)
5353
5454include alias moduleName =
55− varDecl alias (obj (moduleName ++ ".make") <| ref "elm")
55+ varDecl alias (obj (moduleName ++ ".make") <| ref "_elm")
5656
5757internalImports name =
5858 VarDeclStmt ()
@@ -296,14 +296,14 @@ clause span variable (Case.Clause value vars mtch) =
296296 is -> drop (last is + 1) name
297297
298298
299−jsModule :: MetadataModule () () -> String
300−jsModule modul =
299+generate :: MetadataModule () () -> String
300+generate modul =
301301 show . prettyPrint $ setup (Just "Elm") (names modul ++ ["make"]) ++
302− [ assign ("Elm" : names modul ++ ["make"]) (function ["elm"] programStmts) ]
302+ [ assign ("Elm" : names modul ++ ["make"]) (function ["_elm"] programStmts) ]
303303 where
304− thisModule = dotSep ("elm" : names modul ++ ["values"])
304+ thisModule = dotSep ("_elm" : names modul ++ ["values"])
305305 programStmts =
306− concat [ setup (Just "elm") (names modul ++ ["values"])
306+ concat [ setup (Just "_elm") (names modul ++ ["values"])
307307 , [ IfSingleStmt () thisModule (ReturnStmt () (Just thisModule)) ]
308308 , [ internalImports (List.intercalate "." (names modul)) ]
309309 , concatMap jsImport (imports modul)
@@ -315,7 +315,7 @@ jsModule modul =
315315 , [ ReturnStmt () (Just thisModule) ]
316316 ]
317317
318− jsExports = assign ("elm" : names modul ++ ["values"]) (ObjectLit () exs)
318+ jsExports = assign ("_elm" : names modul ++ ["values"]) (ObjectLit () exs)
319319 where
320320 exs = map entry . filter (not . isOp) $ "_op" : exports modul
321321 entry x = (PropId () (var x), ref x)
@@ -329,7 +329,7 @@ jsModule modul =
329329 jsImport (modul,_) = setup Nothing path ++ [ include ]
330330 where
331331 path = split modul
332− include = assign path $ dotSep ("Elm" : path ++ ["make"]) <| ref "elm"
332+ include = assign path $ dotSep ("Elm" : path ++ ["make"]) <| ref "_elm"
333333
334334 setup namespace path = map create paths
335335 where
@@ -338,15 +338,15 @@ jsModule modul =
338338 Nothing -> tail . init $ List.inits path
339339 Just nmspc -> drop 2 . init . List.inits $ nmspc : path
340340
341− addId js = InfixExpr () OpAdd (string (js++"_")) (obj "elm.id")
341+ addId js = InfixExpr () OpAdd (string (js++"_")) (obj "_elm.id")
342342
343343 importEvent (js,base,elm,_) =
344344 [ VarDeclStmt () [ varDecl elm $ obj "Signal.constant" <| evalState (expression base) 0 ]
345345 , ExprStmt () $
346346 obj "document.addEventListener" `call`
347347 [ addId js
348− , function ["e"]
349− [ ExprStmt () $ obj "elm.notify" `call` [dotSep [elm,"id"], obj "e.value"] ]
348+ , function ["_e"]
349+ [ ExprStmt () $ obj "_elm.notify" `call` [dotSep [elm,"id"], obj "_e.value"] ]
350350 ]
351351 ]
352352
@@ -354,13 +354,13 @@ jsModule modul =
354354 ExprStmt () $
355355 ref "A2" `call`
356356 [ obj "Signal.lift"
357− , function ["v"]
358− [ VarDeclStmt () [varDecl "e" $ obj "document.createEvent" <| string "Event"]
357+ , function ["_v"]
358+ [ VarDeclStmt () [varDecl "_e" $ obj "document.createEvent" <| string "Event"]
359359 , ExprStmt () $
360− obj "e.initEvent" `call` [ addId js, BoolLit () True, BoolLit () True ]
361− , ExprStmt () $ AssignExpr () OpAssign (LDot () (ref "e") "value") (ref "v")
362− , ExprStmt () $ obj "document.dispatchEvent" <| ref "e"
363− , ReturnStmt () (Just $ ref "v")
360+ obj "_e.initEvent" `call` [ addId js, BoolLit () True, BoolLit () True ]
361+ , ExprStmt () $ AssignExpr () OpAssign (LDot () (ref "_e") "value") (ref "_v")
362+ , ExprStmt () $ obj "document.dispatchEvent" <| ref "_e"
363+ , ReturnStmt () (Just $ ref "_v")
364364 ]
365365 , ref elm ]
366366
compiler/Generate/Markdown.hs+34−1
@@ -1,6 +1,39 @@
11module Generate.Markdown where
22
33import Text.Pandoc
4+import qualified Data.Set as Set
45
56toHtml :: String -> String
6−toHtml = writeHtmlString def . readMarkdown def
7+toHtml = writeHtmlString writeOptions . readMarkdown readOptions
8+
9+readOptions =
10+ def { readerExtensions = elmExtensions
11+ , readerApplyMacros = False
12+ }
13+
14+writeOptions =
15+ def { writerExtensions = elmExtensions
16+ , writerHighlight = True
17+ }
18+
19+elmExtensions :: Set.Set Extension
20+elmExtensions = Set.fromList
21+ [ Ext_raw_html
22+ , Ext_fenced_code_blocks
23+ , Ext_fenced_code_attributes
24+ , Ext_backtick_code_blocks
25+ , Ext_inline_code_attributes
26+ , Ext_markdown_in_html_blocks
27+ , Ext_escaped_line_breaks
28+ , Ext_fancy_lists
29+ , Ext_startnum
30+ , Ext_definition_lists
31+ , Ext_example_lists
32+ , Ext_all_symbols_escapable
33+ , Ext_intraword_underscores
34+ , Ext_blank_before_blockquote
35+ , Ext_blank_before_header
36+ , Ext_auto_identifiers
37+ , Ext_header_attributes
38+ , Ext_implicit_header_references
39+ ]
compiler/Initialize.hsdeleted−123
@@ -1,123 +0,0 @@
1−module Initialize (buildFromSource, getSortedDependencies) where
2−
3−import Data.Data
4−import Control.Monad.State
5−import qualified Data.Graph as Graph
6−import qualified Data.List as List
7−import qualified Data.Map as Map
8−import qualified Data.Set as Set
9−import System.Directory
10−import System.Exit
11−import System.FilePath as FP
12−import Text.PrettyPrint (Doc)
13−
14−import SourceSyntax.Everything
15−import qualified SourceSyntax.Type as Type
16−import qualified Parse.Parse as Parse
17−import qualified Metadata.Prelude as Prelude
18−import qualified Transform.Check as Check
19−import qualified Transform.SortDefinitions as SD
20−import qualified Type.Inference as TI
21−import qualified Type.Constrain.Declaration as TcDecl
22−import qualified Transform.Canonicalize as Canonical
23−
24−buildFromSource :: Bool -> Interfaces -> String -> Either [Doc] (MetadataModule () ())
25−buildFromSource noPrelude interfaces source =
26− do let add = if noPrelude then id else Prelude.add
27− infixes = Map.fromList . map (\(assoc,lvl,op) -> (op,(lvl,assoc)))
28− . concatMap iFixities $ Map.elems interfaces
29−
30− modul@(Module _ _ _ decls') <- add `fmap` Parse.program infixes source
31−
32− -- check for structural errors
33− Module names exs ims decls <-
34− case Check.mistakes decls' of
35− [] -> return modul
36− ms -> Left ms
37−
38− let exports'
39− | null exs =
40− let get = Set.toList . SD.boundVars in
41− concat [ get pattern | Definition (Def pattern _) <- decls ] ++
42− concat [ map fst ctors | Datatype _ _ ctors <- decls ] ++
43− [ name | TypeAlias name _ (Type.Record _ _) <- decls ]
44− | otherwise = exs
45−
46− metaModule <- Canonical.metadataModule interfaces $ MetadataModule {
47− names = names,
48− path = FP.joinPath names,
49− exports = exports',
50− imports = ims,
51− -- reorder AST into strongly connected components
52− program = SD.sortDefs . dummyLet $ TcDecl.toExpr decls,
53− types = Map.empty,
54− datatypes = [ (name,vars,ctors) | Datatype name vars ctors <- decls ],
55− fixities = [ (assoc,level,op) | Fixity assoc level op <- decls ],
56− aliases = [ (name,tvs,tipe) | TypeAlias name tvs tipe <- decls ],
57− foreignImports = [ (evt,v,name,typ) | ImportEvent evt v name typ <- decls ],
58− foreignExports = [ (evt,name,typ) | ExportEvent evt name typ <- decls ]
59− }
60−
61− types <- TI.infer interfaces metaModule
62−
63− return $ metaModule { types = types }
64−
65−
66−getSortedDependencies :: [FilePath] -> Interfaces -> FilePath -> IO [String]
67−getSortedDependencies srcDirs builtIns root =
68− sortDeps =<< readDeps srcDirs builtIns root
69−
70−type Deps = (FilePath, String, [String])
71−
72−sortDeps :: [Deps] -> IO [String]
73−sortDeps depends =
74− if null mistakes
75− then return (concat sccs)
76− else print msg >> mapM print mistakes >> exitFailure
77− where
78− sccs = map Graph.flattenSCC $ Graph.stronglyConnComp depends
79−
80− mistakes = filter (\scc -> length scc > 1) sccs
81− msg = "A cyclical module dependency or was detected in: "
82−
83−readDeps :: [FilePath] -> Interfaces -> FilePath -> IO [Deps]
84−readDeps srcDirs builtIns root = do
85− let ifaces = (Set.fromList . Map.keys) builtIns
86− evalStateT (go ifaces root) Set.empty
87− where
88− go :: Set.Set String -> FilePath -> StateT (Set.Set String) IO [Deps]
89− go builtIns root = do
90− (root', txt) <- liftIO $ getFile srcDirs root
91− case Parse.dependencies txt of
92− Left err -> liftIO (putStrLn msg >> print err >> exitFailure)
93− where msg = "Error resolving dependencies in " ++ root' ++ ":"
94−
95− Right (name,deps) ->
96− do seen <- get
97− let realDeps = Set.difference (Set.fromList deps) builtIns
98− newDeps = Set.difference (Set.filter (not . isNative) realDeps) seen
99− put (Set.insert name (Set.union newDeps seen))
100− rest <- mapM (go builtIns . toFilePath) (Set.toList newDeps)
101− return ((makeRelative "." root', name, Set.toList realDeps) : concat rest)
102−
103−getFile :: [FilePath] -> FilePath -> IO (FilePath,String)
104−getFile [] path = do
105− putStrLn $ unlines [ "Could not find file: " ++ path
106− , " If it is not in the root directory of your project, use"
107− , " --src-dir to declare additional locations for source files." ]
108− exitFailure
109−
110−getFile (dir:dirs) path = do
111− let path' = dir </> path
112− exists <- doesFileExist path'
113− case exists of
114− True -> (,) path' `fmap` readFile path'
115− False -> getFile dirs path
116−
117−isNative name = List.isPrefixOf "Native." name
118−
119−toFilePath :: String -> FilePath
120−toFilePath name = map swapDots name ++ ext
121− where swapDots '.' = '/'
122− swapDots c = c
123− ext = if isNative name then ".js" else ".elm"
compiler/InterfaceSerialization.hs+4−4
@@ -6,8 +6,7 @@ module InterfaceSerialization ( loadInterface
66import qualified Data.ByteString.Lazy as L
77import qualified Data.Binary as Binary
88
9−import Paths_Elm (version)
10−import Data.Version (showVersion)
9+import qualified Elm.Internal.Version as Version
1110import System.Directory (doesFileExist)
1211import System.IO (hPutStrLn, stderr)
1312import System.Exit (exitFailure)
@@ -42,11 +41,12 @@ interfaceDecode filePath bytes = do
4241validVersion :: FilePath -> (String, ModuleInterface) ->
4342 Either String (String, ModuleInterface)
4443validVersion filePath (name, interface) =
45− if iVersion interface == showVersion version then
44+ if iVersion interface == Version.elmVersion then
4645 Right (name, interface)
4746 else
4847 Left $ concat
4948 [ "Error reading build artifact: ", filePath, "\n"
50− , " It was generated by a different version of the compiler: ", iVersion interface, "\n"
49+ , " It was generated by a different version of the compiler: "
50+ , show (iVersion interface), "\n"
5151 , " Please remove the file and try again.\n"
5252 ]
compiler/Language/Elm.hsdeleted−45
@@ -1,45 +0,0 @@
1−{- | This module exports functions for compiling Elm to JS
2− and some utilities for making it easier to find some Elm-related files.
3−
4− Learning resources for Elm are available at
5− <http://elm-lang.org.elm/Learn.elm> and many interactive examples are
6− available at <http://elm-lang.org/Examples.elm>
7−-}
8−module Language.Elm (compile, moduleName, runtime, docs) where
9−
10−import qualified Data.List as List
11−import qualified Data.Map as Map
12−import Data.Version (showVersion)
13−import Generate.JavaScript (jsModule)
14−import Initialize (buildFromSource)
15−import Parse.Module (getModuleName)
16−import SourceSyntax.Module
17−import Text.Blaze.Html (Html)
18−import qualified Text.PrettyPrint as P
19−import qualified Metadata.Prelude as Prelude
20−import Paths_Elm
21−import System.IO.Unsafe
22−
23−-- |This function compiles Elm code to JavaScript. It will return either
24−-- an error message or the compiled JS code.
25−compile :: String -> Either String String
26−compile source =
27− case buildFromSource False interfaces source of
28− Left docs -> Left . unlines . List.intersperse "" $ map P.render docs
29− Right modul -> Right $ jsModule (modul :: MetadataModule () ())
30−
31−{-# NOINLINE interfaces #-}
32−interfaces :: Interfaces
33−interfaces = unsafePerformIO $ Prelude.interfaces
34−
35−-- |This function extracts the module name of a given source program.
36−moduleName :: String -> Maybe String
37−moduleName = getModuleName
38−
39−-- |The absolute path to Elm's runtime system.
40−runtime :: IO FilePath
41−runtime = getDataFileName "elm-runtime.js"
42−
43−-- |The absolute path to Elm's core library documentation.
44−docs :: IO FilePath
45−docs = getDataFileName "docs.json"
compiler/Paths_El.hs → compiler/Paths_Elm.hrenamed

The content is the same.

compiler/SourceSyntax/Module.hs+11−3
@@ -14,8 +14,7 @@ import SourceSyntax.Type
1414import System.FilePath (joinPath)
1515import Control.Monad (liftM)
1616
17−import Paths_Elm (version)
18−import Data.Version (showVersion)
17+import qualified Elm.Internal.Version as Version
1918
2019data Module tipe var =
2120 Module [String] Exports Imports [Declaration tipe var]
@@ -62,7 +61,7 @@ type Interfaces = Map.Map String ModuleInterface
6261type ADT = (String, [String], [(String,[Type])])
6362
6463data ModuleInterface = ModuleInterface {
65− iVersion :: String,
64+ iVersion :: Version.Version,
6665 iTypes :: Map.Map String Type,
6766 iImports :: [(String, ImportMethod)],
6867 iAdts :: [ADT],
@@ -70,6 +69,15 @@ data ModuleInterface = ModuleInterface {
7069 iFixities :: [(Assoc, Int, String)]
7170} deriving Show
7271
72+metaToInterface metaModule =
73+ ModuleInterface
74+ { iVersion = Version.elmVersion
75+ , iTypes = types metaModule
76+ , iImports = imports metaModule
77+ , iAdts = datatypes metaModule
78+ , iAliases = aliases metaModule
79+ , iFixities = fixities metaModule
80+ }
7381
7482instance Binary ModuleInterface where
7583 get = ModuleInterface <$> get <*> get <*> get <*> get <*> get <*> get
libraries/Basics.elm+7−3
@@ -221,11 +221,15 @@ min = Native.Basics.min
221221max : comparable -> comparable -> comparable
222222max = Native.Basics.max
223223
224−{-| The and operator. True if both inputs are True. -}
224+{-| The and operator. True if both inputs are True.
225+This operator short-circuits if the first argument is False.
226+-}
225227(&&) : Bool -> Bool -> Bool
226228(&&) = Native.Basics.and
227229
228−{-| The or operator. True if one or both inputs are True. -}
230+{-| The or operator. True if one or both inputs are True.
231+This operator short-circuits if the first argument is True.
232+-}
229233(||) : Bool -> Bool -> Bool
230234(||) = Native.Basics.or
231235
@@ -328,7 +332,7 @@ curry : ((a,b) -> c) -> a -> b -> c
328332curry f a b = f (a,b)
329333
330334{-| Change how arguments are passed to a function.
331−This combines two arguments into a sigle pair.
335+This combines two arguments into a single pair.
332336-}
333337uncurry : (a -> b -> c) -> (a,b) -> c
334338uncurry f (a,b) = f a b
libraries/Bitwise.elm+6−6
@@ -13,22 +13,22 @@ module Bitwise where
1313
1414import Native.Bitwise
1515
16−{-| Bitwise &ldquo;and&rdquo;
16+{-| Bitwise AND
1717-}
1818and : Int -> Int -> Int
1919and = Native.Bitwise.and
2020
21−{-| Bitwise &ldquo;or&rdquo;
21+{-| Bitwise OR
2222-}
2323or : Int -> Int -> Int
2424or = Native.Bitwise.or
2525
26−{-| Bitwise &ldquo;xor&rdquo;
26+{-| Bitwise XOR
2727-}
2828xor : Int -> Int -> Int
2929xor = Native.Bitwise.xor
3030
31−{-| Flip each bit individually, often called &ldquo;bitwise not&rdquo;
31+{-| Flip each bit individually, often called bitwise NOT
3232-}
3333complement : Int -> Int
3434complement = Native.Bitwise.complement
@@ -51,7 +51,7 @@ whatever is the topmost bit. This can be used to divide numbers by powers of two
5151
5252This is called an [arithmatic right
5353shift](http://en.wikipedia.org/wiki/Bitwise_operation#Arithmetic_shift),
54−often written (>>), and sometimes called a &ldquo;sign-propagating&rdquo;
54+often written (>>), and sometimes called a sign-propagating
5555right shift because it fills empty spots with copies of the highest bit.
5656-}
5757shiftRight : Int -> Int -> Int
@@ -66,7 +66,7 @@ zeros.
6666
6767This is called an [logical right
6868shift](http://en.wikipedia.org/wiki/Bitwise_operation#Logical_shift), often written (>>>),
69−and sometimes called a &ldquo;zero-fill&rdquo; right shift because it fills empty spots
69+and sometimes called a zero-fill right shift because it fills empty spots
7070with zeros.
7171-}
7272shiftRightLogical : Int -> Int -> Int
libraries/Graphics/Element.elm+1−1
@@ -108,7 +108,7 @@ color c e = let p = e.props in
108108
109109{-| Create an `Element` with a tag. This lets you link directly to it.
110110The element `(tag "all-about-badgers" thirdParagraph)` can be reached
111−with a link lik this: `/facts-about-animals.elm#all-about-badgers`
111+with a link like this: `/facts-about-animals.elm#all-about-badgers`
112112-}
113113tag : String -> Element -> Element
114114tag name e = let p = e.props in
libraries/Graphics/Input.elm+1−1
@@ -113,7 +113,7 @@ hoverables : a -> { events : Signal a,
113113 hoverable : (Bool -> a) -> Element -> Element }
114114hoverables = Native.Graphics.Input.hoverables
115115
116−{-| Detect when the mouse is hovering over a specifici `Element`. -}
116+{-| Detect when the mouse is hovering over a specific `Element`. -}
117117hoverable : Element -> (Element, Signal Bool)
118118hoverable elem =
119119 let pool = hoverables False
libraries/Lazy.elmdeleted−53
@@ -1,53 +0,0 @@
1−module Lazy ( force, lazy, map, apply, bind
2− ) where
3−
4−{-| Library for efficient Lazy evaluation.
5−
6−# Delay
7−@docs lazy
8−
9−# Evaluate
10−@docs force
11−
12−# Transform
13−@docs map, apply, bind
14−-}
15−
16−import Basics ((<|), (.))
17−import Native.Lazy
18−
19−data Lazy a = L { force : () -> a }
20−
21−{-| Delay a computation. This function memoizes results, so
22−it guarantees that the computation will be evaluated at most once.
23−-}
24−lazy : (() -> a) -> Lazy a
25−lazy t = L { force = (Native.Lazy.lazy t) }
26−
27−{-| Evaluate a lazy value. It saves the result so the second time
28−you call `force` it does not run the computation again. -}
29−force : Lazy a -> a
30−force (L r) = r.force ()
31−
32−{-| Lazily apply a function to a lazy value. The computation
33−will be delayed until you force the resulting value.
34−-}
35−map : (a -> b) -> Lazy a -> Lazy b
36−map f t = lazy <| \() ->
37− f . force <| t
38−
39−{-| Lazily apply a lazy function to a lazy value. This can
40−be used to lazily apply a function to many arguments:
41−
42−```haskell
43−f `map` a `apply` b `apply` c
44−```
45−-}
46−apply : Lazy (a -> b) -> Lazy a -> Lazy b
47−apply f x = lazy <| \() ->
48− (force f) (force x)
49−
50−{-| Lazily chain together lazy computations. -}
51−bind : Lazy a -> (a -> Lazy b) -> Lazy b
52−bind x k = lazy <| \() ->
53− force . k . force <| x
libraries/Lazy/Stream.elmdeleted−275
@@ -1,275 +0,0 @@
1−module Lazy.Stream ( head, tail
2− , cons, cons', iterate, repeat, cycle
3− , map, apply, zip, zipWith, scanl
4− , take, drop, splitAt
5− , sampleOn
6− , filter, takeWhile, dropWhile, splitWith
7− ) where
8−
9−{-| This library is for creating and manipulating infinite streams
10−
11−# Create
12−@docs cons, cons', repeat, cycle, iterate
13−
14−# Use
15−@docs head, tail, sampleOn, take, takeWhile, drop, dropWhile, splitAt, splitWith
16−
17−# Transform
18−@docs map, zip, zipWith, scanl, filter, apply
19−
20−-}
21−
22−import Basics ((.), (<|), (-), id, fst, snd)
23−import open Lazy
24−import Signal ((<~), foldp, Signal)
25−
26−data Stream a = S (Lazy (a, Stream a))
27−
28−unS : Stream a -> (a, Stream a)
29−unS (S t) = force t
30−
31−{-| Get the first element of a stream, called the `head`.
32−
33−```haskell
34−head ones == 1
35−```
36−-}
37−head : Stream a -> a
38−head = fst . unS
39−
40−{-| Drop the `head` of a stream, leaving you with the `tail`.
41−
42−```haskell
43−-- 1, 1, 1, 1, ...
44−stillAllOnes = tail
45−```
46−-}
47−tail : Stream a -> Stream a
48−tail = snd . unS
49−
50−{-| Create a stream:
51−
52−```haskell
53−-- 1, 1, 1, 1, ...
54−ones = cons 1 (\() -> ones)
55−```
56− -}
57−cons : a -> (() -> Stream a) -> Stream a
58−cons x txs = let mtxs = lazy txs in
59− S . lazy <| \() ->
60− (x, force mtxs)
61−
62−{-| Create a stream that is slightly more lazy. Notice that the
63−head of the stream is defined within the thunk, so its evaluation
64−is delayed. This is nice when each element of the stream is costly to compute.
65−
66−```haskell
67−-- 1, 1, 1, 1, ...
68−ones = cons' (\_ -> (1,ones))
69−```
70−-}
71−cons' : (() -> (a, Stream a)) -> Stream a
72−cons' = S . lazy
73−
74−{-| Iteratively apply a function to a value:
75−
76−```haskell
77−-- x, f x, f (f x), f (f (f x)), ...
78−iterate f x
79−
80−-- 2, 4, 8, 16, ...
81−powersOf2 = iterate (\n -> n^2) 2
82−```
83−-}
84−iterate : (a -> a) -> a -> Stream a
85−iterate f x =
86− cons' <| \_ -> (x, iterate f (f x))
87−
88−{-| Repeat a value infinitely:
89−
90−```haskell
91−-- 1, 1, 1, 1, ...
92−ones = repeat 1
93−```
94− -}
95−repeat : a -> Stream a
96−repeat x = let go = cons x <| \() -> go
97− in go
98−
99−{-| Infinitely cycle through a list, where the head and tail of
100−the list are given separately to ensure that no one tries to cycle
101−on an empty list:
102−
103−```haskell
104−-- "Alice", "Bob", "Alice", "Bob", ...
105−cycle "Alice" ["Bob"]
106−```
107−-}
108−cycle : a -> [a] -> Stream a
109−cycle x xs =
110− let cycle' ys = case ys of
111− [] -> go
112− (y :: ys) -> cons y (\_ -> cycle' ys)
113− go = cons' <| \_ -> (x, cycle' xs)
114− in go
115−
116−{-| Apply a function to every element of a Stream.
117−
118−```haskell
119−-- 2, 2, 2, 2, ...
120−twos = map (\n -> n + 1) ones
121−```
122−-}
123−map : (a -> b) -> Stream a -> Stream b
124−map f xs =
125− cons' <| \_ -> (f (head xs), map f (tail xs))
126−
127−{-| Pairwise apply a stream of functions to a stream of arguments.
128−When paired with `map`, this can be used to emulate `zipWith` over *n* streams.
129−
130−```haskell
131−zipWith3 : (a -> b -> c -> d) -> Stream a -> Stream b -> Stream c -> Stream d
132−zipWith3 f xs ys zs = f `S.map` xs `S.apply` ys `S.apply` zs
133−```
134−-}
135−apply : Stream (a -> b) -> Stream a -> Stream b
136−apply fs xs = zipWith (<|) fs xs
137−
138−{-| Combine two streams, putting them into tuples pairwise:
139−
140−```haskell
141−-- (1,2), (1,4), (1,8), (1,16), ...
142−pairs = zip ones powersOf2
143−```
144−-}
145−zip : Stream a -> Stream b -> Stream (a,b)
146−zip = zipWith (\x y -> (x,y))
147−
148−{-| Combine two streams, applying the given function pairwise:
149−
150−```haskell
151−-- 3, 5, 9, 17, ...
152−zipWith (+) ones powersOf2
153−```
154−-}
155−zipWith : (a -> b -> c) -> Stream a -> Stream b -> Stream c
156−zipWith f xs ys = cons' <| \() ->
157− (f (head xs) (head ys),
158− zipWith f (tail xs) (tail ys))
159−
160−{-| Scan over a stream from the left, building an infinite stream of reductions.
161−
162−```haskell
163−-- 0, 1, 2, 3, ...
164−runningTotal = scanl (+) 0 ones
165−```
166−-}
167−scanl : (a -> b -> b) -> b -> Stream a -> Stream b
168−scanl f init xs =
169− cons' <| \() -> (init, scanl f (f (head xs) init) (tail xs))
170−
171−{-| Take the first *n* elements of a stream
172−
173−```haskell
174−take 5 powersOf2 == [2,4,8,16,32]
175−```
176−-}
177−take : Int -> Stream a -> [a]
178−take n xs = fst <| splitAt n xs
179−
180−{-| Drop the first *n* elements of a stream
181−
182−```haskell
183−-- 64, 128, 256, 512, ...
184−drop 5 powersOf2
185−```
186−-}
187−drop : Int -> Stream a -> Stream a
188−drop n xs = snd <| splitAt n xs
189−
190−{-| Combination of `take` and `drop`
191−
192−```haskell
193−splitAt n xs == (take n xs, drop n xs)
194−```
195−-}
196−splitAt : Int -> Stream a -> ([a], Stream a)
197−splitAt n xs = case n of
198− 0 -> ([], xs)
199− n -> let (heads, end) = splitAt (n - 1) (tail xs)
200− in (head xs :: heads, end)
201−
202−{-| Turn a stream into a signal of the elements of the stream,
203−advancing through the stream whenever an event in the given signal is
204−fired.
205−-}
206−sampleOn : Signal b -> Stream a -> Signal a
207−sampleOn sig str = let tails = foldp (\_ -> tail) str sig in
208− head <~ tails
209−
210−{-| Filter the elements of a Stream according to a predicate.
211−
212−```haskell
213−-- 1, 3, 5, 7, ...
214−filter isOdd naturals
215−
216−-- Bad! Infinite loop!
217−filter isOdd twos
218−```
219−
220−This can infinite loop if no more elements in the stream satisfy the predicate!
221−-}
222−filter : (a -> Bool) -> Stream a -> Stream a
223−filter pred xs = cons' <| (\() ->
224− let (hd, tl) = unS xs in
225− case pred hd of
226− True -> (hd, filter pred tl)
227− False -> unS <| filter pred tl)
228−
229−{-| Take values from the stream for as long as the predicate holds.
230−This can infinite loop if all elements of the stream satisfy the predicate!
231−
232−```haskell
233−takeWhile (\n -> n < 10) powersOf2 == [2,4,8]
234−
235−-- Bad! Infinite loop!
236−takeWhile isEven powersOf2
237−```
238−
239−This can infinite loop if all elements of the stream satisfy the predicate!
240−-}
241−takeWhile : (a -> Bool) -> Stream a -> [a]
242−takeWhile pred xs = fst <| splitWith pred xs
243−
244−{-| Drop values from the stream as long as the predicate holds.
245−
246−```haskell
247−-- 16, 32, 64, 128, ...
248−dropWhile (\n -> n < 10) powersOf2
249−
250−-- Bad! Infinite loop!
251−dropWhile isEven powersOf2
252−```
253−
254−This can infinite loop if all elements of the stream satisfy the predicate!
255−-}
256−dropWhile : (a -> Bool) -> Stream a -> Stream a
257−dropWhile pred xs = snd <| splitWith pred xs
258−
259−{-| Combination of `takeWhile` and `dropWhile`. Split a stream when
260−the predicate no longer holds.
261−
262−```haskell
263−splitWith pred xs == (takeWhile pred xs, dropWhile pred xs)
264−
265−splitWith (\n -> n < 10) powersOf2 == ([2,4,8], ...)
266−```
267−
268−This can infinite loop if all elements satisfy the predicate!
269−-}
270−splitWith : (a -> Bool) -> Stream a -> ([a], Stream a)
271−splitWith pred xs = let (hd, tl) = unS xs in
272− case pred hd of
273− True -> let (taken, dropped) = splitWith pred tl
274− in (hd :: taken, dropped)
275− False -> ([], xs)
libraries/Native/Lazy.jsdeleted−26
@@ -1,26 +0,0 @@
1−Elm.Native.Lazy = {};
2−Elm.Native.Lazy.make = function(elm) {
3− elm.Native = elm.Native || {};
4− elm.Native.Lazy = elm.Native.Lazy || {};
5−
6− if (elm.Native.Lazy.values) return elm.Native.Lazy.values;
7−
8− var Utils = Elm.Native.Utils.make(elm);
9−
10− function lazy(f) {
11− var value = {};
12− var isEvaled = false;
13− var memoed = function(x) {
14− if(!isEvaled) {
15− value = f(Utils.Tuple0);
16− isEvaled = true;
17− }
18− return value;
19− }
20− return memoed;
21− }
22−
23− return elm.Native.Lazy.values = {
24− lazy : lazy
25− };
26−};
libraries/Signal.elm+3−3
@@ -3,7 +3,7 @@ module Signal where
33`lift8` and infix lift operators `<~` and `~`, combinations, filters, and
44past-dependence.
55
6−Signals are time-varying values. Lifted functions are reevaluated whenver any of
6+Signals are time-varying values. Lifted functions are reevaluated whenever any of
77their input signals has an event. Signal events may be of the same value as the
88previous value of the signal. Such signals are useful for timing and
99past-dependence.
@@ -95,11 +95,11 @@ combine = foldr (Native.Signal.lift2 (::)) (Native.Signal.constant [])
9595 -- fold over non-homogeneous inputs.
9696 -- mergeEither : Signal a -> Signal b -> Signal (Either a b)
9797
98−{-| Count the number of events that have occured. -}
98+{-| Count the number of events that have occurred. -}
9999count : Signal a -> Signal Int
100100count = Native.Signal.count
101101
102−{-| Count the number of events that have occured that satisfy a given predicate.
102+{-| Count the number of events that have occurred that satisfy a given predicate.
103103-}
104104countIf : (a -> Bool) -> Signal a -> Signal Int
105105countIf = Native.Signal.countIf
libraries/Transform2D.elm+7−5
@@ -1,14 +1,16 @@
11module Transform2D where
2−{-| A library for performing [2D matrix transformations](http://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations).
2+{-| A library for performing [2D matrix transformations][affine].
33It is used primarily with the `groupTransform` function from `Graphics.Collage` and
44allows you to do things like rotation, scaling, translation, shearing, and reflection.
55
66Note that all the matrices in this library are 3x3 matrices of homogeneous
7−coordinates, used for affine transformations. Since the third row as always 0 0
8−1, we omit this below.
7+coordinates, used for [affine transformations][affine]. Since the bottom row as
8+always `0 0 1` in these matrices, it is omitted in the diagrams below.
99
10−# Basic Transforms
11−@docs identity, matrix, rotation
10+ [affine]: http://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations
11+
12+# Transforms
13+@docs identity, matrix, rotation, translation, scale, scaleX, scaleY
1214
1315# Multiplication
1416@docs multiply
libraries/elm_dependencies.jsonnew file+40
@@ -0,0 +1,40 @@
1+{ "version": "0.10.0.2"
2+, "summary": "Elm's standard libraries"
3+, "description": "The full set of standard libraries for Elm. This library is pegged to the version number of the compiler, so if you are using Elm 0.11, you should be using version 0.11 of the standard libraries."
4+, "license": "BSD3"
5+, "repository": "http://github.com/evancz/Elm.git"
6+, "elm-version": "0.10.0.2"
7+, "dependencies": {}
8+, "exposed-modules":
9+ [ "Automaton"
10+ , "Basics"
11+ , "Bitwise"
12+ , "Char"
13+ , "Color"
14+ , "Date"
15+ , "Dict"
16+ , "Either"
17+ , "Graphics.Element"
18+ , "Graphics.Collage"
19+ , "Graphics.Input"
20+ , "Http"
21+ , "JavaScript"
22+ , "JavaScript.Experimental"
23+ , "Json"
24+ , "Keyboard"
25+ , "List"
26+ , "Maybe"
27+ , "Mouse"
28+ , "Random"
29+ , "Regex"
30+ , "Set"
31+ , "Signal"
32+ , "String"
33+ , "Text"
34+ , "Time"
35+ , "Touch"
36+ , "Transform2D"
37+ , "WebSocket"
38+ , "Window"
39+ ]
40+}