on master help sign in
Improve the error for bad (++) usages
20e9c3cEvan Czaplicki
src/Reporting/Error/Type.hs+110−29
@@ -22,7 +22,6 @@ module Reporting.Error.Type
22import Prelude hiding (round)
22import Prelude hiding (round)
23import Data.Monoid ((<>))
23import Data.Monoid ((<>))
24
24
25−import qualified AST.Module.Name as ModuleName
26import qualified Data.Index as Index
25import qualified Data.Index as Index
27import qualified Elm.Name as N
26import qualified Elm.Name as N
28import qualified Reporting.Helpers as H
27import qualified Reporting.Helpers as H
@@ -1009,7 +1008,7 @@ opLeftToDocs localizer category op tipe expected =
1009 "<=" -> badCompLeft localizer category "<=" "left" tipe expected
1008 "<=" -> badCompLeft localizer category "<=" "left" tipe expected
1010 ">=" -> badCompLeft localizer category ">=" "left" tipe expected
1009 ">=" -> badCompLeft localizer category ">=" "left" tipe expected
1011
1010
1012− "++" -> badAppend localizer category "left" tipe expected
1011+ "++" -> badAppendLeft localizer category tipe expected
1013
1012
1014 "<|" ->
1013 "<|" ->
1015 ( "The left side of (<|) needs to be a function so I can pipe arguments to it!"
1014 ( "The left side of (<|) needs to be a function so I can pipe arguments to it!"
@@ -1086,7 +1085,7 @@ opRightToDocs localizer category op tipe expected =
1086 "/=" -> badEquality localizer "/=" tipe expected
1085 "/=" -> badEquality localizer "/=" tipe expected
1087
1086
1088 "::" -> error "TODO"
1087 "::" -> error "TODO"
1089− "++" -> EmphRight $ badAppend localizer category "right" tipe expected
1088+ "++" -> badAppendRight localizer category tipe expected
1090
1089
1091 "<|" ->
1090 "<|" ->
1092 EmphRight
1091 EmphRight
@@ -1159,7 +1158,7 @@ isInt :: T.Type -> Bool
1159isInt tipe =
1158isInt tipe =
1160 case tipe of
1159 case tipe of
1161 T.Type home name [] ->
1160 T.Type home name [] ->
1162− home == ModuleName.basics && name == N.int
1161+ T.isInt home name
1163
1162
1164 _ ->
1163 _ ->
1165 False
1164 False
@@ -1169,7 +1168,7 @@ isFloat :: T.Type -> Bool
1169isFloat tipe =
1168isFloat tipe =
1170 case tipe of
1169 case tipe of
1171 T.Type home name [] ->
1170 T.Type home name [] ->
1172− home == ModuleName.basics && name == N.float
1171+ T.isFloat home name
1173
1172
1174 _ ->
1173 _ ->
1175 False
1174 False
@@ -1179,7 +1178,7 @@ isString :: T.Type -> Bool
1179isString tipe =
1178isString tipe =
1180 case tipe of
1179 case tipe of
1181 T.Type home name [] ->
1180 T.Type home name [] ->
1182− home == ModuleName.string && name == N.string
1181+ T.isString home name
1183
1182
1184 _ ->
1183 _ ->
1185 False
1184 False
@@ -1189,7 +1188,7 @@ isList :: T.Type -> Bool
1189isList tipe =
1188isList tipe =
1190 case tipe of
1189 case tipe of
1191 T.Type home name [_] ->
1190 T.Type home name [_] ->
1192− home == ModuleName.list && name == N.list
1191+ T.isList home name
1193
1192
1194 _ ->
1193 _ ->
1195 False
1194 False
@@ -1199,53 +1198,135 @@ isList tipe =
1199-- BAD APPEND
1198-- BAD APPEND
1200
1199
1201
1200
1202−badAppend :: T.Localizer -> Category -> String -> T.Type -> T.Type -> (H.Doc, H.Doc)
1201+data AppendType
1203−badAppend localizer category direction tipe expected =
1202+ = ANumber H.Doc H.Doc
1204− let
1203+ | AString
1205− maybeDetails =
1204+ | AList
1206− case tipe of
1205+ | AOther
1207− T.Type home name []
1208− | ModuleName.basics == home && name == N.int -> Just ("ints", "String.fromInt")
1209− | ModuleName.basics == home && name == N.float -> Just ("floats", "String.fromFloat")
1210
1206
1211− T.FlexSuper T.Number _ ->
1212− Just ("numbers", "String.fromInt")
1213
1207
1214− _ ->
1208+toAppendType :: T.Type -> AppendType
1215− Nothing
1209+toAppendType tipe =
1216− in
1217− case maybeDetails of
1210+ case tipe of
1211+ T.Type home name _
1212+ | T.isInt home name -> ANumber "Int" "String.fromInt"
1213+ | T.isFloat home name -> ANumber "Float" "String.fromFloat"
1214+ | T.isString home name -> AString
1215+ | T.isList home name -> AList
1216+
1217+ T.FlexSuper T.Number _ -> ANumber "number" "String.fromInt"
1218+
1219+ _ -> AOther
1220+
1221+
1222+badAppendLeft :: T.Localizer -> Category -> T.Type -> T.Type -> (H.Doc, H.Doc)
1223+badAppendLeft localizer category tipe expected =
1224+ case toAppendType tipe of
1218− Just (things, stringFromThing) ->
1225+ ANumber thing stringFromThing ->
1219 (
1226 (
1220 H.fillSep
1227 H.fillSep
1228+ ["The","(++)","operator","can","append"
1221− ["The","(++)","operator","is","for","appending",H.dullyellow "List","and"
1229+ ,H.dullyellow "List","and",H.dullyellow "String"
1222− ,H.dullyellow "String","values,","not",H.dullyellow things,"like","this:"
1230+ ,"values,","but","not",H.dullyellow thing,"values","like","this:"
1223 ]
1231 ]
1224 ,
1232 ,
1225 H.fillSep
1233 H.fillSep
1226− ["Try","using",H.green stringFromThing,"to","turn","it","into","a"
1234+ ["Try","using",H.green stringFromThing,"to","turn","it","into","a","string?"
1227− ,H.dullyellow "String" <> "?"
1235+ ,"Or","put","it","in","[]","to","make","it","a","list?"
1236+ ,"Or","switch","to","the","(::)","operator?"
1228 ]
1237 ]
1229 )
1238 )
1230
1239
1231− Nothing ->
1240+ _ ->
1232 (
1241 (
1233 H.reflow $
1242 H.reflow $
1234 "The (++) operator cannot append this type of value:"
1243 "The (++) operator cannot append this type of value:"
1235 ,
1244 ,
1236 loneType localizer tipe expected
1245 loneType localizer tipe expected
1237− ( H.reflow $ toDescription category $
1246+ ( H.reflow $ toDescription category "I am seeing"
1238− "The " <> direction <> " side of (++) is"
1239 ,
1247 ,
1240 [ H.fillSep
1248 [ H.fillSep
1241 ["But","the","(++)","operator","is","only","for","appending"
1249 ["But","the","(++)","operator","is","only","for","appending"
1242 ,H.dullyellow "List","and",H.dullyellow "String","values."
1250 ,H.dullyellow "List","and",H.dullyellow "String","values."
1251+ ,"Maybe","put","this","value","in","[]","to","make","it","a","list?"
1243 ]
1252 ]
1244 ]
1253 ]
1245 )
1254 )
1246 )
1255 )
1247
1256
1248
1257
1258+badAppendRight :: T.Localizer -> Category -> T.Type -> T.Type -> RightDocs
1259+badAppendRight localizer category tipe expected =
1260+ case (toAppendType expected, toAppendType tipe) of
1261+ (AString, ANumber thing stringFromThing) ->
1262+ EmphRight
1263+ (
1264+ H.fillSep
1265+ ["I","thought","I","was","appending",H.dullyellow "String","values","here,"
1266+ ,"not",H.dullyellow thing,"values","like","this:"
1267+ ]
1268+ ,
1269+ H.fillSep
1270+ ["Try","using",H.green stringFromThing
1271+ ,"to","turn","it","into","a","string?"
1272+ ]
1273+ )
1274+
1275+ (AList, ANumber thing _) ->
1276+ EmphRight
1277+ (
1278+ H.fillSep
1279+ ["I","thought","I","was","appending",H.dullyellow "List","values","here,"
1280+ ,"not",H.dullyellow thing,"values","like","this:"
1281+ ]
1282+ ,
1283+ H.reflow "Try putting it in [] to make it a list?"
1284+ )
1285+
1286+ (AString, AList) ->
1287+ EmphBoth
1288+ (
1289+ H.reflow $
1290+ "The (++) operator needs the same type of value on both sides:"
1291+ ,
1292+ H.fillSep
1293+ ["I","see","a",H.dullyellow "String","on","the","left","and","a"
1294+ ,H.dullyellow "List","on","the","right.","Which","should","it","be?"
1295+ ,"Does","the","string","need","[]","around","it","to","become","a","list?"
1296+ ]
1297+ )
1298+
1299+ (AList, AString) ->
1300+ EmphBoth
1301+ (
1302+ H.reflow $
1303+ "The (++) operator needs the same type of value on both sides:"
1304+ ,
1305+ H.fillSep
1306+ ["I","see","a",H.dullyellow "List","on","the","left","and","a"
1307+ ,H.dullyellow "String","on","the","right.","Which","should","it","be?"
1308+ ,"Does","the","string","need","[]","around","it","to","become","a","list?"
1309+ ]
1310+ )
1311+
1312+ (_,_) ->
1313+ EmphBoth
1314+ (
1315+ H.reflow $
1316+ "The (++) operator cannot append these two values:"
1317+ ,
1318+ typeComparison localizer tipe expected
1319+ (
1320+ "I already figured out that the left side of (++) is:"
1321+ ,
1322+ toDescription category $
1323+ "But this clashes with the right side, which is"
1324+ ,
1325+ []
1326+ )
1327+ )
1328+
1329+
1249
1330
1250-- BAD MATH
1331-- BAD MATH
1251
1332
src/Type/Error.hs+4
@@ -9,6 +9,10 @@ module Type.Error
9 , toDoc
9 , toDoc
10 , toDiffDocs
10 , toDiffDocs
11 , Problem(..)
11 , Problem(..)
12+ , isInt
13+ , isFloat
14+ , isString
15+ , isList
12 )
16 )
13 where
17 where
14
18