75c76d62096ea292cfc7d6aa97e580d5c51f12e7
[ghc-hetmet.git] / ghc / compiler / deSugar / DsGRHSs.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section[DsGRHSs]{Matching guarded right-hand-sides (GRHSs)}
5
6 \begin{code}
7 module DsGRHSs ( dsGuarded, dsGRHSs ) where
8
9 #include "HsVersions.h"
10
11 import {-# SOURCE #-} DsExpr  ( dsExpr, dsLet )
12 import {-# SOURCE #-} Match   ( matchSinglePat )
13
14 import HsSyn            ( Stmt(..), HsExpr(..), GRHSs(..), GRHS(..), HsMatchContext(..) )
15 import TcHsSyn          ( TypecheckedGRHSs, TypecheckedPat, TypecheckedStmt, TypecheckedMatchContext )
16 import CoreSyn          ( CoreExpr )
17 import Type             ( Type )
18
19 import DsMonad
20 import DsUtils
21 import Unique           ( Uniquable(..) )
22 import PrelInfo         ( nON_EXHAUSTIVE_GUARDS_ERROR_ID )
23 import TysWiredIn       ( trueDataConId )
24 import PrelNames        ( otherwiseIdKey, hasKey )
25 \end{code}
26
27 @dsGuarded@ is used for both @case@ expressions and pattern bindings.
28 It desugars:
29 \begin{verbatim}
30         | g1 -> e1
31         ...
32         | gn -> en
33         where binds
34 \end{verbatim}
35 producing an expression with a runtime error in the corner if
36 necessary.  The type argument gives the type of the @ei@.
37
38 \begin{code}
39 dsGuarded :: TypecheckedGRHSs -> DsM CoreExpr
40
41 dsGuarded grhss
42   = dsGRHSs PatBindRhs [] grhss                                 `thenDs` \ (err_ty, match_result) ->
43     mkErrorAppDs nON_EXHAUSTIVE_GUARDS_ERROR_ID err_ty ""       `thenDs` \ error_expr ->
44     extractMatchResult match_result error_expr
45 \end{code}
46
47 In contrast, @dsGRHSs@ produces a @MatchResult@.
48
49 \begin{code}
50 dsGRHSs :: TypecheckedMatchContext -> [TypecheckedPat]  -- These are to build a MatchContext from
51         -> TypecheckedGRHSs                             -- Guarded RHSs
52         -> DsM (Type, MatchResult)
53
54 dsGRHSs kind pats (GRHSs grhss binds ty)
55   = mappM (dsGRHS kind pats) grhss              `thenDs` \ match_results ->
56     let 
57         match_result1 = foldr1 combineMatchResults match_results
58         match_result2 = adjustMatchResultDs (dsLet binds) match_result1
59                 -- NB: nested dsLet inside matchResult
60     in
61     returnDs (ty, match_result2)
62
63 dsGRHS kind pats (GRHS guard locn)
64   = matchGuard guard (DsMatchContext kind pats locn)
65 \end{code}
66
67
68 %************************************************************************
69 %*                                                                      *
70 %*  matchGuard : make a MatchResult from a guarded RHS                  *
71 %*                                                                      *
72 %************************************************************************
73
74 \begin{code}
75 matchGuard :: [TypecheckedStmt]         -- Guard
76            -> DsMatchContext            -- Context
77            -> DsM MatchResult
78
79 -- See comments with HsExpr.Stmt re what an ExprStmt means
80 -- Here we must be in a guard context (not do-expression, nor list-comp)        
81
82 matchGuard [ResultStmt expr locn] ctx 
83   = putSrcLocDs locn (dsExpr expr)      `thenDs` \ core_expr ->
84     returnDs (cantFailMatchResult core_expr)
85
86         -- ExprStmts must be guards
87         -- Turn an "otherwise" guard is a no-op
88 matchGuard (ExprStmt (HsVar v) _ _ : stmts) ctx
89   |  v `hasKey` otherwiseIdKey
90   || v `hasKey` getUnique trueDataConId 
91         -- trueDataConId doesn't have the same 
92         -- unique as trueDataCon
93   = matchGuard stmts ctx
94
95 matchGuard (ExprStmt expr _ locn : stmts) ctx
96   = matchGuard stmts ctx                `thenDs` \ match_result ->
97     putSrcLocDs locn (dsExpr expr)      `thenDs` \ pred_expr ->
98     returnDs (mkGuardedMatchResult pred_expr match_result)
99
100 matchGuard (LetStmt binds : stmts) ctx
101   = matchGuard stmts ctx        `thenDs` \ match_result ->
102     returnDs (adjustMatchResultDs (dsLet binds) match_result)
103         -- NB the dsLet occurs inside the match_result
104
105 matchGuard (BindStmt pat rhs locn : stmts) ctx
106   = matchGuard stmts ctx                `thenDs` \ match_result ->
107     putSrcLocDs locn (dsExpr rhs)       `thenDs` \ core_rhs ->
108     matchSinglePat core_rhs ctx pat match_result
109 \end{code}
110
111 Should {\em fail} if @e@ returns @D@
112 \begin{verbatim}
113 f x | p <- e', let C y# = e, f y# = r1
114     | otherwise          = r2 
115 \end{verbatim}