on master help sign in
Fix the confusion with "Cons" and "Nil" in issue #176.

Also add the ExplicitList expression.

commit9a40249e05f076a75f99603d07e88de475d45b61 authorevancz <info@elm-lang.org> dateThu 20 Jun 2013, 21:25 (13 years ago) parent4a6032f
17 files changed+78−67
compiler/Generate/JavaScript.hs+9−3 compiler/Metadata/Libraries.hs+2−2 compiler/Parse/Expression.hs+1−2 compiler/SourceSyntax/Expression.hs+7−10 compiler/SourceSyntax/Pattern.hs+5−5 compiler/SourceSyntax/Rename.hs+2 compiler/Transform/Optimize.hs+4−4 compiler/Transform/Replace.hs+2−1 compiler/Types/Constrain.hs+6 compiler/Types/Solver.hs+2−2 compiler/Types/Types.hs+1−1 libraries/Native/JavaScript.js+1−1 libraries/Native/List.js+27−27 libraries/Native/Show.js+4−4 libraries/Native/Signal/Http.js+1−1 libraries/Native/Signal/Keyboard.js+1−1 libraries/Native/Utils.js+3−3
compiler/Generate/JavaScript.hs+9−3
@@ -29,7 +29,8 @@ internalImports =
2929 ("_N", "N.Utils(elm)"),
3030 ("_L", "N.List(elm)"),
3131 ("_E", "N.Error(elm)"),
32− ("_str", "N.JavaScript(elm).toString")
32+ ("_J", "N.JavaScript(elm)"),
33+ ("_str", "_J.toString")
3334 ]
3435
3536parens s = "(" ++ s ++ ")"
@@ -225,11 +226,16 @@ instance ToJS (Expr t v) where
225226
226227 App e1 e2 -> jsApp e1 e2
227228 Let defs e -> jsLet defs e
229+
230+ ExplicitList es ->
231+ do es' <- mapM toJS' es
232+ return $ "_J.toList" ++ parens (jsList es')
233+
228234 Data name es ->
229235 do fs <- mapM toJS' es
230236 return $ case name of
231− "Nil" -> jsNil
232− "Cons" -> jsCons (head fs) ((head . tail) fs)
237+ "[]" -> jsNil
238+ "::" -> jsCons (head fs) ((head . tail) fs)
233239 _ -> jsObj $ ("ctor:" ++ show name) : fields
234240 where fields = zipWith (\n e -> "_" ++ show n ++ ":" ++ e) [0..] fs
235241
compiler/Metadata/Libraries.hs+2−2
@@ -29,8 +29,8 @@ libraries =
2929 Ok libs -> Map.unionWith Map.union libs nilAndTuples
3030 where nilAndTuples = Map.singleton "Prelude" (Map.fromList pairs)
3131 pairs =
32− [ ("Cons", "a -> [a] -> [a]")
33− , ("Nil", "[a]")
32+ [ ("::", "a -> [a] -> [a]")
33+ , ("[]", "[a]")
3434 ] ++ map makeTuple (inits ['a'..'i'])
3535
3636 makeTuple cs =
compiler/Parse/Expression.hs+1−2
@@ -52,8 +52,7 @@ listTerm =
5252 <|> (braces $ choice
5353 [ try $ do { lo <- expr; whitespace; string ".." ; whitespace
5454 ; Range lo <$> expr }
55− , do (L _ _ e) <- list <$> commaSep expr
56− return e
55+ , ExplicitList <$> commaSep expr
5756 ])
5857
5958parensTerm :: IParser (LExpr t v)
compiler/SourceSyntax/Expression.hs+7−10
@@ -26,6 +26,7 @@ data Expr t v
2626 | MultiIf [(LExpr t v,LExpr t v)]
2727 | Let [Def t v] (LExpr t v)
2828 | Case (LExpr t v) [(Pattern.Pattern, LExpr t v)]
29+ | ExplicitList [LExpr t v]
2930 | Data String [LExpr t v]
3031 | Markdown Pandoc.Pandoc
3132 deriving (Eq, Data, Typeable)
@@ -36,12 +37,9 @@ data Def tipe var
3637 | TypeAnnotation String Type
3738 deriving (Eq, Data, Typeable)
3839
39−cons h t = Location.merge h t (Data "Cons" [h,t])
40−nil = Location.L (Just "[]") Location.NoSpan (Data "Nil" [])
41−list = foldr cons nil
4240tuple es = Data ("Tuple" ++ show (length es)) es
4341
44−delist (Location.L _ _ (Data "Cons" [h,t])) = h : delist t
42+delist (Location.L _ _ (Data "::" [h,t])) = h : delist t
4543delist _ = []
4644
4745
@@ -71,11 +69,10 @@ instance Show (Expr t v) where
7169 Var (c:cs) -> if Help.isOp c then Help.parens (c:cs) else c:cs
7270 Case e pats -> "case "++ show e ++" of " ++ Help.brkt (intercalate " ; " pats')
7371 where pats' = map (\(p,e) -> show p ++ " -> " ++ show e) pats
74− Data name es
75− | name == "Cons" -> ("["++) . (++"]") . intercalate "," . map show $
76− delist (Location.none $ Data "Cons" es)
77− | name == "Nil" -> "[]"
78− | otherwise -> name ++ " " ++ intercalate " " (map show' es)
72+ ExplicitList es -> "[" ++ intercalate "," (map show es) ++ "]"
73+ Data "::" [h,t] -> show h ++ " :: " ++ show t
74+ Data "[]" [] -> "[]"
75+ Data name es -> name ++ " " ++ intercalate " " (map show' es)
7976 Markdown _ -> "[markdown| ... |]"
8077
8178
@@ -99,5 +96,5 @@ needsParens e =
9996 MultiIf _ -> True
10097 Let _ _ -> True
10198 Case _ _ -> True
102− Data name (x:xs) -> name /= "Cons"
99+ Data name (x:xs) -> name /= "::"
103100 _ -> False
compiler/SourceSyntax/Pattern.hs+5−5
@@ -15,8 +15,8 @@ data Pattern = PData String [Pattern]
1515 | PLiteral Literal.Literal
1616 deriving (Eq, Data, Typeable)
1717
18−cons h t = PData "Cons" [h,t]
19−nil = PData "Nil" []
18+cons h t = PData "::" [h,t]
19+nil = PData "[]" []
2020list = foldr cons nil
2121tuple es = PData ("Tuple" ++ show (length es)) es
2222
@@ -29,10 +29,10 @@ instance Show Pattern where
2929 PRecord fs -> brkt (intercalate ", " fs)
3030 PAlias x p -> show p ++ " as " ++ x
3131 PAnything -> "_"
32− PData "Cons" [hd@(PData "Cons" _),tl] ->
32+ PData "::" [hd@(PData "::" _),tl] ->
3333 parens (show hd) ++ " :: " ++ show tl
34− PData "Cons" [hd,tl] -> show hd ++ " :: " ++ show tl
35− PData "Nil" [] -> "[]"
34+ PData "::" [hd,tl] -> show hd ++ " :: " ++ show tl
35+ PData "[]" [] -> "[]"
3636 PData name ps ->
3737 if take 5 name == "Tuple" && all isDigit (drop 5 name) then
3838 parens . intercalate ", " $ map show ps
compiler/SourceSyntax/Rename.hs+2
@@ -108,6 +108,8 @@ instance Rename (Expr t v) where
108108
109109 Data name es -> Data name `liftM` mapM rnm es
110110
111+ ExplicitList es -> ExplicitList `liftM` mapM rnm es
112+
111113 Case e cases -> Case `liftM` rnm e
112114 `ap` mapM (patternRename env) cases
113115
compiler/Transform/Optimize.hs+4−4
@@ -121,7 +121,7 @@ binop op ce1@(L t1 s1 e1) ce2@(L t2 s2 e2) =
121121 ("||", Literal (Boolean True), _) -> bool True
122122 ("||", Literal (Boolean False), _) -> e2
123123
124− ("::", _, _) -> let (L _ _ e) = cons ce1 ce2 in e
124+ ("::", _, _) -> Data "::" [ce1, ce2]
125125
126126 ("++", Literal (Str s1), Literal (Str s2)) -> str $ s1 ++ s2
127127 ("++", Literal (Str s1), Binop "++" (L _ _ (Literal (Str s2))) ce) ->
@@ -129,9 +129,9 @@ binop op ce1@(L t1 s1 e1) ce2@(L t2 s2 e2) =
129129 ("++", Binop "++" e (L _ _ (Literal (Str s1))), Literal (Str s2)) ->
130130 Binop "++" e (c1 . str $ s1 ++ s2)
131131
132− ("++", Data "Nil" [], _) -> e2
133− ("++", _, Data "Nil" []) -> e1
134− ("++", Data "Cons" [h,t], _) -> Data "Cons" [h, none $ binop "++" t ce2]
132+ ("++", Data "[]" [], _) -> e2
133+ ("++", _, Data "[]" []) -> e1
134+ ("++", Data "::" [h,t], _) -> Data "::" [h, none $ binop "++" t ce2]
135135
136136 ("|>", _, _) -> App ce2 ce1
137137 ("<|", _, _) -> App ce1 ce2
compiler/Transform/Replace.hs+2−1
@@ -20,6 +20,7 @@ replace y v expr =
2020 Let defs e -> if y `elem` vs then Let defs e else Let (zip vs (map f es)) (f e)
2121 where (vs,es) = unzip defs
2222 Var x -> if x == y then v else Var x
23+ ExplicitList es -> ExplicitList (map f es)
2324 Data name es -> Data name (map f es)
2425 Case e cases -> Case (f e) $ map (caseReplace y v) cases
2526 _ -> expr
@@ -52,7 +53,7 @@ depth' d expr =
5253 Fold e1 e2 e3 -> maximum [f e1, f e2, f e3]
5354 Async e -> f e
5455 Let defs e -> let (_,es) = unzip defs in maximum $ f e : map f es
55− Data "Cons" es -> maximum $ map (depth' d) es
56+ Data "::" es -> maximum $ map (depth' d) es
5657 Data name es -> maximum $ 1 : map f es
5758 Case e cases -> maximum $ f e : map (f . snd) cases
5859 _ -> d
compiler/Types/Constrain.hs+6
@@ -150,6 +150,12 @@ gen (L _ span expr) =
150150 in concat $ cs' : cs : css
151151 , head ts)
152152
153+ ExplicitList es ->
154+ do (ass,css,ts) <- unzip3 `liftM` mapM gen es
155+ t <- beta
156+ let cs = zipWith (\t' (L a b _) -> L a b (t :=: t')) ts es
157+ return ( unionsA ass, cs ++ concat css, listOf t )
158+
153159 Data name es ->
154160 gen $ foldl' (\f x -> merge f x $ App f x) (loc' $ Var name) es
155161
compiler/Types/Solver.hs+2−2
@@ -28,9 +28,9 @@ crush aliases forall@(Forall xs cs t) =
2828 return $ do ss' <- subs
2929 let ss = Map.toList ss'
3030 cs' = filter (not . isSolved ss) (subst ss cs)
31− f x = (unsafePerformIO $ do
31+ f x = x {-(unsafePerformIO $ do
3232 print forall >> putStrLn "-------"
33− print x >> putStrLn "~~~~~~~") `seq` x
33+ print x >> putStrLn "~~~~~~~") `seq` x-}
3434 return . f $ Forall xs cs' (subst ss t)
3535
3636schemeSubHelp txt span x s t1 rltn t2 = do
compiler/Types/Types.hs+1−1
@@ -71,7 +71,7 @@ parens = ("("++) . (++")")
7171instance Show Type where
7272 show t =
7373 let addParens (c:cs) =
74− if notElem ' ' cs || c == '(' then c:cs else parens (c:cs)
74+ if notElem ' ' cs || c == '(' || c == '{' then c:cs else parens (c:cs)
7575 in case t of
7676 LambdaT t1@(LambdaT _ _) t2 -> parens (show t1) ++ " -> " ++ show t2
7777 LambdaT t1 t2 -> show t1 ++ " -> " ++ show t2
libraries/Native/JavaScript.js+1−1
@@ -44,7 +44,7 @@ Elm.Native.JavaScript = function(elm) {
4444 }
4545 return obj;
4646 }
47− if (type === 'object' && (v.ctor === 'Cons' || v.ctor === 'Nil')) {
47+ if (type === 'object' && (v.ctor === '::' || v.ctor === '[]')) {
4848 var array = List.toArray(v);
4949 if (typeof array[0] === 'string') {
5050 array = array.join('');
libraries/Native/List.js+27−27
@@ -9,7 +9,7 @@ Elm.Native.List = function(elm) {
99 var Utils = Elm.Native.Utils(elm);
1010
1111 // TODO: Improve Nil handling
12− // We can change places like: if (xs.ctor === 'Nil') ... to if (xs === Nil) ...
12+ // We can change places like: if (xs.ctor === '[]') ... to if (xs === Nil) ...
1313 // but only if we're confident Nil can only be defined once.
1414 // Currently (27Mar2013) each module can have different instantiations, so multiple Nil objects can exist
1515 // (and if they're used interchangeably then direct object comparison fails where ctor doesn't).
@@ -17,11 +17,11 @@ Elm.Native.List = function(elm) {
1717 // The performance overhead of the .ctor calls is 5-10% according to jsperf (depending on fn + list size)
1818 // (on firefox 19)
1919
20− var Nil = { ctor:'Nil' };
20+ var Nil = { ctor:'[]' };
2121
2222 // using freeze for every cons would be nice but is a huge (9x on firefox 19)
2323 // performance penalty
24− function Cons(hd,tl) { return { ctor:"Cons", _0:hd, _1:tl }; }
24+ function Cons(hd,tl) { return { ctor:"::", _0:hd, _1:tl }; }
2525
2626 function throwError(f) {
2727 throw new Error("Function '" + f + "' expects a non-empty list!");
@@ -29,7 +29,7 @@ Elm.Native.List = function(elm) {
2929
3030 function toArray(xs) {
3131 var out = [];
32− while (xs.ctor !== 'Nil') {
32+ while (xs.ctor !== '[]') {
3333 out.push(xs._0);
3434 xs = xs._1;
3535 }
@@ -54,11 +54,11 @@ Elm.Native.List = function(elm) {
5454
5555 function append(xs,ys) {
5656 if (typeof xs === "string") { return xs.concat(ys); }
57− if (xs.ctor === 'Nil') { return ys; }
57+ if (xs.ctor === '[]') { return ys; }
5858 var root = Cons(xs._0, Nil);
5959 var curr = root;
6060 xs = xs._1;
61− while (xs.ctor !== 'Nil') {
61+ while (xs.ctor !== '[]') {
6262 curr._1 = Cons(xs._0, Nil);
6363 xs = xs._1;
6464 curr = curr._1;
@@ -67,13 +67,13 @@ Elm.Native.List = function(elm) {
6767 return root;
6868 }
6969
70− function head(v) { return v.ctor === 'Nil' ? throwError('head') : v._0; }
71− function tail(v) { return v.ctor === 'Nil' ? throwError('tail') : v._1; }
70+ function head(v) { return v.ctor === '[]' ? throwError('head') : v._0; }
71+ function tail(v) { return v.ctor === '[]' ? throwError('tail') : v._1; }
7272
7373 function last(xs) {
74− if (xs.ctor === 'Nil') { throwError('last'); }
74+ if (xs.ctor === '[]') { throwError('last'); }
7575 var out = xs._0;
76− while (xs.ctor !== 'Nil') {
76+ while (xs.ctor !== '[]') {
7777 out = xs._0;
7878 xs = xs._1;
7979 }
@@ -82,7 +82,7 @@ Elm.Native.List = function(elm) {
8282
8383 function map(f, xs) {
8484 var arr = [];
85− while (xs.ctor !== 'Nil') {
85+ while (xs.ctor !== '[]') {
8686 arr.push(f(xs._0));
8787 xs = xs._1;
8888 }
@@ -93,7 +93,7 @@ Elm.Native.List = function(elm) {
9393 // ie, foldl :: (a -> b -> b) -> b -> [a] -> b
9494 function foldl(f, b, xs) {
9595 var acc = b;
96− while (xs.ctor !== 'Nil') {
96+ while (xs.ctor !== '[]') {
9797 acc = A2(f, xs._0, acc);
9898 xs = xs._1;
9999 }
@@ -110,11 +110,11 @@ Elm.Native.List = function(elm) {
110110 }
111111
112112 function foldl1(f, xs) {
113− return xs.ctor === 'Nil' ? throwError('foldl1') : foldl(f, xs._0, xs._1);
113+ return xs.ctor === '[]' ? throwError('foldl1') : foldl(f, xs._0, xs._1);
114114 }
115115
116116 function foldr1(f, xs) {
117− if (xs.ctor === 'Nil') { throwError('foldr1'); }
117+ if (xs.ctor === '[]') { throwError('foldr1'); }
118118 var arr = toArray(xs);
119119 var acc = arr.pop();
120120 for (var i = arr.length; i--; ) {
@@ -134,12 +134,12 @@ Elm.Native.List = function(elm) {
134134 }
135135
136136 function scanl1(f, xs) {
137− return xs.ctor === 'Nil' ? throwError('scanl1') : scanl(f, xs._0, xs._1);
137+ return xs.ctor === '[]' ? throwError('scanl1') : scanl(f, xs._0, xs._1);
138138 }
139139
140140 function filter(pred, xs) {
141141 var arr = [];
142− while (xs.ctor !== 'Nil') {
142+ while (xs.ctor !== '[]') {
143143 if (pred(xs._0)) { arr.push(xs._0); }
144144 xs = xs._1;
145145 }
@@ -148,7 +148,7 @@ Elm.Native.List = function(elm) {
148148
149149 function length(xs) {
150150 var out = 0;
151− while (xs.ctor !== 'Nil') {
151+ while (xs.ctor !== '[]') {
152152 out += 1;
153153 xs = xs._1;
154154 }
@@ -156,7 +156,7 @@ Elm.Native.List = function(elm) {
156156 }
157157
158158 function member(x, xs) {
159− while (xs.ctor !== 'Nil') {
159+ while (xs.ctor !== '[]') {
160160 if (Utils.eq(x,xs._0)) return true;
161161 xs = xs._1;
162162 }
@@ -166,7 +166,7 @@ Elm.Native.List = function(elm) {
166166 function reverse(xs) { return fromArray(toArray(xs).reverse()); }
167167
168168 function concat(xss) {
169− if (xss.ctor === 'Nil') return xss;
169+ if (xss.ctor === '[]') return xss;
170170 var arr = toArray(xss);
171171 var xs = arr[arr.length-1];
172172 for (var i = arr.length-1; i--; ) {
@@ -176,7 +176,7 @@ Elm.Native.List = function(elm) {
176176 }
177177
178178 function all(pred, xs) {
179− while (xs.ctor !== 'Nil') {
179+ while (xs.ctor !== '[]') {
180180 if (!pred(xs._0)) return false;
181181 xs = xs._1;
182182 }
@@ -184,7 +184,7 @@ Elm.Native.List = function(elm) {
184184 }
185185
186186 function any(pred, xs) {
187− while (xs.ctor !== 'Nil') {
187+ while (xs.ctor !== '[]') {
188188 if (pred(xs._0)) return true;
189189 xs = xs._1;
190190 }
@@ -193,7 +193,7 @@ Elm.Native.List = function(elm) {
193193
194194 function zipWith(f, xs, ys) {
195195 var arr = [];
196− while (xs.ctor !== 'Nil' && ys.ctor !== 'Nil') {
196+ while (xs.ctor !== '[]' && ys.ctor !== '[]') {
197197 arr.push(A2(f, xs._0, ys._0));
198198 xs = xs._1;
199199 ys = ys._1;
@@ -203,7 +203,7 @@ Elm.Native.List = function(elm) {
203203
204204 function zip(xs, ys) {
205205 var arr = [];
206− while (xs.ctor !== 'Nil' && ys.ctor !== 'Nil') {
206+ while (xs.ctor !== '[]' && ys.ctor !== '[]') {
207207 arr.push(Utils.Tuple2(xs._0, ys._0));
208208 xs = xs._1;
209209 ys = ys._1;
@@ -221,7 +221,7 @@ Elm.Native.List = function(elm) {
221221
222222 function take(n, xs) {
223223 var arr = [];
224− while (xs.ctor !== 'Nil' && n > 0) {
224+ while (xs.ctor !== '[]' && n > 0) {
225225 arr.push(xs._0);
226226 xs = xs._1;
227227 --n;
@@ -230,7 +230,7 @@ Elm.Native.List = function(elm) {
230230 }
231231
232232 function drop(n, xs) {
233− while (xs.ctor !== 'Nil' && n > 0) {
233+ while (xs.ctor !== '[]' && n > 0) {
234234 xs = xs._1;
235235 --n;
236236 }
@@ -239,11 +239,11 @@ Elm.Native.List = function(elm) {
239239
240240 function join(sep, xss) {
241241 if (typeof sep === 'string') return toArray(xss).join(sep);
242− if (xss.ctor === 'Nil') return Nil;
242+ if (xss.ctor === '[]') return Nil;
243243 var s = toArray(sep);
244244 var out = toArray(xss._0);
245245 xss = xss._1;
246− while (xss.ctor !== 'Nil') {
246+ while (xss.ctor !== '[]') {
247247 out = out.concat(s, toArray(xss._0));
248248 xss = xss._1;
249249 }
libraries/Native/Show.js+4−4
@@ -44,7 +44,7 @@ Elm.Native.Show = function(elm) {
4444 output.push(toString(v[k]));
4545 }
4646 return "(" + output.join(",") + ")";
47− } else if (v.ctor === "Cons") {
47+ } else if (v.ctor === "::") {
4848 var isStr = typeof v._0 === "string",
4949 start = isStr ? '"' : "[",
5050 end = isStr ? '"' : "]",
@@ -52,18 +52,18 @@ Elm.Native.Show = function(elm) {
5252 f = !isStr ? toString : showChar;
5353 var output = start + f(v._0);
5454 v = v._1;
55− while (v.ctor === "Cons") {
55+ while (v.ctor === "::") {
5656 output += sep + f(v._0);
5757 v = v._1;
5858 }
5959 return output + end;
60− } else if (v.ctor === "Nil") {
60+ } else if (v.ctor === "[]") {
6161 return "[]";
6262 } else if (v.ctor === "RBNode" || v.ctor === "RBEmpty") {
6363 var cons = F3(function(k,v,acc){return NList.Cons(Tuple2(k,v),acc)});
6464 var list = A3(Dict.foldr, cons, NList.Nil, v);
6565 var name = "Dict";
66− if (list.ctor === "Cons" && list._0._1.ctor === "Tuple0") {
66+ if (list.ctor === "::" && list._0._1.ctor === "Tuple0") {
6767 name = "Set";
6868 list = A2(List.map, function(x){return x._0}, list);
6969 }
libraries/Native/Signal/Http.js+1−1
@@ -11,7 +11,7 @@ Elm.Native.Http = function(elm) {
1111
1212
1313 function registerReq(queue,responses) { return function(req) {
14− if (req.url.ctor !== 'Nil') { sendReq(queue,responses,req); }
14+ if (req.url.ctor !== '[]') { sendReq(queue,responses,req); }
1515 };
1616 }
1717
libraries/Native/Signal/Keyboard.js+1−1
@@ -35,7 +35,7 @@ Elm.Native.Keyboard = function(elm) {
3535 function dir(up, down, left, right) {
3636 function f(ks) {
3737 var x = 0, y = 0;
38− while (ks.ctor == "Cons") {
38+ while (ks.ctor === "::") {
3939 switch (ks._0) {
4040 case left : --x; break;
4141 case right: ++x; break;
libraries/Native/Utils.js+3−3
@@ -25,10 +25,10 @@ Elm.Native.Utils = function(elm) {
2525 var ord;
2626 if (typeof x !== 'object') return x === y ? EQ : x < y ? LT : GT;
2727
28− if (x.ctor === "Cons" || x.ctor === "Nil") {
28+ if (x.ctor === "::" || x.ctor === "[]") {
2929 while (true) {
30− if (x.ctor === "Nil" && y.ctor === "Nil") return EQ;
31− if (x.ctor !== y.ctor) return x.ctor === 'Nil' ? LT : GT;
30+ if (x.ctor === "[]" && y.ctor === "[]") return EQ;
31+ if (x.ctor !== y.ctor) return x.ctor === '[]' ? LT : GT;
3232 ord = cmp(x._0, y._0);
3333 if (ord !== EQ) return ord;
3434 x = x._1;