on master help sign in
Merge remote-tracking branch 'elm-lang/webgl' into webgl
commit99c11393ae0ad01fd199dc047b7715c61589f791 authorJohn P Mayer Jr <john.p.mayer.jr@gmail.com> dateFri 2 May 2014, 00:54 (13 years ago) parent2d75c39b080f8d
27 files changed+402−216
Elm-Test+1−1 Elm.cabal+8−5 automaton+1−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+15−8 compiler/Type/ExtraChecks.hs+2−3 compiler/Type/Unify.hs+5−1 libraries/Array.elm+31−22 libraries/Dict.elm+20−20 libraries/List.elm+18−14 libraries/Native/Array.js+72−27 libraries/Native/Error.js+2−4 libraries/Native/String.js+2−2 libraries/Native/Utils.js+21−14 libraries/String.elm+8−8 libraries/elm_dependencies.json+6−5 tests/elm/Test.elm+13−5 tests/elm/Test/Array.elm+37−29 tests/elm/Test/Dict.elm+5−5 tests/elm/Test/List.elm+38 tests/elm/Test/Set.elm+8−7 tests/elm/Test/String.elm+28−17 tests/elm/Test/Trampoline.elm+3−3 tests/hs/LibTest.hs+5−2
Elm-Test+1−1

Submodule changed.

