on master help sign in
Add syntax messages for let defs and destructs
commit7c7dabb827c355fd8985bcfd90664485e2a9a7ee authorEvan Czaplicki <evancz@users.noreply.github.com> dateTue 21 May 2019, 16:42 (7 years ago) parentfb43331
2 files changed+341−34
compiler/src/Parse/Expression.hs+3−3 compiler/src/Reporting/Error/Syntax.hs+338−31
compiler/src/Parse/Expression.hs+3−3
@@ -535,19 +535,19 @@ chompDefArgsAndBody start name tipe revArgs =
535535chompMatchingName :: Name.Name -> Parser E.Def (A.Located Name.Name)
536536chompMatchingName expectedName =
537537 let
538− (P.Parser parserL) = Var.lower (E.DefNameRepeat expectedName)
538+ (P.Parser parserL) = Var.lower E.DefNameRepeat
539539 in
540540 P.Parser $ \state@(P.State _ _ _ sr sc) cok eok cerr eerr ->
541541 let
542542 cokL name newState@(P.State _ _ _ er ec) =
543543 if expectedName == name
544544 then cok (A.At (A.Region (A.Position sr sc) (A.Position er ec)) name) newState
545− else cerr sr sc (E.DefNameMatch expectedName name)
545+ else cerr sr sc (E.DefNameMatch name)
546546
547547 eokL name newState@(P.State _ _ _ er ec) =
548548 if expectedName == name
549549 then eok (A.At (A.Region (A.Position sr sc) (A.Position er ec)) name) newState
550− else eerr sr sc (E.DefNameMatch expectedName name)
550+ else eerr sr sc (E.DefNameMatch name)
551551 in
552552 parserL state cokL eokL cerr eerr
553553
compiler/src/Reporting/Error/Syntax.hs+338−31
@@ -325,8 +325,8 @@ data Let
325325data Def
326326 = DefSpace Space Row Col
327327 | DefType Type Row Col
328− | DefNameRepeat Name.Name Row Col
329− | DefNameMatch Name.Name Name.Name Row Col
328+ | DefNameRepeat Row Col
329+ | DefNameMatch Name.Name Row Col
330330 | DefArg Pattern Row Col
331331 | DefEquals Row Col
332332 | DefBody Expr Row Col
@@ -2005,7 +2005,7 @@ toDeclDefReport source name declDef startRow startCol =
20052005 D.stack
20062006 [ D.reflow $
20072007 "Type annotations always appear directly above the relevant\
2008− \ definition, without anything else (even doc comments) in between."
2008+ \ definition, without anything else in between. (Not even doc comments!)"
20092009 , declDefNote
20102010 ]
20112011 )
@@ -2109,6 +2109,7 @@ declDefNote =
21092109data Context
21102110 = InNode Node Row Col Context
21112111 | InDef Name.Name Row Col
2112+ | InDestruct Row Col
21122113
21132114
21142115data Node
@@ -2124,16 +2125,18 @@ data Node
21242125 deriving (Eq)
21252126
21262127
2127−getDefName :: Context -> Name.Name
2128+getDefName :: Context -> Maybe Name.Name
21282129getDefName context =
21292130 case context of
2130− InDef name _ _ -> name
2131+ InDestruct _ _ -> Nothing
2132+ InDef name _ _ -> Just name
21312133 InNode _ _ _ c -> getDefName c
21322134
21332135
21342136isWithin :: Node -> Context -> Bool
21352137isWithin desiredNode context =
21362138 case context of
2139+ InDestruct _ _ -> False
21372140 InDef _ _ _ -> False
21382141 InNode actualNode _ _ _ -> desiredNode == actualNode
21392142
@@ -2229,6 +2232,7 @@ toExprReport source context expr startRow startCol =
22292232 let
22302233 (contextRow, contextCol, aThing) =
22312234 case context of
2235+ InDestruct r c -> (r, c, "a definition")
22322236 InDef name r c -> (r, c, "the `" ++ Name.toChars name ++ "` definition")
22332237 InNode NRecord r c _ -> (r, c, "a record")
22342238 InNode NParens r c _ -> (r, c, "some parentheses")
@@ -2688,7 +2692,6 @@ toOperatorReport source context operator row col =
26882692 BadEquals ->
26892693 let
26902694 region = toRegion row col
2691− name = getDefName context
26922695 in
26932696 Report.Report "UNEXPECTED EQUALS" region [] $
26942697 Code.toSnippet source region Nothing
@@ -2705,18 +2708,24 @@ toOperatorReport source context operator row col =
27052708 "Records look like { x = 3, y = 4 } with the equals sign right\
27062709 \ after the field name. So maybe you forgot a comma?"
27072710 else
2708− "I may be getting confused by your indentation. Is this supposed to be part of\
2709− \ a definition AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2710− \ the problem may be a bit before the equals sign. I need all definitions to\
2711− \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2712− \ this new definition is indented a bit too much."
2711+ case getDefName context of
2712+ Nothing ->
2713+ "I may be getting confused by your indentation. I need all definitions to be indented\
2714+ \ exactly the same amount, so if this is meant to be a new definition, it may have too\
2715+ \ many spaces in front of it."
2716+
2717+ Just name ->
2718+ "I may be getting confused by your indentation. I think I am still parsing the `"
2719+ ++ Name.toChars name ++ "` definition. Is this supposed to be part of a definition\
2720+ \ after that? If so, the problem may be a bit before the equals sign. I need all\
2721+ \ definitions to be indented exactly the same amount, so the problem may be that\
2722+ \ this new definition has too many spaces in front of it."
27132723 ]
27142724 )
27152725
27162726 BadHasType ->
27172727 let
27182728 region = toRegion row col
2719− name = getDefName context
27202729 in
27212730 Report.Report "UNEXPECTED SYMBOL" region [] $
27222731 Code.toSnippet source region Nothing $
@@ -2724,23 +2733,31 @@ toOperatorReport source context operator row col =
27242733 D.reflow $
27252734 "I was not expecting to run into the \"has type\" symbol here:"
27262735 ,
2727− D.stack
2728− [
2736+ case getDefName context of
2737+ Nothing ->
27292738 D.fillSep
27302739 ["Maybe","you","want",D.green "::","instead?"
27312740 ,"To","put","something","on","the","front","of","a","list?"
27322741 ]
2733− , D.toSimpleNote $
2734− "The single colon is reserved for type annotations and record types, but I think\
2735− \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
2736− ,
2737− D.toSimpleNote $
2738− "I may be getting confused by your indentation. Is this supposed to be part of\
2739− \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2740− \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
2741− \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2742− \ this new definition is indented a bit too much."
2743− ]
2742+
2743+ Just name ->
2744+ D.stack
2745+ [
2746+ D.fillSep
2747+ ["Maybe","you","want",D.green "::","instead?"
2748+ ,"To","put","something","on","the","front","of","a","list?"
2749+ ]
2750+ , D.toSimpleNote $
2751+ "The single colon is reserved for type annotations and record types, but I think\
2752+ \ I am parsing the definition of `" ++ Name.toChars name ++ "` right now."
2753+ ,
2754+ D.toSimpleNote $
2755+ "I may be getting confused by your indentation. Is this supposed to be part of\
2756+ \ a type annotation AFTER the `" ++ Name.toChars name ++ "` definition? If so,\
2757+ \ the problem may be a bit before the \"has type\" symbol. I need all definitions to\
2758+ \ be exactly aligned (with exactly the same indentation) so the problem may be that\
2759+ \ this new definition is indented a bit too much."
2760+ ]
27442761 )
27452762
27462763
@@ -2824,10 +2841,10 @@ toLetReport source context let_ startRow startCol =
28242841 "I was expecting the name of a definition next."
28252842
28262843 LetDef name def row col ->
2827− error "TODO LetDef" name def row col
2844+ toLetDefReport source name def row col
28282845
28292846 LetDestruct destruct row col ->
2830− error "TODO LetDestruct" destruct row col
2847+ toLetDestructReport source destruct row col
28312848
28322849 LetBody expr row col ->
28332850 toExprReport source context expr row col
@@ -2883,6 +2900,294 @@ toUnfinishLetReport source row col startRow startCol message =
28832900 )
28842901
28852902
2903+toLetDefReport :: Code.Source -> Name.Name -> Def -> Row -> Col -> Report.Report
2904+toLetDefReport source name def startRow startCol =
2905+ case def of
2906+ DefSpace space row col ->
2907+ toSpaceReport source space row col
2908+
2909+ DefType tipe row col ->
2910+ toTypeReport source (TC_Annotation name) tipe row col
2911+
2912+ DefNameRepeat row col ->
2913+ let
2914+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2915+ region = toRegion row col
2916+ in
2917+ Report.Report "EXPECTING DEFINITION" region [] $
2918+ Code.toSnippet source surroundings (Just region)
2919+ (
2920+ D.reflow $
2921+ "I just saw the type annotation for `" ++ Name.toChars name
2922+ ++ "` so I was expecting to see its definition here:"
2923+ ,
2924+ D.stack
2925+ [ D.reflow $
2926+ "Type annotations always appear directly above the relevant\
2927+ \ definition, without anything else in between."
2928+ , defNote
2929+ ]
2930+ )
2931+
2932+ DefNameMatch defName row col ->
2933+ let
2934+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2935+ region = toRegion row col
2936+ in
2937+ Report.Report "NAME MISMATCH" region [] $
2938+ Code.toSnippet source surroundings (Just region)
2939+ (
2940+ D.reflow $
2941+ "I just saw a type annotation for `" ++ Name.toChars name ++ "`, but it is followed by a definition for `" ++ Name.toChars defName ++ "`:"
2942+ ,
2943+ D.stack
2944+ [ D.reflow $
2945+ "These names do not match! Is there a typo?"
2946+ , D.indent 4 $ D.fillSep $
2947+ [D.dullyellow (D.fromName defName),"->",D.green (D.fromName name)]
2948+ ]
2949+ )
2950+
2951+ DefArg pattern row col ->
2952+ toPatternReport source PArg pattern row col
2953+
2954+ DefEquals row col ->
2955+ case Code.whatIsNext source row col of
2956+ Code.Keyword keyword ->
2957+ let
2958+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2959+ region = toKeywordRegion row col keyword
2960+ in
2961+ Report.Report "RESERVED WORD" region [] $
2962+ Code.toSnippet source surroundings (Just region)
2963+ (
2964+ D.reflow $
2965+ "It looks like you are trying to use `" ++ keyword ++ "` as an argument:"
2966+ ,
2967+ D.reflow $
2968+ "This is a reserved word! Try using some other name?"
2969+ )
2970+
2971+ Code.Operator op ->
2972+ let
2973+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2974+ region = toKeywordRegion row col op
2975+ in
2976+ Report.Report "UNEXPECTED SYMBOL" region [] $
2977+ Code.toSnippet source surroundings (Just region)
2978+ (
2979+ D.reflow $
2980+ "I was not expecting to see this symbol here:"
2981+ ,
2982+ D.stack
2983+ [ D.reflow $
2984+ "I am not sure what is going wrong exactly, so here is a valid\
2985+ \ definition (with an optional type annotation) for reference:"
2986+ , D.vcat
2987+ [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
2988+ , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
2989+ , D.indent 6 $ D.fillSep ["x","+","y"]
2990+ ]
2991+ , D.reflow $
2992+ "Try to use that format with your `" ++ Name.toChars name ++ "` definition!"
2993+ ]
2994+ )
2995+
2996+ _ ->
2997+ let
2998+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
2999+ region = toRegion row col
3000+ in
3001+ Report.Report "PROBLEM IN DEFINITION" region [] $
3002+ Code.toSnippet source surroundings (Just region)
3003+ (
3004+ D.reflow $
3005+ "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3006+ ,
3007+ D.stack
3008+ [ D.reflow $
3009+ "I am not sure what is going wrong exactly, so here is a valid\
3010+ \ definition (with an optional type annotation) for reference:"
3011+ , D.vcat
3012+ [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3013+ , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3014+ , D.indent 4 $ D.fillSep ["x","+","y"]
3015+ ]
3016+ , D.reflow $
3017+ "Try to use that format!"
3018+ ]
3019+ )
3020+
3021+ DefBody expr row col ->
3022+ toExprReport source (InDef name startRow startCol) expr row col
3023+
3024+ DefIndentEquals row col ->
3025+ let
3026+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3027+ region = toRegion row col
3028+ in
3029+ Report.Report "UNFINISHED DEFINITION" region [] $
3030+ Code.toSnippet source surroundings (Just region)
3031+ (
3032+ D.reflow $
3033+ "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3034+ ,
3035+ D.stack
3036+ [ D.reflow $
3037+ "I was expecting to see an argument or an equals sign next."
3038+ , defNote
3039+ ]
3040+ )
3041+
3042+ DefIndentType row col ->
3043+ let
3044+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3045+ region = toRegion row col
3046+ in
3047+ Report.Report "UNFINISHED DEFINITION" region [] $
3048+ Code.toSnippet source surroundings (Just region)
3049+ (
3050+ D.reflow $
3051+ "I got stuck while parsing the `" ++ Name.toChars name ++ "` type annotation:"
3052+ ,
3053+ D.stack
3054+ [ D.reflow $
3055+ "I just saw a colon, so I am expecting to see a type next."
3056+ , defNote
3057+ ]
3058+ )
3059+
3060+ DefIndentBody row col ->
3061+ let
3062+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3063+ region = toRegion row col
3064+ in
3065+ Report.Report "UNFINISHED DEFINITION" region [] $
3066+ Code.toSnippet source surroundings (Just region)
3067+ (
3068+ D.reflow $
3069+ "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3070+ ,
3071+ D.stack
3072+ [ D.reflow $
3073+ "I was expecting to see an expression next. What is it equal to?"
3074+ , declDefNote
3075+ ]
3076+ )
3077+
3078+ DefAlignment indent row col ->
3079+ let
3080+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3081+ region = toRegion row col
3082+ offset = indent - col
3083+ in
3084+ Report.Report "PROBLEM IN DEFINITION" region [] $
3085+ Code.toSnippet source surroundings (Just region)
3086+ (
3087+ D.reflow $
3088+ "I got stuck while parsing the `" ++ Name.toChars name ++ "` definition:"
3089+ ,
3090+ D.reflow $
3091+ "I just saw a type annotation indented " ++ show indent ++ " spaces, so I was\
3092+ \ expecting to see the corresponding definition next with the exact same amount\
3093+ \ of indentation. It looks like this line needs "
3094+ ++ show offset ++ " more " ++ (if offset == 1 then "space" else "spaces") ++ "?"
3095+ )
3096+
3097+
3098+
3099+defNote :: D.Doc
3100+defNote =
3101+ D.stack
3102+ [ D.reflow $
3103+ "Here is a valid definition (with a type annotation) for reference:"
3104+ , D.vcat
3105+ [ D.indent 4 $ D.fillSep [D.green "add",":","Int","->","Int","->","Int"]
3106+ , D.indent 4 $ D.fillSep [D.green "add","x","y","="]
3107+ , D.indent 6 $ D.fillSep ["x","+","y"]
3108+ ]
3109+ , D.reflow $
3110+ "The top line (called a \"type annotation\") is optional. You can leave it off\
3111+ \ if you want. As you get more comfortable with Elm and as your project grows,\
3112+ \ it becomes more and more valuable to add them though! They work great as\
3113+ \ compiler-verified documentation, and they often improve error messages!"
3114+ ]
3115+
3116+
3117+toLetDestructReport :: Code.Source -> Destruct -> Row -> Col -> Report.Report
3118+toLetDestructReport source destruct startRow startCol =
3119+ case destruct of
3120+ DestructSpace space row col ->
3121+ toSpaceReport source space row col
3122+
3123+ DestructPattern pattern row col ->
3124+ toPatternReport source PLet pattern row col
3125+
3126+ DestructEquals row col ->
3127+ let
3128+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3129+ region = toRegion row col
3130+ in
3131+ Report.Report "PROBLEM IN DEFINITION" region [] $
3132+ Code.toSnippet source surroundings (Just region)
3133+ (
3134+ D.reflow $
3135+ "I got stuck trying to parse this definition:"
3136+ ,
3137+ case Code.whatIsNext source row col of
3138+ Code.Operator ":" ->
3139+ D.stack
3140+ [ D.reflow $
3141+ "I was expecting to see an equals sign next, followed by an expression\
3142+ \ telling me what to compute."
3143+ , D.toSimpleNote $
3144+ "It looks like you may be trying to write a type annotation? It is not\
3145+ \ possible to add type annotations on destructuring definitions like this.\
3146+ \ You can assign a name to the overall structure, put a type annotation on\
3147+ \ that, and then destructure separately though."
3148+ ]
3149+
3150+ _ ->
3151+ D.reflow $
3152+ "I was expecting to see an equals sign next, followed by an expression\
3153+ \ telling me what to compute."
3154+ )
3155+
3156+ DestructBody expr row col ->
3157+ toExprReport source (InDestruct startRow startCol) expr row col
3158+
3159+ DestructIndentEquals row col ->
3160+ let
3161+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3162+ region = toRegion row col
3163+ in
3164+ Report.Report "UNFINISHED DEFINITION" region [] $
3165+ Code.toSnippet source surroundings (Just region)
3166+ (
3167+ D.reflow $
3168+ "I got stuck trying to parse this definition:"
3169+ ,
3170+ D.reflow $
3171+ "I was expecting to see an equals sign next, followed by an expression\
3172+ \ telling me what to compute."
3173+ )
3174+
3175+ DestructIndentBody row col ->
3176+ let
3177+ surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
3178+ region = toRegion row col
3179+ in
3180+ Report.Report "UNFINISHED DEFINITION" region [] $
3181+ Code.toSnippet source surroundings (Just region)
3182+ (
3183+ D.reflow $
3184+ "I got stuck while parsing this definition:"
3185+ ,
3186+ D.reflow $
3187+ "I was expecting to see an expression next. What is it equal to?"
3188+ )
3189+
3190+
28863191
28873192-- CASE
28883193
@@ -3928,6 +4233,7 @@ toFuncReport source context func startRow startCol =
39284233data PContext
39294234 = PCase
39304235 | PArg
4236+ | PLet
39314237
39324238
39334239toPatternReport :: Code.Source -> PContext -> Pattern -> Row -> Col -> Report.Report
@@ -3948,16 +4254,17 @@ toPatternReport source context pattern startRow startCol =
39484254 let
39494255 surroundings = A.Region (A.Position startRow startCol) (A.Position row col)
39504256 region = toKeywordRegion row col keyword
3951− aThing =
4257+ inThisThing =
39524258 case context of
3953− PArg -> "an argument"
3954− PCase -> "a pattern"
4259+ PArg -> "as an argument"
4260+ PCase -> "in this pattern"
4261+ PLet -> "in this pattern"
39554262 in
39564263 Report.Report "RESERVED WORD" region [] $
39574264 Code.toSnippet source surroundings (Just region)
39584265 (
39594266 D.reflow $
3960− "It looks like you are trying to use `" ++ keyword ++ "` as " ++ aThing ++ ":"
4267+ "It looks like you are trying to use `" ++ keyword ++ "` " ++ inThisThing ++ ":"
39614268 ,
39624269 D.reflow $
39634270 "This is a reserved word! Try using some other name?"