1{-# OPTIONS_GHC -Wall #-}
2module Validate (declarations) where
4import Control.Monad (foldM)
5import qualified Data.Map as Map
6import qualified Data.Set as Set
7import qualified Data.Foldable as F
8import qualified Data.Traversable as T
10import AST.Expression.General as Expr
11import qualified AST.Expression.Source as Source
12import qualified AST.Expression.Valid as Valid
13import qualified AST.Declaration as D
14import qualified AST.Pattern as Pattern
15import qualified AST.Type as Type
16import Elm.Utils ((|>))
17import qualified Reporting.Annotation as A
18import qualified Reporting.Error.Syntax as Error
19import qualified Reporting.Region as R
20import qualified Reporting.Result as Result
28 A.Annotated (R.Region, Maybe (A.Located String)) a
32 :: [D.CommentOr (A.Located a)]
33 -> Result.Result wrn Error.Error [Commented a]
34collapseComments listWithComments =
35 case listWithComments of
39 D.Comment msg : D.Whatever (A.A region a) : rest ->
42 A.A (region, Just msg) a
44 fmap (entry:) (collapseComments rest)
46 D.Comment (A.A region _) : D.Comment _ : _ ->
47 Result.throw region Error.CommentOnComment
49 [D.Comment (A.A region _)] ->
50 Result.throw region Error.CommentOnNothing
52 D.Whatever (A.A region a) : rest ->
55 A.A (region, Nothing) a
57 fmap (entry:) (collapseComments rest)
61-- VALIDATE STRUCTURED SOURCE
64declarations :: [D.Source] -> Result.Result wrn Error.Error [D.Valid]
65declarations sourceDecls =
67 collapseComments sourceDecls
73 (declDuplicates validDecls : map findBadTypeVars validDecls)
79-- VALIDATE DECLARATIONS
83 :: [Commented D.Source']
84 -> Result.Result wrn Error.Error [D.Valid]
85validateDecls commentedDecls =
86 case commentedDecls of
90 A.A (region, maybeComment) decl : rest ->
95 A.A (region, fmap A.drop maybeComment) validDecl
97 fmap (entry:) (validateDecls rest)
100 D.Union name tvars ctors ->
101 addRest (D.Union name tvars ctors)
103 D.Alias name tvars alias ->
104 addRest (D.Alias name tvars alias)
106 D.Fixity assoc prec op ->
107 addRest (D.Fixity assoc prec op)
110 validateDeclsHelp maybeComment def rest
114 :: Maybe (A.Located String)
116 -> [Commented D.Source']
117 -> Result.Result wrn Error.Error [D.Valid]
118validateDeclsHelp maybeComment (A.A region def) decls =
121 (region, fmap A.drop maybeComment)
123 makeDef pat expr maybeType =
124 D.Def (Valid.Definition pat expr maybeType)
127 Source.Definition pat expr ->
129 <$> validateDef makeDef ann pat expr Nothing
130 <*> validateDecls decls
132 Source.Annotation name tipe ->
134 A.A (_, Just (A.A commentRegion _)) _ : _ ->
135 Result.throw commentRegion (Error.CommentAfterAnnotation name)
137 A.A _ (D.Def (A.A _ (Source.Definition pat expr))) : rest
138 | Pattern.isVar name pat ->
140 <$> validateDef makeDef ann pat expr (Just tipe)
141 <*> validateDecls rest
144 Result.throw region (Error.TypeWithoutDefinition name)
148-- VALIDATE DEFINITIONS
151definitions :: [Source.Def] -> Result.Result wrn Error.Error [Valid.Def]
152definitions sourceDefs =
153 do validDefs <- definitionsHelp sourceDefs
154 let patterns = map (\(Valid.Definition p _ _) -> p) validDefs
155 defDuplicates patterns
159definitionsHelp :: [Source.Def] -> Result.Result wrn Error.Error [Valid.Def]
160definitionsHelp sourceDefs =
165 A.A region (Source.Definition pat expr) : rest ->
167 <$> fmap A.drop (validateDef Valid.Definition region pat expr Nothing)
168 <*> definitionsHelp rest
170 A.A r1 (Source.Annotation name tipe) : rest ->
172 A.A r2 (Source.Definition pat expr) : rest'
173 | Pattern.isVar name pat ->
175 <$> fmap A.drop (validateDef Valid.Definition (R.merge r1 r2) pat expr (Just tipe))
176 <*> definitionsHelp rest'
179 Result.throw r1 (Error.TypeWithoutDefinition name)
183 :: (Pattern.Raw -> Valid.Expr -> Maybe Type.Raw -> def)
188 -> Result.Result wrn Error.Error (A.Annotated annotation def)
189validateDef makeDef annotation pat expr maybeType =
190 do validExpr <- expression expr
191 validateDefPattern pat validExpr
192 return $ A.A annotation (makeDef pat validExpr maybeType)
195validateDefPattern :: Pattern.Raw -> Valid.Expr -> Result.Result wrn Error.Error ()
196validateDefPattern pattern body =
197 case fst (Expr.collectLambdas body) of
203 A.A _ (Pattern.Var _) ->
208 (A.A start _) = pattern
209 (A.A end _) = last args
211 Result.throw (R.merge start end) (Error.BadFunctionName (length args))
215-- VALIDATE EXPRESSIONS
218expression :: Source.Expr -> Result.Result wrn Error.Error Valid.Expr
219expression (A.A ann sourceExpression) =
221 case sourceExpression of
225 Lambda pattern body ->
227 <$> validatePattern pattern
230 Binop op leftExpr rightExpr ->
232 <$> expression leftExpr
233 <*> expression rightExpr
238 <*> T.traverse (\(p,b) -> (,) <$> validatePattern p <*> expression b) branches
241 Data name <$> T.traverse expression args
246 Range lowExpr highExpr ->
248 <$> expression lowExpr
249 <*> expression highExpr
251 ExplicitList expressions ->
253 <$> T.traverse expression expressions
255 App funcExpr argExpr ->
257 <$> expression funcExpr
258 <*> expression argExpr
260 If branches finally ->
262 <$> T.traverse both branches
263 <*> expression finally
265 Access record field ->
267 <$> expression record
270 Update record fields ->
272 <$> expression record
273 <*> T.traverse second fields
277 checkDups seenFields (field,_) =
278 if Set.member field seenFields then
279 Result.throw ann (Error.DuplicateFieldName field)
282 return (Set.insert field seenFields)
284 do _ <- foldM checkDups Set.empty fields
285 Record <$> T.traverse second fields
292 GLShader uid src gltipe ->
293 return (GLShader uid src gltipe)
296second :: (a, Source.Expr) -> Result.Result wrn Error.Error (a, Valid.Expr)
297second (value, expr) =
298 (,) value <$> expression expr
302 :: (Source.Expr, Source.Expr)
303 -> Result.Result wrn Error.Error (Valid.Expr, Valid.Expr)
305 (,) <$> expression expr1 <*> expression expr2
312validatePattern :: Pattern.Raw -> Result.Result wrn Error.Error Pattern.Raw
313validatePattern pattern =
314 do detectDuplicates Error.BadPattern (Pattern.boundVars pattern)
323 :: (String -> Error.Error)
324 -> [A.Located String]
325 -> Result.Result wrn Error.Error ()
326detectDuplicates tag names =
327 let add (A.A region name) dict =
328 Map.insertWith (++) name [region] dict
331 Map.toList (foldr add Map.empty pairs)
333 check (name, regions) =
336 Result.throw region (tag name)
341 F.traverse_ check (makeGroups names)
344defDuplicates :: [Pattern.Raw] -> Result.Result wrn Error.Error ()
345defDuplicates patterns =
346 concatMap Pattern.boundVars patterns
347 |> detectDuplicates Error.DuplicateDefinition
350declDuplicates :: [D.Valid] -> Result.Result wrn Error.Error ()
351declDuplicates decls =
353 (valueLists, typeLists) =
354 unzip (map extractValues decls)
357 <$> detectDuplicates Error.DuplicateValueDeclaration (concat valueLists)
358 <*> detectDuplicates Error.DuplicateTypeDeclaration (concat typeLists)
361extractValues :: D.Valid -> ([A.Located String], [A.Located String])
362extractValues (A.A (region, _) decl) =
364 D.Def (Valid.Definition pattern _ _) ->
365 ( Pattern.boundVars pattern
369 D.Union name _ ctors ->
370 ( map (A.A region . fst) ctors
374 D.Alias name _ (A.A _ (Type.RRecord _ _)) ->
391-- UNBOUND TYPE VARIABLES
394findBadTypeVars :: D.Valid -> Result.Result wrn Error.Error ()
395findBadTypeVars (A.A (region,_) decl) =
400 D.Union name boundVars ctors ->
401 case diff boundVars (concatMap freeVars (concatMap snd ctors)) of
407 (Error.UnboundTypeVarsInUnion name boundVars unbound)
409 D.Alias name boundVars tipe ->
410 case diff boundVars (freeVars tipe) of
416 (Error.UnboundTypeVarsInAlias name boundVars unbound)
420 (Error.UnusedTypeVarsInAlias name boundVars unused)
424 (Error.MessyTypeVarsInAlias name boundVars unused unbound)
430diff :: [String] -> [A.Located String] -> ([String], [String])
437 Set.fromList (map A.drop right)
439 ( Set.toList (Set.difference leftSet rightSet)
440 , Set.toList (Set.difference rightSet leftSet)
445freeVars :: Type.Raw -> [A.Located String]
446freeVars (A.A region tipe) =
448 Type.RLambda t1 t2 ->
449 freeVars t1 ++ freeVars t2
458 concatMap freeVars (t:ts)
460 Type.RRecord fields ext ->
461 maybe [] freeVars ext
462 ++ concatMap (freeVars . snd) fields
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list