Elm.cabal+8−5
@@ -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,6 +95,7 @@ Library
9595 Paths_Elm
9696
9797 Build-depends: aeson,
98+ aeson-pretty,
9899 base >=4.2 && <5,
99100 binary >= 0.7.0.0,
100101 blaze-html >= 0.5 && < 0.8,
@@ -178,6 +179,7 @@ Executable elm
178179 Paths_Elm
179180
180181 Build-depends: aeson,
182+ aeson-pretty,
181183 base >=4.2 && <5,
182184 binary >= 0.7.0.0,
183185 blaze-html >= 0.5 && < 0.8,
@@ -255,10 +257,11 @@ Test-Suite compiler-tests
255257 HUnit,
256258 QuickCheck >= 2 && < 3,
257259 aeson,
260+ aeson-pretty,
258261 base >=4.2 && <5,
259262 binary >= 0.7.0.0,
260− blaze-html == 0.5.* || == 0.6.*,
261− blaze-markup == 0.5.1.*,
263+ blaze-html,
264+ blaze-markup,
262265 bytestring,
263266 cmdargs,
264267 containers >= 0.3,
@@ -286,4 +289,4 @@ Test-Suite lib-tests
286289 directory,
287290 Elm,
288291 filepath,
289− process >= 1.2
292+ process
automaton+1−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+15−8
@@ -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+31−22
@@ -11,10 +11,10 @@ reads, updates, and appends.
1111@docs length, push, append
1212
1313# Get and Set
14−@docs get, getSafe, getUnsafe, set
14+@docs get, getOrElse, getOrFail, set
1515
1616# Taking Arrays Apart
17−@docs toList, toIndexedList, slice
17+@docs slice, toList, toIndexedList
1818
1919# Mapping and Folding
2020@docs map, indexedMap, foldl, foldr
@@ -122,20 +122,21 @@ push = Native.Array.push
122122
123123{-| Get the element at a particular index.
124124
125− getUnsafe 2 (A.fromList [3,2,1]) == 1
125+ getOrFail 0 (A.fromList [0,1,2]) == 0
126126
127127Warning: this function will result in a runtime error if the index is not found,
128−so it is best to use `get` or `getSafe` unless you are very confident the index
129−will be found.
128+so it is best to use `get` or `getOrElse` unless you are sure the index will be
129+found.
130130-}
131−getUnsafe : Int -> Array a -> a
132−getUnsafe = Native.Array.get
131+getOrFail : Int -> Array a -> a
132+getOrFail = Native.Array.get
133133
134134{-| Return Just the element at the index or Nothing if the index is out of range.
135135
136− get 2 (fromList [3,2,1]) == Just 2
137− get 5 (fromList [3,2,1]) == Nothing
138− get -1 (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
139140-}
140141get : Int -> Array a -> Maybe a
141142get i array =
@@ -143,14 +144,14 @@ get i array =
143144 then Just (Native.Array.get i array)
144145 else Nothing
145146
146−{-| Get the element at the index. If the index is out of range, the given default
147−element is returned.
147+{-| Get the element at the index. Or if the index is out of range, a default
148+value is returned.
148149
149− getSafe 0 2 (fromList [3,2,1]) == 1
150− getSafe 0 5 (fromList [3,2,1]) == 0
150+ getOrElse 0 2 (fromList [0,1,2]) == 2
151+ getOrElse 0 5 (fromList [0,1,2]) == 0
151152-}
152−getSafe : a -> Int -> Array a -> a
153−getSafe default i array =
153+getOrElse : a -> Int -> Array a -> a
154+getOrElse default i array =
154155 if 0 <= i && i < Native.Array.length array
155156 then Native.Array.get i array
156157 else default
@@ -163,13 +164,21 @@ If the index is out of range, the array is unaltered.
163164set : Int -> a -> Array a -> Array a
164165set = Native.Array.set
165166
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. You can select from the end by giving a negative Int.
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`.
169171
170− slice 1 2 (fromList [0,1,2,3,4]) == fromList [1,2]
171− slice 1 -2 (fromList [0,1,2,3,4]) == fromList [1,2,3]
172− slice -3 -2 (fromList [0,1,2,3,4]) == fromList [2,3]
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.
177+
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]
180+
181+This makes it pretty easy to `pop` the last element off of an array: `slice 0 -1 array`
173182-}
174183slice : Int -> Int -> Array a -> Array a
175184slice = Native.Array.slice
libraries/Dict.elm+20−20
@@ -1,5 +1,5 @@
11module Dict (empty,singleton,insert,update
2− ,get,getSafe,getUnsafe
2+ ,get,getOrElse,getOrFail
33 ,remove,member
44 ,filter
55 ,partition
@@ -19,7 +19,7 @@ Insert, remove, and query operations all take *O(log n)* time.
1919@docs empty, singleton, insert, update, remove
2020
2121# Query
22−@docs member, get, getMaybe, getWithDefault
22+@docs member, get, getOrElse, getOrFail
2323
2424# Combine
2525@docs union, intersect, diff
@@ -96,7 +96,7 @@ dictionary.
9696 get "Mouse" animals == Just Mouse
9797 get "Spike" animals == Nothing
9898
99−The `getSafe` and `getUnsafe` are built-in ways to handle common ways of
99+The `getOrElse` and `getOrFail` are built-in ways to handle common ways of
100100using the resulting `Maybe`.
101101-}
102102get : comparable -> Dict comparable v -> Maybe v
@@ -114,41 +114,41 @@ return a default value.
114114
115115 animals = fromList [ ("Tom", Cat), ("Jerry", Mouse) ]
116116
117− getSafe Dog "Tom" animals == Cat
118− getSafe Dog "Mouse" animals == Mouse
119− getSafe Dog "Spike" animals == Dog
117+ getOrElse Dog "Tom" animals == Cat
118+ getOrElse Dog "Mouse" animals == Mouse
119+ getOrElse Dog "Spike" animals == Dog
120120-}
121−getSafe : v -> comparable -> Dict comparable v -> v
122−getSafe base k t =
121+getOrElse : v -> comparable -> Dict comparable v -> v
122+getOrElse base k t =
123123 case t of
124124 RBEmpty LBlack -> base
125125 RBNode _ k' v l r ->
126126 case Native.Utils.compare k k' of
127− LT -> getSafe base k l
127+ LT -> getOrElse base k l
128128 EQ -> v
129− GT -> getSafe base k r
129+ GT -> getOrElse base k r
130130
131131{-| Get the value associated with a key.
132132
133133 animals = fromList [ ("Tom", Cat), ("Jerry", Mouse) ]
134134
135− get "Tom" animals == Cat
136− get "Mouse" animals == Mouse
137− get "Spike" animals == -- Runtime Error!
135+ getOrFail "Tom" animals == Cat
136+ getOrFail "Mouse" animals == Mouse
137+ getOrFail "Spike" animals == -- Runtime Error!
138138
139139Warning: this function will result in a runtime error if the key is not found,
140−so it is best to use `get` or `getSafe` unless you are very confident the key
141−will be found.
140+so it is best to use `get` or `getOrElse` unless you are sure the key will be
141+found.
142142-}
143−getUnsafe : comparable -> Dict comparable v -> v
144−getUnsafe k t =
143+getOrFail : comparable -> Dict comparable v -> v
144+getOrFail k t =
145145 case t of
146− RBEmpty LBlack -> Native.Error.raise "key not found when using 'getUnsafe'"
146+ RBEmpty LBlack -> Native.Error.raise "key not found when using 'getOrFail'"
147147 RBNode _ k' v l r ->
148148 case Native.Utils.compare k k' of
149− LT -> getUnsafe k l
149+ LT -> getOrFail k l
150150 EQ -> v
151− GT -> getUnsafe k r
151+ GT -> getOrFail k r
152152
153153{-| Determine if a key is in a dictionary. -}
154154member : comparable -> Dict comparable v -> Bool
libraries/List.elm+18−14
@@ -171,11 +171,11 @@ not.
171171 partition isEven [0..5] == ([0,2,4], [1,3,5])
172172-}
173173partition : (a -> Bool) -> [a] -> ([a],[a])
174−partition pred lst =
175− case lst of
176− [] -> ([],[])
177− x::xs -> let (bs,cs) = partition pred xs in
178− 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 ([],[])
179179
180180{-| Combine two lists, combining them into tuples pairwise.
181181If one list is longer, the extra elements are dropped.
@@ -194,12 +194,14 @@ If one list is longer, the extra elements are dropped.
194194zipWith : (a -> b -> c) -> [a] -> [b] -> [c]
195195zipWith = Native.List.zipWith
196196
197−{-| 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+-}
198201unzip : [(a,b)] -> ([a],[b])
199−unzip pairs =
200− case pairs of
201− [] -> ([],[])
202− (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 ([], [])
203205
204206{-| Places the given value between all of the lists in the second
205207argument and concatenates the result.
@@ -215,10 +217,12 @@ join = Native.List.join
215217-}
216218intersperse : a -> [a] -> [a]
217219intersperse sep xs =
218− case xs of
219− a::b::cs -> a :: sep :: intersperse sep (b::cs)
220− [a] -> [a]
221− [] -> []
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
222226
223227{-| Take the first n members of a list: `(take 2 [1,2,3,4] == [1,2])` -}
224228take : Int -> [a] -> [a]
libraries/Native/Array.js+72−27
@@ -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,7 +24,6 @@ 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.
2827 function get(i, array) {
2928 if (i < 0 || i >= length(array)) {
3029 throw new Error("Index " + i + " is out of range. Check the length of " +
@@ -34,31 +33,39 @@ Elm.Native.Array.make = function(elm) {
3433 }
3534
3635 function unsafeGet(i, array) {
37− if (array.height == 0) {
38− return array.table[i];
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];
3941 }
40− var slot = getSlot(i, array);
41− var offset = slot > 0 ? array.lengths[slot-1] : 0;
42− return unsafeGet(i - offset, array.table[slot]);
42+ array = array.table[slot];
43+ }
44+ return array.table[i];
4345 }
4446
4547 // Sets the value at the index i. Only the nodes leading to i will get
4648 // copied and updated.
47− function set(i, item, a) {
48− if (length(a) <= i) {
49− return a;
49+ function set(i, item, array) {
50+ if (i < 0 || length(array) <= i) {
51+ return array;
5052 }
51− var newA = nodeCopy(a);
52− newA.table = a.table.slice();
53+ return unsafeSet(i, item, array);
54+ }
5355
54− if (a.height == 0) {
55− 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;
5661 } else {
57− var slot = getSlot(i, a);
58− var sub = slot > 0 ? a.lengths[slot-1] : 0;
59− 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]);
6067 }
61− return newA;
68+ return array;
6269 }
6370
6471 function initialize(len, f) {
@@ -255,9 +262,6 @@ Elm.Native.Array.make = function(elm) {
255262 return b;
256263 }
257264
258− // Returns a sliced tree. "to" is inclusive, but this may change,
259− // when I understand, why e.g. JS does not handle it this way. :-)
260− // If "from" or "to" is negative, they will select from the end on.
261265 // TODO: currently, it slices the right, then the left. This can be
262266 // optimized.
263267 function slice(from, to, a) {
@@ -274,7 +278,7 @@ Elm.Native.Array.make = function(elm) {
274278 // Handle leaf level.
275279 if (a.height == 0) {
276280 var newA = { ctor:"_Array", height:0 };
277− newA.table = a.table.slice(0, to + 1);
281+ newA.table = a.table.slice(0, to);
278282 return newA;
279283 }
280284
@@ -533,10 +537,8 @@ Elm.Native.Array.make = function(elm) {
533537 // Calculates in which slot of "table" the item probably is, then
534538 // find the exact slot via forward searching in "lengths". Returns the index.
535539 function getSlot(i, a) {
536− var slot = Math.floor(i / (Math.pow(M, a.height)));
537− while (a.lengths[slot] <= i) {
538− slot++
539− }
540+ var slot = i >> (5 * a.height);
541+ while (a.lengths[slot - 1] > i) { slot--; }
540542 return slot;
541543 }
542544
@@ -571,6 +573,46 @@ Elm.Native.Array.make = function(elm) {
571573 , lengths:[length(a), length(a) + length(b)] };
572574 }
573575
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+
574616 Elm.Native.Array.values = {
575617 empty:empty,
576618 fromList:fromList,
@@ -585,7 +627,10 @@ Elm.Native.Array.make = function(elm) {
585627 indexedMap:F2(indexedMap),
586628 foldl:F3(foldl),
587629 foldr:F3(foldr),
588− length:length
630+ length:length,
631+
632+ toJSArray:toJSArray,
633+ fromJSArray:fromJSArray
589634 };
590635
591636 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/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/Utils.js+21−14
@@ -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;
19− }
20− if (typeof x === 'function') {
21− throw new Error('Equality error: general function equality is ' +
22− 'undecidable, and therefore, unsupported');
2330 }
24− return x === y;
31+ return true;
2532 }
2633
2734 // code in Generate/JavaScript.hs depends on the particular
libraries/String.elm+8−8
@@ -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
@@ -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"
tests/elm/Test.elm+13−5
@@ -9,13 +9,21 @@ import IO.IO (..)
99import IO.Runner (Request, Response)
1010import IO.Runner as Run
1111
12−import Test.String as String
13−import Test.Trampoline as Trampoline
1412import Test.Array as Array
1513import Test.Dict as Dict
16−
17−tests : [Test]
18−tests = String.tests ++ Trampoline.tests ++ Array.tests ++ Dict.tests
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+ ]
1927
2028console : IO ()
2129console = runDisplay tests
tests/elm/Test/Array.elm+37−29
@@ -2,13 +2,14 @@ module Test.Array (tests) where
22
33import List
44import Array
5+import Native.Array
56
67import ElmTest.Assertion (..)
78import ElmTest.Test (..)
89
9−tests : [Test]
10+tests : Test
1011tests =
11− let creationTests =
12+ let creationTests = suite "Creation"
1213 [ test "empty" <| assertEqual Array.empty (Array.fromList [])
1314 , test "initialize" <| assertEqual (Array.initialize 4 id) (Array.fromList [0,1,2,3])
1415 , test "initialize 2" <| assertEqual (Array.initialize 4 (\n -> n*n)) (Array.fromList [0,1,4,9])
@@ -20,35 +21,42 @@ tests =
2021 , test "repeat 3" <| assertEqual (Array.repeat 3 "cat") (Array.fromList ["cat","cat","cat"])
2122 , test "fromList" <| assertEqual (Array.fromList []) Array.empty
2223 ]
23− basicsTests =
24− [ test "length" <| assertEqual (Array.length (Array.fromList [1,2,3])) 3
25− , test "length - Long" <| assertEqual (Array.length (Array.repeat 10000 0)) 10000
26− , test "push" <| assertEqual (Array.push 3 (Array.fromList [1,2])) (Array.fromList [1,2,3])
27− , test "append" <| assertEqual (Array.toList <| Array.append (Array.repeat 2 42) (Array.repeat 3 81)) ([42,42,81,81,81])
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)))
2829 ]
29− getAndSetTests =
30− [ test "get" <| assertEqual (Array.get 1 (Array.fromList [3,2,1])) (Just 2)
31− , test "get 2" <| assertEqual (Array.get 5 (Array.fromList [3,2,1])) Nothing
32− , test "get 3" <| assertEqual (Array.get -1 (Array.fromList [3,2,1])) Nothing
33− , test "getSafe 1" <| assertEqual (Array.getSafe 0 2 (Array.fromList [3,2,1])) 1
34− , test "getSafe 2" <| assertEqual (Array.getSafe 0 5 (Array.fromList [3,2,1])) 0
35− , test "getUnsafe" <| assertEqual (Array.getUnsafe 2 (Array.fromList [3,2,1])) 1
36− , test "set" <| assertEqual (Array.set 1 7 (Array.fromList [1,2,3])) (Array.fromList [1,7,3])
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]))
3738 ]
38− takingArraysApartTests =
39− [ test "toList" <| assertEqual (Array.toList (Array.fromList [3,5,8])) [3,5,8]
40− , test "toIndexedList" <| assertEqual (Array.toIndexedList (Array.fromList ["cat","dog"])) [(0,"cat"), (1,"dog")]
41− , test "slice" <| assertEqual (Array.slice 1 2 (Array.fromList [0,1,2,3,4])) (Array.fromList [1,2])
42− , test "slice 2" <| assertEqual (Array.slice 1 -2 (Array.fromList [0,1,2,3,4])) (Array.fromList [1,2,3])
43− , test "slice 3" <| assertEqual (Array.slice -3 -2 (Array.fromList [0,1,2,3,4])) (Array.fromList [2,3])
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]))
4446 ]
45− mappingAndFoldingTests =
46− [ test "map" <| assertEqual (Array.map sqrt (Array.fromList [1,4,9])) (Array.fromList [1,2,3])
47− , test "indexedMap" <| assertEqual (Array.indexedMap (*) (Array.fromList [5,5,5])) (Array.fromList [0,5,10])
48− , test "foldl" <| assertEqual (Array.foldl (::) [] (Array.fromList [1,2,3])) [3,2,1]
49− , test "foldr" <| assertEqual (Array.foldr (+) 0 (Array.repeat 3 5)) 15
50− , test "foldr 2" <| assertEqual (Array.foldr (::) [] (Array.fromList [1,2,3])) [1,2,3]
51− , test "filter" <| assertEqual (Array.filter (\x -> x `mod` 2 == 0) (Array.fromList [1..6])) (Array.fromList [2,4,6])
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])))
5257 ]
5358 in
54− List.concat [creationTests, basicsTests, getAndSetTests, takingArraysApartTests, mappingAndFoldingTests]
59+ suite "Array"
60+ [ creationTests, basicsTests, getAndSetTests
61+ , takingArraysApartTests, mappingAndFoldingTests, nativeTests
62+ ]
tests/elm/Test/Dict.elm+5−5
@@ -9,18 +9,18 @@ import ElmTest.Test (..)
99animals : Dict.Dict String String
1010animals = Dict.fromList [ ("Tom", "cat"), ("Jerry", "mouse") ]
1111
12−tests : [Test]
12+tests : Test
1313tests =
1414 let getTests =
1515 [ test "get 1" <| assertEqual (Just "cat") (Dict.get "Tom" animals)
1616 , test "get 2" <| assertEqual Nothing (Dict.get "Spike" animals)
17− , test "getSafe 1" <| assertEqual "mouse" (Dict.getSafe "dog" "Jerry" animals)
18− , test "getSafe 2" <| assertEqual "dog" (Dict.getSafe "dog" "Spike" animals)
19− , test "getUnsafe" <| assertEqual "cat" (Dict.getUnsafe "Tom" 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)
2020 ]
2121 filterTests =
2222 [ test "filter" <| assertEqual (Dict.singleton "Tom" "cat") (Dict.filter (\k v -> k == "Tom") animals)
2323 , test "partition" <| assertEqual (Dict.singleton "Tom" "cat", Dict.singleton "Jerry" "mouse") (Dict.partition (\k v -> k == "Tom") animals)
2424 ]
2525 in
26− List.concat [ getTests, filterTests ]
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.elm+8−7
@@ -1,26 +1,27 @@
11module Test.Set (tests) where
22
33import Set
4+import Set (Set)
45import List
56
67import ElmTest.Assertion (..)
78import ElmTest.Test (..)
89
9−set : Set
10+set : Set Int
1011set = Set.fromList [1..100]
1112
12−setPart1 : Set
13+setPart1 : Set Int
1314setPart1 = Set.fromList [1..50]
1415
15−setPart2 : Set
16+setPart2 : Set Int
1617setPart2 = Set.fromList [51..100]
1718
1819pred : Int -> Bool
1920pred x = x <= 50
2021
21−tests : [Test]
22+tests : Test
2223tests =
2324 let
24− filterTests = [assertEqual setPart1 <| filter pred set]
25− partitionTests = [assertEqual (setPart1, setPart2) <| partition pred set]
26− in List.concat [partitionTests, filterTests]
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.elm+28−17
@@ -6,21 +6,32 @@ import String (..)
66import ElmTest.Assertion (..)
77import ElmTest.Test (..)
88
9−tests : [Test]
9+tests : Test
1010tests =
11− let isEmptyTests = [test "empty is empty" <| assert <| isEmpty "",
12− test "not empty" <| assert <| not . isEmpty <| "the world"]
13− lengthTest = test "length of innumerable" <| assertEqual 11 (length "innumerable")
14− reverseTest = test "reverse test" <| assertEqual "desserts" (reverse "stressed")
15− repeatTest = test "repeat test" <| assertEqual "hahaha" (repeat 3 "ha")
16− unconsTests = [test "nonempty uncons" <| assertEqual (Just ('a',"bc")) (uncons "abc"),
17− test "empty uncons" <| assertEqual Nothing (uncons "")]
18− appendTest = test "append test" <| assertEqual "butterfly" (append "butter" "fly")
19− concatTest = test "concat test" <| assertEqual "nevertheless" (concat ["never","the","less"])
20− splitTests = [test "split commas" <| assertEqual ["cat","dog","cow"] (split "," "cat,dog,cow"),
21− test "split slashes"<| assertEqual ["home","evan","Desktop", ""] (split "/" "home/evan/Desktop/")]
22− joinTests = [test "join spaces" <| assertEqual "cat dog cow" (join " " ["cat","dog","cow"]),
23− test "join slashes" <| assertEqual "home/evan/Desktop" (join "/" ["home","evan","Desktop"])]
24−
25− endsWithTest = test "endsWith Check" (assert <| endsWith "h" "th")
26− in List.concat [isEmptyTests, [lengthTest, reverseTest, repeatTest], unconsTests, [appendTest, concatTest], splitTests, joinTests, [endsWithTest]]
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.elm+3−3
@@ -21,9 +21,9 @@ goodSum n =
2121 _ -> Continue (\_ -> sumT (x-1) (acc+x))
2222 in trampoline <| sumT n 0
2323
24−tests : [Test]
24+tests : Test
2525tests =
2626 let mkLoopCheck n = test ("Equivalent Loop Check #"++ show n) (assertEqual (badSum n) (goodSum n))
27− loopChecks = map mkLoopCheck [0..25]
27+ loopChecks = suite "Equivalent to untrampolined Tests" <| map mkLoopCheck [0..25]
2828 noStackOverflow = test "Trampoline Deep Recursion Test" (assertEqual 500000500000 (goodSum 1000000))
29− in noStackOverflow :: loopChecks
29+ in suite "Trampoline Tests" [noStackOverflow, loopChecks]
tests/hs/LibTest.hs+5−2
@@ -1,5 +1,7 @@
11module Main where
22
3+import Control.Monad (unless)
4+import Data.List (isInfixOf)
35import System.Directory
46import System.Exit
57import System.FilePath
@@ -11,8 +13,9 @@ main :: IO ()
1113main = do
1214 top <- getCurrentDirectory
1315 let ioScript s = top</>"IO"</>s
14− runCmd "git submodule init"
15− runCmd "npm install jsdom"
16+ runCmd "git submodule update --init"
17+ out <- readProcess "npm" ["ls", "--parseable"] ""
18+ unless ("jsdom" `isInfixOf` out) $ runCmd "npm install jsdom"
1619 setCurrentDirectory $ top</>"tests"</>"elm"
1720 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"]
1821 runCmd $ unwords ["cat ", ioScript "prescript.js", Elm.runtime, "build"</>"Test.js", ioScript "handler.js", "> exe.js"]