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
24-- VALIDATE DECLARATIONS
29 -> Result.Result wrn Error.Error [D.ValidDecl]
30declarations sourceDecls =
31 do validDecls <- validateDecls Nothing sourceDecls
33 <$> declDuplicates validDecls
34 <*> T.traverse checkDecl validDecls
40 -> Result.Result wrn Error.Error [D.ValidDecl]
41validateDecls maybeComment sourceDecls =
49 validateDecls (Just comment) decls
52 validateDeclsHelp maybeComment decl decls
57 -> A.Located D.SourceDecl'
59 -> Result.Result wrn Error.Error [D.ValidDecl]
60validateDeclsHelp comment (A.A region decl) decls =
61 let addRest validDecl =
62 (:) (A.A (region, comment) validDecl)
63 <$> validateDecls Nothing decls
66 D.Datatype name tvars ctors ->
67 addRest (D.Datatype name tvars ctors)
69 D.TypeAlias name tvars alias ->
70 addRest (D.TypeAlias name tvars alias)
72 D.Fixity assoc prec op ->
73 addRest (D.Fixity assoc prec op)
76 defHelp comment def decls
80-- VALIDATE DEFINITIONS IN DECLARATIONS
87 -> Result.Result wrn Error.Error [D.ValidDecl]
88defHelp comment (A.A region def) decls =
89 let addRest def' rest =
90 (:) (A.A (region, comment) (D.Definition def'))
91 <$> validateDecls Nothing rest
94 Source.Definition pat expr ->
95 do expr' <- expression expr
96 let def' = Valid.Definition pat expr' Nothing
100 Source.TypeAnnotation name tipe ->
102 D.Decl (A.A _ (D.Definition (A.A _
103 (Source.Definition pat@(A.A _ (Pattern.Var name')) expr)))) : rest
105 do expr' <- expression expr
106 let def' = Valid.Definition pat expr' (Just tipe)
111 Result.throw region (Error.TypeWithoutDefinition name)
115-- VALIDATE DEFINITIONS
118definitions :: [Source.Def] -> Result.Result wrn Error.Error [Valid.Def]
119definitions sourceDefs =
120 do validDefs <- definitionsHelp sourceDefs
121 let patterns = map (\(Valid.Definition p _ _) -> p) validDefs
122 defDuplicates patterns
126definitionsHelp :: [Source.Def] -> Result.Result wrn Error.Error [Valid.Def]
127definitionsHelp sourceDefs =
132 A.A _ (Source.Definition pat expr) : rest ->
133 do expr' <- expression expr
134 let def = Valid.Definition pat expr' Nothing
136 (:) def <$> definitionsHelp rest
138 A.A region (Source.TypeAnnotation name tipe) : rest ->
140 A.A _ (Source.Definition pat@(A.A _ (Pattern.Var name')) expr) : rest'
142 do expr' <- expression expr
143 let def = Valid.Definition pat expr' (Just tipe)
145 (:) def <$> definitionsHelp rest'
148 Result.throw region (Error.TypeWithoutDefinition name)
151checkDefinition :: Valid.Def -> Result.Result wrn Error.Error ()
152checkDefinition (Valid.Definition pattern body _) =
153 case fst (Expr.collectLambdas body) of
159 A.A _ (Pattern.Var _) ->
164 (A.A start _) = pattern
165 (A.A end _) = last args
167 Result.throw (R.merge start end) (Error.BadFunctionName (length args))
171-- VALIDATE EXPRESSIONS
174expression :: Source.Expr -> Result.Result wrn Error.Error Valid.Expr
175expression (A.A ann sourceExpression) =
177 case sourceExpression of
181 Lambda pattern body ->
183 <$> validatePattern pattern
186 Binop op leftExpr rightExpr ->
188 <$> expression leftExpr
189 <*> expression rightExpr
194 <*> T.traverse (\(p,b) -> (,) <$> validatePattern p <*> expression b) branches
197 Data name <$> T.traverse expression args
202 Range lowExpr highExpr ->
204 <$> expression lowExpr
205 <*> expression highExpr
207 ExplicitList expressions ->
209 <$> T.traverse expression expressions
211 App funcExpr argExpr ->
213 <$> expression funcExpr
214 <*> expression argExpr
216 If branches finally ->
218 <$> T.traverse both branches
219 <*> expression finally
221 Access record field ->
223 <$> expression record
226 Update record fields ->
228 <$> expression record
229 <*> T.traverse second fields
233 checkDups seenFields (field,_) =
234 if Set.member field seenFields then
235 Result.throw ann (Error.DuplicateFieldName field)
238 return (Set.insert field seenFields)
240 do _ <- foldM checkDups Set.empty fields
241 Record <$> T.traverse second fields
248 GLShader uid src gltipe ->
249 return (GLShader uid src gltipe)
252second :: (a, Source.Expr) -> Result.Result wrn Error.Error (a, Valid.Expr)
253second (value, expr) =
254 (,) value <$> expression expr
258 :: (Source.Expr, Source.Expr)
259 -> Result.Result wrn Error.Error (Valid.Expr, Valid.Expr)
261 (,) <$> expression expr1 <*> expression expr2
268validatePattern :: Pattern.RawPattern -> Result.Result wrn Error.Error Pattern.RawPattern
269validatePattern pattern =
270 do detectDuplicates Error.BadPattern (Pattern.boundVars pattern)
279 :: (String -> Error.Error)
280 -> [A.Located String]
281 -> Result.Result wrn Error.Error ()
282detectDuplicates tag names =
283 let add (A.A region name) dict =
284 Map.insertWith (++) name [region] dict
287 Map.toList (foldr add Map.empty pairs)
289 check (name, regions) =
292 Result.throw region (tag name)
297 F.traverse_ check (makeGroups names)
301 :: [Pattern.RawPattern]
302 -> Result.Result wrn Error.Error ()
303defDuplicates patterns =
304 concatMap Pattern.boundVars patterns
305 |> detectDuplicates Error.DuplicateDefinition
308declDuplicates :: [D.ValidDecl] -> Result.Result wrn Error.Error ()
309declDuplicates decls =
310 let (valueLists, typeLists) = unzip (map extractValues decls)
313 <$> detectDuplicates Error.DuplicateValueDeclaration (concat valueLists)
314 <*> detectDuplicates Error.DuplicateTypeDeclaration (concat typeLists)
317extractValues :: D.ValidDecl -> ([A.Located String], [A.Located String])
318extractValues (A.A (region, _) decl) =
320 D.Definition (Valid.Definition pattern _ _) ->
321 ( Pattern.boundVars pattern
325 D.Datatype name _ ctors ->
326 ( map (A.A region . fst) ctors
330 D.TypeAlias name _ (A.A _ (Type.RRecord _ _)) ->
335 D.TypeAlias name _ _ ->
347-- UNBOUND TYPE VARIABLES
350checkDecl :: D.ValidDecl -> Result.Result wrn Error.Error ()
351checkDecl (A.A (region,_) decl) =
356 D.Datatype name boundVars ctors ->
357 case diff boundVars (concatMap freeVars (concatMap snd ctors)) of
363 (Error.UnboundTypeVarsInUnion name boundVars unbound)
365 D.TypeAlias name boundVars tipe ->
366 case diff boundVars (freeVars tipe) of
372 (Error.UnboundTypeVarsInAlias name boundVars unbound)
376 (Error.UnusedTypeVarsInAlias name boundVars unused)
380 (Error.MessyTypeVarsInAlias name boundVars unused unbound)
386diff :: [String] -> [A.Located String] -> ([String], [String])
393 Set.fromList (map A.drop right)
395 ( Set.toList (Set.difference leftSet rightSet)
396 , Set.toList (Set.difference rightSet leftSet)
401freeVars :: Type.Raw -> [A.Located String]
402freeVars (A.A region tipe) =
404 Type.RLambda t1 t2 ->
405 freeVars t1 ++ freeVars t2
414 concatMap freeVars (t:ts)
416 Type.RRecord fields ext ->
417 maybe [] freeVars ext
418 ++ 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