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 sourceDecls
32 <$> declDuplicates validDecls
33 <*> T.traverse (checkDecl isRoot) validDecls
38 -> Result.Result wrn Error.Error [D.ValidDecl]
39validateDecls sourceDecls =
45 validateDeclsHelp decl decls
51 -> Result.Result wrn Error.Error [D.ValidDecl]
52validateDeclsHelp (A.A region decl) decls =
53 let addRest validDecl =
54 (:) (A.A region validDecl) <$> validateDecls decls
57 D.Datatype name tvars ctors ->
58 addRest (D.Datatype name tvars ctors)
60 D.TypeAlias name tvars alias ->
61 addRest (D.TypeAlias name tvars alias)
63 D.Fixity assoc prec op ->
64 addRest (D.Fixity assoc prec op)
70 portHelp region port decls
73-- VALIDATE DEFINITIONS IN DECLARATIONS
78 -> Result.Result wrn Error.Error [D.ValidDecl]
79defHelp (A.A region def) decls =
80 let addRest def' rest =
81 (:) (A.A region (D.Definition def')) <$> validateDecls rest
84 Source.Definition pat expr ->
85 do expr' <- Validate.expression expr
86 let def' = Valid.Definition pat expr' Nothing
89 Source.TypeAnnotation name tipe ->
91 A.A _ (D.Definition (A.A _ (Source.Definition pat@(A.A _ (Pattern.Var name')) expr))) : rest
93 do expr' <- Validate.expression expr
94 let def' = Valid.Definition pat expr' (Just tipe)
98 Result.throw region (Error.TypeWithoutDefinition name)
101-- VALIDATE PORTS IN DECLARATIONS
107 -> Result.Result wrn Error.Error [D.ValidDecl]
108portHelp region port decls =
109 let addRest port' rest =
110 (:) (A.A region (D.Port port')) <$> validateDecls rest
113 D.PortDefinition name _ ->
114 Result.throw region (Error.PortWithoutAnnotation name)
116 D.PortAnnotation name tipe ->
118 A.A _ (D.Port (D.PortDefinition name' expr)) : rest
120 do expr' <- Validate.expression expr
121 let port' = D.Out name expr' tipe
125 addRest (D.In name tipe) decls
128-- VALIDATE DEFINITIONS
130definitions :: [Source.Def] -> Result.Result wrn Error.Error [Valid.Def]
131definitions sourceDefs =
132 do validDefs <- definitionsHelp sourceDefs
133 let patterns = map (\(Valid.Definition p _ _) -> p) validDefs
134 defDuplicates patterns
138definitionsHelp :: [Source.Def] -> Result.Result wrn Error.Error [Valid.Def]
139definitionsHelp sourceDefs =
144 A.A _ (Source.Definition pat expr) : rest ->
145 do expr' <- expression expr
146 let def = Valid.Definition pat expr' Nothing
147 (:) def <$> definitionsHelp rest
149 A.A region (Source.TypeAnnotation name tipe) : rest ->
151 A.A _ (Source.Definition pat@(A.A _ (Pattern.Var name')) expr) : rest'
153 do expr' <- expression expr
154 let def = Valid.Definition pat expr' (Just tipe)
155 (:) def <$> definitionsHelp rest'
158 Result.throw region (Error.TypeWithoutDefinition name)
161-- VALIDATE EXPRESSIONS
163expression :: Source.Expr -> Result.Result wrn Error.Error Valid.Expr
164expression (A.A ann sourceExpression) =
166 case sourceExpression of
170 Lambda pattern body ->
171 Lambda pattern <$> expression body
173 Binop op leftExpr rightExpr ->
175 <$> expression leftExpr
176 <*> expression rightExpr
181 <*> T.traverse second branches
184 Data name <$> T.traverse expression args
189 Range lowExpr highExpr ->
191 <$> expression lowExpr
192 <*> expression highExpr
194 ExplicitList expressions ->
196 <$> T.traverse expression expressions
198 App funcExpr argExpr ->
200 <$> expression funcExpr
201 <*> expression argExpr
204 MultiIf <$> T.traverse both branches
206 Access record field ->
208 <$> expression record
211 Remove record field ->
213 <$> expression record
216 Insert record field expr ->
218 <$> expression record
222 Modify record fields ->
224 <$> expression record
225 <*> T.traverse second fields
229 <$> T.traverse second fields
236 GLShader uid src gltipe ->
237 return (GLShader uid src gltipe)
243 return (In name tipe)
245 Out name expr tipe ->
246 do expr' <- expression expr
247 return (Out name expr' tipe)
249 Task name expr tipe ->
250 do expr' <- expression expr
251 return (Task name expr' tipe)
254second :: (a, Source.Expr) -> Result.Result wrn Error.Error (a, Valid.Expr)
255second (value, expr) =
256 (,) value <$> expression expr
260 :: (Source.Expr, Source.Expr)
261 -> Result.Result wrn Error.Error (Valid.Expr, Valid.Expr)
263 (,) <$> expression expr1 <*> expression expr2
269 :: (String -> Error.Error)
270 -> [A.Located String]
271 -> Result.Result wrn Error.Error ()
272detectDuplicates tag names =
273 let add (A.A region name) dict =
274 Map.insertWith (++) name [region] dict
277 Map.toList (foldr add Map.empty pairs)
279 check (name, regions) =
282 Result.throw region (tag name)
287 F.traverse_ check (makeGroups names)
291 :: [Pattern.RawPattern]
292 -> Result.Result wrn Error.Error ()
293defDuplicates patterns =
294 concatMap Pattern.boundVars patterns
295 |> detectDuplicates Error.DuplicateDefinition
298declDuplicates :: [D.ValidDecl] -> Result.Result wrn Error.Error ()
299declDuplicates decls =
300 let (valueLists, typeLists) = unzip (map extractValues decls)
303 <$> detectDuplicates Error.DuplicateValueDeclaration (concat valueLists)
304 <*> detectDuplicates Error.DuplicateTypeDeclaration (concat typeLists)
307extractValues :: D.ValidDecl -> ([A.Located String], [A.Located String])
308extractValues (A.A region decl) =
310 D.Definition (Valid.Definition pattern _ _) ->
311 ( Pattern.boundVars pattern
315 D.Datatype name _ ctors ->
316 ( map (A.A region . fst) ctors
320 D.TypeAlias name _ (A.A _ (Type.RRecord _ _)) ->
325 D.TypeAlias name _ _ ->
331 ( [A.A region (D.validPortName port)]
341-- UNBOUND TYPE VARIABLES
343checkDecl :: Bool -> D.ValidDecl -> Result.Result wrn Error.Error ()
344checkDecl isRoot (A.A region decl) =
349 D.Datatype name boundVars ctors ->
350 let frees = concatMap freeVars (concatMap snd ctors)
352 case findUnbound boundVars frees of
358 (v:vs) = Set.toList (Set.fromList unbound)
361 (Error.UnboundTypeVarsInUnion name boundVars v vs ctors)
363 D.TypeAlias name boundVars tipe ->
364 case findUnbound boundVars (freeVars tipe) of
370 (v:vs) = Set.toList (Set.fromList unbound)
373 (Error.UnboundTypeVarsInAlias name boundVars v vs tipe)
378 else Result.throw region Error.UnexpectedPort
384findUnbound :: [String] -> [A.Located String] -> [String]
385findUnbound boundVars frees =
386 let bounds = Set.fromList boundVars
389 Set.notMember x bounds
391 filter isUnbound (map A.drop frees)
395freeVars :: Type.Raw -> [A.Located String]
396freeVars (A.A region tipe) =
398 Type.RLambda t1 t2 ->
399 freeVars t1 ++ freeVars t2
408 concatMap freeVars (t:ts)
410 Type.RRecord fields ext ->
411 maybe [] freeVars ext
412 ++ 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