on master help sign in
Merge branch 'master' into webgl

Conflicts: server/elm-server.cabal

commitb080f8d34b7e61862cb20fb67b211ff1bd1c9cbf authorEvan Czaplicki <info@elm-lang.org> dateThu 1 May 2014, 15:48 (13 years ago) parent8c6e080adaa65f
65 files changed+916−567
.gitignore+4 .gitmodules+9 CONTRIBUTING.md+20−19 Elm-Test+1 Elm.cabal+27−17 IO+1 README.md+11−46 automaton+1 changelog.md+8−6 compiler/Elm/Internal/Dependencies.hs+41−4 compiler/Elm/Internal/Name.hs+2−2 compiler/Generate/JavaScript.hs+2−1 compiler/Generate/JavaScript/Ports.hs+16−9 compiler/Type/ExtraChecks.hs+2−3 compiler/Type/Unify.hs+5−1 libraries/Array.elm+90−82 libraries/Dict.elm+76−18 libraries/Graphics/Input.elm+1−1 libraries/List.elm+25−15 libraries/Native/Array.js+202−56 libraries/Native/Error.js+2−4 libraries/Native/Graphics/Input.js−29 libraries/Native/String.js+2−2 libraries/Native/Text.js+1 libraries/Native/Utils.js+39−22 libraries/Set.elm+11−1 libraries/Signal.elm+8−13 libraries/String.elm+9−9 libraries/elm_dependencies.json+6−5 runtime/Render/Element.js+8−2 server/LICENSE−30 server/Server.hs−127 server/Setup.hs−2 server/elm-server.cabal−41 tests/elm/Test.elm+37 tests/elm/Test/Array.elm+62 tests/elm/Test/Dict.elm+26 tests/elm/Test/List.elm+38 tests/elm/Test/Set.elm+27 tests/elm/Test/String.elm+37 tests/elm/Test/Trampoline.elm+29 tests/Main.hs → tests/hs/CompilerTest.hs tests/hs/LibTest.hs+30 tests/Tests/Compiler.hs → tests/hs/Tests/Compiler.hs tests/Tests/Property.hs → tests/hs/Tests/Property.hs tests/Tests/Property/Arbitrary.hs → tests/hs/Tests/Property/Arbitrary.hs tests/test-files/bad/BBTArgs → tests/hs/test-files/bad/BBTArgs tests/test-files/bad/InfiniteType.elm → tests/hs/test-files/bad/InfiniteType.elm tests/test-files/bad/NonElementMain.elm → tests/hs/test-files/bad/NonElementMain.elm tests/test-files/bad/Strings/ExtraClose.elm → tests/hs/test-files/bad/Strings/ExtraClose.elm tests/test-files/good/AliasSubstitution.elm → tests/hs/test-files/good/AliasSubstitution.elm tests/test-files/good/NoExpressions.elm → tests/hs/test-files/good/NoExpressions.elm tests/test-files/good/Otherwise.elm → tests/hs/test-files/good/Otherwise.elm tests/test-files/good/Ports.elm → tests/hs/test-files/good/Ports.elm tests/test-files/good/QuotesAndComments.elm → tests/hs/test-files/good/QuotesAndComments.elm tests/test-files/good/Soundness/Apply.elm → tests/hs/test-files/good/Soundness/Apply.elm tests/test-files/good/Soundness/ApplyAnnotated.elm → tests/hs/test-files/good/Soundness/ApplyAnnotated.elm tests/test-files/good/Soundness/Id.elm → tests/hs/test-files/good/Soundness/Id.elm tests/test-files/good/Soundness/IdAnnotated.elm → tests/hs/test-files/good/Soundness/IdAnnotated.elm tests/test-files/good/Soundness/TrickyId.elm → tests/hs/test-files/good/Soundness/TrickyId.elm tests/test-files/good/Soundness/TrickyIdAnnotated.elm → tests/hs/test-files/good/Soundness/TrickyIdAnnotated.elm tests/test-files/good/Strings/Multiline.elm → tests/hs/test-files/good/Strings/Multiline.elm tests/test-files/good/Strings/MultilineNormal.elm → tests/hs/test-files/good/Strings/MultilineNormal.elm tests/test-files/good/Unify/LockedVars.elm → tests/hs/test-files/good/Unify/LockedVars.elm tests/test-files/good/Unify/NonHomogeneousRecords.elm → tests/hs/test-files/good/Unify/NonHomogeneousRecords.elm
.gitignore+4
@@ -13,3 +13,7 @@ data
1313build
1414cache
1515*~
16+tests/elm/build/
17+tests/elm/cache/
18+tests/elm/exe.js
19+node_modules/
.gitmodulesnew file+9
@@ -0,0 +1,9 @@
1+[submodule "IO"]
2+ path = IO
3+ url = https://github.com/maxsnew/IO.git
4+[submodule "automaton"]
5+ path = automaton
6+ url = https://github.com/evancz/automaton.git
7+[submodule "Elm-Test"]
8+ path = Elm-Test
9+ url = https://github.com/deadfoxygrandpa/Elm-Test.git
CONTRIBUTING.md+20−19
@@ -5,31 +5,32 @@ describes the basic standards for opening pull requests:
55
66## Branches
77
8− * The master branch of Elm is for tagging previous releases
9− and non-breaking changes, like bug fixes. This branch is
10− handy for folks who want to build the most recent public
11− release from source.
8+ * [The master branch](https://github.com/elm-lang/Elm/tree/master) is the
9+ home of the next release of the compiler so new features and improvements
10+ get merged there. Most pull requests should target this branch!
1211
13− * The dev branch is where the most active development occurs.
14− It is the home of the next release of the compiler so new
15− features and improvements get merged there.
12+ * [The stable branch](https://github.com/elm-lang/Elm/tree/stable) is for
13+ tagging previous releases and critical bug fixes. This branch is handy for
14+ folks who want to build the most recent public release from source.
15+
16+If you are working on a fairly large feature, we will probably want to merge it
17+in as its own branch and do some testing before bringing it into the master
18+branch. This way we can keep releases of the master branch independent of new
19+features.
1620
1721## Opening a pull request
1822
19−**Please open PRs against the [dev branch of
20−Elm](http://github.com/evancz/elm/tree/dev) whenever possible.** Changes that
21−are compatible with the API of master will be merged to master as soon as
22−possible. Changes that affect Elm's API will be merged to master with a future
23−release of the compiler.
23+**Please open PRs against the [master branch of
24+Elm](http://github.com/elm-lang/elm/tree/master) whenever possible.**
2425
25−Note that changes in the master branch of [Elm](https://github.com/evancz/Elm/)
26+Note that changes in the master branch of [Elm](https://github.com/elm-lang/Elm/)
2627are able to be compiled against the master branch of the [elm-lang.org
27−repo](https://github.com/evancz/elm-lang.org), and the dev branch of
28−[Elm](https://github.com/evancz/Elm/) is able to be built with the dev branch of
29−the [elm-lang.org repo](https://github.com/evancz/elm-lang.org). Please make
30−sure that your changes maintain this compatibility.
28+repo](https://github.com/elm-lang/elm-lang.org), and the stable branch of
29+[Elm](https://github.com/elm-lang/Elm/) is able to be built with the stable
30+branch of the [elm-lang.org repo](https://github.com/elm-lang/elm-lang.org).
31+Please make sure that your changes maintain this compatibility.
3132
3233## Licensing
3334
34−You should sign the [contributor agreement](ContributorAgreement.pdf)
35−and send it to <info@elm-lang.org> before opening your pull request.
35+You need to sign the [contributor agreement](ContributorAgreement.pdf)
36+and send it to <info@elm-lang.org> before opening your pull request.
Elm-Testnew file+1

Submodule changed.

Elm.cabal+27−17
@@ -1,5 +1,5 @@
11Name: Elm
2−Version: 0.12
2+Version: 0.12.1
33Synopsis: The Elm language module.
44Description: Elm aims to make client-side web-development more pleasant.
55 It is a statically/strongly typed, functional reactive
@@ -27,7 +27,7 @@ Cabal-version: >=1.9
2727
2828source-repository head
2929 type: git
30− location: git://github.com/evancz/Elm.git
30+ location: git://github.com/elm-lang/Elm.git
3131
3232Library
3333 exposed-modules: Elm.Internal.Dependencies,
@@ -95,8 +95,9 @@ Library
9595 Paths_Elm
9696
9797 Build-depends: aeson,
98+ aeson-pretty,
9899 base >=4.2 && <5,
99− binary >= 0.6.4.0,
100+ binary >= 0.7.0.0,
100101 blaze-html >= 0.5 && < 0.8,
101102 blaze-markup,
102103 bytestring,
@@ -178,8 +179,9 @@ Executable elm
178179 Paths_Elm
179180
180181 Build-depends: aeson,
182+ aeson-pretty,
181183 base >=4.2 && <5,
182− binary >= 0.6.4.0,
184+ binary >= 0.7.0.0,
183185 blaze-html >= 0.5 && < 0.8,
184186 blaze-markup,
185187 bytestring,
@@ -224,7 +226,7 @@ Executable elm-doc
224226 Build-depends: aeson,
225227 aeson-pretty,
226228 base >=4.2 && <5,
227− binary >= 0.6.4.0,
229+ binary >= 0.7.0.0,
228230 bytestring,
229231 cmdargs,
230232 containers >= 0.3,
@@ -239,35 +241,33 @@ Executable elm-doc
239241 text,
240242 union-find
241243
242−Test-Suite test-elm
244+Test-Suite compiler-tests
243245 Type: exitcode-stdio-1.0
244− Hs-Source-Dirs: tests, compiler
245− Main-is: Main.hs
246+ Hs-Source-Dirs: tests/hs, compiler
247+ Main-is: CompilerTest.hs
246248 other-modules: Tests.Compiler
247249 Tests.Property
248250 Tests.Property.Arbitrary
249251 SourceSyntax.Helpers
250252 SourceSyntax.Literal
251253 SourceSyntax.PrettyPrint
252− build-depends: base,
253− directory,
254− Elm,
255− test-framework,
254+ build-depends: test-framework,
256255 test-framework-hunit,
257256 test-framework-quickcheck2 >= 0.3,
258257 HUnit,
259− pretty,
260258 QuickCheck >= 2 && < 3,
261− filemanip,
262259 aeson,
260+ aeson-pretty,
263261 base >=4.2 && <5,
264− binary >= 0.6.4.0,
265− blaze-html == 0.5.* || == 0.6.*,
266− blaze-markup == 0.5.1.*,
262+ binary >= 0.7.0.0,
263+ blaze-html,
264+ blaze-markup,
267265 bytestring,
268266 cmdargs,
269267 containers >= 0.3,
270268 directory,
269+ Elm,
270+ filemanip,
271271 filepath,
272272 indents,
273273 language-ecmascript >=0.15 && < 1.0,
@@ -280,3 +280,13 @@ Test-Suite test-elm
280280 transformers >= 0.2,
281281 union-find,
282282 unordered-containers
283+
284+Test-Suite lib-tests
285+ Type: exitcode-stdio-1.0
286+ Hs-Source-Dirs: tests/hs
287+ Main-is: LibTest.hs
288+ build-depends: base,
289+ directory,
290+ Elm,
291+ filepath,
292+ process
IOnew file+1

Submodule changed.

README.md+11−46
@@ -4,55 +4,20 @@ Learn about the Elm programming language at [elm-lang.org](http://elm-lang.org/)
44
55## Install
66
7−**Arch Linux** &mdash; follow [these directions](https://github.com/elm-lang/Elm/wiki/Installing-Elm#arch-linux) and then
8−jump to the [My First Project](#my-first-project) section.
9−<br/>
10−**OS X 10.9 or XCode 5** &mdash; follow
11−[these directions](http://justtesting.org/post/64947952690/the-glasgow-haskell-compiler-ghc-on-os-x-10-9)
12−before continuing with the platform agnostic directions below.
7+Follow [these instructions][installer] if you just want to use Elm. To build
8+the compiler from source, run the following commands:
139
14−**Platform Agnostic** &mdash;
15−download the [Haskell Platform 2012.2.0.0 or later](http://hackage.haskell.org/platform/).
16−Once the Haskell Platform is installed:
10+ [installer]: https://github.com/elm-lang/elm-platform/blob/master/README.md#elm-platform
1711
18− cabal update
19− cabal install elm
20− cabal install elm-server
12+```bash
13+git clone https://github.com/elm-lang/Elm.git
14+cd Elm
15+cabal configure
16+cabal build
17+```
2118
22−## Use
23−
24−To use `elm` and `elm-server` you may need to add a new directory to your PATH.
25−
26−Cabal should tell you where your executables are located upon
27−successful installation. It'll be something like `/home/evan/.cabal/bin`
28−which you should append to your PATH variable.
29−See this tutorial if you are new to changing your PATH in
30−[Unix/Linux](http://www.cyberciti.biz/faq/unix-linux-adding-path/).
31−
32−## My First Project
33−
34−Now we will create a simple Elm project.
35−The following commands will set-up a very basic project and start the Elm server.
36−
37− mkdir helloElm
38− cd helloElm
39− printf "import Mouse\n\nmain = lift asText Mouse.position" > Main.elm
40− elm-server
41−
42−The first two commands create a new directory and navigate into it. The `printf`
43−commands place a simple program into `Main.elm`. Do this manually if you do not
44−have `printf`. The final command starts the Elm server at [localhost:8000](http://localhost:8000/),
45−allowing you to navigate to `Main.elm` and see your first program in action.
46−
47−#### Final Notes
48−
49−The `elm` package provides
50−[some utility functions](http://hackage.haskell.org/package/Elm) for
51−working with Elm in Haskell. This can be useful for creating tooling
52−for Elm, and has been useful for projects like
53−[the website](http://elm-lang.org/) and
54−[`elm-get`](https://github.com/elm-lang/elm-get). Email the list if you
55−want to rely on these functions!
19+This will build the compiler in `/dist/build/elm/elm` but it will not be on
20+your PATH.
5621
5722If you are stuck, email
5823[the list](https://groups.google.com/forum/?fromgroups#!forum/elm-discuss)
automatonnew file+1

Submodule changed.

changelog.md+8−6
@@ -1,5 +1,12 @@
11
2−## 0.13
2+## 0.12.1
3+
4+## Improvements:
5+
6+ * New Array library (thanks entirely to @Xashili)
7+ * Json.Value can flow through ports
8+ * Improve speed and stack usage in List library (thanks to @maxsnew)
9+ * Add Dict.filter and Dict.partition (thanks to @hdgarrood)
310
411#### Breaking Changes:
512
@@ -7,11 +14,6 @@
714 * Revamp JavaScript.Experimental library to have slightly better names
815 * Remove JavaScript library which was made redundant by ports
916
10−## Improvements:
11−
12− * Json.Value can flow through ports, so you can bring in values even
13− if they don't conform to a consistent type.
14−
1517## 0.12
1618
1719#### Breaking Changes:
compiler/Elm/Internal/Dependencies.hs+41−4
@@ -5,9 +5,12 @@ import Control.Applicative
55import Control.Monad.Error
66import qualified Control.Exception as E
77import Data.Aeson
8+import Data.Aeson.Encode.Pretty
89import qualified Data.List as List
910import qualified Data.ByteString.Lazy as BS
1011import qualified Data.HashMap.Strict as Map
12+import qualified Data.Text as T
13+
1114import qualified Elm.Internal.Name as N
1215import qualified Elm.Internal.Version as V
1316import qualified Elm.Internal.Paths as Path
@@ -22,14 +25,32 @@ data Deps = Deps
2225 , exposed :: [String]
2326 , elmVersion :: V.Version
2427 , dependencies :: [(N.Name,V.Version)]
25− } deriving Show
28+ } deriving (Show, Eq, Ord)
2629
2730data MiniDeps = Mini [(N.Name,V.Version)]
31+ deriving (Show, Eq, Ord)
32+
33+instance ToJSON MiniDeps where
34+ toJSON (Mini m) = toJSON m
2835
2936instance FromJSON MiniDeps where
3037 parseJSON (Object obj) = Mini <$> getDependencies obj
3138 parseJSON _ = mzero
3239
40+instance ToJSON Deps where
41+ toJSON d = object [
42+ "version" .= version d,
43+ "summary" .= summary d,
44+ "description" .= description d,
45+ "license" .= license d,
46+ "repository" .= repo d,
47+ "exposed-modules" .= exposed d,
48+ "elm-version" .= elmVersion d,
49+ "dependencies" .= (jsonDeps . dependencies $ d)
50+ ]
51+ where jsonDeps = Map.fromList . map (mapFst (T.pack . show))
52+ mapFst f (a,b) = (f a, b)
53+
3354instance FromJSON Deps where
3455 parseJSON (Object obj) =
3556 do version <- get obj "version" "your projects version number"
@@ -110,8 +131,24 @@ withDeps handle path =
110131 case result of
111132 Right bytes -> return bytes
112133 Left _ -> throwError $
113− "could not find file " ++ path ++
114− "\n You may need to create a dependency file for your project."
134+ "could not find " ++ path ++ " file. You may need to create one.\n" ++
135+ " For an example of how to fill in the dependencies file, check out\n" ++
136+ " <https://github.com/evancz/automaton/blob/master/elm_dependencies.json>"
115137
116138depsAt :: FilePath -> ErrorT String IO Deps
117−depsAt = withDeps id
139+depsAt = withDeps id
140+
141+-- | Encode dependencies in a canonical JSON format
142+prettyJSON :: Deps -> BS.ByteString
143+prettyJSON = encodePretty' config
144+ where config = defConfig { confCompare = order }
145+ order = keyOrder [ "name",
146+ "version",
147+ "summary",
148+ "description",
149+ "license",
150+ "repo",
151+ "exposed-modules",
152+ "elm-version",
153+ "dependencies"
154+ ]
compiler/Elm/Internal/Name.hs+2−2
@@ -10,7 +10,7 @@ import qualified Data.Maybe as Maybe
1010import Data.Typeable
1111
1212data Name = Name { user :: String, project :: String }
13− deriving (Typeable,Eq)
13+ deriving (Typeable,Eq, Ord)
1414
1515instance Binary Name where
1616 get = Name <$> get <*> get
@@ -48,4 +48,4 @@ errorMsg string =
4848 unlines
4949 [ "Dependency file has an invalid name: " ++ string
5050 , "Must have format user/project and match a public github project."
51− ]
51+ ]
compiler/Generate/JavaScript.hs+2−1
@@ -34,10 +34,11 @@ include alias moduleName =
3434
3535internalImports :: String -> Statement ()
3636internalImports name =
37− VarDeclStmt ()
37+ VarDeclStmt ()
3838 [ varDecl "_N" (obj "Elm.Native")
3939 , include "_U" "_N.Utils"
4040 , include "_L" "_N.List"
41+ , include "_A" "_N.Array"
4142 , include "_E" "_N.Error"
4243 , varDecl "$moduleName" (string name)
4344 ]
compiler/Generate/JavaScript/Ports.hs+16−9
@@ -20,7 +20,7 @@ check x jsType continue =
2020 JSNumber -> [typeof "number"]
2121 JSBoolean -> [typeof "boolean"]
2222 JSString -> [typeof "string", instanceof "String"]
23− JSArray -> [instanceof "Array"]
23+ JSArray -> [(obj "_U.isJSArray" <|)]
2424 JSObject fields -> [jsFold OpLAnd (typeof "object" : map member fields)]
2525
2626incoming :: Type -> Expression ()
@@ -38,7 +38,7 @@ inc tipe x =
3838
3939 Data "Json.Value" [] ->
4040 obj "Native.Json.fromJS" <| x
41−
41+
4242 Data ctor []
4343 | ctor == "Int" -> from JSNumber
4444 | ctor == "Float" -> from JSNumber
@@ -55,8 +55,12 @@ inc tipe x =
5555
5656 | ctor == "_List" ->
5757 check x JSArray (obj "_L.fromArray" <| array)
58− where
59− array = DotRef () x (var "map") <| incoming t
58+
59+ | ctor == "Array.Array" ->
60+ check x JSArray (obj "_A.fromJSArray" <| array)
61+
62+ where
63+ array = DotRef () x (var "map") <| incoming t
6064
6165 Data ctor ts
6266 | Help.isTuple ctor -> check x JSArray tuple
@@ -67,10 +71,10 @@ inc tipe x =
6771 , inc t (BracketRef () x (IntLit () n)))
6872
6973 Data _ _ ->
70− error "bad ADT got to port generation code"
74+ error "bad ADT got to incoming port generation code"
7175
7276 Record _ (Just _) ->
73− error "bad record got to port generation code"
77+ error "bad record got to incoming port generation code"
7478
7579 Record fields Nothing ->
7680 check x (JSObject (map fst fields)) object
@@ -117,16 +121,19 @@ out tipe x =
117121 | ctor == "_List" ->
118122 DotRef () (obj "_L.toArray" <| x) (var "map") <| outgoing t
119123
124+ | ctor == "Array.Array" ->
125+ DotRef () (obj "_A.toJSArray" <| x) (var "map") <| outgoing t
126+
120127 Data ctor ts
121128 | Help.isTuple ctor ->
122129 let convert n t = out t $ DotRef () x $ var ('_':show n)
123130 in ArrayLit () $ zipWith convert [0..] ts
124−
131+
125132 Data _ _ ->
126− error "bad ADT got to port generation code"
133+ error "bad ADT got to outgoing port generation code"
127134
128135 Record _ (Just _) ->
129− error "bad record got to port generation code"
136+ error "bad record got to outgoing port generation code"
130137
131138 Record fields Nothing ->
132139 ObjectLit () keys
compiler/Type/ExtraChecks.hs+2−3
@@ -60,8 +60,7 @@ portTypes rules expr =
6060 | otherwise -> err' True "an unsupported type"
6161 where
6262 primitives =
63− ["Int","Float","String","Bool","Maybe.Maybe","_List","Json.Value"]
64−
63+ ["Int","Float","String","Bool","Maybe.Maybe","_List","Array.Array","Json.Value"]
6564 validConstructor =
6665 ctor `elem` primitives || Help.isTuple ctor
6766
@@ -102,7 +101,7 @@ portTypes rules expr =
102101 , txt [ "It contains ", kind, ":\n" ]
103102 , (P.nest 4 . SPP.pretty $ Alias.realias rules tipe) <> P.text "\n"
104103 , txt [ "Acceptable values for ", dir "incoming" "outgoing", " ports include:" ]
105− , txt [ " Ints, Floats, Bools, Strings, Maybes, Lists, Tuples," ]
104+ , txt [ " Ints, Floats, Bools, Strings, Maybes, Lists, Arrays, Tuples," ]
106105 , txt [ " Json.Values, ", dir "" "first-order functions, ", "and concrete records." ]
107106 ] ++ if couldBeAlias then aliasWarning else []
108107
compiler/Type/Unify.hs+5−1
@@ -86,6 +86,10 @@ actuallyUnify region variable1 variable2 = do
8686 TS.addError region (Just $ Maybe.fromMaybe msg maybe) variable1 variable2
8787 where msg = "A comparable must be an Int, Float, Char, String, list, or tuple."
8888
89+ appendableError maybe =
90+ TS.addError region (Just $ Maybe.fromMaybe msg maybe) variable1 variable2
91+ where msg = "An appendable must be of type String, List, or Text."
92+
8993 unifyComparable var name
9094 | name `elem` ["Int","Float","Char","String","comparable"] = flexAndUnify var
9195 | otherwise = comparableError Nothing
@@ -108,7 +112,7 @@ actuallyUnify region variable1 variable2 = do
108112 do struct <- liftIO $ collectApps varFlex
109113 case struct of
110114 List _ -> flexAndUnify varSuper
111− _ -> comparableError Nothing
115+ _ -> appendableError Nothing
112116
113117 rigidError variable = TS.addError region (Just hint) variable1 variable2
114118 where
libraries/Array.elm+90−82
@@ -1,23 +1,23 @@
11module Array where
22
3−{-| A library for immutable arrays. The elements in an array must have the same
4−type. The arrays are implemented in Relaxed Radix Balanced-Trees for fast
5−reads, updates, and concatenation.
3+{-| A library for fast immutable arrays. The elements in an array must have the
4+same type. The arrays are implemented in Relaxed Radix Balanced-Trees for fast
5+reads, updates, and appends.
66
7−If you use more then one map or zip function on an array, consider turning it
8−into a list before operating on it, and then turning it back into an array.
7+# Creating Arrays
8+@docs empty, repeat, initialize, fromList
99
1010# Basics
11−@docs empty, length, get, getMaybe, getSafe
11+@docs length, push, append
1212
13−# Putting Arrays Together
14−@docs fill, fromList, concat, set, updates, push
13+# Get and Set
14+@docs get, getOrElse, getOrFail, set
1515
1616# Taking Arrays Apart
17−@docs toList, toIndexedList, indices, slice
17+@docs slice, toList, toIndexedList
1818
19−# Mapping, folding, zipping
20−@docs map, indexedMap, foldl, foldr, zip, zipWith
19+# Mapping and Folding
20+@docs map, indexedMap, foldl, foldr
2121-}
2222
2323import Native.Array
@@ -27,17 +27,29 @@ import List
2727
2828data Array a = Array
2929
30−{-| Fills an array with a given length and a default element.
30+{-| Initialize an array. `initialize n f` creates an array of length `n` with
31+the element at index `i` initialized to the result of `(f i)`.
3132
32− fill 3 5 == fromList [5,5,5]
33+ initialize 4 id == fromList [0,1,2,3]
34+ initialize 4 (\n -> n*n) == fromList [0,1,4,9]
35+ initialize 4 (always 0) == fromList [0,0,0,0]
3336-}
34−fill : Int -> a -> Array a
35−fill len e = fromList <| List.map (always e) [1..len]
37+initialize : Int -> (Int -> a) -> Array a
38+initialize = Native.Array.initialize
39+
40+{-| Creates an array with a given length, filled with a default element.
41+
42+ repeat 5 0 == fromList [0,0,0,0,0]
43+ repeat 3 "cat" == fromList ["cat","cat","cat"]
44+
45+Notice that `repeat 3 x` is the same as `initialize 3 (always x)`.
46+-}
47+repeat : Int -> a -> Array a
48+repeat n e = initialize n (always e)
3649
37−-- TODO: make this a native function.
3850{-| Create an array from a list. -}
3951fromList : [a] -> Array a
40−fromList = List.foldl (Native.Array.push) Native.Array.empty
52+fromList = Native.Array.fromList
4153
4254{-| Create a list of elements from an array.
4355
@@ -46,24 +58,19 @@ fromList = List.foldl (Native.Array.push) Native.Array.empty
4658toList : Array a -> [a]
4759toList = Native.Array.toList
4860
49−{-| Create a list of the possible indices of an array.
50−
51− indices (fromList [3,5,8] == [0,1,2])
52−-}
53−indices : Array a -> [Int]
54−indices a = [0..Native.Array.length a - 1]
55−
5661-- TODO: make this a native function.
57−{-| Create a list of tuples (Index, Element) from an array.
62+{-| Create an indexed list from an array. Each element of the array will be
63+paired with its index.
5864
59− toIndexedList (fromList [3,5,8]) == [(0,3), (1,5), (2,8)]
65+ toIndexedList (fromList ["cat","dog"]) == [(0,"cat"), (1,"dog")]
6066-}
6167toIndexedList : Array a -> [(Int, a)]
62−toIndexedList a = List.zip (indices a) (Native.Array.toList a)
68+toIndexedList array =
69+ List.zip [ 0 .. Native.Array.length array - 1 ] (Native.Array.toList array)
6370
6471{-| Apply a function on every element in an array.
6572
66− map (\x -> x*x) (fromList [1,2,3]) == fromList [1,4,9]
73+ map sqrt (fromList [1,4,9]) == fromList [1,2,3]
6774-}
6875map : (a -> b) -> Array a -> Array b
6976map = Native.Array.map
@@ -75,36 +82,29 @@ map = Native.Array.map
7582indexedMap : (Int -> a -> b) -> Array a -> Array b
7683indexedMap = Native.Array.indexedMap
7784
78−{-| Reduce an array from the left.
85+{-| Reduce an array from the left. Read `foldl` as &ldquo;fold from the left&rdquo;.
7986
80− foldl (+) 0 (fill 3 5) == 15
87+ foldl (::) [] (fromList [1,2,3]) == [3,2,1]
8188-}
8289foldl : (a -> b -> b) -> b -> Array a -> b
8390foldl = Native.Array.foldl
8491
85−{-| Reduce an array from the right.
92+{-| Reduce an array from the right. Read `foldr` as &ldquo;fold from the right&rdquo;.
8693
87− foldr (::) [] (fromList [1,2,3]) == [3,2,1]
94+ foldr (+) 0 (repeat 3 5) == 15
8895-}
8996foldr : (a -> b -> b) -> b -> Array a -> b
9097foldr = Native.Array.foldr
9198
92−{-| Zip the elements of two arrays via a tuple into a new array. If one array is
93−longer, the extra elements are dropped.
94−
95− zip (fromList [1,2,3,4]) (fromList [0,0,0]) = fromList [(1,0), (2,0), (3,0)]
96−-}
97−zip : Array a -> Array b -> Array (a,b)
98−zip = zipWith (,)
99−
100−{-| Zips the elements of two arrays via a function into a new array. If one array
101−is longer, the extra elements are dropped.
99+{-| Keep only elements that satisfy the predicate:
102100
103− zipWith (+) (fill 3 5) (fill 5 8) == fill 3 13
101+ filter isEven (fromList [1..6]) == (fromList [2,4,6])
104102-}
105−zipWith : (a -> b -> c) -> Array a -> Array b -> Array c
106−zipWith f a b =
107− fromList <| List.zipWith f (Native.Array.toList a) (Native.Array.toList b)
103+filter : (a -> Bool) -> Array a -> Array a
104+filter isOkay arr =
105+ let update x xs = if isOkay x then Native.Array.push x xs else xs
106+ in
107+ Native.Array.foldl update Native.Array.empty arr
108108
109109{-| Return an empty array.
110110
@@ -120,57 +120,65 @@ empty = Native.Array.empty
120120push : a -> Array a -> Array a
121121push = Native.Array.push
122122
123−{-| Return the element at the index. Breaks, if index is out of range. If the
124−array length is unkown, use safeGet oder getWithDefault.
123+{-| Get the element at a particular index.
125124
126− get 2 (A.fromList [3,2,1]) == 1
125+ getOrFail 0 (A.fromList [0,1,2]) == 0
126+
127+Warning: this function will result in a runtime error if the index is not found,
128+so it is best to use `get` or `getOrElse` unless you are sure the index will be
129+found.
127130-}
128−get : Int -> Array a -> a
129−get = Native.Array.get
131+getOrFail : Int -> Array a -> a
132+getOrFail = Native.Array.get
130133
131134{-| Return Just the element at the index or Nothing if the index is out of range.
132135
133− getMaybe 2 (A.fromList [3,2,1]) == Just 2
134− getMaybe 5 (A.fromList [3,2,1]) == Nothing
136+ get 0 (fromList [0,1,2]) == Just 0
137+ get 2 (fromList [0,1,2]) == Just 2
138+ get 5 (fromList [0,1,2]) == Nothing
139+ get -1 (fromList [0,1,2]) == Nothing
135140-}
136−getMaybe : Int -> Array a -> Maybe a
137−getMaybe i array = if Native.Array.length array > i
138− then Just (Native.Array.get i array)
139− else Nothing
141+get : Int -> Array a -> Maybe a
142+get i array =
143+ if 0 <= i && i < Native.Array.length array
144+ then Just (Native.Array.get i array)
145+ else Nothing
140146
141−{-| Get the element at the index. If the index is out of range, the given default
142−element is returned.
147+{-| Get the element at the index. Or if the index is out of range, a default
148+value is returned.
143149
144− getSafe 0 2 (A.fromList [3,2,1]) == 1
145− getSafe 0 5 (A.fromList [3,2,1]) == 0
150+ getOrElse 0 2 (fromList [0,1,2]) == 2
151+ getOrElse 0 5 (fromList [0,1,2]) == 0
146152-}
147−getSafe : a -> Int -> Array a -> a
148−getSafe default i array = if Native.Array.length array > i
149− then Native.Array.get i array else default
153+getOrElse : a -> Int -> Array a -> a
154+getOrElse default i array =
155+ if 0 <= i && i < Native.Array.length array
156+ then Native.Array.get i array
157+ else default
150158
151−{-| Set the element at the index. Returns the updated array, or if the index is
152−out of range, the unaltered array.
159+{-| Set the element at a particular index. Returns an updated array.
160+If the index is out of range, the array is unaltered.
153161
154162 set 1 7 (fromList [1,2,3]) == fromList [1,7,3]
155163-}
156164set : Int -> a -> Array a -> Array a
157165set = Native.Array.set
158166
159−{-| Update an array with a a list tuples, wherein the first Int is the index.
167+{-| Get a sub-section of an array: `(slice start end array)`. The `start` is a
168+zero-based index where we will start our slice. The `end` is a zero-based index
169+that indicates the end of the slice. The slice extracts up to but not including
170+`end`.
160171
161− updates [(1,7),(2,8)] (fill 3 1) == fromList [1,7,8]
162−-}
163−updates : [(Int, a)] -> Array a -> Array a
164−updates us array = List.foldl (uncurry Native.Array.set) array us
172+ slice 0 3 (fromList [0,1,2,3,4]) == fromList [0,1,2]
173+ slice 1 4 (fromList [0,1,2,3,4]) == fromList [1,2,3]
174+
175+Both the `start` and `end` indexes can be negative, indicating an offset from
176+the end of the array.
165177
166−{-| Slice an array given a range. The selection is inclusive, so the last
167−element in the selection will also be in the new array. This may change in the
168−future.
169−You can select from the end by giving a negative Int.
178+ slice 1 -1 (fromList [0,1,2,3,4]) == fromList [1,2,3]
179+ slice -2 5 (fromList [0,1,2,3,4]) == fromList [3,4]
170180
171− slice 1 2 (fromList [0,1,2,3,4]) == fromList [1,2]
172− slice 1 -2 (fromList [0,1,2,3,4]) == fromList [1,2,3]
173− slice -3 -2 (fromList [0,1,2,3,4]) == fromList [2,3]
181+This makes it pretty easy to `pop` the last element off of an array: `slice 0 -1 array`
174182-}
175183slice : Int -> Int -> Array a -> Array a
176184slice = Native.Array.slice
@@ -182,9 +190,9 @@ slice = Native.Array.slice
182190length : Array a -> Int
183191length = Native.Array.length
184192
185−{-| Concat two arrays to a new one.
193+{-| Append two arrays to a new one.
186194
187− concat (fill 3 1) (fill 4 2) == fromList [1,1,1,2,2,2,2]
195+ append (array 2 42) (array 3 81) == fromList [42,42,81,81,81]
188196-}
189−concat : Array a -> Array a -> Array a
190−concat = Native.Array.concat
197+append : Array a -> Array a -> Array a
198+append = Native.Array.append
libraries/Dict.elm+76−18
@@ -1,6 +1,8 @@
11module Dict (empty,singleton,insert,update
2− ,lookup,findWithDefault
2+ ,get,getOrElse,getOrFail
33 ,remove,member
4+ ,filter
5+ ,partition
46 ,foldl,foldr,map
57 ,union,intersect,diff
68 ,keys,values
@@ -17,7 +19,7 @@ Insert, remove, and query operations all take *O(log n)* time.
1719@docs empty, singleton, insert, update, remove
1820
1921# Query
20−@docs member, lookup, findWithDefault
22+@docs member, get, getOrElse, getOrFail
2123
2224# Combine
2325@docs union, intersect, diff
@@ -26,7 +28,7 @@ Insert, remove, and query operations all take *O(log n)* time.
2628@docs keys, values, toList, fromList
2729
2830# Transform
29−@docs map, foldl, foldr
31+@docs map, foldl, foldr, filter, partition
3032
3133-}
3234
@@ -84,33 +86,74 @@ max t =
8486 RBNode _ _ _ _ r -> max r
8587 RBEmpty _ -> Native.Error.raise "(max Empty) is not defined"
8688
87−{-| Lookup the value associated with a key. -}
88−lookup : comparable -> Dict comparable v -> Maybe v
89−lookup k t =
89+{-| Get the value associated with a key. If the key is not found, return
90+`Nothing`. This is useful when you are not sure if a key will be in the
91+dictionary.
92+
93+ animals = fromList [ ("Tom", Cat), ("Jerry", Mouse) ]
94+
95+ get "Tom" animals == Just Cat
96+ get "Mouse" animals == Just Mouse
97+ get "Spike" animals == Nothing
98+
99+The `getOrElse` and `getOrFail` are built-in ways to handle common ways of
100+using the resulting `Maybe`.
101+-}
102+get : comparable -> Dict comparable v -> Maybe v
103+get k t =
90104 case t of
91105 RBEmpty LBlack -> Nothing
92106 RBNode _ k' v l r ->
93107 case Native.Utils.compare k k' of
94− LT -> lookup k l
108+ LT -> get k l
95109 EQ -> Just v
96− GT -> lookup k r
110+ GT -> get k r
111+
112+{-| Get the value associated with a key. If the key is not found,
113+return a default value.
97114
98−{-| Find the value associated with a key. If the key is not found,
99−return the default value. -}
100−findWithDefault : v -> comparable -> Dict comparable v -> v
101−findWithDefault base k t =
115+ animals = fromList [ ("Tom", Cat), ("Jerry", Mouse) ]
116+
117+ getOrElse Dog "Tom" animals == Cat
118+ getOrElse Dog "Mouse" animals == Mouse
119+ getOrElse Dog "Spike" animals == Dog
120+-}
121+getOrElse : v -> comparable -> Dict comparable v -> v
122+getOrElse base k t =
102123 case t of
103124 RBEmpty LBlack -> base
104125 RBNode _ k' v l r ->
105126 case Native.Utils.compare k k' of
106− LT -> findWithDefault base k l
127+ LT -> getOrElse base k l
107128 EQ -> v
108− GT -> findWithDefault base k r
129+ GT -> getOrElse base k r
130+
131+{-| Get the value associated with a key.
132+
133+ animals = fromList [ ("Tom", Cat), ("Jerry", Mouse) ]
134+
135+ getOrFail "Tom" animals == Cat
136+ getOrFail "Mouse" animals == Mouse
137+ getOrFail "Spike" animals == -- Runtime Error!
138+
139+Warning: this function will result in a runtime error if the key is not found,
140+so it is best to use `get` or `getOrElse` unless you are sure the key will be
141+found.
142+-}
143+getOrFail : comparable -> Dict comparable v -> v
144+getOrFail k t =
145+ case t of
146+ RBEmpty LBlack -> Native.Error.raise "key not found when using 'getOrFail'"
147+ RBNode _ k' v l r ->
148+ case Native.Utils.compare k k' of
149+ LT -> getOrFail k l
150+ EQ -> v
151+ GT -> getOrFail k r
109152
110153{-| Determine if a key is in a dictionary. -}
111154member : comparable -> Dict comparable v -> Bool
112155-- Does t contain k?
113−member k t = isJust <| lookup k t
156+member k t = isJust <| get k t
114157
115158ensureBlackRoot : Dict k v -> Dict k v
116159ensureBlackRoot t =
@@ -327,9 +370,7 @@ union t1 t2 = foldl insert t2 t1
327370{-| Keep a key-value pair when its key appears in the second dictionary.
328371Preference is given to values in the first dictionary. -}
329372intersect : Dict comparable v -> Dict comparable v -> Dict comparable v
330−intersect t1 t2 =
331− let combine k v t = if k `member` t2 then insert k v t else t
332− in foldl combine empty t1
373+intersect t1 t2 = filter (\k _ -> k `member` t2) t1
333374
334375{-| Keep a key-value pair when its key does not appear in the second dictionary.
335376Preference is given to the first dictionary. -}
@@ -351,3 +392,20 @@ toList t = foldr (\k v acc -> (k,v) :: acc) [] t
351392{-| Convert an association list into a dictionary. -}
352393fromList : [(comparable,v)] -> Dict comparable v
353394fromList assocs = List.foldl (\(k,v) d -> insert k v d) empty assocs
395+
396+{-| Keep a key-value pair when it satisfies a predicate. -}
397+filter : (comparable -> v -> Bool) -> Dict comparable v -> Dict comparable v
398+filter p dict =
399+ let add k v t = if p k v then insert k v t else t
400+ in foldl add empty dict
401+
402+{-| Partition a dictionary according to a predicate. The first dictionary
403+contains all key-value pairs which satisfy the predicate, and the second
404+contains the rest.
405+-}
406+partition : (comparable -> v -> Bool) -> Dict comparable v -> (Dict comparable v, Dict comparable v)
407+partition p dict =
408+ let add k v (t1, t2) = if p k v
409+ then (insert k v t1, t2)
410+ else (t1, insert k v t2)
411+ in foldl add (empty, empty) dict
libraries/Graphics/Input.elm+1−1
@@ -89,7 +89,7 @@ button = Native.Graphics.Input.button
8989
9090 prettyButton : Element
9191 prettyButton =
92− customButton click.handle
92+ customButton click.handle ()
9393 (image 100 40 "/button_up.jpg")
9494 (image 100 40 "/button_hover.jpg")
9595 (image 100 40 "/button_down.jpg")
libraries/List.elm+25−15
@@ -163,13 +163,19 @@ maximum = foldl1 max
163163minimum : [comparable] -> comparable
164164minimum = foldl1 min
165165
166−{-| Split a list based on the predicate. -}
166+{-| Partition a list based on a predicate. The first list contains all values
167+that satisfy the predicate, and the second list contains all the value that do
168+not.
169+
170+ partition (\x -> x < 3) [0..5] == ([0,1,2], [3,4,5])
171+ partition isEven [0..5] == ([0,2,4], [1,3,5])
172+-}
167173partition : (a -> Bool) -> [a] -> ([a],[a])
168−partition pred lst =
169− case lst of
170− [] -> ([],[])
171− x::xs -> let (bs,cs) = partition pred xs in
172− if pred x then (x::bs,cs) else (bs,x::cs)
174+partition pred =
175+ let step x (ts, fs) = if pred x
176+ then (x::ts, fs)
177+ else (ts, x::fs)
178+ in foldr step ([],[])
173179
174180{-| Combine two lists, combining them into tuples pairwise.
175181If one list is longer, the extra elements are dropped.
@@ -188,12 +194,14 @@ If one list is longer, the extra elements are dropped.
188194zipWith : (a -> b -> c) -> [a] -> [b] -> [c]
189195zipWith = Native.List.zipWith
190196
191−{-| Decompose a list of tuples. -}
197+{-| Decompose a list of tuples.
198+
199+ unzip [(0, True), (17, False), (1337, True)] == ([0,17,1337], [True,False,True])
200+-}
192201unzip : [(a,b)] -> ([a],[b])
193−unzip pairs =
194− case pairs of
195− [] -> ([],[])
196− (x,y)::ps -> let (xs,ys) = (unzip ps) in (x::xs,y::ys)
202+unzip =
203+ let step (x,y) (xs, ys) = (x::xs, y::ys)
204+ in foldr step ([], [])
197205
198206{-| Places the given value between all of the lists in the second
199207argument and concatenates the result.
@@ -209,10 +217,12 @@ join = Native.List.join
209217-}
210218intersperse : a -> [a] -> [a]
211219intersperse sep xs =
212− case xs of
213− a::b::cs -> a :: sep :: intersperse sep (b::cs)
214− [a] -> [a]
215− [] -> []
220+ case xs of
221+ [] -> []
222+ hd::tl ->
223+ let step x rest = sep :: x :: rest
224+ spersed = foldr step [] tl
225+ in hd :: spersed
216226
217227{-| Take the first n members of a list: `(take 2 [1,2,3,4] == [1,2])` -}
218228take : Int -> [a] -> [a]
libraries/Native/Array.js+202−56
@@ -1,4 +1,4 @@
1−Elm.Native.Array = {};
1+Elm.Native.Array = {};
22Elm.Native.Array.make = function(elm) {
33 elm.Native = elm.Native || {};
44 elm.Native.Array = elm.Native.Array || {};
@@ -24,38 +24,144 @@ Elm.Native.Array.make = function(elm) {
2424 // An empty array.
2525 var empty = { ctor:"_Array", height:0, table:new Array() };
2626
27− // Gets the value at index i recursively.
28− function get(i, a) {
29− if (a.height == 0) {
30− if (i < a.table.length) {
31− return a.table[i];
32− } else {
33− throw new Error("Index "+ i +" is out of range. Check the length of your array first or use getSafe or getMaybe.");
27+ function get(i, array) {
28+ if (i < 0 || i >= length(array)) {
29+ throw new Error("Index " + i + " is out of range. Check the length of " +
30+ "your array first or use getMaybe or getWithDefault.");
3431 }
35− }
32+ return unsafeGet(i, array);
33+ }
3634
37− var slot = getSlot(i, a);
38− var sub = slot > 0 ? a.lengths[slot-1] : 0;
39− return get(i - sub, a.table[slot]);
35+ function unsafeGet(i, array) {
36+ for (var x = array.height; x > 0; x--) {
37+ var slot = i >> (x * 5);
38+ if (slot > 0) {
39+ while (array.lengths[slot - 1] > i) { slot--; }
40+ i -= array.lengths[slot - 1];
41+ }
42+ array = array.table[slot];
43+ }
44+ return array.table[i];
4045 }
4146
4247 // Sets the value at the index i. Only the nodes leading to i will get
4348 // copied and updated.
44− function set(i, item, a) {
45− if (length(a) <= i) {
46− return a;
49+ function set(i, item, array) {
50+ if (i < 0 || length(array) <= i) {
51+ return array;
4752 }
48− var newA = nodeCopy(a);
49− newA.table = a.table.slice();
53+ return unsafeSet(i, item, array);
54+ }
5055
51− if (a.height == 0) {
52− newA.table[i] = item;
56+ function unsafeSet(i, item, array) {
57+ array = nodeCopy(array);
58+
59+ if (array.height == 0) {
60+ array.table[i] = item;
5361 } else {
54− var slot = getSlot(i, a);
55− var sub = slot > 0 ? a.lengths[slot-1] : 0;
56− newA.table[slot] = set(i - sub, item, a.table[slot]);
62+ var slot = getSlot(i, array);
63+ if (slot > 0) {
64+ i -= array.lengths[slot - 1];
65+ }
66+ array.table[slot] = unsafeSet(i, item, array.table[slot]);
67+ }
68+ return array;
69+ }
70+
71+ function initialize(len, f) {
72+ if (len == 0) { return empty; }
73+ var h = Math.floor(Math.log(len)/Math.log(M));
74+ return initialize_(f, h, 0, len);
75+ }
76+
77+ function initialize_(f, h, from, to) {
78+ if (h == 0) {
79+ var table = new Array((to - from) % (M + 1));
80+ for (var i = 0; i < table.length; i++) {
81+ table[i] = f(from + i);
82+ }
83+ return { ctor:"_Array", height:0, table:table };
84+ }
85+
86+ var step = Math.pow(M, h);
87+ var table = new Array(Math.ceil((to - from) / step));
88+ var lengths = new Array(table.length);
89+ for (var i = 0; i < table.length; i++) {
90+ table[i] = initialize_( f, h - 1, from + (i * step)
91+ , Math.min(from + ((i + 1) * step), to));
92+ lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0);
93+ }
94+ return { ctor:"_Array", height:h, table:table, lengths:lengths };
95+ }
96+
97+ function fromList(list) {
98+ if (list == List.Nil) { return empty; }
99+
100+ // Allocate M sized blocks (table) and write list elements to it.
101+ var table = new Array(M);
102+ var nodes = new Array();
103+ var i = 0;
104+
105+ while (list.ctor !== '[]') {
106+ table[i] = list._0;
107+ list = list._1;
108+ i++;
109+
110+ // table is full, so we can push a leaf containing it into the
111+ // next node.
112+ if (i == M) {
113+ fromListPush({ ctor:"_Array", height:0, table:table }
114+ , nodes);
115+ table = new Array(M);
116+ i = 0;
117+ }
118+ }
119+
120+ // Maybe there is something left on the table.
121+ if (i > 0) {
122+ fromListPush({ ctor:"_Array", height:0, table:table.splice(0,i) }
123+ , nodes);
124+ }
125+
126+ // Go through all of the nodes and eventually push them into higher nodes.
127+ for (var h = 0; h < nodes.length - 1; h++) {
128+ if (nodes[h].table.length > 0) {
129+ fromListPush(nodes[h], nodes);
130+ }
131+ }
132+
133+ var head = nodes[nodes.length - 1];
134+ if (head.height > 0 && head.table.length == 1) {
135+ return head.table[0];
136+ } else {
137+ return head;
138+ }
139+ }
140+
141+ // Push a node into a higher node as a child.
142+ function fromListPush(toPush, nodes) {
143+ var h = toPush.height;
144+
145+ // Maybe the node on this height does not exist.
146+ if (nodes.length == h) {
147+ nodes.push({ ctor:"_Array", height:h + 1
148+ , table:new Array()
149+ , lengths:new Array() });
150+ }
151+
152+ nodes[h].table.push(toPush);
153+ var len = length(toPush);
154+ if (nodes[h].lengths.length > 0) {
155+ len += nodes[h].lengths[nodes[h].lengths.length - 1];
156+ }
157+ nodes[h].lengths.push(len);
158+
159+ if (nodes[h].table.length == M) {
160+ fromListPush(nodes[h], nodes);
161+ nodes[h] = { ctor:"_Array", height:h + 1
162+ , table:new Array()
163+ , lengths:new Array() };
57164 }
58− return newA;
59165 }
60166
61167 // Pushes an item via push_ to the bottom right of a tree.
@@ -65,7 +171,7 @@ Elm.Native.Array.make = function(elm) {
65171 return pushed;
66172 }
67173
68− newTree = create(item, a.height);
174+ var newTree = create(item, a.height);
69175 return siblise(a, newTree);
70176 }
71177
@@ -143,22 +249,19 @@ Elm.Native.Array.make = function(elm) {
143249 }
144250
145251 function foldl(f, b, a) {
146− for (var i = a.table.length - 1; i >= 0; i--) {
252+ for (var i = 0; i < a.table.length; i++) {
147253 b = A2(f, a.height == 0 ? a.table[i] : foldl(f, b, a.table[i]), b);
148254 }
149255 return b;
150256 }
151257
152258 function foldr(f, b, a) {
153− for (var i = 0; i < a.table.length; i++) {
259+ for (var i = a.table.length; i--; ) {
154260 b = A2(f, a.height == 0 ? a.table[i] : foldr(f, b, a.table[i]), b);
155261 }
156262 return b;
157263 }
158264
159− // Returns a sliced tree. "to" is inclusive, but this may change,
160− // when I understand, why e.g. JS does not handle it this way. :-)
161− // If "from" or "to" is negative, they will select from the end on.
162265 // TODO: currently, it slices the right, then the left. This can be
163266 // optimized.
164267 function slice(from, to, a) {
@@ -175,7 +278,7 @@ Elm.Native.Array.make = function(elm) {
175278 // Handle leaf level.
176279 if (a.height == 0) {
177280 var newA = { ctor:"_Array", height:0 };
178− newA.table = a.table.slice(0, to + 1);
281+ newA.table = a.table.slice(0, to);
179282 return newA;
180283 }
181284
@@ -232,15 +335,15 @@ Elm.Native.Array.make = function(elm) {
232335 return newA;
233336 }
234337
235− // Concats two trees.
236− // TODO: Add support for concatting trees of different sizes. Current
237− // behavior will just rise the lower tree and then concat them.
238− function concat(a, b) {
239− if (b.height > a.height) { return concat(parentise(a, b.height), b); }
240− if (a.height > b.height) { return concat(a, parentise(b, a.height)); }
241− if (a.height == 0) { return concat(parentise(a, 1), parentise(b, 1)); }
338+ // Appends two trees.
339+ // TODO: Add support for appending trees of different sizes. Current
340+ // behavior will just rise the lower tree and then append them.
341+ function append(a,b) {
342+ if (b.height > a.height) { return append(parentise(a, b.height), b); }
343+ if (a.height > b.height) { return append(a, parentise(b, a.height)); }
344+ if (a.height == 0) { return append(parentise(a, 1), parentise(b, 1)); }
242345
243− var c = concat_(a, b);
346+ var c = append_(a, b);
244347 if (c[1].table.length > 0) {
245348 return siblise(c[0], c[1]);
246349 } else {
@@ -249,9 +352,9 @@ Elm.Native.Array.make = function(elm) {
249352 }
250353
251354 // Returns an array of two nodes. The second node _may_ be empty. This case
252− // needs to be handled by the function, that called concat_. May be only
355+ // needs to be handled by the function, that called append_. May be only
253356 // called for trees with an minimal height of 1.
254− function concat_(a, b) {
357+ function append_(a, b) {
255358 if (a.height == 1) {
256359 // Check if balancing is needed and return based on that.
257360 var toRemove = calcToRemove(a, b);
@@ -262,18 +365,18 @@ Elm.Native.Array.make = function(elm) {
262365 return shuffle(a, b, toRemove);
263366 }
264367
265− var concated = concat_(botRight(a), botLeft(b));
368+ var appended = append_(botRight(a), botLeft(b));
266369 a = nodeCopy(a), b = nodeCopy(b);
267370
268371 // Adjust the bottom right side of the new tree.
269− a.table[a.table.length - 1] = concated[0];
270− a.lengths[a.lengths.length - 1] = length(concated[0])
372+ a.table[a.table.length - 1] = appended[0];
373+ a.lengths[a.lengths.length - 1] = length(appended[0])
271374 a.lengths[a.lengths.length - 1] += a.lengths.length > 1 ? a.lengths[a.lengths.length - 2] : 0;
272375
273376 // Adjust the bottom left side of the new tree.
274− if (concated[1].table.length > 0) {
275− b.table[0] = concated[1];
276− b.lengths[0] = length(concated[1]);
377+ if (appended[1].table.length > 0) {
378+ b.table[0] = appended[1];
379+ b.lengths[0] = length(appended[1]);
277380 for (var i = 1, len = length(b.table[0]); i < b.lengths.length; i++) {
278381 len += length(b.table[i]);
279382 b.lengths[i] = len;
@@ -423,21 +526,19 @@ Elm.Native.Array.make = function(elm) {
423526 }
424527
425528 // Returns how many items are in the tree.
426− function length(a) {
427− if (a.height == 0) {
428− return a.table.length;
529+ function length(array) {
530+ if (array.height == 0) {
531+ return array.table.length;
429532 } else {
430− return a.lengths[a.lengths.length - 1];
533+ return array.lengths[array.lengths.length - 1];
431534 }
432535 }
433536
434537 // Calculates in which slot of "table" the item probably is, then
435538 // find the exact slot via forward searching in "lengths". Returns the index.
436539 function getSlot(i, a) {
437− var slot = Math.floor(i / (Math.pow(M, a.height)));
438− while (a.lengths[slot] <= i) {
439− slot++
440− }
540+ var slot = i >> (5 * a.height);
541+ while (a.lengths[slot - 1] > i) { slot--; }
441542 return slot;
442543 }
443544
@@ -472,10 +573,52 @@ Elm.Native.Array.make = function(elm) {
472573 , lengths:[length(a), length(a) + length(b)] };
473574 }
474575
576+ function toJSArray(a) {
577+ var jsArray = new Array(length(a));
578+ toJSArray_(jsArray, 0, a);
579+ return jsArray;
580+ }
581+
582+ function toJSArray_(jsArray, i, a) {
583+ for (var t = 0; t < a.table.length; t++) {
584+ if (a.height == 0) {
585+ jsArray[i + t] = a.table[t];
586+ } else {
587+ var inc = t == 0 ? 0 : a.lengths[t - 1];
588+ toJSArray_(jsArray, i + inc, a.table[t]);
589+ }
590+ }
591+ }
592+
593+ function fromJSArray(jsArray) {
594+ if (jsArray.length == 0) { return empty; }
595+ var h = Math.floor(Math.log(jsArray.length) / Math.log(M));
596+ return fromJSArray_(jsArray, h, 0, jsArray.length);
597+ }
598+
599+ function fromJSArray_(jsArray, h, from, to) {
600+ if (h == 0) {
601+ return { ctor:"_Array", height:0
602+ , table:jsArray.slice(from, to) };
603+ }
604+
605+ var step = Math.pow(M, h);
606+ var table = new Array(Math.ceil((to - from) / step));
607+ var lengths = new Array(table.length);
608+ for (var i = 0; i < table.length; i++) {
609+ table[i] = fromJSArray_( jsArray, h - 1, from + (i * step)
610+ , Math.min(from + ((i + 1) * step), to));
611+ lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0);
612+ }
613+ return { ctor:"_Array", height:h, table:table, lengths:lengths };
614+ }
615+
475616 Elm.Native.Array.values = {
476617 empty:empty,
618+ fromList:fromList,
477619 toList:toList,
478− concat:F2(concat),
620+ initialize:F2(initialize),
621+ append:F2(append),
479622 push:F2(push),
480623 slice:F3(slice),
481624 get:F2(get),
@@ -484,7 +627,10 @@ Elm.Native.Array.make = function(elm) {
484627 indexedMap:F2(indexedMap),
485628 foldl:F3(foldl),
486629 foldr:F3(foldr),
487− length:length
630+ length:length,
631+
632+ toJSArray:toJSArray,
633+ fromJSArray:fromJSArray
488634 };
489635
490636 return elm.Native.Array.values = Elm.Native.Array.values;
libraries/Native/Error.js+2−4
@@ -4,8 +4,6 @@ Elm.Native.Error.make = function(elm) {
44 elm.Native.Error = elm.Native.Error || {};
55 if (elm.Native.Error.values) return elm.Native.Error.values;
66
7− var fromString = Elm.Native.JavaScript.make(elm).fromString;
8−
97 function indent(lines) {
108 var msg = '';
119 for (var i = 0; i < lines.length; ++i) {
@@ -26,7 +24,7 @@ Elm.Native.Error.make = function(elm) {
2624 throw new Error('Runtime error in module ' + moduleName + ' (' + span + '):' + msg);
2725 }
2826
29− function raise(str) { throw new Error(fromString(str)); }
27+ function raise(str) { throw new Error(str); }
3028
3129 return elm.Native.Error.values = { Case: Case, If: If, raise: raise };
32−};
30+};
libraries/Native/Graphics/Input.js−29
@@ -134,13 +134,6 @@ Elm.Native.Graphics.Input.make = function(elm) {
134134
135135 btn.appendChild(btn.elm_up);
136136
137− var clicker = newNode('div');
138− clicker.style.width = btn.elm_up.style.width;
139− clicker.style.height = btn.elm_up.style.height;
140− clicker.style.position = 'absolute';
141− clicker.style.top = 0;
142− btn.appendChild(clicker);
143−
144137 return btn;
145138 }
146139
@@ -297,29 +290,7 @@ Elm.Native.Graphics.Input.make = function(elm) {
297290 }));
298291 }
299292
300− function mouseUpdate(event) {
301− var direction = field.selectionDirection === 'forward' ? 'Forward' : 'Backward';
302− elm.notify(field.elm_signal.id, field.elm_handler({
303− _:{},
304− string: field.value,
305− selection: {
306− _:{},
307− start: field.selectionStart,
308− end: field.selectionEnd,
309− direction: { ctor: direction }
310− },
311− }));
312− }
313− function mousedown(event) {
314− mouseUpdate(event);
315− elm.node.addEventListener('mouseup', mouseup);
316− }
317− function mouseup(event) {
318− mouseUpdate(event);
319− elm.node.removeEventListener('mouseup', mouseup)
320− }
321293 field.addEventListener('input', inputUpdate);
322− field.addEventListener('mousedown', mousedown);
323294 field.addEventListener('focus', function() {
324295 field.elm_hasFocus = true;
325296 });
libraries/Native/String.js+2−2
@@ -73,7 +73,7 @@ Elm.Native.String.make = function(elm) {
7373 return result;
7474 }
7575
76− function sub(start, end, str) {
76+ function slice(start, end, str) {
7777 return str.slice(start,end);
7878 }
7979 function left(n, str) {
@@ -216,7 +216,7 @@ Elm.Native.String.make = function(elm) {
216216 join: F2(join),
217217 repeat: F2(repeat),
218218
219− sub: F3(sub),
219+ slice: F3(slice),
220220 left: F2(left),
221221 right: F2(right),
222222 dropLeft: F2(dropLeft),
libraries/Native/Text.js+1
@@ -153,6 +153,7 @@ Elm.Native.Text.make = function(elm) {
153153 typeface : F2(typeface),
154154 color : F2(color),
155155 link : F2(link),
156+ style : F2(style),
156157
157158 leftAligned : block('left'),
158159 rightAligned : block('right'),
libraries/Native/Utils.js+39−22
@@ -5,23 +5,30 @@ Elm.Native.Utils.make = function(elm) {
55 elm.Native.Utils = elm.Native.Utils || {};
66 if (elm.Native.Utils.values) return elm.Native.Utils.values;
77
8− function eq(x,y) {
9− if (x === y) return true;
10− if (typeof x === "object") {
11− var c = 0;
12− for (var i in x) {
13− ++c;
14− if (!eq(x[i],y[i])) {
15− return false;
8+ function eq(l,r) {
9+ var stack = [{'x': l, 'y': r}]
10+ while (stack.length > 0) {
11+ var front = stack.pop();
12+ var x = front.x;
13+ var y = front.y;
14+ if (x === y) continue;
15+ if (typeof x === "object") {
16+ var c = 0;
17+ for (var i in x) {
18+ ++c;
19+ stack.push({ 'x': x[i], 'y': y[i] });
1620 }
21+ if (c !== Object.keys(y).length) {
22+ return false;
23+ };
24+ } else if (typeof x === 'function') {
25+ throw new Error('Equality error: general function equality is ' +
26+ 'undecidable, and therefore, unsupported');
27+ } else {
28+ return false;
1729 }
18− return c === Object.keys(y).length;
1930 }
20− if (typeof x === 'function') {
21− throw new Error('Equality error: general function equality is ' +
22− 'undecidable, and therefore, unsupported');
23− }
24− return x === y;
31+ return true;
2532 }
2633
2734 // code in Generate/JavaScript.hs depends on the particular
@@ -30,11 +37,15 @@ Elm.Native.Utils.make = function(elm) {
3037 function compare(x,y) { return { ctor: ord[cmp(x,y)+1] } }
3138 function cmp(x,y) {
3239 var ord;
33− if (typeof x !== 'object' || x instanceof String){
40+ if (typeof x !== 'object'){
3441 return x === y ? EQ : x < y ? LT : GT;
3542 }
36−
37− if (x.ctor === "::" || x.ctor === "[]") {
43+ else if (x.isChar){
44+ var a = x.toString();
45+ var b = y.toString();
46+ return a === b ? EQ : a < b ? LT : GT;
47+ }
48+ else if (x.ctor === "::" || x.ctor === "[]") {
3849 while (true) {
3950 if (x.ctor === "[]" && y.ctor === "[]") return EQ;
4051 if (x.ctor !== y.ctor) return x.ctor === '[]' ? LT : GT;
@@ -44,8 +55,7 @@ Elm.Native.Utils.make = function(elm) {
4455 y = y._1;
4556 }
4657 }
47−
48− if (x.ctor.slice(0,6) === '_Tuple') {
58+ else if (x.ctor.slice(0,6) === '_Tuple') {
4959 var n = x.ctor.slice(6) - 0;
5060 var err = 'cannot compare tuples with more than 6 elements.';
5161 if (n === 0) return EQ;
@@ -58,9 +68,11 @@ Elm.Native.Utils.make = function(elm) {
5868 if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
5969 return EQ;
6070 }
61− throw new Error('Comparison error: comparison is only defined on ints, ' +
62− 'floats, times, chars, strings, lists of comparable values, ' +
63− 'and tuples of comparable values.')
71+ else {
72+ throw new Error('Comparison error: comparison is only defined on ints, ' +
73+ 'floats, times, chars, strings, lists of comparable values, ' +
74+ 'and tuples of comparable values.');
75+ }
6476 }
6577
6678
@@ -205,6 +217,10 @@ Elm.Native.Utils.make = function(elm) {
205217 return Tuple2(posx, posy);
206218 }
207219
220+ function isJSArray(a) {
221+ return a instanceof Array;
222+ }
223+
208224 return elm.Native.Utils.values = {
209225 eq:eq,
210226 cmp:cmp,
@@ -224,6 +240,7 @@ Elm.Native.Utils.make = function(elm) {
224240 mod : F2(mod),
225241 htmlHeight: F2(htmlHeight),
226242 getXY: getXY,
243+ isJSArray: isJSArray,
227244 toFloat: function(x) { return +x; }
228245 };
229246};
libraries/Set.elm+11−1
@@ -2,6 +2,7 @@
22module Set (empty,singleton,insert,remove
33 ,member
44 ,foldl,foldr,map
5+ ,filter,partition
56 ,union,intersect,diff
67 ,toList,fromList
78 ) where
@@ -25,7 +26,7 @@ Insert, remove, and query operations all take *O(log n)* time.
2526@docs toList, fromList
2627
2728# Transform
28−@docs map, foldl, foldr
29+@docs map, foldl, foldr, filter, partition
2930
3031-}
3132
@@ -88,3 +89,12 @@ foldr f b s = Dict.foldr (\k _ b -> f k b) b s
8889{-| Map a function onto a set, creating a new set with no duplicates. -}
8990map : (comparable -> comparable') -> Set comparable -> Set comparable'
9091map f s = fromList (List.map f (toList s))
92+
93+{-| Create a new set consisting only of elements which satisfy a predicate. -}
94+filter : (comparable -> Bool) -> Set comparable -> Set comparable
95+filter p set = Dict.filter (\k _ -> p k) set
96+
97+{-| Create two new sets; the first consisting of elements which satisfy a
98+predicate, the second consisting of elements which do not. -}
99+partition : (comparable -> Bool) -> Set comparable -> (Set comparable, Set comparable)
100+partition p set = Dict.partition (\k _ -> p k) set
libraries/Signal.elm+8−13
@@ -31,10 +31,7 @@ the `Time` library.
3131
3232import Native.Signal
3333import List (foldr)
34−
3534import Basics (fst, snd, not)
36−import Native.Error
37−import Maybe as M
3835
3936data Signal a = Signal
4037
@@ -120,20 +117,18 @@ initially. -}
120117dropIf : (a -> Bool) -> a -> Signal a -> Signal a
121118dropIf = Native.Signal.dropIf
122119
123−{-| Keep events only when the first signal is true. When the first signal
124−becomes true, the most recent value of the second signal will be propagated.
125−Until the first signal becomes false again, all events will be propagated. Elm
126−does not allow undefined signals, so a base case must be provided in case the
127−first signal is not true initially. -}
120+{-| Keep events only when the first signal is true. Elm does not allow undefined
121+signals, so a base case must be provided in case the first signal is not true
122+initially.
123+-}
128124keepWhen : Signal Bool -> a -> Signal a -> Signal a
129125keepWhen bs def sig =
130126 snd <~ (keepIf fst (False, def) ((,) <~ (sampleOn sig bs) ~ sig))
131127
132−{-| Drop events when the first signal is true. When the first signal becomes
133−false, the most recent value of the second signal will be propagated. Until the
134−first signal becomes true again, all events will be propagated. Elm does not
135−allow undefined signals, s oa base case must be provided in case the first
136−signal is true initially. -}
128+{-| Drop events when the first signal is true. Elm does not allow undefined
129+signals, so a base case must be provided in case the first signal is true
130+initially.
131+-}
137132dropWhen : Signal Bool -> a -> Signal a -> Signal a
138133dropWhen bs = keepWhen (not <~ bs)
139134
libraries/String.elm+9−9
@@ -6,10 +6,10 @@ are enclosed in `"double quotes"`. Strings are *not* lists of characters.
66@docs isEmpty, length, reverse, repeat
77
88# Building and Splitting
9−@docs cons, uncons, append, concat, split, join, words, lines
9+@docs cons, uncons, append, concat, split, join, words, lines
1010
1111# Get Substrings
12−@docs sub, left, right, dropLeft, dropRight
12+@docs slice, left, right, dropLeft, dropRight
1313
1414# Check for Substrings
1515@docs contains, startsWith, endsWith, indexes, indices
@@ -114,7 +114,7 @@ foldr = Native.String.foldr
114114{-| Split a string using a given separator.
115115
116116 split "," "cat,dog,cow" == ["cat","dog","cow"]
117− split "/" "home/evan/Desktop/" == ["home","evan","Desktop"]
117+ split "/" "home/evan/Desktop/" == ["home","evan","Desktop", ""]
118118
119119Use `Regex.split` if you need something more flexible.
120120-}
@@ -139,13 +139,13 @@ repeat = Native.String.repeat
139139{-| Take a substring given a start and end index. Negative indexes
140140are taken starting from the *end* of the list.
141141
142− sub 7 9 "snakes on a plane!" == "on"
143− sub 0 6 "snakes on a plane!" == "snakes"
144− sub 0 -7 "snakes on a plane!" == "snakes on a"
145− sub -6 -1 "snakes on a plane!" == "plane"
142+ slice 7 9 "snakes on a plane!" == "on"
143+ slice 0 6 "snakes on a plane!" == "snakes"
144+ slice 0 -7 "snakes on a plane!" == "snakes on a"
145+ slice -6 -1 "snakes on a plane!" == "plane"
146146-}
147−sub : Int -> Int -> String -> String
148−sub = Native.String.sub
147+slice : Int -> Int -> String -> String
148+slice = Native.String.slice
149149
150150{-| Take N characters from the left side of a string. -}
151151left : Int -> String -> String
libraries/elm_dependencies.json+6−5
@@ -1,12 +1,13 @@
1−{ "version": "0.12"
1+{ "version": "0.12.1"
22, "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.12, you should be using version 0.12 of the 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.12.1, you should be using version 0.12.1 of the standard libraries."
44, "license": "BSD3"
5−, "repository": "http://github.com/evancz/Elm.git"
6−, "elm-version": "0.12"
5+, "repository": "http://github.com/elm-lang/Elm.git"
6+, "elm-version": "0.12.1"
77, "dependencies": {}
88, "exposed-modules":
9− [ "Basics"
9+ [ "Array"
10+ , "Basics"
1011 , "Bitwise"
1112 , "Char"
1213 , "Color"
runtime/Render/Element.js+8−2
@@ -31,6 +31,7 @@ function setProps(elem, e) {
3131 a.style.display = 'block';
3232 a.style.position = 'absolute';
3333 e.style.position = 'relative';
34+ a.style.pointerEvents = 'auto';
3435 e.appendChild(a);
3536 }
3637 if (props.hover.ctor !== '_Tuple0') {
@@ -45,8 +46,9 @@ function setProps(elem, e) {
4546function addClick(e, handler) {
4647 e.style.pointerEvents = 'auto';
4748 e.elm_click_handler = handler;
48− function trigger() {
49+ function trigger(ev) {
4950 e.elm_click_handler(Utils.Tuple0);
51+ ev.stopPropagation();
5052 }
5153 e.elm_click_trigger = trigger;
5254 e.addEventListener('click', trigger);
@@ -63,14 +65,16 @@ function addHover(e, handler) {
6365 e.elm_hover_handler = handler;
6466 e.elm_hover_count = 0;
6567
66− function over() {
68+ function over(evt) {
6769 if (e.elm_hover_count++ > 0) return;
6870 e.elm_hover_handler(true);
71+ evt.stopPropagation();
6972 }
7073 function out(evt) {
7174 if (e.contains(evt.toElement || evt.relatedTarget)) return;
7275 e.elm_hover_count = 0;
7376 e.elm_hover_handler(false);
77+ evt.stopPropagation();
7478 }
7579 e.elm_hover_over = over;
7680 e.elm_hover_out = out;
@@ -232,6 +236,7 @@ function rawHtml(elem) {
232236 }
233237 document.body.removeChild(div);
234238 div.style.visibility = 'visible';
239+ div.style.pointerEvents = 'auto';
235240 return div;
236241}
237242
@@ -375,6 +380,7 @@ function updateProps(node, curr, next) {
375380 a.style.display = 'block';
376381 a.style.position = 'absolute';
377382 e.style.position = 'relative';
383+ a.style.pointerEvents = 'auto';
378384 e.appendChild(a);
379385 } else {
380386 node.lastNode.href = props.href;
server/LICENSEdeleted−30
@@ -1,30 +0,0 @@
1−Copyright (c)2012-2014, Evan Czaplicki
2−
3−All rights reserved.
4−
5−Redistribution and use in source and binary forms, with or without
6−modification, are permitted provided that the following conditions are met:
7−
8− * Redistributions of source code must retain the above copyright
9− notice, this list of conditions and the following disclaimer.
10−
11− * Redistributions in binary form must reproduce the above
12− copyright notice, this list of conditions and the following
13− disclaimer in the documentation and/or other materials provided
14− with the distribution.
15−
16− * Neither the name of Evan Czaplicki nor the names of other
17− contributors may be used to endorse or promote products derived
18− from this software without specific prior written permission.
19−
20−THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21−"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22−LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23−A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24−OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25−SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26−LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27−DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28−THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29−(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30−OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
server/Server.hsdeleted−127
@@ -1,127 +0,0 @@
1−{-# OPTIONS_GHC -Wall #-}
2−{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
3−module Main where
4−
5−import Control.Applicative ((<$>),(<|>))
6−import Control.Monad (guard)
7−import Control.Monad.Trans (MonadIO(liftIO))
8−import qualified Data.ByteString as BS
9−import qualified Data.ByteString.Char8 as BSC
10−import qualified Data.HashMap.Strict as Map
11−import qualified Data.Version as Version
12−import System.Console.CmdArgs
13−import System.Directory
14−import System.Exit
15−import System.FilePath
16−import System.Process
17−import System.IO (hGetContents, Handle)
18−
19−import Paths_elm_server (version)
20−import qualified Elm.Internal.Paths as Elm
21−import Snap.Core
22−import Snap.Http.Server
23−import Snap.Util.FileServe
24−
25−data Flags = Flags
26− { port :: Int
27− , runtime :: Maybe FilePath
28− } deriving (Data,Typeable,Show,Eq)
29−
30−flags :: Flags
31−flags = Flags
32− { port = 8000 &= help "set the port of the server"
33− , runtime = Nothing &= typFile
34− &= help "Specify a custom location for Elm's runtime system."
35− } &= help "Quickly reload Elm projects in your browser. Just refresh to recompile.\n\
36− \It serves static files and freshly recompiled Elm files."
37− &= helpArg [explicit, name "help", name "h"]
38− &= versionArg [ explicit, name "version", name "v"
39− , summary (Version.showVersion version)
40− ]
41− &= summary ("Elm Server " ++ Version.showVersion version ++
42− ", (c) Evan Czaplicki 2011-2014")
43−
44−
45−config :: Config Snap a
46−config = setAccessLog ConfigNoLog (setErrorLog ConfigNoLog defaultConfig)
47−
48−-- | Set up the server.
49−main :: IO ()
50−main = do
51− cargs <- cmdArgs flags
52− putStrLn $ "Elm Server " ++ Version.showVersion version ++
53− ": Just refresh a page to recompile it!"
54− httpServe (setPort (port cargs) config) $
55− serveRuntime (maybe Elm.runtime id (runtime cargs))
56− <|> serveElm
57− <|> serveDirectoryWith directoryConfig "."
58−
59−directoryConfig :: MonadSnap m => DirectoryConfig m
60−directoryConfig =
61− fancyDirectoryConfig
62− { indexGenerator = defaultIndexGenerator defaultMimeTypes indexStyle
63− , mimeTypes = Map.insert ".elm" "text/html" defaultMimeTypes
64− }
65−
66−indexStyle :: BS.ByteString
67−indexStyle =
68− "body { margin:0; font-family:sans-serif; background:rgb(245,245,245);\
69− \ font-family: calibri, verdana, helvetica, arial; }\
70− \div.header { padding: 40px 50px; font-size: 24px; }\
71− \div.content { padding: 0 40px }\
72− \div.footer { display:none; }\
73− \table { width:100%; border-collapse:collapse; }\
74− \td { padding: 6px 10px; }\
75− \tr:nth-child(odd) { background:rgb(216,221,225); }\
76− \td { font-family:monospace }\
77− \th { background:rgb(90,99,120); color:white; text-align:left;\
78− \ padding:10px; font-weight:normal; }"
79−
80−runtimeName :: String
81−runtimeName = "elm-runtime.js"
82−
83−serveRuntime :: FilePath -> Snap ()
84−serveRuntime runtimePath =
85− do file <- BSC.unpack . rqPathInfo <$> getRequest
86− guard (file == runtimeName)
87− serveFileAs "application/javascript" runtimePath
88−
89−serveElm :: Snap ()
90−serveElm =
91− do file <- BSC.unpack . rqPathInfo <$> getRequest
92− exists <- liftIO $ doesFileExist file
93− guard (exists && takeExtension file == ".elm")
94− onSuccess (compile file) (serve file)
95− where
96− compile file =
97− let elmArgs = [ "--make", "--runtime=" ++ runtimeName, file ]
98− in createProcess $ (proc "elm" elmArgs) { std_out = CreatePipe }
99−
100− serve file =
101− serveFileAs "text/html; charset=UTF-8" ("build" </> replaceExtension file "html")
102−
103−failure :: String -> Snap ()
104−failure msg =
105− do modifyResponse $ setResponseStatus 404 "Not found"
106− writeBS $ BSC.pack msg
107−
108−onSuccess :: IO (t, Maybe Handle, t1, ProcessHandle) -> Snap () -> Snap ()
109−onSuccess action success =
110− do (_, stdout, _, handle) <- liftIO action
111− exitCode <- liftIO $ waitForProcess handle
112− case (exitCode, stdout) of
113− (ExitFailure 127, _) ->
114− failure "Error: elm compiler not found in your path."
115−
116− (ExitFailure _, Just out) ->
117− failure =<< liftIO (hGetContents out)
118−
119− (ExitFailure _, Nothing) ->
120− failure "See command line for error message."
121−
122− (ExitSuccess, _) -> success
123−
124−{--
125−pageTitle :: String -> String
126−pageTitle = dropExtension . takeBaseName
127−--}
server/Setup.hsdeleted−2
@@ -1,2 +0,0 @@
1−import Distribution.Simple
2−main = defaultMain
server/elm-server.cabaldeleted−41
@@ -1,41 +0,0 @@
1−Name: elm-server
2−Version: 0.12
3−Synopsis: Server for developing Elm projects
4−Description: Provides a standalone Snap server that serves static files.
5− For Elm files, it recompiles them and serves them as HTML,
6− so you can just refresh to see the new version.
7−
8−Homepage: http://elm-lang.org
9−
10−License: BSD3
11−License-file: LICENSE
12−
13−Author: Evan Czaplicki
14−Maintainer: info@elm-lang.org
15−Copyright: Copyright: (c) 2011-2014 Evan Czaplicki
16−
17−Category: Compiler, Language
18−
19−Build-type: Simple
20−
21−--Extra-source-files: README.md
22−Cabal-version: >=1.8
23−
24−source-repository head
25− type: git
26− location: git://github.com/evancz/Elm.git
27−
28−Executable elm-server
29− Main-is: Server.hs
30− Build-depends: base >=4.2 && <5,
31− bytestring,
32− cmdargs,
33− containers >= 0.3,
34− directory,
35− filepath,
36− Elm >= 0.12,
37− snap-core,
38− snap-server,
39− mtl,
40− process,
41− unordered-containers
tests/elm/Test.elmnew file+37
@@ -0,0 +1,37 @@
1+module Main where
2+
3+import ElmTest.Assertion as A
4+import ElmTest.Run as R
5+import ElmTest.Runner.Console (runDisplay)
6+import ElmTest.Test (..)
7+
8+import IO.IO (..)
9+import IO.Runner (Request, Response)
10+import IO.Runner as Run
11+
12+import Test.Array as Array
13+import Test.Dict as Dict
14+import Test.List as List
15+import Test.Set as Set
16+import Test.String as String
17+import Test.Trampoline as Trampoline
18+
19+tests : Test
20+tests = suite "Elm Standard Library Tests" [ List.tests,
21+ String.tests,
22+ Trampoline.tests,
23+ Array.tests,
24+ Dict.tests,
25+ Set.tests
26+ ]
27+
28+console : IO ()
29+console = runDisplay tests
30+
31+port requests : Signal [{ mPut : Maybe String
32+ , mExit : Maybe Int
33+ , mGet : Bool
34+ }]
35+port requests = Run.run responses console
36+
37+port responses : Signal (Maybe String)
tests/elm/Test/Array.elmnew file+62
@@ -0,0 +1,62 @@
1+module Test.Array (tests) where
2+
3+import List
4+import Array
5+import Native.Array
6+
7+import ElmTest.Assertion (..)
8+import ElmTest.Test (..)
9+
10+tests : Test
11+tests =
12+ let creationTests = suite "Creation"
13+ [ test "empty" <| assertEqual Array.empty (Array.fromList [])
14+ , test "initialize" <| assertEqual (Array.initialize 4 id) (Array.fromList [0,1,2,3])
15+ , test "initialize 2" <| assertEqual (Array.initialize 4 (\n -> n*n)) (Array.fromList [0,1,4,9])
16+ , test "initialize 3" <| assertEqual (Array.initialize 4 (always 0)) (Array.fromList [0,0,0,0])
17+ , test "initialize Empty" <| assertEqual (Array.initialize 0 id) Array.empty
18+ , test "initialize 4" <| assertEqual (Array.initialize 2 (always 0)) (Array.fromList [0,0])
19+ , test "repeat" <| assertEqual (Array.repeat 5 40) (Array.fromList [40,40,40,40,40])
20+ , test "repeat 2" <| assertEqual (Array.repeat 5 0) (Array.fromList [0,0,0,0,0])
21+ , test "repeat 3" <| assertEqual (Array.repeat 3 "cat") (Array.fromList ["cat","cat","cat"])
22+ , test "fromList" <| assertEqual (Array.fromList []) Array.empty
23+ ]
24+ basicsTests = suite "Basics"
25+ [ test "length" <| assertEqual 3 (Array.length (Array.fromList [1,2,3]))
26+ , test "length - Long" <| assertEqual 10000 (Array.length (Array.repeat 10000 0))
27+ , test "push" <| assertEqual (Array.fromList [1,2,3]) (Array.push 3 (Array.fromList [1,2]))
28+ , test "append" <| assertEqual [42,42,81,81,81] (Array.toList (Array.append (Array.repeat 2 42) (Array.repeat 3 81)))
29+ ]
30+ getAndSetTests = suite "Get and Set"
31+ [ test "get" <| assertEqual (Just 2) (Array.get 1 (Array.fromList [3,2,1]))
32+ , test "get 2" <| assertEqual Nothing (Array.get 5 (Array.fromList [3,2,1]))
33+ , test "get 3" <| assertEqual Nothing (Array.get -1 (Array.fromList [3,2,1]))
34+ , test "getOrElse 1" <| assertEqual 1 (Array.getOrElse 0 2 (Array.fromList [3,2,1]))
35+ , test "getOrElse 2" <| assertEqual 0 (Array.getOrElse 0 5 (Array.fromList [3,2,1]))
36+ , test "getOrFail" <| assertEqual 1 (Array.getOrFail 2 (Array.fromList [3,2,1]))
37+ , test "set" <| assertEqual (Array.fromList [1,7,3]) (Array.set 1 7 (Array.fromList [1,2,3]))
38+ ]
39+ takingArraysApartTests = suite "Taking Arrays Apart"
40+ [ test "toList" <| assertEqual [3,5,8] (Array.toList (Array.fromList [3,5,8]))
41+ , test "toIndexedList" <| assertEqual [(0,"cat"), (1,"dog")] (Array.toIndexedList (Array.fromList ["cat","dog"]))
42+ , test "slice 1" <| assertEqual (Array.fromList [0,1,2]) (Array.slice 0 3 (Array.fromList [0,1,2,3,4]))
43+ , test "slice 2" <| assertEqual (Array.fromList [1,2,3]) (Array.slice 1 4 (Array.fromList [0,1,2,3,4]))
44+ , test "slice 3" <| assertEqual (Array.fromList [1,2,3]) (Array.slice 1 -1 (Array.fromList [0,1,2,3,4]))
45+ , test "slice 4" <| assertEqual (Array.fromList [2]) (Array.slice -3 -2 (Array.fromList [0,1,2,3,4]))
46+ ]
47+ mappingAndFoldingTests = suite "Mapping and Folding"
48+ [ test "map" <| assertEqual (Array.fromList [1,2,3]) (Array.map sqrt (Array.fromList [1,4,9]))
49+ , test "indexedMap" <| assertEqual (Array.fromList [0,5,10]) (Array.indexedMap (*) (Array.fromList [5,5,5]))
50+ , test "foldl" <| assertEqual [3,2,1] (Array.foldl (::) [] (Array.fromList [1,2,3]))
51+ , test "foldr 1" <| assertEqual 15 (Array.foldr (+) 0 (Array.repeat 3 5))
52+ , test "foldr 2" <| assertEqual [1,2,3] (Array.foldr (::) [] (Array.fromList [1,2,3]))
53+ , test "filter" <| assertEqual (Array.fromList [2,4,6]) (Array.filter (\x -> x `mod` 2 == 0) (Array.fromList [1..6]))
54+ ]
55+ nativeTests = suite "Conversion to JS Arrays"
56+ [ test "jsArrays" <| assertEqual (Array.fromList [1..1100]) (Native.Array.fromJSArray (Native.Array.toJSArray (Array.fromList [1..1100])))
57+ ]
58+ in
59+ suite "Array"
60+ [ creationTests, basicsTests, getAndSetTests
61+ , takingArraysApartTests, mappingAndFoldingTests, nativeTests
62+ ]
tests/elm/Test/Dict.elmnew file+26
@@ -0,0 +1,26 @@
1+module Test.Dict (tests) where
2+
3+import Dict
4+import List
5+
6+import ElmTest.Assertion (..)
7+import ElmTest.Test (..)
8+
9+animals : Dict.Dict String String
10+animals = Dict.fromList [ ("Tom", "cat"), ("Jerry", "mouse") ]
11+
12+tests : Test
13+tests =
14+ let getTests =
15+ [ test "get 1" <| assertEqual (Just "cat") (Dict.get "Tom" animals)
16+ , test "get 2" <| assertEqual Nothing (Dict.get "Spike" animals)
17+ , test "getOrElse 1" <| assertEqual "mouse" (Dict.getOrElse "dog" "Jerry" animals)
18+ , test "getOrElse 2" <| assertEqual "dog" (Dict.getOrElse "dog" "Spike" animals)
19+ , test "getOrFail" <| assertEqual "cat" (Dict.getOrFail "Tom" animals)
20+ ]
21+ filterTests =
22+ [ test "filter" <| assertEqual (Dict.singleton "Tom" "cat") (Dict.filter (\k v -> k == "Tom") animals)
23+ , test "partition" <| assertEqual (Dict.singleton "Tom" "cat", Dict.singleton "Jerry" "mouse") (Dict.partition (\k v -> k == "Tom") animals)
24+ ]
25+ in
26+ suite "Dict Tests" <| List.concat [ getTests, filterTests ]
tests/elm/Test/List.elmnew file+38
@@ -0,0 +1,38 @@
1+module Test.List (tests) where
2+
3+import List
4+
5+import ElmTest.Assertion (..)
6+import ElmTest.Test (..)
7+
8+tests : Test
9+tests =
10+ let partitionTests =
11+ let p1 = id
12+ p2 x = x < 3
13+ isEven n = n `mod` 2 == 0
14+ in suite "partition Tests" [ test "simple partition" <| assertEqual ([True],[False]) (List.partition p1 [False, True]),
15+ test "order check" <| assertEqual ([2,1], [5,6]) (List.partition p2 [2,5,6,1]),
16+ test "partition doc check 1" <| assertEqual ([0,1,2], [3,4,5]) (partition p2 [0..5]),
17+ test "partition doc check 2" <| assertEqual ([0,2,4], [1,3,5]) (partition isEven [0..5]),
18+ let n = 100000
19+ ts = repeat n True
20+ fs = repeat n False
21+ in test "partition stress test" <| assertEqual (ts, fs) (partition p1 (fs++ts))
22+ ]
23+ unzipTests = suite "unzip Tests" [
24+ test "unzip doc check" <| assertEqual ([0,17,1337],[True,False,True]) (unzip [(0, True), (17, False), (1337, True)]),
25+ let n = 100000
26+ ts = repeat n True
27+ fs = repeat n False
28+ in test "unzip stress test" <| assertEqual (ts, fs) (unzip (zip ts fs))
29+ ]
30+ intersperseTests = suite "intersperse Tests" [
31+ test "intersperse doc check" <| assertEqual ["turtles","on","turtles","on","turtles"] (intersperse "on" ["turtles","turtles","turtles"]),
32+ let n = 100000
33+ ts = repeat n True
34+ fs = repeat n False
35+ in test "intersperse stress test" <| assertEqual (tail . List.concat <| zipWith (\x y -> [x,y]) fs ts)
36+ (intersperse False ts)
37+ ]
38+ in suite "List Tests" [partitionTests, unzipTests, intersperseTests]
tests/elm/Test/Set.elmnew file+27
@@ -0,0 +1,27 @@
1+module Test.Set (tests) where
2+
3+import Set
4+import Set (Set)
5+import List
6+
7+import ElmTest.Assertion (..)
8+import ElmTest.Test (..)
9+
10+set : Set Int
11+set = Set.fromList [1..100]
12+
13+setPart1 : Set Int
14+setPart1 = Set.fromList [1..50]
15+
16+setPart2 : Set Int
17+setPart2 = Set.fromList [51..100]
18+
19+pred : Int -> Bool
20+pred x = x <= 50
21+
22+tests : Test
23+tests =
24+ let
25+ filterTests = suite "filter Tests" [test "Simple filter" <| assertEqual setPart1 <| Set.filter pred set]
26+ partitionTests = suite "partition Tests" [test "Simple partition" <| assertEqual (setPart1, setPart2) <| Set.partition pred set]
27+ in suite "Set Tests" [partitionTests, filterTests]
tests/elm/Test/String.elmnew file+37
@@ -0,0 +1,37 @@
1+module Test.String (tests) where
2+
3+import List
4+import String (..)
5+
6+import ElmTest.Assertion (..)
7+import ElmTest.Test (..)
8+
9+tests : Test
10+tests =
11+ let simpleTests = suite "Simple Stuff"
12+ [ test "is empty" <| assert (isEmpty "")
13+ , test "is not empty" <| assert (not (isEmpty ("the world")))
14+ , test "length" <| assertEqual 11 (length "innumerable")
15+ , test "endsWith" (assert <| endsWith "ship" "spaceship")
16+ , test "reverse" <| assertEqual "desserts" (reverse "stressed")
17+ , test "repeat" <| assertEqual "hahaha" (repeat 3 "ha")
18+ ]
19+
20+ combiningTests = suite "Combining Strings"
21+ [ test "uncons non-empty" <| assertEqual (Just ('a',"bc")) (uncons "abc")
22+ , test "uncons empty" <| assertEqual Nothing (uncons "")
23+ , test "append 1" <| assertEqual "butterfly" (append "butter" "fly")
24+ , test "append 2" <| assertEqual "butter" (append "butter" "")
25+ , test "append 3" <| assertEqual "butter" (append "" "butter")
26+ , test "concat" <| assertEqual "nevertheless" (concat ["never","the","less"])
27+ , test "split commas" <| assertEqual ["cat","dog","cow"] (split "," "cat,dog,cow")
28+ , test "split slashes"<| assertEqual ["home","steve","Desktop", ""] (split "/" "home/steve/Desktop/")
29+ , test "join spaces" <| assertEqual "cat dog cow" (join " " ["cat","dog","cow"])
30+ , test "join slashes" <| assertEqual "home/steve/Desktop" (join "/" ["home","steve","Desktop"])
31+ , test "slice 1" <| assertEqual "c" (slice 2 3 "abcd")
32+ , test "slice 2" <| assertEqual "abc" (slice 0 3 "abcd")
33+ , test "slice 3" <| assertEqual "abc" (slice 0 -1 "abcd")
34+ , test "slice 4" <| assertEqual "cd" (slice -2 4 "abcd")
35+ ]
36+ in
37+ suite "String" [ simpleTests, combiningTests ]
tests/elm/Test/Trampoline.elmnew file+29
@@ -0,0 +1,29 @@
1+module Test.Trampoline (tests) where
2+
3+import Trampoline (..)
4+
5+import ElmTest.Assertion (..)
6+import ElmTest.Test (..)
7+
8+badSum : Int -> Int
9+badSum n =
10+ let loop x acc =
11+ case x of
12+ 0 -> acc
13+ _ -> loop (x-1) (acc+x)
14+ in loop n 0
15+
16+goodSum : Int -> Int
17+goodSum n =
18+ let sumT x acc =
19+ case x of
20+ 0 -> Done acc
21+ _ -> Continue (\_ -> sumT (x-1) (acc+x))
22+ in trampoline <| sumT n 0
23+
24+tests : Test
25+tests =
26+ let mkLoopCheck n = test ("Equivalent Loop Check #"++ show n) (assertEqual (badSum n) (goodSum n))
27+ loopChecks = suite "Equivalent to untrampolined Tests" <| map mkLoopCheck [0..25]
28+ noStackOverflow = test "Trampoline Deep Recursion Test" (assertEqual 500000500000 (goodSum 1000000))
29+ in suite "Trampoline Tests" [noStackOverflow, loopChecks]
tests/Main.hs → tests/hs/CompilerTest.hsrenamed

The content is the same.

tests/hs/LibTest.hsnew file+30
@@ -0,0 +1,30 @@
1+module Main where
2+
3+import Control.Monad (unless)
4+import Data.List (isInfixOf)
5+import System.Directory
6+import System.Exit
7+import System.FilePath
8+import System.Process
9+
10+import Elm.Internal.Paths as Elm
11+
12+main :: IO ()
13+main = do
14+ top <- getCurrentDirectory
15+ let ioScript s = top</>"IO"</>s
16+ runCmd "git submodule update --init"
17+ out <- readProcess "npm" ["ls", "--parseable"] ""
18+ unless ("jsdom" `isInfixOf` out) $ runCmd "npm install jsdom"
19+ setCurrentDirectory $ top</>"tests"</>"elm"
20+ runCmd $ concat [top</>"dist"</>"build"</>"elm"</>"elm --make --only-js --src-dir=" , top</>"automaton", " --src-dir=", top</>"IO", " --src-dir=", top</>"Elm-Test", " Test.elm"]
21+ runCmd $ unwords ["cat ", ioScript "prescript.js", Elm.runtime, "build"</>"Test.js", ioScript "handler.js", "> exe.js"]
22+ exitWith =<< waitForProcess =<< (runCommand "node exe.js")
23+ where runCmd cmd = do
24+ putStrLn cmd
25+ exitCode <- waitForProcess =<< runCommand cmd
26+ case exitCode of
27+ ExitSuccess -> return ()
28+ ExitFailure _ -> error "something went wrong"
29+
30+
tests/Tests/Compiler.hs → tests/hs/Tests/Compiler.hsrenamed

The content is the same.

tests/Tests/Property.hs → tests/hs/Tests/Property.hsrenamed

The content is the same.

tests/Tests/Property/Arbitrary.hs → tests/hs/Tests/Property/Arbitrary.hsrenamed

The content is the same.

tests/test-files/bad/BBTArgs → tests/hs/test-files/bad/BBTArgsrenamed

The content is the same.

tests/test-files/bad/InfiniteType.elm → tests/hs/test-files/bad/InfiniteType.elmrenamed

The content is the same.

tests/test-files/bad/NonElementMain.elm → tests/hs/test-files/bad/NonElementMain.elmrenamed

The content is the same.

tests/test-files/bad/Strings/ExtraClose.elm → tests/hs/test-files/bad/Strings/ExtraClose.elmrenamed

The content is the same.

tests/test-files/good/AliasSubstitution.elm → tests/hs/test-files/good/AliasSubstitution.elmrenamed

The content is the same.

tests/test-files/good/NoExpressions.elm → tests/hs/test-files/good/NoExpressions.elmrenamed

The content is the same.

tests/test-files/good/Otherwise.elm → tests/hs/test-files/good/Otherwise.elmrenamed

The content is the same.

tests/test-files/good/Ports.elm → tests/hs/test-files/good/Ports.elmrenamed

The content is the same.

tests/test-files/good/QuotesAndComments.elm → tests/hs/test-files/good/QuotesAndComments.elmrenamed

The content is the same.

tests/test-files/good/Soundness/Apply.elm → tests/hs/test-files/good/Soundness/Apply.elmrenamed

The content is the same.

tests/test-files/good/Soundness/ApplyAnnotated.elm → tests/hs/test-files/good/Soundness/ApplyAnnotated.elmrenamed

The content is the same.

tests/test-files/good/Soundness/Id.elm → tests/hs/test-files/good/Soundness/Id.elmrenamed

The content is the same.

tests/test-files/good/Soundness/IdAnnotated.elm → tests/hs/test-files/good/Soundness/IdAnnotated.elmrenamed

The content is the same.

tests/test-files/good/Soundness/TrickyId.elm → tests/hs/test-files/good/Soundness/TrickyId.elmrenamed

The content is the same.

tests/test-files/good/Soundness/TrickyIdAnnotated.elm → tests/hs/test-files/good/Soundness/TrickyIdAnnotated.elmrenamed

The content is the same.

tests/test-files/good/Strings/Multiline.elm → tests/hs/test-files/good/Strings/Multiline.elmrenamed

The content is the same.

tests/test-files/good/Strings/MultilineNormal.elm → tests/hs/test-files/good/Strings/MultilineNormal.elmrenamed

The content is the same.

tests/test-files/good/Unify/LockedVars.elm → tests/hs/test-files/good/Unify/LockedVars.elmrenamed

The content is the same.

tests/test-files/good/Unify/NonHomogeneousRecords.elm → tests/hs/test-files/good/Unify/NonHomogeneousRecords.elmrenamed

The content is the same.