1{-# OPTIONS_GHC -Wall #-}
2module Transform.Check (mistakes) where
4import qualified Data.List as List
5import qualified Data.Maybe as Maybe
6import qualified Data.Set as Set
8import qualified AST.Expression.Valid as Valid
9import qualified AST.Declaration as D
10import qualified AST.Pattern as Pattern
11import qualified AST.Type as T
12import qualified Transform.Expression as Expr
15import Elm.Utils ((|>))
16import Text.PrettyPrint as P
19mistakes :: [D.ValidDecl] -> [Doc]
22 [ illFormedTypeDecls decls
23 , map P.text (duplicateTypeDeclarations decls)
24 , map P.text (duplicateValues decls)
30dups :: Ord a => [a] -> [a]
34 |> filter ((>1) . length)
38duplicateValues :: [D.ValidDecl] -> [String]
39duplicateValues decls =
40 map msg (dups (portNames ++ concatMap Pattern.boundVarList defPatterns)) ++
41 case mapM exprDups defExprs of
42 Left name -> [msg name]
47 "Name Collision: There can only be one definition of '" ++ x ++ "'."
49 (defPatterns, defExprs) =
50 unzip [ (pat,expr) | D.Definition (Valid.Definition pat expr _) <- decls ]
53 [ D.validPortName port | D.Port port <- decls ]
55 exprDups :: Valid.Expr -> Either String Valid.Expr
57 Expr.crawlLet defsDups expr
59 defsDups :: [Valid.Def] -> Either String [Valid.Def]
61 let varsIn (Valid.Definition pattern _ _) = Pattern.boundVarList pattern in
62 case dups $ concatMap varsIn defs of
67duplicateTypeDeclarations :: [D.ValidDecl] -> [String]
68duplicateTypeDeclarations decls =
69 map dupTypeError (dups (typeNames ++ aliasNames))
70 ++ map dupCtorError (dups (ctorNames ++ aliasNames))
73 [ name | D.Datatype name _ _ <- decls ]
76 [ name | D.TypeAlias name _ _ <- decls ]
79 concat [ map fst patterns | D.Datatype _ _ patterns <- decls ]
82dupTypeError :: String -> String
84 "Name Collision: There can only be one type named '" ++ name ++ "'"
87dupCtorError :: String -> String
89 "Name Collision: There can only be one constructor named '" ++ name ++ "'.\n"
90 ++ " Constructors are created for record type aliases and for union types, so\n"
91 ++ " something should be renamed or moved to a different module."
94-- FREE TYPE VARIABLES IN TYPE DECLARATIONS
96illFormedTypeDecls :: [D.ValidDecl] -> [Doc]
97illFormedTypeDecls decls =
98 map report (Maybe.mapMaybe isIllFormed (aliases ++ adts))
101 [ (decl, tvars, [tipe]) | decl@(D.TypeAlias _ tvars tipe) <- decls ]
104 [ (decl, tvars, concatMap snd ctors) | decl@(D.Datatype _ tvars ctors) <- decls ]
109 Set.union (freeVars t1) (freeVars t2)
118 Set.unions (map freeVars (t:ts))
120 T.Record fields ext ->
121 let ext' = maybe Set.empty freeVars ext
123 Set.unions (ext' : map (freeVars . snd) fields)
125 T.Aliased _ args t ->
126 freeVars (T.dealias args t)
128 undeclared tvars tipes =
129 Set.difference used declared
131 used = Set.unions (map freeVars tipes)
132 declared = Set.fromList tvars
134 isIllFormed (decl, tvars, tipes) =
135 let unbound = undeclared tvars tipes in
138 else Just (decl, Set.toList unbound)
140 report (decl, tvars) =
141 P.vcat [ P.text $ "Error: type variable" ++ listing ++ " unbound in:"
143 , nest 4 (pretty decl) ]
147 [tvar] -> " " ++ quote tvar ++ " is"
148 _ -> "s" ++ addCommas (map ((++) " ") (addAnd (map quote tvars))) ++ " are"
151 | length xs < 3 = concat xs
152 | otherwise = List.intercalate "," xs
156 | otherwise = zipWith (++) (replicate (length xs - 1) "" ++ ["and "]) xs
158 quote tvar = "'" ++ tvar ++ "'"
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