| ... |
... |
@@ -275,22 +275,22 @@ They capture the essence of statement expansions as implemented in `expand_do_st |
|
275
|
275
|
|
|
276
|
276
|
DO【 _ 】 maps a sequence of do statements and recursively converts them into expressions
|
|
277
|
277
|
|
|
278
|
|
- (1) DO【 s; ss 】 = ‹ExpansionStmt s›((>>) (‹PopErrCtxt› s) (‹PopErrCtxt› DO【 ss 】))
|
|
|
278
|
+ (1) DO【 s; ss 】 = ‹ExpansionStmt s›((>>) s (DO【 ss 】))
|
|
279
|
279
|
|
|
280
|
280
|
(2) DO【 p <- e; ss 】 = if p is irrefutable
|
|
281
|
281
|
then ‹ExpansionStmt (p <- e)›
|
|
282
|
|
- (>>=) (‹PopExprCtxt› s) ((\ p -> ‹PopExprCtxt› DO【 ss 】))
|
|
|
282
|
+ (>>=) s ((\ p -> DO【 ss 】))
|
|
283
|
283
|
else ‹ExpansionStmt (p <- e)›
|
|
284
|
|
- (>>=) (‹PopExprCtxt› s)
|
|
285
|
|
- (\case p -> ‹PopExprCtxt› DO【 ss 】
|
|
286
|
|
- _ -> fail "pattern p failure")
|
|
|
284
|
+ (>>=) s
|
|
|
285
|
+ (\case p -> DO【 ss 】
|
|
|
286
|
+ _ -> ‹ExpansionPat (p <- e) p› fail "pattern p failure")
|
|
287
|
287
|
|
|
288
|
288
|
(3) DO【 let x = e; ss 】
|
|
289
|
|
- = ‹ExpansionStmt (let x = e)› (let x = e in (‹PopErrCtxt›DO【 ss 】))
|
|
|
289
|
+ = ‹ExpansionStmt (let x = e)› (let x = e in (DO【 ss 】))
|
|
290
|
290
|
|
|
291
|
291
|
|
|
292
|
292
|
(4) DO【 rec ss; sss 】
|
|
293
|
|
- = (>>=) e (\vars -> ‹PopErrCtxt›DO【 sss 】))
|
|
|
293
|
+ = (>>=) e (\vars -> DO【 sss 】))
|
|
294
|
294
|
where (vars, e) = RECDO【 ss 】
|
|
295
|
295
|
|
|
296
|
296
|
(5) DO【 s 】 = s
|
| ... |
... |
@@ -428,10 +428,10 @@ It stores the original statement (with location) and the expanded expression |
|
428
|
428
|
‹ExpandedThingRn do { e1; e2; e3 }› -- Original Do Expression
|
|
429
|
429
|
-- Expanded Do Expression
|
|
430
|
430
|
(‹ExpandedThingRn e1› -- Original Statement
|
|
431
|
|
- ({(>>) ‹PopErrCtxt› e1} -- Expanded Expression
|
|
432
|
|
- ‹PopErrCtxt› (‹ExpandedThingRn e2›
|
|
433
|
|
- ({(>>) ‹PopErrCtxt› e2}
|
|
434
|
|
- ‹PopErrCtxt› (‹ExpandedThingRn e3› {e3})))))
|
|
|
431
|
+ ({(>>) ‹ExpandedThingRn e1› e1} -- Expanded Expression
|
|
|
432
|
+ (‹ExpandedThingRn e2›
|
|
|
433
|
+ ({(>>) ‹ExpandedThingRn e2› e2}
|
|
|
434
|
+ (‹ExpandedThingRn e3› {e3})))))
|
|
435
|
435
|
|
|
436
|
436
|
* Whenever the typechecker steps through an `ExpandedThingRn`,
|
|
437
|
437
|
we push the original statement in the error context, set the error location to the
|
| ... |
... |
@@ -441,7 +441,7 @@ It stores the original statement (with location) and the expanded expression |
|
441
|
441
|
|
|
442
|
442
|
* Recall, that when a source function argument fails to typecheck,
|
|
443
|
443
|
we print an error message like "In the second argument of the function f..".
|
|
444
|
|
- However, `(>>)` is generated thus, we don't want to display that to the user; it would be confusing.
|
|
|
444
|
+ However, `(>>)` is compiler expanded thus, we don't want to display that to the user; it would be confusing.
|
|
445
|
445
|
But also, we do not want to completely ignore it as we do want to keep the error blame carets
|
|
446
|
446
|
as precise as possible, and not just blame the complete `do`-block.
|
|
447
|
447
|
Thus, when we typecheck the application `(>>) e1`, we push the "In the stmt of do block e1" with
|
| ... |
... |
@@ -452,15 +452,15 @@ It stores the original statement (with location) and the expanded expression |
|
452
|
452
|
and before moving to the next statement of the `do`-block, we need to first pop the top
|
|
453
|
453
|
of the error context stack which contains the error message for
|
|
454
|
454
|
the previous statement: eg. "In the stmt of a do block: e1".
|
|
455
|
|
- This is explicitly encoded in the expansion expression using
|
|
456
|
|
- the `XXExprGhcRn.PopErrCtxt`. Whenever `GHC.Tc.Gen.Expr.tcExpr` (via `GHC.Tc.Gen.tcXExpr`)
|
|
457
|
|
- sees a `PopErrCtxt` it calls `GHC.Tc.Utils.Monad.popErrCtxt` to pop of the top of error context stack.
|
|
458
|
|
- See ‹PopErrCtxt› in the example above.
|
|
459
|
|
- Without this popping business for error context stack,
|
|
460
|
|
- if there is a type error in `e2`, we would get a spurious and confusing error message
|
|
|
455
|
+ This popping is implicitly done when we push the error context message for the next statment.
|
|
|
456
|
+ See Note [ErrCtxtStack Manipulation] and `LclEnv.setLclCtxtSrcCodeOrigin`
|
|
|
457
|
+
|
|
|
458
|
+ Sans the popping business for error context stack,
|
|
|
459
|
+ if there were to be a type error in `e2`, we would get a spurious and confusing error message
|
|
461
|
460
|
which mentions "In the stmt of a do block e1" along with the message
|
|
462
|
461
|
"In the stmt of a do block e2".
|
|
463
|
462
|
|
|
|
463
|
+
|
|
464
|
464
|
B. Expanding Bind Statements
|
|
465
|
465
|
-----------------------------
|
|
466
|
466
|
A `do`-block with a bind statement:
|
| ... |
... |
@@ -473,7 +473,7 @@ It stores the original statement (with location) and the expanded expression |
|
473
|
473
|
--
|
|
474
|
474
|
(‹ExpandedThingRn (p <- e1)› -- Original Statement
|
|
475
|
475
|
(((>>=) e1) -- Expanded Expression
|
|
476
|
|
- ‹PopErrCtxt› ((\ p -> ‹ExpandedThingRn (e2)› e2)))
|
|
|
476
|
+ ((\ p -> ‹ExpandedThingRn (e2)› e2)))
|
|
477
|
477
|
)
|
|
478
|
478
|
|
|
479
|
479
|
|