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.Result as Result
23-- VALIDATE DECLARATIONS
28 -> Result.Result wrn Error.Error [D.ValidDecl]
29declarations isRoot sourceDecls =
30 do validDecls <- validateDecls Nothing sourceDecls
32 <$> declDuplicates validDecls
33 <*> T.traverse (checkDecl isRoot) validDecls
39 -> Result.Result wrn Error.Error [D.ValidDecl]
40validateDecls maybeComment sourceDecls =
48 validateDecls (Just comment) decls
51 validateDeclsHelp maybeComment decl decls
56 -> A.Located D.SourceDecl'
58 -> Result.Result wrn Error.Error [D.ValidDecl]
59validateDeclsHelp comment (A.A region decl) decls =
60 let addRest validDecl =
61 (:) (A.A (region, comment) validDecl)
62 <$> validateDecls Nothing decls
65 D.Datatype name tvars ctors ->
66 addRest (D.Datatype name tvars ctors)
68 D.TypeAlias name tvars alias ->
69 addRest (D.TypeAlias name tvars alias)
71 D.Fixity assoc prec op ->
72 addRest (D.Fixity assoc prec op)
75 defHelp comment def decls
78 portHelp comment region port decls
81-- 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' <- Validate.expression expr
96 let def' = Valid.Definition pat expr' Nothing
99 Source.TypeAnnotation name tipe ->
101 D.Decl (A.A _ (D.Definition (A.A _
102 (Source.Definition pat@(A.A _ (Pattern.Var name')) expr)))) : rest
104 do expr' <- Validate.expression expr
105 let def' = Valid.Definition pat expr' (Just tipe)
109 Result.throw region (Error.TypeWithoutDefinition name)
112-- VALIDATE PORTS IN DECLARATIONS
119 -> Result.Result wrn Error.Error [D.ValidDecl]
120portHelp comment region port decls =
121 let addRest port' rest =
122 (:) (A.A (region,comment) (D.Port port'))
123 <$> validateDecls Nothing rest
126 D.PortDefinition name _ ->
127 Result.throw region (Error.PortWithoutAnnotation name)
129 D.PortAnnotation name tipe ->
131 D.Decl (A.A _ (D.Port (D.PortDefinition name' expr))) : rest
133 do expr' <- Validate.expression expr
134 let port' = D.Out name expr' tipe
138 addRest (D.In name tipe) decls
141-- VALIDATE DEFINITIONS
143definitions :: [Source.Def] -> Result.Result wrn Error.Error [Valid.Def]
144definitions sourceDefs =
145 do validDefs <- definitionsHelp sourceDefs
146 let patterns = map (\(Valid.Definition p _ _) -> p) validDefs
147 defDuplicates patterns
151definitionsHelp :: [Source.Def] -> Result.Result wrn Error.Error [Valid.Def]
152definitionsHelp sourceDefs =
157 A.A _ (Source.Definition pat expr) : rest ->
158 do expr' <- expression expr
159 let def = Valid.Definition pat expr' Nothing
160 (:) def <$> definitionsHelp rest
162 A.A region (Source.TypeAnnotation name tipe) : rest ->
164 A.A _ (Source.Definition pat@(A.A _ (Pattern.Var name')) expr) : rest'
166 do expr' <- expression expr
167 let def = Valid.Definition pat expr' (Just tipe)
168 (:) def <$> definitionsHelp rest'
171 Result.throw region (Error.TypeWithoutDefinition name)
174-- VALIDATE EXPRESSIONS
176expression :: Source.Expr -> Result.Result wrn Error.Error Valid.Expr
177expression (A.A ann sourceExpression) =
179 case sourceExpression of
183 Lambda pattern body ->
184 Lambda pattern <$> expression body
186 Binop op leftExpr rightExpr ->
188 <$> expression leftExpr
189 <*> expression rightExpr
194 <*> T.traverse second 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 MultiIf branches finally ->
218 <$> T.traverse both branches
219 <*> expression finally
221 Access record field ->
223 <$> expression record
226 Remove record field ->
228 <$> expression record
231 Insert record field expr ->
233 <$> expression record
237 Modify record fields ->
239 <$> expression record
240 <*> T.traverse second fields
244 <$> T.traverse second fields
251 GLShader uid src gltipe ->
252 return (GLShader uid src gltipe)
258 return (In name tipe)
260 Out name expr tipe ->
261 do expr' <- expression expr
262 return (Out name expr' tipe)
264 Task name expr tipe ->
265 do expr' <- expression expr
266 return (Task name expr' tipe)
269 return (Crash details)
272second :: (a, Source.Expr) -> Result.Result wrn Error.Error (a, Valid.Expr)
273second (value, expr) =
274 (,) value <$> expression expr
278 :: (Source.Expr, Source.Expr)
279 -> Result.Result wrn Error.Error (Valid.Expr, Valid.Expr)
281 (,) <$> expression expr1 <*> expression expr2
287 :: (String -> Error.Error)
288 -> [A.Located String]
289 -> Result.Result wrn Error.Error ()
290detectDuplicates tag names =
291 let add (A.A region name) dict =
292 Map.insertWith (++) name [region] dict
295 Map.toList (foldr add Map.empty pairs)
297 check (name, regions) =
300 Result.throw region (tag name)
305 F.traverse_ check (makeGroups names)
309 :: [Pattern.RawPattern]
310 -> Result.Result wrn Error.Error ()
311defDuplicates patterns =
312 concatMap Pattern.boundVars patterns
313 |> detectDuplicates Error.DuplicateDefinition
316declDuplicates :: [D.ValidDecl] -> Result.Result wrn Error.Error ()
317declDuplicates decls =
318 let (valueLists, typeLists) = unzip (map extractValues decls)
321 <$> detectDuplicates Error.DuplicateValueDeclaration (concat valueLists)
322 <*> detectDuplicates Error.DuplicateTypeDeclaration (concat typeLists)
325extractValues :: D.ValidDecl -> ([A.Located String], [A.Located String])
326extractValues (A.A (region, _) decl) =
328 D.Definition (Valid.Definition pattern _ _) ->
329 ( Pattern.boundVars pattern
333 D.Datatype name _ ctors ->
334 ( map (A.A region . fst) ctors
338 D.TypeAlias name _ (A.A _ (Type.RRecord _ _)) ->
343 D.TypeAlias name _ _ ->
349 ( [A.A region (D.validPortName port)]
359-- UNBOUND TYPE VARIABLES
361checkDecl :: Bool -> D.ValidDecl -> Result.Result wrn Error.Error ()
362checkDecl isRoot (A.A (region,_) decl) =
367 D.Datatype name boundVars ctors ->
368 let frees = concatMap freeVars (concatMap snd ctors)
370 case findUnbound boundVars frees of
376 (v:vs) = Set.toList (Set.fromList unbound)
379 (Error.UnboundTypeVarsInUnion name boundVars v vs ctors)
381 D.TypeAlias name boundVars tipe ->
382 case findUnbound boundVars (freeVars tipe) of
388 (v:vs) = Set.toList (Set.fromList unbound)
391 (Error.UnboundTypeVarsInAlias name boundVars v vs tipe)
396 else Result.throw region Error.UnexpectedPort
402findUnbound :: [String] -> [A.Located String] -> [String]
403findUnbound boundVars frees =
404 let bounds = Set.fromList boundVars
407 Set.notMember x bounds
409 filter isUnbound (map A.drop frees)
413freeVars :: Type.Raw -> [A.Located String]
414freeVars (A.A region tipe) =
416 Type.RLambda t1 t2 ->
417 freeVars t1 ++ freeVars t2
426 concatMap freeVars (t:ts)
428 Type.RRecord fields ext ->
429 maybe [] freeVars ext
430 ++ 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