1module Transform.Check (mistakes) where
3import Transform.SortDefinitions (boundVars)
4import SourceSyntax.Everything
5import SourceSyntax.PrettyPrint
6import qualified SourceSyntax.Type as T
7import Data.List as List
8import qualified Data.Map as Map
9import qualified Data.Maybe as Maybe
10import qualified Data.Set as Set
11import Text.PrettyPrint as P
14mistakes :: [Declaration t v] -> [Doc]
16 concat [ infiniteTypeAliases decls
17 , illFormedTypes decls
18 , map P.text (duplicateConstructors decls)
19 , map P.text (concatMap findErrors (getLets decls)) ]
21 findErrors defs = duplicates defs ++ badOrder defs
23getLets :: [Declaration t v] -> [[Def t v]]
24getLets decls = defs : concatMap defLets defs
26 defs = [ d | Definition d <- decls ]
30 TypeAnnotation _ _ -> []
31 Def _ expr -> exprLets expr
36 Lambda p e -> exprLets e
37 Binop op e1 e2 -> exprLets e1 ++ exprLets e2
38 Case e cases -> exprLets e ++ concatMap (exprLets . snd) cases
39 Data name es -> concatMap exprLets es
41 Range e1 e2 -> exprLets e1 ++ exprLets e2
42 ExplicitList es -> concatMap exprLets es
43 App e1 e2 -> exprLets e1 ++ exprLets e2
44 MultiIf branches -> concatMap (\(b,e) -> exprLets b ++ exprLets e) branches
45 Access e lbl -> exprLets e
46 Remove e lbl -> exprLets e
47 Insert e lbl v -> exprLets e ++ exprLets v
48 Modify e fields -> exprLets e ++ concatMap (exprLets . snd) fields
49 Record fields -> concatMap (exprLets . snd) fields
50 Markdown uid md es -> []
51 Let defs body -> [defs] ++ exprLets body
53dups :: Eq a => [a] -> [a]
54dups = map head . filter ((>1) . length) . List.group
56dupErr :: String -> String -> String
58 "Syntax Error: There can only be one " ++ err ++ " '" ++ x ++ "'."
60duplicates :: [Def t v] -> [String]
62 map defMsg (dups definitions) ++ map annMsg (dups annotations)
64 annotations = List.sort [ name | TypeAnnotation name _ <- defs ]
65 definitions = List.sort $ concatMap Set.toList [ boundVars pattern | Def pattern _ <- defs ]
66 defMsg = dupErr "definition of"
67 annMsg = dupErr "type annotation for"
69duplicateConstructors :: [Declaration t v] -> [String]
70duplicateConstructors decls =
71 map typeMsg (dups typeCtors) ++ map dataMsg (dups dataCtors)
73 typeCtors = List.sort [ name | Datatype name _ _ <- decls ]
74 dataCtors = List.sort . concat $
75 [ map fst patterns | Datatype _ _ patterns <- decls ]
76 dataMsg = dupErr "definition of data constructor"
77 typeMsg = dupErr "definition of type constructor"
79badOrder :: [Def t v] -> [String]
80badOrder defs = go defs
82 msg x = "Syntax Error: The type annotation for '" ++ x ++
83 "' must be directly above its definition."
87 TypeAnnotation name _ : Def (PVar name') _ : rest
88 | name == name' -> go rest
90 TypeAnnotation name _ : rest -> [msg name] ++ go rest
96illFormedTypes :: [Declaration t v] -> [Doc]
97illFormedTypes decls = map report (Maybe.mapMaybe isIllFormed (aliases ++ adts))
99 aliases = [ (decl, tvars, [tipe]) | decl@(TypeAlias _ tvars tipe) <- decls ]
100 adts = [ (decl, tvars, concatMap snd ctors) | decl@(Datatype _ tvars ctors) <- decls ]
104 T.Lambda t1 t2 -> Set.union (freeVars t1) (freeVars t2)
105 T.Var x -> Set.singleton x
106 T.Data _ ts -> Set.unions (map freeVars ts)
107 T.EmptyRecord -> Set.empty
108 T.Record fields ext -> Set.unions (freeVars ext : map (freeVars . snd) fields)
110 undeclared tvars tipes = Set.difference used declared
112 used = Set.unions (map freeVars tipes)
113 declared = Set.fromList tvars
115 isIllFormed (decl, tvars, tipes) =
116 let unbound = undeclared tvars tipes in
117 if Set.null unbound then Nothing
118 else Just (decl, Set.toList unbound)
120 report (decl, tvars) =
121 P.vcat [ P.text $ "Error: type variable" ++ listing ++ " unbound in:"
123 , nest 4 (pretty decl) ]
127 [tvar] -> " " ++ quote tvar ++ " is"
128 _ -> "s" ++ addCommas (map ((++) " ") (addAnd (map quote tvars))) ++ " are"
131 | length xs < 3 = concat xs
132 | otherwise = intercalate "," xs
136 | otherwise = zipWith (++) (replicate (length xs - 1) "" ++ ["and "]) xs
138 quote tvar = "'" ++ tvar ++ "'"
141infiniteTypeAliases :: [Declaration t v] -> [Doc]
142infiniteTypeAliases decls =
143 [ report decl | decl@(TypeAlias name _ tipe) <- decls, isInfinite name tipe ]
145 isInfinite name tipe =
146 let infinite = isInfinite name in
148 T.Lambda a b -> infinite a || infinite b
150 T.Data name' ts -> name == name' || any infinite ts
151 T.EmptyRecord -> False
152 T.Record fields ext -> infinite ext || any (infinite . snd) fields
154 report decl@(TypeAlias name args tipe) =
155 P.vcat [ P.text $ eightyCharLines 0 msg1
157 , P.text $ eightyCharLines 0 msg2
158 , indented (Datatype name args [(name,[tipe])])
159 , P.text $ eightyCharLines 0 msg3 ++ "\n"
162 indented decl = P.text "\n " <> pretty decl <> P.text "\n"
164 msg1 = "Type alias '" ++ name ++ "' is an infinite type. " ++
165 "Notice that it appears in its own definition, so when \
166 \you expand it, it just keeps getting bigger:"
167 msg2 = "Try this instead:"
168 msg3 = "It looks very similar, but an algebraic data type (ADT) \
169 \actually creates a new type. Unlike with a type alias, this \
170 \freshly created type is meaningful on its own, so an ADT \
171 \does not need to be expanded."
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