on master help sign in
Merge branch 'master' into canonicalize
commitab175214fe22e3aaa6f0b29cfd0dce7246c1988a authorEvan Czaplicki <info@elm-lang.org> dateFri 25 Apr 2014, 03:52 (13 years ago) parenta159f20729da57
7 files changed+120−60
libraries/List.elm+18−14 libraries/Native/Array.js+26−21 libraries/Native/Utils.js+21−14 tests/elm/Test.elm+6−4 tests/elm/Test/List.elm+38 tests/elm/Test/Set.elm+6−5 tests/hs/LibTest.hs+5−2
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+26−21
@@ -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) {
@@ -533,10 +540,8 @@ Elm.Native.Array.make = function(elm) {
533540 // Calculates in which slot of "table" the item probably is, then
534541 // find the exact slot via forward searching in "lengths". Returns the index.
535542 function getSlot(i, a) {
536− var slot = Math.floor(i / (Math.pow(M, a.height)));
537− while (a.lengths[slot] <= i) {
538− slot++
539− }
543+ var slot = i >> (5 * a.height);
544+ while (a.lengths[slot - 1] > i) { slot--; }
540545 return slot;
541546 }
542547
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
tests/elm/Test.elm+6−4
@@ -9,13 +9,15 @@ 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−
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+
1719tests : [Test]
18−tests = String.tests ++ Trampoline.tests ++ Array.tests ++ Dict.tests
20+tests = String.tests ++ Trampoline.tests ++ Array.tests ++ Dict.tests ++ Set.tests ++ List.tests
1921
2022console : IO ()
2123console = runDisplay tests
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 [ 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 = [
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 = [
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 List.concat [partitionTests, unzipTests, intersperseTests]
tests/elm/Test/Set.elm+6−5
@@ -1,18 +1,19 @@
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
@@ -21,6 +22,6 @@ pred x = x <= 50
2122tests : [Test]
2223tests =
2324 let
24− filterTests = [assertEqual setPart1 <| filter pred set]
25− partitionTests = [assertEqual (setPart1, setPart2) <| partition pred set]
25+ filterTests = [test "Simple filter" <| assertEqual setPart1 <| Set.filter pred set]
26+ partitionTests = [test "Simple partition" <| assertEqual (setPart1, setPart2) <| Set.partition pred set]
2627 in List.concat [partitionTests, filterTests]
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"]