@@ -2,9 +2,15 @@
2module Reporting.Error.Syntax where
2module Reporting.Error.Syntax where
4import qualified Data.Aeson as Json
4import qualified Data.Aeson as Json
5+import qualified Data.List as List
5import qualified Text.Parsec.Error as Parsec
6import qualified Text.Parsec.Error as Parsec
7+import qualified Text.PrettyPrint as P
8+import Text.PrettyPrint ((<+>))
7−import qualified Reporting.Region as R
10+import qualified AST.Helpers as Help
11+import qualified AST.Type as Type
12+import Elm.Utils ((|>))
13+import qualified Reporting.PrettyPrint as P
@@ -15,15 +21,103 @@ data Error
15 | DuplicateValueDeclaration String
21 | DuplicateValueDeclaration String
16 | DuplicateTypeDeclaration String
22 | DuplicateTypeDeclaration String
17 | DuplicateDefinition String
23 | DuplicateDefinition String
18− | UnboundTypeVar String String
24+ | UnboundTypeVarsInAlias String [String] String [String] Type.Raw
25+ | UnboundTypeVarsInUnion String [String] String [String] [(String, [Type.Raw])]
21-- TO STRING
28-- TO STRING
23−toString :: R.Region -> Error -> String
30+toHint :: Error -> String
24−toString region err =
31+toHint err =
25 case err of
32 case err of
26− _ -> error "Syntax.toString" region
33+ Parse messages ->
34+ error "TODO" messages
36+ InfixDuplicate opName ->
37+ "The infix declarations for " ++ operator ++ " must be removed.\n\n"
38+ ++ "The precedence and associativity can only be set in one place, and\n"
39+ ++ "this information has already been set somewhere else."
43+ then "(" ++ opName ++ ")"
44+ else "`" ++ opName ++ "`"
46+ TypeWithoutDefinition valueName ->
47+ "There is a type annotation for '" ++ valueName ++ "' but there"
48+ ++ "is no corresponding definition! I need something like this:\n\n"
49+ ++ " " ++ valueName ++ " = 42\n\n"
50+ ++ "And be sure to put the definition directly below the type annotation."
52+ PortWithoutAnnotation portName ->
53+ "There is a port named '" ++ portName ++ "' but it does not have"
54+ ++ "a type annotation! I need something like this:\n\n"
55+ ++ indent ("port " ++ portName ++ " : Signal Int") ++ "\n\n"
56+ ++ "And be sure to put this annotation directly above the port definition."
58+ DuplicateValueDeclaration name ->
59+ "Multiple top-level declarations define '" ++ name ++ "',\n"
60+ ++ "but the name overlap makes all uses of '" ++ name ++ "' ambiguous.\n"
61+ ++ "How can we know which you want?!\n\n"
62+ ++ "Find all the top-level variables named '" ++ name ++ "' and\n"
63+ ++ "do some renaming. Make sure the names are distinct!"
65+ DuplicateTypeDeclaration tipeName ->
66+ "Multiple declarations define a type '" ++ tipeName ++ "',\n"
67+ ++ "but the name overlap makes all uses of '" ++ tipeName ++ "' ambiguous.\n"
68+ ++ "How can we know which you want?!\n\n"
69+ ++ "Find all the types named '" ++ tipeName ++ "' and\n"
70+ ++ "do some renaming. Make sure the names are distinct!"
72+ DuplicateDefinition name ->
73+ "This let-expression defines multiple variables named '" ++ name ++ "',\n"
74+ ++ "but the name overlap makes all uses of '" ++ name ++ "' ambiguous.\n"
75+ ++ "How can we know which you want?!\n\n"
76+ ++ "Find the variables named '" ++ name ++ "' in this let-expression and\n"
77+ ++ "do some renaming. Make sure the names are distinct!"
79+ UnboundTypeVarsInAlias typeName givenVars tvar tvars tipe ->
80+ unboundTypeVars typeName tvar tvars $ P.render $
82+ (P.text "type alias" <+> P.text typeName <+> P.hsep vars <+> P.equals)
84+ (P.pretty False tipe)
86+ vars = map P.text (givenVars ++ tvar : tvars)
89+ UnboundTypeVarsInUnion typeName givenVars tvar tvars ctors ->
90+ unboundTypeVars typeName tvar tvars $ P.render $
92+ [ P.text "type" <+> P.text typeName <+> P.hsep vars
94+ |> zipWith (<+>) (P.text "=" : repeat (P.text "|"))
99+ vars = map P.text (givenVars ++ tvar : tvars)
100+ toDoc (ctor, args) =
101+ P.text ctor <+> P.hsep (map (P.pretty True) args)
104+unboundTypeVars :: String -> String -> [String] -> String -> String
105+unboundTypeVars typeName tvar tvars revisedDeclaration =
106+ "In the definition of type '" ++ typeName ++ "' you use the following\n"
107+ ++ "unbound type variable" ++ s ++ ": " ++ List.intercalate ", " (tvar:tvars) ++ "\n\n"
108+ ++ "All type variables must be listed to avoid sneaky type errors.\n"
109+ ++ "Imagine one '" ++ typeName ++ "' where '" ++ tvar ++ "' is an Int and\n"
110+ ++ "another where it is a Bool. They both look like a '" ++ typeName ++ "'\n"
111+ ++ "to the type checker, but they are actually different types!\n\n"
112+ ++ "Maybe you want a definition like this?\n\n"
113+ ++ indent revisedDeclaration ++ "\n\n"
115+ s = if null tvars then "" else "s"
118+indent :: String -> String
120+ List.intercalate "\n" (map (" " ++ ) (lines string))
29-- TO JSON
123-- TO JSON
@@ -32,4 +126,3 @@ toJson :: Error -> Json.Value
32toJson err =
126toJson err =
33 case err of
127 case err of
34 _ -> error "Syntax.toJson"
128 _ -> error "Syntax.toJson"