1{-# OPTIONS_GHC -Wall #-}
2module Validate (declarations) where
4import Control.Applicative ((<$>),(<*>))
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
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.Task as Task
23-- VALIDATE DECLARATIONS
27 -> Task.Task wrn Error.Error [D.ValidDecl]
28declarations sourceDecls =
29 do validDecls <- validateDecls sourceDecls
31 <$> declDuplicates validDecls
32 <*> T.traverse checkDecl validDecls
37 -> Task.Task wrn Error.Error [D.ValidDecl]
38validateDecls sourceDecls =
44 validateDeclsHelp decl decls
50 -> Task.Task wrn Error.Error [D.ValidDecl]
51validateDeclsHelp (A.A region decl) decls =
52 let addRest validDecl =
53 (:) (A.A region validDecl) <$> validateDecls decls
56 D.Datatype name tvars ctors ->
57 addRest (D.Datatype name tvars ctors)
59 D.TypeAlias name tvars alias ->
60 addRest (D.TypeAlias name tvars alias)
62 D.Fixity assoc prec op ->
63 addRest (D.Fixity assoc prec op)
69 portHelp region port decls
72-- VALIDATE DEFINITIONS IN DECLARATIONS
77 -> Task.Task wrn Error.Error [D.ValidDecl]
78defHelp (A.A region def) decls =
79 let addRest def' rest =
80 (:) (A.A region (D.Definition def')) <$> validateDecls rest
83 Source.Definition pat expr ->
84 do expr' <- Validate.expression expr
85 let def' = Valid.Definition pat expr' Nothing
88 Source.TypeAnnotation name tipe ->
90 A.A _ (D.Definition (A.A _ (Source.Definition pat@(A.A _ (Pattern.Var name')) expr))) : rest
92 do expr' <- Validate.expression expr
93 let def' = Valid.Definition pat expr' (Just tipe)
97 Task.throw region (Error.TypeWithoutDefinition name)
100-- VALIDATE PORTS IN DECLARATIONS
106 -> Task.Task wrn Error.Error [D.ValidDecl]
107portHelp region port decls =
108 let addRest port' rest =
109 (:) (A.A region (D.Port port')) <$> validateDecls rest
112 D.PortDefinition name _ ->
113 Task.throw region (Error.PortWithoutAnnotation name)
115 D.PortAnnotation name tipe ->
117 A.A _ (D.Port (D.PortDefinition name' expr)) : rest
119 do expr' <- Validate.expression expr
120 let port' = D.Out name expr' tipe
124 addRest (D.In name tipe) decls
127-- VALIDATE DEFINITIONS
129definitions :: [Source.Def] -> Task.Task wrn Error.Error [Valid.Def]
130definitions sourceDefs =
131 do validDefs <- definitionsHelp sourceDefs
132 let patterns = map (\(Valid.Definition p _ _) -> p) validDefs
133 defDuplicates patterns
137definitionsHelp :: [Source.Def] -> Task.Task wrn Error.Error [Valid.Def]
138definitionsHelp sourceDefs =
143 A.A _ (Source.Definition pat expr) : rest ->
144 do expr' <- expression expr
145 let def = Valid.Definition pat expr' Nothing
146 (:) def <$> definitionsHelp rest
148 A.A region (Source.TypeAnnotation name tipe) : rest ->
150 A.A _ (Source.Definition pat@(A.A _ (Pattern.Var name')) expr) : rest'
152 do expr' <- expression expr
153 let def = Valid.Definition pat expr' (Just tipe)
154 (:) def <$> definitionsHelp rest'
157 Task.throw region (Error.TypeWithoutDefinition name)
160-- VALIDATE EXPRESSIONS
162expression :: Source.Expr -> Task.Task wrn Error.Error Valid.Expr
163expression (A.A ann sourceExpression) =
165 case sourceExpression of
169 Lambda pattern body ->
170 Lambda pattern <$> expression body
172 Binop op leftExpr rightExpr ->
174 <$> expression leftExpr
175 <*> expression rightExpr
180 <*> T.traverse second branches
183 Data name <$> T.traverse expression args
188 Range lowExpr highExpr ->
190 <$> expression lowExpr
191 <*> expression highExpr
193 ExplicitList expressions ->
195 <$> T.traverse expression expressions
197 App funcExpr argExpr ->
199 <$> expression funcExpr
200 <*> expression argExpr
203 MultiIf <$> T.traverse both branches
205 Access record field ->
207 <$> expression record
210 Remove record field ->
212 <$> expression record
215 Insert record field expr ->
217 <$> expression record
221 Modify record fields ->
223 <$> expression record
224 <*> T.traverse second fields
228 <$> T.traverse second fields
235 GLShader uid src gltipe ->
236 return (GLShader uid src gltipe)
242 return (In name tipe)
244 Out name expr tipe ->
245 do expr' <- expression expr
246 return (Out name expr' tipe)
248 Task name expr tipe ->
249 do expr' <- expression expr
250 return (Task name expr' tipe)
253second :: (a, Source.Expr) -> Task.Task wrn Error.Error (a, Valid.Expr)
254second (value, expr) =
255 (,) value <$> expression expr
259 :: (Source.Expr, Source.Expr)
260 -> Task.Task wrn Error.Error (Valid.Expr, Valid.Expr)
262 (,) <$> expression expr1 <*> expression expr2
268 :: (String -> Error.Error)
269 -> [A.Located String]
270 -> Task.Task wrn Error.Error ()
271detectDuplicates tag names =
272 let add (A.A region name) dict =
273 Map.insertWith (++) name [region] dict
276 Map.toList (foldr add Map.empty pairs)
278 check (name, regions) =
281 Task.throw region (tag name)
286 F.traverse_ check (makeGroups names)
290 :: [Pattern.RawPattern]
291 -> Task.Task wrn Error.Error ()
292defDuplicates patterns =
293 concatMap Pattern.boundVars patterns
294 |> detectDuplicates Error.DuplicateDefinition
297declDuplicates :: [D.ValidDecl] -> Task.Task wrn Error.Error ()
298declDuplicates decls =
299 let (valueLists, typeLists) = unzip (map extractValues decls)
302 <$> detectDuplicates Error.DuplicateValueDeclaration (concat valueLists)
303 <*> detectDuplicates Error.DuplicateTypeDeclaration (concat typeLists)
306extractValues :: D.ValidDecl -> ([A.Located String], [A.Located String])
307extractValues (A.A region decl) =
309 D.Definition (Valid.Definition pattern _ _) ->
310 ( Pattern.boundVars pattern
314 D.Datatype name _ ctors ->
315 ( map (A.A region . fst) ctors
319 D.TypeAlias name _ (A.A _ (Type.RRecord _ _)) ->
324 D.TypeAlias name _ _ ->
330 ( [A.A region (D.validPortName port)]
340-- UNBOUND TYPE VARIABLES
342checkDecl :: D.ValidDecl -> Task.Task wrn Error.Error ()
343checkDecl (A.A _ decl) =
348 D.Datatype name boundVars ctors ->
349 F.traverse_ (checkTypeVars name boundVars) (concatMap snd ctors)
351 D.TypeAlias name boundVars tipe ->
352 checkTypeVars name boundVars tipe
361checkTypeVars :: String -> [String] -> Type.Raw -> Task.Task wrn Error.Error ()
362checkTypeVars name boundVars tipe =
363 let bounds = Set.fromList boundVars
365 check (A.A region free) =
366 if Set.member free bounds
368 else Task.throw region (Error.UnboundTypeVar name free)
370 F.traverse_ check (freeVars tipe)
373freeVars :: Type.Raw -> [A.Located String]
374freeVars (A.A region tipe) =
376 Type.RLambda t1 t2 ->
377 freeVars t1 ++ freeVars t2
386 concatMap freeVars (t:ts)
388 Type.RRecord fields ext ->
389 maybe [] freeVars ext
390 ++ 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