1{-# OPTIONS_GHC -Wall #-}
2module Reporting.Error.Syntax where
4import qualified Data.List as List
5import qualified Data.Set as Set
6import qualified Text.Parsec.Error as Parsec
8import qualified AST.Helpers as Help
9import qualified AST.Type as Type
10import qualified Reporting.Render.Type as RenderType
11import qualified Reporting.Report as Report
15 = Parse [Parsec.Message]
18 | InfixDuplicate String
19 | TypeWithoutDefinition String
20 | PortWithoutAnnotation String
22 | DuplicateFieldName String
23 | DuplicateValueDeclaration String
24 | DuplicateTypeDeclaration String
25 | DuplicateDefinition String
26 | UnboundTypeVarsInAlias String [String] String [String] Type.Raw
27 | UnboundTypeVarsInUnion String [String] String [String] [(String, [Type.Raw])]
32toReport :: RenderType.Localizer -> Error -> Report.Report
33toReport localizer err =
36 parseErrorReport messages
38 BadFunctionName arity ->
40 "BAD FUNCTION DEFINITION"
41 "Complex patterns cannot be used as function names."
42 ( "This function definition has " ++ show arity ++ " arguments, but instead of a normal name like\n"
43 ++ "`add` or `reverse` it has a pattern. There is no way to \"deconstruct\" a\n"
44 ++ "function with pattern matching, so this needs to be changed to a normal name."
50 ("The free variable `" ++ name ++ "` appears more than once in this pattern.")
51 ( "Rename the variables so there are no duplicates.\n\n"
52 ++ "In Elm, pattern matching works by binding these free variables to subsections\n"
53 ++ "of the matching value. It does not make sense to have the same name for two\n"
54 ++ "different subsections though! When you say `" ++ name ++ "` in some code, there\n"
55 ++ "is no way for me to know which subsection you mean!"
58 InfixDuplicate opName ->
61 ("The infix declarations for " ++ operator ++ " must be removed.")
62 ("The precedence and associativity can only be set in one place, and\n"
63 ++ "this information has already been set somewhere else."
68 then "(" ++ opName ++ ")"
69 else "`" ++ opName ++ "`"
71 TypeWithoutDefinition valueName ->
74 ("There is a type annotation for `" ++ valueName ++ "` but there"
75 ++ " is no corresponding definition!"
77 ("Directly below the type annotation, put a definition like:\n\n"
78 ++ " " ++ valueName ++ " = 42"
81 PortWithoutAnnotation portName ->
84 ("Port `" ++ portName ++ "` does not have a type annotation!")
85 ("Directly above the port definition, I need something like this:\n\n"
86 ++ " port " ++ portName ++ " : Signal Int"
93 "This module has ports, but ports can only appear in the main module."
94 ( "Ports in library code would create hidden dependencies where importing a\n"
95 ++ "module could bring in constraints not captured in the public API. Furthermore,\n"
96 ++ "if the module is imported twice, do we send values out the port twice?"
99 DuplicateFieldName name ->
102 ("This record has more than one field named `" ++ name ++ "`.")
103 "There can only be one. Do some renaming to make sure the names are distinct!"
105 DuplicateValueDeclaration name ->
107 "DUPLICATE DEFINITION"
108 ("Naming multiple top-level values `" ++ name ++ "` makes things\n"
109 ++ "ambiguous. When you say `" ++ name ++ "` which one do you want?"
111 ("Find all the top-level values named `" ++ name ++ "` and\n"
112 ++ "do some renaming. Make sure the names are distinct!"
115 DuplicateTypeDeclaration name ->
117 "DUPLICATE DEFINITION"
118 ("Naming multiple types `" ++ name ++ "` makes things ambiguous\n"
119 ++ "When you say `" ++ name ++ "` which one do you want?"
121 ("Find all the types named `" ++ name ++ "` and\n"
122 ++ "do some renaming. Make sure the names are distinct!"
125 DuplicateDefinition name ->
127 "DUPLICATE DEFINITION"
128 ("Naming multiple values `" ++ name ++ "` in a single let-expression makes\n"
129 ++ "things ambiguous. When you say `" ++ name ++ "` which one do you want?"
131 ("Find all the values named `" ++ name ++ "` in this let-expression and\n"
132 ++ "do some renaming. Make sure the names are distinct!"
135 UnboundTypeVarsInAlias typeName givenVars tvar tvars tipe ->
136 unboundTypeVars typeName tvar tvars $
137 RenderType.aliasDecl localizer typeName (givenVars ++ tvar : tvars) tipe
139 UnboundTypeVarsInUnion typeName givenVars tvar tvars ctors ->
140 unboundTypeVars typeName tvar tvars $
141 RenderType.typeDecl localizer typeName (givenVars ++ tvar : tvars) ctors
144unboundTypeVars :: String -> String -> [String] -> String -> Report.Report
145unboundTypeVars typeName tvar tvars revisedDeclaration =
148 ( "Not all type variables in `" ++ typeName ++ "` are listed, making sneaky\n"
149 ++ "type errors possible. Unbound type variables include: "
150 ++ List.intercalate ", " (tvar:tvars)
152 ( "You probably want this definition instead:\n"
153 ++ concatMap ("\n "++) (lines revisedDeclaration) ++ "\n\n"
154 ++ "Here's why. Imagine one `" ++ typeName ++ "` where `" ++ tvar ++ "` is an Int and\n"
155 ++ "another where it is a Bool. When we explicitly list the type variables, type\n"
156 ++ "checker can see that they are actually different types."
160-- TAGGING PARSE ERRORS
166freshLine = "FRESH_LINE"
169whitespace = "WHITESPACE"
171keyword :: String -> String
175unkeyword :: String -> Maybe String
177 if List.isPrefixOf "KEYWORD=" message
178 then Just (drop (length "KEYWORD=") message)
182-- REPORTING PARSE ERRORS
184parseErrorReport :: [Parsec.Message] -> Report.Report
185parseErrorReport messages =
187 addMsg message hint =
189 Parsec.SysUnExpect _msg ->
192 Parsec.UnExpect _msg ->
198 if msg `elem` [whitespace, newline, freshLine]
202 hint { _expected = Set.insert msg' (_expected hint) }
204 Parsec.Message msg ->
205 hint { _messages = msg : _messages hint }
207 (ParseHint msgs expects) =
208 foldr addMsg emptyHint messages
213 case unkeyword msg of
215 "It looks like the keyword `" ++ kwd ++ "` is being used as a variable.\n"
216 ++ "Try renaming it to something else."
220 _ -> "I ran into something unexpected when parsing your code!"
226 "I am looking for one of the following things:\n"
227 ++ concatMap ("\n "++) (Set.toList expects)
229 Report.simple "SYNTAX PROBLEM" preHint postHint
232data ParseHint = ParseHint
233 { _messages :: [String]
234 , _expected :: Set.Set String
239emptyHint :: ParseHint
241 ParseHint [] Set.empty
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