X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FdeSugar%2FDsGRHSs.lhs;h=eea61bafb2cfae76a00e7215de4fc79de759a9c0;hb=eb57096f08bbccf59e6551b135fbde5ed22a0fa8;hp=63c41d70a46f5e1996f8588c07ebc18dd1fbe1c5;hpb=44f98be5b3bc7aaf2c5961667b16ee8eca3e67c1;p=ghc-hetmet.git diff --git a/ghc/compiler/deSugar/DsGRHSs.lhs b/ghc/compiler/deSugar/DsGRHSs.lhs index 63c41d7..eea61ba 100644 --- a/ghc/compiler/deSugar/DsGRHSs.lhs +++ b/ghc/compiler/deSugar/DsGRHSs.lhs @@ -1,46 +1,30 @@ % -% (c) The GRASP/AQUA Project, Glasgow University, 1992-1994 +% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % \section[DsGRHSs]{Matching guarded right-hand-sides (GRHSs)} \begin{code} +module DsGRHSs ( dsGuarded, dsGRHSs ) where + #include "HsVersions.h" -module DsGRHSs ( dsGuarded, dsGRHSs ) where +import {-# SOURCE #-} DsExpr ( dsLExpr, dsLocalBinds ) +import {-# SOURCE #-} Match ( matchSinglePat ) -IMP_Ubiq() -#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 201 -IMPORT_DELOOPER(DsLoop) -- break dsExpr/dsBinds-ish loop -#else -import {-# SOURCE #-} DsExpr ( dsExpr ) -import {-# SOURCE #-} DsBinds ( dsBinds ) -import {-# SOURCE #-} Match ( match ) -#endif - -import HsSyn ( GRHSsAndBinds(..), GRHS(..), - HsExpr(..), HsBinds, Stmt(..), - HsLit, Match, Fixity, DoOrListComp, HsType, ArithSeqInfo - ) -import TcHsSyn ( SYN_IE(TypecheckedGRHSsAndBinds), SYN_IE(TypecheckedGRHS), - SYN_IE(TypecheckedPat), SYN_IE(TypecheckedHsBinds), - SYN_IE(TypecheckedHsExpr), SYN_IE(TypecheckedStmt) - ) -import CoreSyn ( SYN_IE(CoreBinding), GenCoreBinding(..), SYN_IE(CoreExpr), mkCoLetsAny ) +import HsSyn ( Stmt(..), HsExpr(..), GRHSs(..), GRHS(..), + LHsExpr, HsMatchContext(..), Pat(..) ) +import CoreSyn ( CoreExpr ) +import Var ( Id ) +import Type ( Type ) import DsMonad import DsUtils - -#if __GLASGOW_HASKELL__ < 200 -import Id ( GenId ) -#endif -import CoreUtils ( coreExprType, mkCoreIfThenElse ) -import PrelVals ( nON_EXHAUSTIVE_GUARDS_ERROR_ID ) -import Outputable ( PprStyle(..) ) -import SrcLoc ( SrcLoc{-instance-} ) -import Type ( SYN_IE(Type) ) -import Unique ( Unique, otherwiseIdKey ) -import UniqFM ( Uniquable(..) ) -import Util ( panic ) +import Unique ( Uniquable(..) ) +import PrelInfo ( nON_EXHAUSTIVE_GUARDS_ERROR_ID ) +import TysWiredIn ( trueDataConId ) +import PrelNames ( otherwiseIdKey, hasKey ) +import Name ( Name ) +import SrcLoc ( unLoc, Located(..) ) \end{code} @dsGuarded@ is used for both @case@ expressions and pattern bindings. @@ -52,65 +36,39 @@ It desugars: where binds \end{verbatim} producing an expression with a runtime error in the corner if -necessary. The type argument gives the type of the ei. +necessary. The type argument gives the type of the @ei@. \begin{code} -dsGuarded :: TypecheckedGRHSsAndBinds - -> DsM CoreExpr - -dsGuarded (GRHSsAndBindsOut grhss binds err_ty) - = dsBinds False{-don't auto scc-} binds `thenDs` \ core_binds -> - dsGRHSs err_ty PatBindMatch [] grhss `thenDs` \ (MatchResult can_it_fail _ core_grhss_fn _) -> - case can_it_fail of - CantFail -> returnDs (mkCoLetsAny core_binds (core_grhss_fn (panic "It can't fail"))) - CanFail -> mkErrorAppDs nON_EXHAUSTIVE_GUARDS_ERROR_ID err_ty "" `thenDs` \ error_expr -> - returnDs (mkCoLetsAny core_binds (core_grhss_fn error_expr)) +dsGuarded :: GRHSs Id -> Type -> DsM CoreExpr + +dsGuarded grhss rhs_ty + = dsGRHSs PatBindRhs [] grhss rhs_ty `thenDs` \ match_result -> + mkErrorAppDs nON_EXHAUSTIVE_GUARDS_ERROR_ID rhs_ty "" `thenDs` \ error_expr -> + extractMatchResult match_result error_expr \end{code} -Desugar a list of (grhs, expr) pairs [grhs = guarded -right-hand-side], as in: -\begin{verbatim} -p | g1 = e1 - | g2 = e2 - ... - | gm = em -\end{verbatim} -We supply a @CoreExpr@ for the case in which all of -the guards fail. +In contrast, @dsGRHSs@ produces a @MatchResult@. \begin{code} -dsGRHSs :: Type -- Type of RHSs - -> DsMatchKind -> [TypecheckedPat] -- These are to build a MatchContext from - -> [TypecheckedGRHS] -- Guarded RHSs +dsGRHSs :: HsMatchContext Name -> [Pat Id] -- These are to build a MatchContext from + -> GRHSs Id -- Guarded RHSs + -> Type -- Type of RHS -> DsM MatchResult -dsGRHSs ty kind pats [grhs] = dsGRHS ty kind pats grhs - -dsGRHSs ty kind pats (grhs:grhss) - = dsGRHS ty kind pats grhs `thenDs` \ match_result1 -> - dsGRHSs ty kind pats grhss `thenDs` \ match_result2 -> - combineGRHSMatchResults match_result1 match_result2 - -dsGRHS ty kind pats (OtherwiseGRHS expr locn) - = putSrcLocDs locn $ - dsExpr expr `thenDs` \ core_expr -> - let - expr_fn = \ ignore -> core_expr +dsGRHSs hs_ctx pats (GRHSs grhss binds) rhs_ty + = mappM (dsGRHS hs_ctx pats rhs_ty) grhss `thenDs` \ match_results -> + let + match_result1 = foldr1 combineMatchResults match_results + match_result2 = adjustMatchResultDs (dsLocalBinds binds) match_result1 + -- NB: nested dsLet inside matchResult in - returnDs (MatchResult CantFail ty expr_fn (DsMatchContext kind pats locn)) + returnDs match_result2 -dsGRHS ty kind pats (GRHS guard expr locn) - = putSrcLocDs locn $ - dsExpr expr `thenDs` \ core_expr -> - let - expr_fn = \ ignore -> core_expr - in - matchGuard guard (MatchResult CantFail ty expr_fn (DsMatchContext kind pats locn)) +dsGRHS hs_ctx pats rhs_ty (L loc (GRHS guards rhs)) + = matchGuards (map unLoc guards) hs_ctx rhs rhs_ty \end{code} - - %************************************************************************ %* * %* matchGuard : make a MatchResult from a guarded RHS * @@ -118,34 +76,53 @@ dsGRHS ty kind pats (GRHS guard expr locn) %************************************************************************ \begin{code} -matchGuard :: [TypecheckedStmt] -- Guard - -> MatchResult -- What to do if the guard succeeds - -> DsM MatchResult - -matchGuard [] body_result = returnDs body_result - - -- Turn an "otherwise" guard is a no-op -matchGuard (GuardStmt (HsVar v) _ : stmts) body_result - | uniqueOf v == otherwiseIdKey - = matchGuard stmts body_result - -matchGuard (GuardStmt expr _ : stmts) body_result - = matchGuard stmts body_result `thenDs` \ (MatchResult _ ty body_fn cxt) -> - dsExpr expr `thenDs` \ core_expr -> - let - expr_fn = \ fail -> mkCoreIfThenElse core_expr (body_fn fail) fail - in - returnDs (MatchResult CanFail ty expr_fn cxt) - -matchGuard (LetStmt binds : stmts) body_result - = matchGuard stmts body_result `thenDs` \ match_result -> - dsBinds False{-don't auto scc-} binds `thenDs` \ core_binds -> - returnDs (mkCoLetsMatchResult core_binds match_result) - -matchGuard (BindStmt pat rhs _ : stmts) body_result - = matchGuard stmts body_result `thenDs` \ match_result -> - dsExpr rhs `thenDs` \ core_rhs -> - newSysLocalDs (coreExprType core_rhs) `thenDs` \ scrut_var -> - match [scrut_var] [EqnInfo [pat] match_result] [] `thenDs` \ match_result' -> - returnDs (mkCoLetsMatchResult [NonRec scrut_var core_rhs] match_result') +matchGuards :: [Stmt Id] -- Guard + -> HsMatchContext Name -- Context + -> LHsExpr Id -- RHS + -> Type -- Type of RHS of guard + -> DsM MatchResult + +-- See comments with HsExpr.Stmt re what an ExprStmt means +-- Here we must be in a guard context (not do-expression, nor list-comp) + +matchGuards [] ctx rhs rhs_ty + = do { core_rhs <- dsLExpr rhs + ; return (cantFailMatchResult core_rhs) } + + -- ExprStmts must be guards + -- Turn an "otherwise" guard is a no-op. This ensures that + -- you don't get a "non-exhaustive eqns" message when the guards + -- finish in "otherwise". + -- NB: The success of this clause depends on the typechecker not + -- wrapping the 'otherwise' in empty HsTyApp or HsCoerce constructors + -- If it does, you'll get bogus overlap warnings +matchGuards (ExprStmt (L _ (HsVar v)) _ _ : stmts) ctx rhs rhs_ty + | v `hasKey` otherwiseIdKey + || v `hasKey` getUnique trueDataConId + -- trueDataConId doesn't have the same unique as trueDataCon + = matchGuards stmts ctx rhs rhs_ty + +matchGuards (ExprStmt expr _ _ : stmts) ctx rhs rhs_ty + = matchGuards stmts ctx rhs rhs_ty `thenDs` \ match_result -> + dsLExpr expr `thenDs` \ pred_expr -> + returnDs (mkGuardedMatchResult pred_expr match_result) + +matchGuards (LetStmt binds : stmts) ctx rhs rhs_ty + = matchGuards stmts ctx rhs rhs_ty `thenDs` \ match_result -> + returnDs (adjustMatchResultDs (dsLocalBinds binds) match_result) + -- NB the dsLet occurs inside the match_result + -- Reason: dsLet takes the body expression as its argument + -- so we can't desugar the bindings without the + -- body expression in hand + +matchGuards (BindStmt pat bind_rhs _ _ : stmts) ctx rhs rhs_ty + = matchGuards stmts ctx rhs rhs_ty `thenDs` \ match_result -> + dsLExpr bind_rhs `thenDs` \ core_rhs -> + matchSinglePat core_rhs ctx pat rhs_ty match_result \end{code} + +Should {\em fail} if @e@ returns @D@ +\begin{verbatim} +f x | p <- e', let C y# = e, f y# = r1 + | otherwise = r2 +\end{verbatim}