X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FdeSugar%2FDsGRHSs.lhs;h=60c67bc440eef4efcb619951fdc91aa51460a419;hb=550421384b8364cdaf3135f7859c9f7d7ee1fff1;hp=938d8657ed0fe4f99a035b1ebc797e9851a79964;hpb=7b0181919416d8f04324575b7e17031ca692f5b0;p=ghc-hetmet.git diff --git a/ghc/compiler/deSugar/DsGRHSs.lhs b/ghc/compiler/deSugar/DsGRHSs.lhs index 938d865..60c67bc 100644 --- a/ghc/compiler/deSugar/DsGRHSs.lhs +++ b/ghc/compiler/deSugar/DsGRHSs.lhs @@ -1,32 +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} -#include "HsVersions.h" - module DsGRHSs ( dsGuarded, dsGRHSs ) where -import Ubiq -import DsLoop -- break dsExpr/dsBinds-ish loop +#include "HsVersions.h" + +import {-# SOURCE #-} DsExpr ( dsLExpr, dsLet ) +import {-# SOURCE #-} Match ( matchSinglePat ) -import HsSyn ( GRHSsAndBinds(..), GRHS(..), - HsExpr, HsBinds ) -import TcHsSyn ( TypecheckedGRHSsAndBinds(..), TypecheckedGRHS(..), - TypecheckedPat(..), TypecheckedHsBinds(..), - TypecheckedHsExpr(..) ) -import CoreSyn ( CoreBinding(..), CoreExpr(..), mkCoLetsAny ) +import HsSyn ( Stmt(..), HsExpr(..), GRHSs(..), GRHS(..), + HsMatchContext(..), Pat(..), LStmt ) +import CoreSyn ( CoreExpr ) +import Type ( Type ) +import Var ( Id ) import DsMonad import DsUtils - -import CoreUtils ( mkCoreIfThenElse ) -import PrelInfo ( stringTy, nON_EXHAUSTIVE_GUARDS_ERROR_ID ) -import PprStyle ( PprStyle(..) ) -import Pretty ( ppShow ) -import SrcLoc ( SrcLoc{-instance-} ) -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. @@ -38,63 +36,83 @@ 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 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 -> DsM CoreExpr + +dsGuarded grhss + = dsGRHSs PatBindRhs [] grhss `thenDs` \ (err_ty, match_result) -> + mkErrorAppDs nON_EXHAUSTIVE_GUARDS_ERROR_ID err_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 - -> 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 :: HsMatchContext Name -> [Pat Id] -- These are to build a MatchContext from + -> GRHSs Id -- Guarded RHSs + -> DsM (Type, MatchResult) + +dsGRHSs kind pats (GRHSs grhss binds ty) + = mappM (dsGRHS kind pats) grhss `thenDs` \ match_results -> + let + match_result1 = foldr1 combineMatchResults match_results + match_result2 = adjustMatchResultDs (dsLet binds) match_result1 + -- NB: nested dsLet inside matchResult in - returnDs (MatchResult CantFail ty expr_fn (DsMatchContext kind pats locn)) - ) - -dsGRHS ty kind pats (GRHS guard expr locn) - = putSrcLocDs locn ( - dsExpr guard `thenDs` \ core_guard -> - dsExpr expr `thenDs` \ core_expr -> - let - expr_fn = \ fail -> mkCoreIfThenElse core_guard core_expr fail - in - returnDs (MatchResult CanFail ty expr_fn (DsMatchContext kind pats locn)) - ) + returnDs (ty, match_result2) + +dsGRHS kind pats (L loc (GRHS guard)) + = matchGuard (map unLoc guard) (DsMatchContext kind pats loc) \end{code} +%************************************************************************ +%* * +%* matchGuard : make a MatchResult from a guarded RHS * +%* * +%************************************************************************ + +\begin{code} +matchGuard :: [Stmt Id] -- Guard + -> DsMatchContext -- Context + -> 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) + +matchGuard [ResultStmt expr] ctx + = dsLExpr expr `thenDs` \ core_expr -> + returnDs (cantFailMatchResult core_expr) + + -- ExprStmts must be guards + -- Turn an "otherwise" guard is a no-op +matchGuard (ExprStmt (L _ (HsVar v)) _ : stmts) ctx + | v `hasKey` otherwiseIdKey + || v `hasKey` getUnique trueDataConId + -- trueDataConId doesn't have the same + -- unique as trueDataCon + = matchGuard stmts ctx + +matchGuard (ExprStmt expr _ : stmts) ctx + = matchGuard stmts ctx `thenDs` \ match_result -> + dsLExpr expr `thenDs` \ pred_expr -> + returnDs (mkGuardedMatchResult pred_expr match_result) + +matchGuard (LetStmt binds : stmts) ctx + = matchGuard stmts ctx `thenDs` \ match_result -> + returnDs (adjustMatchResultDs (dsLet binds) match_result) + -- NB the dsLet occurs inside the match_result + +matchGuard (BindStmt pat rhs : stmts) ctx + = matchGuard stmts ctx `thenDs` \ match_result -> + dsLExpr rhs `thenDs` \ core_rhs -> + matchSinglePat core_rhs ctx pat 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}