@@ -3,6 +3,7 @@ module Validate (declarations) where
4import Control.Monad (foldM)
4import Control.Monad (foldM)
5import qualified Data.Map as Map
5import qualified Data.Map as Map
6+import qualified Data.Maybe as Maybe
6import qualified Data.Set as Set
7import qualified Data.Set as Set
7import qualified Data.Foldable as F
8import qualified Data.Foldable as F
8import qualified Data.Traversable as T
9import qualified Data.Traversable as T
@@ -21,94 +22,225 @@ import qualified Reporting.Result as Result
24−-- VALIDATE DECLARATIONS
25+-- COLLAPSE COMMENTS
29+ A.Annotated (R.Region, Maybe (A.Located String)) a
33+ :: [D.CommentOr (A.Located a)]
34+ -> Result.Result wrn Error.Error [Commented a]
35+collapseComments listWithComments =
36+ case listWithComments of
40+ D.Comment msg : D.Whatever (A.A region a) : rest ->
43+ A.A (region, Just msg) a
45+ fmap (entry:) (collapseComments rest)
47+ D.Comment (A.A region _) : D.Comment _ : _ ->
48+ Result.throw region Error.CommentOnComment
50+ [D.Comment (A.A region _)] ->
51+ Result.throw region Error.CommentOnNothing
53+ D.Whatever (A.A region a) : rest ->
56+ A.A (region, Nothing) a
58+ fmap (entry:) (collapseComments rest)
65+data StructuredSource =
67+ { _decls :: [Commented D.Source']
68+ , _cmds :: Maybe [Commented Source.Effect]
69+ , _subs :: Maybe [Commented Source.Effect]
28− :: [D.SourceDecl]
73+extractEffects :: [Commented D.SourceOrDefine] -> Result.Result wrn Error.Error StructuredSource
74+extractEffects commentedDecls =
75+ case commentedDecls of
77+ Result.ok (Src [] Nothing Nothing)
79+ A.A ann (D.Source decl) : rest ->
80+ do restSrc <- extractEffects rest
81+ return $ restSrc { _decls = A.A ann decl : _decls restSrc }
83+ A.A (region, _) (D.Define name commentOrEffects) : rest ->
84+ do restSrc <- extractEffects rest
87+ case _cmds restSrc of
89+ do effects <- collapseComments commentOrEffects
90+ Result.ok $ restSrc { _cmds = Just effects }
93+ Result.throw region (Error.DefineDuplicate name)
96+ case _subs restSrc of
98+ do effects <- collapseComments commentOrEffects
99+ Result.ok $ restSrc { _subs = Just effects }
102+ Result.throw region (Error.DefineDuplicate name)
105+ Result.throw region (Error.DefineUnknown name)
109+-- VALIDATE STRUCTURED SOURCE
29− -> Result.Result wrn Error.Error [D.ValidDecl]
112+declarations :: [D.Source] -> Result.Result wrn Error.Error [D.Valid]
30declarations sourceDecls =
113declarations sourceDecls =
114+ do (Src decls cmds subs) <-
115+ extractEffects =<< collapseComments sourceDecls
31− do validDecls <- validateDecls Nothing sourceDecls
118+ validateDecls decls
121+ validateEffects (Maybe.fromMaybe [] cmds)
124+ validateEffects (Maybe.fromMaybe [] subs)
32 (\_ _ -> validDecls)
126 (\_ _ -> validDecls)
33 <$> declDuplicates validDecls
127 <$> declDuplicates validDecls
34 <*> T.traverse checkDecl validDecls
128 <*> T.traverse checkDecl validDecls
132+-- VALIDATE DECLARATIONS
37validateDecls
135validateDecls
38− :: Maybe String
136+ :: [Commented D.Source']
40− -> Result.Result wrn Error.Error [D.ValidDecl]
137+ -> Result.Result wrn Error.Error [D.Valid]
41−validateDecls maybeComment sourceDecls =
138+validateDecls commentedDecls =
42− case sourceDecls of
139+ case commentedDecls of
44− return []
141+ Result.ok []
46− sourceDecl : decls ->
143+ A.A (region, maybeComment) decl : rest ->
148+ A.A (region, fmap A.drop maybeComment) validDecl
150+ fmap (entry:) (validateDecls rest)
47− case sourceDecl of
152+ case decl of
48− D.Comment comment ->
153+ D.Union name tvars ctors ->
49− validateDecls (Just comment) decls
154+ addRest (D.Union name tvars ctors)
51− D.Decl decl ->
156+ D.Alias name tvars alias ->
157+ addRest (D.Alias name tvars alias)
159+ D.Fixity assoc prec op ->
160+ addRest (D.Fixity assoc prec op)
52− validateDeclsHelp maybeComment decl decls
163+ validateDeclsHelp maybeComment def rest
55validateDeclsHelp
166validateDeclsHelp
56− :: Maybe String
167+ :: Maybe (A.Located String)
57− -> A.Located D.SourceDecl'
168+ -> Source.Def
58− -> [D.SourceDecl]
169+ -> [Commented D.Source']
59− -> Result.Result wrn Error.Error [D.ValidDecl]
170+ -> Result.Result wrn Error.Error [D.Valid]
60−validateDeclsHelp comment (A.A region decl) decls =
171+validateDeclsHelp maybeComment (A.A region def) decls =
61− let addRest validDecl =
172+ let
62− (:) (A.A (region, comment) validDecl)
173+ makeDef pat expr maybeType =
63− <$> validateDecls Nothing decls
174+ D.Def (Valid.Definition pat expr maybeType)
177+ (region, fmap A.drop maybeComment)
65− case decl of
179+ case def of
66− D.Datatype name tvars ctors ->
180+ Source.Definition pat expr ->
67− addRest (D.Datatype name tvars ctors)
181+ (:)
182+ <$> validateDef makeDef ann pat expr Nothing
183+ <*> validateDecls decls
185+ Source.Annotation name tipe ->
187+ A.A (_, Just (A.A commentRegion _)) _ : _ ->
188+ Result.throw commentRegion (Error.CommentAfterAnnotation name)
69− D.TypeAlias name tvars alias ->
190+ A.A _ (D.Def (A.A _ (Source.Definition pat expr))) : rest
70− addRest (D.TypeAlias name tvars alias)
191+ | Pattern.isVar name pat ->
193+ <$> validateDef makeDef ann pat expr (Just tipe)
194+ <*> validateDecls rest
72− D.Fixity assoc prec op ->
196+ _ ->
73− addRest (D.Fixity assoc prec op)
197+ Result.throw region (Error.TypeWithoutDefinition name)
76− defHelp comment def decls
80−-- VALIDATE DEFINITIONS IN DECLARATIONS
205+ :: [Commented Source.Effect]
206+ -> Result.Result wrn Error.Error [A.Commented Valid.Effect]
207+validateEffects effects =
83−defHelp
212+ A.A (region, maybeComment) effect : rest ->
84− :: Maybe String
213+ validateEffectsHelp (region, fmap A.drop maybeComment) effect rest
87− -> Result.Result wrn Error.Error [D.ValidDecl]
88−defHelp 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)
107− checkDefinition def'
217+ :: (R.Region, Maybe String)
219+ -> [Commented Source.Effect]
220+ -> Result.Result wrn Error.Error [A.Commented Valid.Effect]
221+validateEffectsHelp ann effect remainingEffects =
224+ Result.throw (fst ann) (error "TODO")
226+ Source.Def pat expr ->
228+ <$> validateDef Valid.Def ann pat expr Nothing
229+ <*> validateEffects remainingEffects
231+ Source.Type name tipe ->
232+ case remainingEffects of
233+ A.A (_, Just (A.A commentRegion _)) _ : _ ->
234+ Result.throw commentRegion (Error.CommentAfterAnnotation name)
236+ A.A _ (Source.Def pat expr) : rest
237+ | Pattern.isVar name pat ->
239+ <$> validateDef Valid.Def ann pat expr (Just tipe)
240+ <*> validateEffects rest
111− Result.throw region (Error.TypeWithoutDefinition name)
243+ Result.throw (fst ann) (Error.TypeWithoutDefinition name)
@@ -127,29 +259,40 @@ definitionsHelp :: [Source.Def] -> Result.Result wrn Error.Error [Valid.Def]
127definitionsHelp sourceDefs =
259definitionsHelp sourceDefs =
128 case sourceDefs of
260 case sourceDefs of
130− return []
262+ return []
132− A.A _ (Source.Definition pat expr) : rest ->
264+ A.A region (Source.Definition pat expr) : rest ->
133− do expr' <- expression expr
265+ (:)
134− let def = Valid.Definition pat expr' Nothing
266+ <$> fmap A.drop (validateDef Valid.Definition region pat expr Nothing)
136− (:) def <$> definitionsHelp rest
267+ <*> definitionsHelp rest
138− A.A region (Source.TypeAnnotation name tipe) : rest ->
269+ A.A r1 (Source.Annotation name tipe) : rest ->
139− case rest of
270+ case rest of
140− A.A _ (Source.Definition pat@(A.A _ (Pattern.Var name')) expr) : rest'
271+ A.A r2 (Source.Definition pat expr) : rest'
141− | name == name' ->
272+ | Pattern.isVar name pat ->
142− do expr' <- expression expr
273+ (:)
143− let def = Valid.Definition pat expr' (Just tipe)
274+ <$> fmap A.drop (validateDef Valid.Definition (R.merge r1 r2) pat expr (Just tipe))
145− (:) def <$> definitionsHelp rest'
275+ <*> definitionsHelp rest'
148− Result.throw region (Error.TypeWithoutDefinition name)
278+ Result.throw r1 (Error.TypeWithoutDefinition name)
282+ :: (Pattern.Raw -> Valid.Expr -> Maybe Type.Raw -> def)
151−checkDefinition :: Valid.Def -> Result.Result wrn Error.Error ()
287+ -> Result.Result wrn Error.Error (A.Annotated annotation def)
152−checkDefinition (Valid.Definition pattern body _) =
288+validateDef makeDef annotation pat expr maybeType =
289+ do validExpr <- expression expr
290+ validateDefPattern pat validExpr
291+ return $ A.A annotation (makeDef pat validExpr maybeType)
294+validateDefPattern :: Pattern.Raw -> Valid.Expr -> Result.Result wrn Error.Error ()
295+validateDefPattern pattern body =
153 case fst (Expr.collectLambdas body) of
296 case fst (Expr.collectLambdas body) of
155 return ()
298 return ()
@@ -265,7 +408,7 @@ both (expr1, expr2) =
265-- VALIDATE PATTERNS
408-- VALIDATE PATTERNS
268−validatePattern :: Pattern.RawPattern -> Result.Result wrn Error.Error Pattern.RawPattern
411+validatePattern :: Pattern.Raw -> Result.Result wrn Error.Error Pattern.Raw
269validatePattern pattern =
412validatePattern pattern =
270 do detectDuplicates Error.BadPattern (Pattern.boundVars pattern)
413 do detectDuplicates Error.BadPattern (Pattern.boundVars pattern)
271 return pattern
414 return pattern
@@ -297,15 +440,13 @@ detectDuplicates tag names =
297 F.traverse_ check (makeGroups names)
440 F.traverse_ check (makeGroups names)
301− :: [Pattern.RawPattern]
302− -> Result.Result wrn Error.Error ()
443+defDuplicates :: [Pattern.Raw] -> Result.Result wrn Error.Error ()
303defDuplicates patterns =
444defDuplicates patterns =
304 concatMap Pattern.boundVars patterns
445 concatMap Pattern.boundVars patterns
305 |> detectDuplicates Error.DuplicateDefinition
446 |> detectDuplicates Error.DuplicateDefinition
308−declDuplicates :: [D.ValidDecl] -> Result.Result wrn Error.Error ()
449+declDuplicates :: [D.Valid] -> Result.Result wrn Error.Error ()
309declDuplicates decls =
450declDuplicates decls =
310 let (valueLists, typeLists) = unzip (map extractValues decls)
451 let (valueLists, typeLists) = unzip (map extractValues decls)
@@ -314,25 +455,25 @@ declDuplicates decls =
314 <*> detectDuplicates Error.DuplicateTypeDeclaration (concat typeLists)
455 <*> detectDuplicates Error.DuplicateTypeDeclaration (concat typeLists)
317−extractValues :: D.ValidDecl -> ([A.Located String], [A.Located String])
458+extractValues :: D.Valid -> ([A.Located String], [A.Located String])
318extractValues (A.A (region, _) decl) =
459extractValues (A.A (region, _) decl) =
319 case decl of
460 case decl of
320− D.Definition (Valid.Definition pattern _ _) ->
461+ D.Def (Valid.Definition pattern _ _) ->
321 ( Pattern.boundVars pattern
462 ( Pattern.boundVars pattern
325− D.Datatype name _ ctors ->
466+ D.Union name _ ctors ->
326 ( map (A.A region . fst) ctors
467 ( map (A.A region . fst) ctors
327 , [A.A region name]
468 , [A.A region name]
330− D.TypeAlias name _ (A.A _ (Type.RRecord _ _)) ->
471+ D.Alias name _ (A.A _ (Type.RRecord _ _)) ->
331 ( [A.A region name]
472 ( [A.A region name]
332 , [A.A region name]
473 , [A.A region name]
335− D.TypeAlias name _ _ ->
476+ D.Alias name _ _ ->
337 , [A.A region name]
478 , [A.A region name]
@@ -347,13 +488,13 @@ extractValues (A.A (region, _) decl) =
347-- UNBOUND TYPE VARIABLES
488-- UNBOUND TYPE VARIABLES
350−checkDecl :: D.ValidDecl -> Result.Result wrn Error.Error ()
491+checkDecl :: D.Valid -> Result.Result wrn Error.Error ()
351checkDecl (A.A (region,_) decl) =
492checkDecl (A.A (region,_) decl) =
352 case decl of
493 case decl of
353− D.Definition _ ->
494+ D.Def _ ->
354 return ()
495 return ()
356− D.Datatype name boundVars ctors ->
497+ D.Union name boundVars ctors ->
357 case diff boundVars (concatMap freeVars (concatMap snd ctors)) of
498 case diff boundVars (concatMap freeVars (concatMap snd ctors)) of
358 (_, []) ->
499 (_, []) ->
359 return ()
500 return ()
@@ -362,7 +503,7 @@ checkDecl (A.A (region,_) decl) =
362 Result.throw region
503 Result.throw region
363 (Error.UnboundTypeVarsInUnion name boundVars unbound)
504 (Error.UnboundTypeVarsInUnion name boundVars unbound)
365− D.TypeAlias name boundVars tipe ->
506+ D.Alias name boundVars tipe ->
366 case diff boundVars (freeVars tipe) of
507 case diff boundVars (freeVars tipe) of
367 ([], []) ->
508 ([], []) ->
368 return ()
509 return ()
@@ -400,20 +541,20 @@ diff left right =
401freeVars :: Type.Raw -> [A.Located String]
542freeVars :: Type.Raw -> [A.Located String]
402freeVars (A.A region tipe) =
543freeVars (A.A region tipe) =
403− case tipe of
544+ case tipe of
404− Type.RLambda t1 t2 ->
545+ Type.RLambda t1 t2 ->
405− freeVars t1 ++ freeVars t2
546+ freeVars t1 ++ freeVars t2
407− Type.RVar x ->
548+ Type.RVar x ->
408− [A.A region x]
549+ [A.A region x]
410− Type.RType _ ->
551+ Type.RType _ ->
413− Type.RApp t ts ->
554+ Type.RApp t ts ->
414− concatMap freeVars (t:ts)
555+ concatMap freeVars (t:ts)
416− Type.RRecord fields ext ->
557+ Type.RRecord fields ext ->
417− maybe [] freeVars ext
558+ maybe [] freeVars ext
418− ++ concatMap (freeVars . snd) fields
559+ ++ concatMap (freeVars . snd) fields