on master help sign in
Add parse error messages for operators and field accessors
5ce58a1Evan Czaplicki
compiler/src/Parse/Expression.hs+4−3
@@ -273,7 +273,7 @@ chompExprEnd start (State ops expr args end) =
273 , -- operator
273 , -- operator
274 do Space.checkIndent end E.IndentMoreExpr
274 do Space.checkIndent end E.IndentMoreExpr
275 op@(A.At (A.Region opStart opEnd) opName) <- addLocation (Symbol.operator E.Start E.OperatorReserved)
275 op@(A.At (A.Region opStart opEnd) opName) <- addLocation (Symbol.operator E.Start E.OperatorReserved)
276− Space.chompAndCheckIndent E.Space E.IndentOperatorRight
276+ Space.chompAndCheckIndent E.Space (E.IndentOperatorRight opName)
277 newStart <- getPosition
277 newStart <- getPosition
278 if "-" == opName && end /= opStart && opEnd == newStart
278 if "-" == opName && end /= opStart && opEnd == newStart
279 then
279 then
@@ -284,7 +284,8 @@ chompExprEnd start (State ops expr args end) =
284 let arg = A.at opStart newEnd (Src.Negate negatedExpr)
284 let arg = A.at opStart newEnd (Src.Negate negatedExpr)
285 chompExprEnd start (State ops expr (arg:args) newEnd)
285 chompExprEnd start (State ops expr (arg:args) newEnd)
286 else
286 else
287− oneOf E.OperatorRight
287+ let err = E.OperatorRight opName in
288+ oneOf err
288 [ -- term
289 [ -- term
289 do newExpr <- possiblyNegativeTerm newStart
290 do newExpr <- possiblyNegativeTerm newStart
290 newEnd <- getPosition
291 newEnd <- getPosition
@@ -294,7 +295,7 @@ chompExprEnd start (State ops expr args end) =
294
295
295 , -- final term
296 , -- final term
296 do (newLast, newEnd) <-
297 do (newLast, newEnd) <-
297− oneOf E.OperatorRight
298+ oneOf err
298 [ let_ newStart
299 [ let_ newStart
299 , case_ newStart
300 , case_ newStart
300 , if_ newStart
301 , if_ newStart
compiler/src/Reporting/Error/Syntax.hs+198−117
@@ -231,8 +231,7 @@ data Expr
231 --
231 --
232 | Dot Row Col
232 | Dot Row Col
233 | Access Row Col
233 | Access Row Col
234− | OperatorRHS Row Col
235− | OperatorRight Row Col
234+ | OperatorRight Name.Name Row Col
236 | OperatorReserved Operator Row Col
235 | OperatorReserved Operator Row Col
237 --
236 --
238 | Start Row Col
237 | Start Row Col
@@ -242,7 +241,7 @@ data Expr
242 | Space Space Row Col
241 | Space Space Row Col
243 | EndlessShader Row Col
242 | EndlessShader Row Col
244 | ShaderProblem [Char.Char] Row Col
243 | ShaderProblem [Char.Char] Row Col
245− | IndentOperatorRight Row Col
244+ | IndentOperatorRight Name.Name Row Col
246 | IndentMoreExpr Row Col
245 | IndentMoreExpr Row Col
247
246
248
247
@@ -791,7 +790,7 @@ toDeclDefReport source name declDef _ _ =
791
790
792
791
793toExprReport :: Code.Source -> Name.Name -> Expr -> Row -> Col -> Report.Report
792toExprReport :: Code.Source -> Name.Name -> Expr -> Row -> Col -> Report.Report
794−toExprReport source _ expr _ _ =
793+toExprReport source name expr _ _ =
795 case expr of
794 case expr of
796 Let _ _ _ ->
795 Let _ _ _ ->
797 error "TODO Let"
796 error "TODO Let"
@@ -817,20 +816,58 @@ toExprReport source _ expr _ _ =
817 Func _ _ _ ->
816 Func _ _ _ ->
818 error "TODO Func"
817 error "TODO Func"
819
818
820− Dot _ _ ->
819+ Dot row col ->
821− error "TODO Dot"
820+ let region = toRegion row col in
822−
821+ Report.Report "EXPECTING RECORD ACCESSOR" region [] $
823− Access _ _ ->
822+ Report.toCodeSnippet source region Nothing
824− error "TODO Access"
823+ (
824+ D.reflow $
825+ "I was expecting to see a record accessor here:"
826+ ,
827+ D.fillSep
828+ ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
829+ ,"that","accesses","a","value","from","a","record."
830+ ]
831+ )
825
832
826− OperatorRHS _ _ ->
833+ Access row col ->
827− error "TODO OperatorRHS"
834+ let region = toRegion row col in
835+ Report.Report "EXPECTING RECORD ACCESSOR" region [] $
836+ Report.toCodeSnippet source region Nothing
837+ (
838+ D.reflow $
839+ "I am trying to parse a record accessor here:"
840+ ,
841+ D.stack
842+ [
843+ D.fillSep
844+ ["Something","like",D.dullyellow".name","or",D.dullyellow".price"
845+ ,"that","accesses","a","value","from","a","record."
846+ ]
847+ ,
848+ D.toSimpleNote $
849+ "Record field names must start with a lower case letter!"
850+ ]
851+ )
828
852
829− OperatorRight _ _ ->
853+ OperatorRight op row col ->
830− error "TODO OperatorRight"
854+ let region = toRegion row col in
855+ Report.Report "MISSING EXPRESSION" region [] $
856+ Report.toCodeSnippet source region Nothing
857+ (
858+ D.reflow $
859+ "I need to see an expression after this " ++ Name.toChars op ++ " operator:"
860+ ,
861+ D.fillSep $
862+ ["You","can","just","put","anything","for","now,","like"
863+ ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
864+ ,"Once","there","is","something","there,","I","can","give","more"
865+ ,"specific","hints","about","what","type","of","value","is","needed!"
866+ ]
867+ )
831
868
832− OperatorReserved _ _ _ ->
869+ OperatorReserved operator row col ->
833− error "TODO OperatorReserved"
870+ toOperatorReport source name operator row col
834
871
835 Start _ _ ->
872 Start _ _ ->
836 error "TODO Start"
873 error "TODO Start"
@@ -877,8 +914,29 @@ toExprReport source _ expr _ _ =
877 ]
914 ]
878 )
915 )
879
916
880− IndentOperatorRight _ _ ->
917+ IndentOperatorRight op row col ->
881− error "TODO IndentOperatorRight"
918+ let region = toRegion row col in
919+ Report.Report "MISSING EXPRESSION" region [] $
920+ Report.toCodeSnippet source region Nothing
921+ (
922+ D.reflow $
923+ "I need to see an expression after this " ++ Name.toChars op ++ " operator:"
924+ ,
925+ D.stack
926+ [
927+ D.fillSep $
928+ ["You","can","just","put","anything","for","now,","like"
929+ ,D.dullyellow "42","or",D.dullyellow"\"hello\"" <> "."
930+ ,"Once","there","is","something","there,","I","can","give","more"
931+ ,"specific","hints","about","what","type","of","value","is","needed!"
932+ ]
933+ ,
934+ D.toSimpleNote $
935+ "I may be getting confused by your indentation? The easiest way to make sure\
936+ \ this is not an indentation problem is to put the expression on the right of\
937+ \ the " ++ Name.toChars op ++ " operator on the same line."
938+ ]
939+ )
882
940
883 IndentMoreExpr _ _ ->
941 IndentMoreExpr _ _ ->
884 error "TODO IndentMoreExpr"
942 error "TODO IndentMoreExpr"
@@ -1145,6 +1203,129 @@ toNumberReport source number row col =
1145 )
1203 )
1146
1204
1147
1205
1206+toOperatorReport :: Code.Source -> Name.Name -> Operator -> Row -> Col -> Report.Report
1207+toOperatorReport source name operator row col =
1208+ case operator of
1209+ OpDot ->
1210+ let
1211+ region = toRegion row col
1212+ in
1213+ Report.Report "UNEXPECTED SYMBOL" region [] $
1214+ Report.toCodeSnippet source region Nothing
1215+ (
1216+ "I was not expecting this dot:"
1217+ ,
1218+ D.reflow $
1219+ "Dots are for record access and decimal points, so\
1220+ \ they cannot float around on their own. Maybe\
1221+ \ there is some extra whitespace?"
1222+ )
1223+
1224+ OpPipe ->
1225+ let
1226+ region = toRegion row col
1227+ in
1228+ Report.Report "UNEXPECTED SYMBOL" region [] $
1229+ Report.toCodeSnippet source region Nothing
1230+ (
1231+ D.reflow $
1232+ "I was not expecting this vertical bar:"
1233+ ,
1234+ D.reflow $
1235+ "Vertical bars should only appear in custom type declarations. Maybe you want || instead?"
1236+ )
1237+
1238+ OpArrow ->
1239+ let
1240+ region = toWiderRegion row col 2
1241+ in
1242+ Report.Report "UNEXPECTED ARROW" region [] $
1243+ Report.toCodeSnippet source region Nothing $
1244+ if error "TODO inCase" then
1245+ (
1246+ D.reflow $
1247+ "I was not expecting to see an arrow here:"
1248+ ,
1249+ D.stack
1250+ [
1251+ D.reflow $
1252+ "I think I am parsing a `case` expression right now, so it makes sense to\
1253+ \ see arrows around here. This one is confusing me though!"
1254+ ,
1255+ D.toSimpleHint $
1256+ "I may be getting confused by the indentation. Every pattern in a `case` must be\
1257+ \ exactly aligned (with exactly the same amount of indentation) so maybe this arrow\
1258+ \ appears after the next `case` pattern (correctly!) but the pattern itself is\
1259+ \ indented too far?"
1260+ ]
1261+ )
1262+
1263+ else
1264+ (
1265+ D.reflow $
1266+ "I was not expecting an arrow here:"
1267+ ,
1268+ D.reflow $
1269+ "Arrows should only appear in `case` expressions and anonymous functions. Maybe\
1270+ \ you want > or >= instead?"
1271+ )
1272+
1273+ OpEquals ->
1274+ let
1275+ region = toRegion row col
1276+ in
1277+ Report.Report "UNEXPECTED EQUALS" region [] $
1278+ Report.toCodeSnippet source region Nothing
1279+ (
1280+ D.reflow $
1281+ "I was not expecting to see this equals sign:"
1282+ ,
1283+ D.stack
1284+ [
1285+ D.reflow "Maybe you want == instead? To check if two values are equal?"
1286+ ,
1287+ D.toSimpleNote $
1288+ if error "TODO is within record?" then
1289+ "Records look like { x = 3, y = 4 } with the equals sign right\
1290+ \ after the field name. So maybe you forgot a comma?"
1291+ else
1292+ "I may be getting confused by your indentation. Is this supposed to be part of\
1293+ \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1294+ \ the problem may be a bit before the equals sign. I need all definitions to\
1295+ \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1296+ \ this new definition is indented a bit too much."
1297+ ]
1298+ )
1299+
1300+ OpHasType ->
1301+ let
1302+ region = toRegion row col
1303+ in
1304+ Report.Report "UNEXPECTED SYMBOL" region [] $
1305+ Report.toCodeSnippet source region Nothing $
1306+ (
1307+ D.reflow $
1308+ "I was not expecting to run into the \"has type\" symbol here:"
1309+ ,
1310+ D.stack
1311+ [
1312+ D.fillSep
1313+ ["Maybe","you","want",D.green "::","instead?"
1314+ ,"To","put","something","on","the","front","of","a","list?"
1315+ ]
1316+ , D.toSimpleNote $
1317+ "The single colon is reserved for type annotations and record types, but I think\
1318+ \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
1319+ ,
1320+ D.toSimpleNote $
1321+ "I may be getting confused by your indentation. Is this supposed to be part of\
1322+ \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
1323+ \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
1324+ \ be exactly aligned (with exactly the same indentation) so the problem may be that\
1325+ \ this new definition is indented a bit too much."
1326+ ]
1327+ )
1328+
1148
1329
1149{-
1330{-
1150 case err of
1331 case err of
@@ -1471,52 +1652,6 @@ problemToDocs problem =
1471 "Delete the underscore and it shoulld be fine!"
1652 "Delete the underscore and it shoulld be fine!"
1472 )
1653 )
1473
1654
1474− BadOp op stack ->
1475− case op of
1476− HasType ->
1477− badOp stack "A" "\"has type\" operator"
1478− "type annotations and record types"
1479− "Maybe you want :: instead? Or maybe something is indented too much?"
1480−
1481− Equals ->
1482− (
1483− "I was not expecting this equals sign"
1484− <> contextToString " here" " while parsing " stack <> "."
1485− ,
1486− toBadEqualsHint stack
1487− )
1488−
1489− Arrow ->
1490− if isCaseRelated stack then
1491− (
1492− "I ran into a stray arrow while parsing this `case` expression."
1493− ,
1494− D.reflow $
1495− "All branches in a `case` must be indented the exact\
1496− \ same amount, so the patterns are vertically\
1497− \ aligned. Maybe this branch is indented too much?"
1498− )
1499−
1500− else
1501− badOp stack "An" "arrow"
1502− "cases expressions and anonymous functions"
1503− "Maybe you want > or >= instead?"
1504−
1505− Pipe ->
1506− badOp stack "A" "vertical bar"
1507− "type declarations"
1508− "Maybe you want || instead?"
1509−
1510− Dot ->
1511− (
1512− "I was not expecting this dot."
1513− ,
1514− D.reflow $
1515− "Dots are for record access and decimal points, so\
1516− \ they cannot float around on their own. Maybe\
1517− \ there is some extra whitespace?"
1518− )
1519−
1520 Theories stack allTheories ->
1655 Theories stack allTheories ->
1521 (
1656 (
1522 D.reflow $
1657 D.reflow $
@@ -1548,60 +1683,6 @@ problemToDocs problem =
1548
1683
1549
1684
1550
1685
1551−-- BAD OP HELPERS
1552−
1553−
1554−badOp :: ContextStack -> String -> String -> String -> String -> ( D.Doc, D.Doc )
1555−badOp stack article opName setting hint =
1556− (
1557− D.reflow $
1558− "I was not expecting this " <> opName
1559− <> contextToString " here" " while parsing " stack <> "."
1560− ,
1561− D.reflow $
1562− article <> " " <> opName <> " should only appear in "
1563− <> setting <> ". " <> hint
1564− )
1565−
1566−
1567−toBadEqualsHint :: ContextStack -> D.Doc
1568−toBadEqualsHint stack =
1569− case stack of
1570− [] ->
1571− D.reflow $
1572− "Maybe you want == instead? Or maybe something is indented too much?"
1573−
1574− (ExprRecord, _) : _ ->
1575− D.reflow $
1576− "Records look like { x = 3, y = 4 } with the equals sign right\
1577− \ after the field name. Maybe you forgot a comma?"
1578−
1579− (Definition _, _) : rest ->
1580− D.reflow $
1581− "Maybe this is supposed to be a separate definition? If so, it\
1582− \ is indented too far. "
1583− <>
1584− if any ((==) ExprLet . fst) rest then
1585− "All definitions in a `let` expression must be vertically aligned."
1586− else
1587− "Spaces are not allowed before top-level definitions."
1588−
1589− _ : rest ->
1590− toBadEqualsHint rest
1591−
1592−
1593−
1594−isCaseRelated :: ContextStack -> Bool
1595−isCaseRelated stack =
1596− case stack of
1597− [] ->
1598− False
1599−
1600− (context, _) : rest ->
1601− context == ExprCase || isCaseRelated rest
1602−
1603−
1604−
1605-- CONTEXT
1686-- CONTEXT
1606
1687
1607
1688