on master help sign in
Rule out duplicate fields in Validate phase and provide nice error message
a2427f5Evan Czaplicki
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/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