on master help sign in
Merge pull request #1074 from elm-lang/dev
719f335Evan Czaplicki
elm-compiler.cabal+1
@@ -78,6 +78,7 @@ Library
78 Elm.Compiler.Version,
78 Elm.Compiler.Version,
79 Generate.JavaScript,
79 Generate.JavaScript,
80 Generate.JavaScript.BuiltIn,
80 Generate.JavaScript.BuiltIn,
81+ Generate.JavaScript.Expression,
81 Generate.JavaScript.Helpers,
82 Generate.JavaScript.Helpers,
82 Generate.JavaScript.Literal,
83 Generate.JavaScript.Literal,
83 Generate.JavaScript.Port,
84 Generate.JavaScript.Port,
src/Generate/JavaScript/Expression.hs+7−18
@@ -127,24 +127,13 @@ generateCode expr =
127 jsExpr $ BuiltIn.recordUpdate jsRecord jsFields
127 jsExpr $ BuiltIn.recordUpdate jsRecord jsFields
128
128
129 Record fields ->
129 Record fields ->
130− do fields' <-
130+ let
131− forM fields $ \(field, e) ->
131+ toField (field, value) =
132+ do jsValue <- generateJsExpr value
132− (,) (Var.safe field) <$> generateJsExpr e
133+ return (prop (Var.safe field), jsValue)
133−
134+ in
134− let fieldMap =
135+ do jsFields <- mapM toField fields
135− List.foldl' combine Map.empty fields'
136−
137− jsExpr $ ObjectLit () $ (prop "_", hidden fieldMap) : visible fieldMap
136+ jsExpr $ ObjectLit () jsFields
138− where
139− combine record (field, value) =
140− Map.insertWith (++) field [value] record
141−
142− hidden fs =
143− ObjectLit () . map (prop *** ArrayLit ()) $
144− Map.toList (Map.filter (not . null) (Map.map tail fs))
145−
146− visible fs =
147− map (first prop) (Map.toList (Map.map head fs))
148
137
149 Binop op leftExpr rightExpr ->
138 Binop op leftExpr rightExpr ->
150 binop op leftExpr rightExpr
139 binop op leftExpr rightExpr
src/Optimize/Patterns/DecisionTree.hs+3
@@ -159,6 +159,9 @@ toDecisionTree variantDict rawBranches =
159 (_, []) ->
159 (_, []) ->
160 Decision path decisionEdges Nothing
160 Decision path decisionEdges Nothing
161
161
162+ ([], _ : _) ->
163+ toDecisionTree variantDict fallback
164+
162 (_, _) ->
165 (_, _) ->
163 Decision path decisionEdges (Just (toDecisionTree variantDict fallback))
166 Decision path decisionEdges (Just (toDecisionTree variantDict fallback))
164
167
src/Reporting/Error/Syntax.hs+7
@@ -21,6 +21,7 @@ data Error
21 | TypeWithoutDefinition String
21 | TypeWithoutDefinition String
22 | PortWithoutAnnotation String
22 | PortWithoutAnnotation String
23 | UnexpectedPort
23 | UnexpectedPort
24+ | DuplicateFieldName String
24 | DuplicateValueDeclaration String
25 | DuplicateValueDeclaration String
25 | DuplicateTypeDeclaration String
26 | DuplicateTypeDeclaration String
26 | DuplicateDefinition String
27 | DuplicateDefinition String
@@ -97,6 +98,12 @@ toReport dealiaser err =
97 ++ "if the module is imported twice, do we send values out the port twice?"
98 ++ "if the module is imported twice, do we send values out the port twice?"
98 )
99 )
99
100
101+ DuplicateFieldName name ->
102+ Report.simple
103+ "DUPLICATE FIELD"
104+ ("This record has more than one field named `" ++ name ++ "`.")
105+ "There can only be one. Do some renaming to make sure the names are distinct!"
106+
100 DuplicateValueDeclaration name ->
107 DuplicateValueDeclaration name ->
101 Report.simple
108 Report.simple
102 "DUPLICATE DEFINITION"
109 "DUPLICATE DEFINITION"
src/Validate.hs+11−2
@@ -1,6 +1,7 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2module Validate (declarations) where
2module Validate (declarations) where
3
3
4+import Control.Monad (foldM)
4import qualified Data.Map as Map
5import qualified Data.Map as Map
5import qualified Data.Set as Set
6import qualified Data.Set as Set
6import qualified Data.Foldable as F
7import qualified Data.Foldable as F
@@ -253,8 +254,16 @@ expression (A.A ann sourceExpression) =
253 <*> T.traverse second fields
254 <*> T.traverse second fields
254
255
255 Record fields ->
256 Record fields ->
256− Record
257+ let
258+ checkDups seenFields (field,_) =
259+ if Set.member field seenFields then
260+ Result.throw ann (Error.DuplicateFieldName field)
261+
262+ else
263+ return (Set.insert field seenFields)
264+ in
265+ do _ <- foldM checkDups Set.empty fields
257− <$> T.traverse second fields
266+ Record <$> T.traverse second fields
258
267
259 Let defs body ->
268 Let defs body ->
260 Let
269 Let
tests/test-files/good-expected-js/AliasSubstitution.elm.js+1−3
@@ -4,8 +4,6 @@ Elm.Main.make = function (_elm) {
4 _elm.Main = _elm.Main || {};
4 _elm.Main = _elm.Main || {};
5 if (_elm.Main.values) return _elm.Main.values;
5 if (_elm.Main.values) return _elm.Main.values;
6 var _op = {};
6 var _op = {};
7− var extractVec = function (v) {
7+ var extractVec = function (v) { return {x: v.x,y: v.y};};
8− return {_: {},x: v.x,y: v.y};
9− };
10 return _elm.Main.values = {_op: _op,extractVec: extractVec};
8 return _elm.Main.values = {_op: _op,extractVec: extractVec};
11};
9};
tests/test-files/good-expected-js/Ports.elm.js+1−1
@@ -10,7 +10,7 @@ Elm.Main.make = function (_elm) {
10 return {name: v.name,age: v.age};
10 return {name: v.name,age: v.age};
11 });
11 });
12 },
12 },
13− _utils.list([{_: {},age: 42,name: "Tom"}]));
13+ _utils.list([{name: "Tom",age: 42}]));
14 var time = Elm.Native.Port.make(_elm).outbound("time",
14 var time = Elm.Native.Port.make(_elm).outbound("time",
15 function (v) {
15 function (v) {
16 return v;
16 return v;
tests/test-files/good-expected-js/PortsWithTypeAliases.elm.js+1−1
@@ -21,6 +21,6 @@ Elm.Main.make = function (_elm) {
21 ,y: typeof v.y === "number" ? v.y : _U.badPort("a number",
21 ,y: typeof v.y === "number" ? v.y : _U.badPort("a number",
22 v.y)} : _U.badPort("an object with fields `x`, `y`",v);
22 v.y)} : _U.badPort("an object with fields `x`, `y`",v);
23 });
23 });
24− var Point = F2(function (a,b) { return {_: {},x: a,y: b};});
24+ var Point = F2(function (a,b) { return {x: a,y: b};});
25 return _elm.Main.values = {_op: _op,Point: Point};
25 return _elm.Main.values = {_op: _op,Point: Point};
26};
26};
tests/test-files/good-expected-js/Unify/NonHomogeneousRecords.elm.js+1−1
@@ -5,6 +5,6 @@ Elm.Main.make = function (_elm) {
5 if (_elm.Main.values) return _elm.Main.values;
5 if (_elm.Main.values) return _elm.Main.values;
6 var _op = {};
6 var _op = {};
7 var f = function (t) { var y = t.y;var x = t.x;return t;};
7 var f = function (t) { var y = t.y;var x = t.x;return t;};
8− var Thing = F2(function (a,b) { return {_: {},x: a,y: b};});
8+ var Thing = F2(function (a,b) { return {x: a,y: b};});
9 return _elm.Main.values = {_op: _op,Thing: Thing,f: f};
9 return _elm.Main.values = {_op: _op,Thing: Thing,f: f};
10};
10};