View patterns, record wildcards, and record puns
[ghc-hetmet.git] / compiler / deSugar / DsUtils.lhs
index 29e7773..9d787ad 100644 (file)
@@ -1,23 +1,32 @@
 %
+% (c) The University of Glasgow 2006
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-\section[DsUtils]{Utilities for desugaring}
+
+Utilities for desugaring
 
 This module exports some utility functions of no great interest.
 
 \begin{code}
+{-# OPTIONS -w #-}
+-- The above warning supression flag is a temporary kludge.
+-- While working on this module you are encouraged to remove it and fix
+-- any warnings in the module. See
+--     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
+-- for details
+
 module DsUtils (
        EquationInfo(..), 
        firstPat, shiftEqns,
        
-       mkDsLet, mkDsLets,
+       mkDsLet, mkDsLets, mkDsApp, mkDsApps,
 
        MatchResult(..), CanItFail(..), 
        cantFailMatchResult, alwaysFailMatchResult,
        extractMatchResult, combineMatchResults, 
        adjustMatchResult,  adjustMatchResultDs,
-       mkCoLetMatchResult, mkGuardedMatchResult, 
-       matchCanFail,
+       mkCoLetMatchResult, mkViewMatchResult, mkGuardedMatchResult, 
+       matchCanFail, mkEvalMatchResult,
        mkCoPrimCaseMatchResult, mkCoAlgCaseMatchResult,
        wrapBind, wrapBinds,
 
@@ -31,7 +40,8 @@ module DsUtils (
        
        dsSyntaxTable, lookupEvidence,
 
-       selectSimpleMatchVarL, selectMatchVars, selectMatchVar
+       selectSimpleMatchVarL, selectMatchVars, selectMatchVar,
+       mkTickBox, mkOptTickBox, mkBinaryTickBox
     ) where
 
 #include "HsVersions.h"
@@ -40,44 +50,37 @@ import {-# SOURCE #-}       Match ( matchSimply )
 import {-# SOURCE #-}  DsExpr( dsExpr )
 
 import HsSyn
-import TcHsSyn         ( hsPatType )
+import TcHsSyn
 import CoreSyn
-import Constants       ( mAX_TUPLE_SIZE )
+import Constants
 import DsMonad
 
-import CoreUtils       ( exprType, mkIfThenElse, mkCoerce, bindNonRec )
-import MkId            ( iRREFUT_PAT_ERROR_ID, mkReboxingAlt, mkNewTypeBody )
-import Id              ( idType, Id, mkWildId, mkTemplateLocals, mkSysLocal )
-import Var             ( Var )
-import Name            ( Name )
-import Literal         ( Literal(..), mkStringLit, inIntRange, tARGET_MAX_INT )
-import TyCon           ( isNewTyCon, tyConDataCons )
-import DataCon         ( DataCon, dataConSourceArity, dataConTyCon, dataConTag )
-import Type            ( mkFunTy, isUnLiftedType, Type, splitTyConApp, mkTyVarTy )
-import TcType          ( tcEqType )
-import TysPrim         ( intPrimTy )
-import TysWiredIn      ( nilDataCon, consDataCon, 
-                          tupleCon, mkTupleTy,
-                         unitDataConId, unitTy,
-                          charTy, charDataCon, 
-                          intTy, intDataCon, 
-                         isPArrFakeCon )
-import BasicTypes      ( Boxity(..) )
-import UniqSet         ( mkUniqSet, minusUniqSet, isEmptyUniqSet )
-import UniqSupply      ( splitUniqSupply, uniqFromSupply, uniqsFromSupply )
-import PrelNames       ( unpackCStringName, unpackCStringUtf8Name, 
-                         plusIntegerName, timesIntegerName, smallIntegerDataConName, 
-                         lengthPName, indexPName )
+import CoreUtils
+import MkId
+import Id
+import Var
+import Name
+import Literal
+import TyCon
+import DataCon
+import Type
+import Coercion
+import TysPrim
+import TysWiredIn
+import BasicTypes
+import UniqSet
+import UniqSupply
+import PrelNames
 import Outputable
-import SrcLoc          ( Located(..), unLoc )
-import Util             ( isSingleton, zipEqual, sortWith )
-import ListSetOps      ( assocDefault )
+import SrcLoc
+import Util
+import ListSetOps
 import FastString
-import Data.Char       ( ord )
+import StaticFlags
+
+import Data.Char
 
-#ifdef DEBUG
-import Util            ( notNull )     -- Used in an assertion
-#endif
+infixl 4 `mkDsApp`, `mkDsApps`
 \end{code}
 
 
@@ -124,16 +127,71 @@ back again.
 
 \begin{code}
 mkDsLet :: CoreBind -> CoreExpr -> CoreExpr
-mkDsLet (NonRec bndr rhs) body
-  | isUnLiftedType (idType bndr) 
+mkDsLet (NonRec bndr rhs) body -- See Note [CoreSyn let/app invariant]
+  | isUnLiftedType (idType bndr) && not (exprOkForSpeculation rhs)
   = Case rhs bndr (exprType body) [(DEFAULT,[],body)]
 mkDsLet bind body
   = Let bind body
 
 mkDsLets :: [CoreBind] -> CoreExpr -> CoreExpr
 mkDsLets binds body = foldr mkDsLet body binds
+
+-----------
+mkDsApp :: CoreExpr -> CoreExpr -> CoreExpr
+-- Check the invariant that the arg of an App is ok-for-speculation if unlifted
+-- See CoreSyn Note [CoreSyn let/app invariant]
+mkDsApp fun (Type ty) = App fun (Type ty)
+mkDsApp fun arg       = mk_val_app fun arg arg_ty res_ty
+                     where
+                       (arg_ty, res_ty) = splitFunTy (exprType fun)
+
+-----------
+mkDsApps :: CoreExpr -> [CoreExpr] -> CoreExpr
+-- Slightly more efficient version of (foldl mkDsApp)
+mkDsApps fun args
+  = go fun (exprType fun) args
+  where
+    go fun fun_ty []               = fun
+    go fun fun_ty (Type ty : args) = go (App fun (Type ty)) (applyTy fun_ty ty) args
+    go fun fun_ty (arg     : args) = go (mk_val_app fun arg arg_ty res_ty) res_ty args
+                                  where
+                                    (arg_ty, res_ty) = splitFunTy fun_ty
+-----------
+mk_val_app fun arg arg_ty res_ty       -- See Note [CoreSyn let/app invariant]
+  | not (isUnLiftedType arg_ty) || exprOkForSpeculation arg
+  = App fun arg                -- The vastly common case
+
+mk_val_app (Var f `App` Type ty1 `App` Type ty2 `App` arg1) arg2 _ res_ty
+  | f == seqId         -- Note [Desugaring seq]
+  = Case arg1 (mkWildId ty1) res_ty [(DEFAULT,[],arg2)]
+
+mk_val_app fun arg arg_ty res_ty
+  = Case arg (mkWildId arg_ty) res_ty [(DEFAULT,[],App fun (Var arg_id))]
+  where
+    arg_id = mkWildId arg_ty   -- Lots of shadowing, but it doesn't matter,
+                               -- because 'fun ' should not have a free wild-id
 \end{code}
 
+Note [Desugaring seq]  cf Trac #1031
+~~~~~~~~~~~~~~~~~~~~~
+   f x y = x `seq` (y `seq` (# x,y #))
+
+The [CoreSyn let/app invariant] means that, other things being equal, because 
+the argument to the outer 'seq' has an unlifted type, we'll use call-by-value thus:
+
+   f x y = case (y `seq` (# x,y #)) of v -> x `seq` v
+
+But that is bad for two reasons: 
+  (a) we now evaluate y before x, and 
+  (b) we can't bind v to an unboxed pair
+
+Seq is very, very special!  So we recognise it right here, and desugar to
+       case x of _ -> case y of _ -> (# x,y #)
+
+The special case would be valid for all calls to 'seq', but it's only *necessary*
+for ones whose second argument has an unlifted type. So we only catch the latter
+case here, to avoid unnecessary tests.
+
 
 %************************************************************************
 %*                                                                     *
@@ -148,12 +206,14 @@ otherwise, make one up.
 
 \begin{code}
 selectSimpleMatchVarL :: LPat Id -> DsM Id
-selectSimpleMatchVarL pat = selectMatchVar (unLoc pat) (hsPatType pat)
+selectSimpleMatchVarL pat = selectMatchVar (unLoc pat)
 
 -- (selectMatchVars ps tys) chooses variables of type tys
 -- to use for matching ps against.  If the pattern is a variable,
 -- we try to use that, to save inventing lots of fresh variables.
--- But even if it is a variable, its type might not match.  Consider
+--
+-- OLD, but interesting note:
+--    But even if it is a variable, its type might not match.  Consider
 --     data T a where
 --       T1 :: Int -> T Int
 --       T2 :: a   -> T a
@@ -161,23 +221,19 @@ selectSimpleMatchVarL pat = selectMatchVar (unLoc pat) (hsPatType pat)
 --     f :: T a -> a -> Int
 --     f (T1 i) (x::Int) = x
 --     f (T2 i) (y::a)   = 0
--- Then we must not choose (x::Int) as the matching variable!
-
-selectMatchVars :: [Pat Id] -> [Type] -> DsM [Id]
-selectMatchVars []     []      = return []
-selectMatchVars (p:ps) (ty:tys) = do { v  <- selectMatchVar  p  ty
-                                    ; vs <- selectMatchVars ps tys
-                                    ; return (v:vs) }
-
-selectMatchVar (BangPat pat)   pat_ty  = selectMatchVar (unLoc pat) pat_ty
-selectMatchVar (LazyPat pat)   pat_ty  = selectMatchVar (unLoc pat) pat_ty
-selectMatchVar (VarPat var)    pat_ty  = try_for var        pat_ty
-selectMatchVar (AsPat var pat) pat_ty  = try_for (unLoc var) pat_ty
-selectMatchVar other_pat       pat_ty  = newSysLocalDs pat_ty   -- OK, better make up one...
-
-try_for var pat_ty 
-  | idType var `tcEqType` pat_ty = returnDs var
-  | otherwise                   = newSysLocalDs pat_ty
+--    Then we must not choose (x::Int) as the matching variable!
+-- And nowadays we won't, because the (x::Int) will be wrapped in a CoPat
+
+selectMatchVars :: [Pat Id] -> DsM [Id]
+selectMatchVars ps = mapM selectMatchVar ps
+
+selectMatchVar (BangPat pat)   = selectMatchVar (unLoc pat)
+selectMatchVar (LazyPat pat)   = selectMatchVar (unLoc pat)
+selectMatchVar (ParPat pat)    = selectMatchVar (unLoc pat)
+selectMatchVar (VarPat var)    = return var
+selectMatchVar (AsPat var pat) = return (unLoc var)
+selectMatchVar other_pat       = newSysLocalDs (hsPatType other_pat)
+                                 -- OK, better make up one...
 \end{code}
 
 
@@ -193,7 +249,7 @@ worthy of a type synonym and a few handy functions.
 
 \begin{code}
 firstPat :: EquationInfo -> Pat Id
-firstPat eqn = head (eqn_pats eqn)
+firstPat eqn = ASSERT( notNull (eqn_pats eqn) ) head (eqn_pats eqn)
 
 shiftEqns :: [EquationInfo] -> [EquationInfo]
 -- Drop the first pattern in each equation
@@ -236,7 +292,7 @@ combineMatchResults (MatchResult CanFail      body_fn1)
 combineMatchResults match_result1@(MatchResult CantFail body_fn1) match_result2
   = match_result1
 
-adjustMatchResult :: (CoreExpr -> CoreExpr) -> MatchResult -> MatchResult
+adjustMatchResult :: DsWrapper -> MatchResult -> MatchResult
 adjustMatchResult encl_fn (MatchResult can_it_fail body_fn)
   = MatchResult can_it_fail (\fail -> body_fn fail     `thenDs` \ body ->
                                      returnDs (encl_fn body))
@@ -261,8 +317,17 @@ seqVar var body = Case (Var var) var (exprType body)
                        [(DEFAULT, [], body)]
 
 mkCoLetMatchResult :: CoreBind -> MatchResult -> MatchResult
-mkCoLetMatchResult bind match_result
-  = adjustMatchResult (mkDsLet bind) match_result
+mkCoLetMatchResult bind = adjustMatchResult (mkDsLet bind)
+
+-- (mkViewMatchResult var' viewExpr var mr) makes the expression
+-- let var' = viewExpr var in mr
+mkViewMatchResult :: Id -> CoreExpr -> Id -> MatchResult -> MatchResult
+mkViewMatchResult var' viewExpr var = 
+    adjustMatchResult (mkDsLet (NonRec var' (mkDsApp viewExpr (Var var))))
+
+mkEvalMatchResult :: Id -> Type -> MatchResult -> MatchResult
+mkEvalMatchResult var ty
+  = adjustMatchResult (\e -> Case (Var var) var ty [(DEFAULT, [], e)]) 
 
 mkGuardedMatchResult :: CoreExpr -> MatchResult -> MatchResult
 mkGuardedMatchResult pred_expr (MatchResult can_it_fail body_fn)
@@ -305,9 +370,11 @@ mkCoAlgCaseMatchResult var ty match_alts
        --  the scrutinised Id to be sufficiently refined to have a TyCon in it]
 
        -- Stuff for newtype
-    (con1, arg_ids1, match_result1) = head match_alts
-    arg_id1    = head arg_ids1
-    newtype_rhs = mkNewTypeBody tycon (idType arg_id1) (Var var)
+    (con1, arg_ids1, match_result1) = ASSERT( notNull match_alts ) head match_alts
+    arg_id1    = ASSERT( notNull arg_ids1 ) head arg_ids1
+    var_ty      = idType var
+    (tc, ty_args) = splitNewTyConApp var_ty
+    newtype_rhs = unwrapNewTypeBody tc ty_args (Var var)
                
        -- Stuff for data types
     data_cons      = tyConDataCons tycon
@@ -551,7 +618,7 @@ mkSelectorBinds pat val_expr
        --
        -- So to get the type of 'v', use the pattern not the rhs.  Often more
        -- efficient too.
-    newSysLocalDs (hsPatType pat)      `thenDs` \ val_var ->
+    newSysLocalDs (hsLPatType pat)     `thenDs` \ val_var ->
 
        -- For the error message we make one error-app, to avoid duplication.
        -- But we need it at different types... so we use coerce for that
@@ -587,15 +654,16 @@ mkSelectorBinds pat val_expr
                    (Var bndr_var) error_expr                   `thenDs` \ rhs_expr ->
         returnDs (bndr_var, rhs_expr)
       where
-        error_expr = mkCoerce (idType bndr_var) (Var err_var)
+        error_expr = mkCoerce co (Var err_var)
+        co         = mkUnsafeCoercion (exprType (Var err_var)) (idType bndr_var)
 
     is_simple_lpat p = is_simple_pat (unLoc p)
 
-    is_simple_pat (TuplePat ps Boxed _)    = all is_triv_lpat ps
-    is_simple_pat (ConPatOut _ _ _ _ ps _) = all is_triv_lpat (hsConArgs ps)
-    is_simple_pat (VarPat _)              = True
-    is_simple_pat (ParPat p)              = is_simple_lpat p
-    is_simple_pat other                           = False
+    is_simple_pat (TuplePat ps Boxed _)        = all is_triv_lpat ps
+    is_simple_pat (ConPatOut{ pat_args = ps }) = all is_triv_lpat (hsConPatArgs ps)
+    is_simple_pat (VarPat _)                  = True
+    is_simple_pat (ParPat p)                  = is_simple_lpat p
+    is_simple_pat other                               = False
 
     is_triv_lpat p = is_triv_pat (unLoc p)
 
@@ -806,7 +874,6 @@ mkCoreSel vars the_var scrut_var scrut
         [(DataAlt (tupleCon Boxed (length vars)), vars, Var the_var)]
 \end{code}
 
-
 %************************************************************************
 %*                                                                     *
 \subsection[mkFailurePair]{Code for pattern-matching and other failures}
@@ -881,4 +948,43 @@ mkFailurePair expr
     ty = exprType expr
 \end{code}
 
-
+\begin{code}
+mkOptTickBox :: Maybe (Int,[Id]) -> CoreExpr -> DsM CoreExpr
+mkOptTickBox Nothing e   = return e
+mkOptTickBox (Just (ix,ids)) e = mkTickBox ix ids e
+
+mkTickBox :: Int -> [Id] -> CoreExpr -> DsM CoreExpr
+mkTickBox ix vars e = do
+       uq <- newUnique         
+       mod <- getModuleDs
+       let tick | opt_Hpc   = mkTickBoxOpId uq mod ix
+                | otherwise = mkBreakPointOpId uq mod ix
+       uq2 <- newUnique        
+       let occName = mkVarOcc "tick"
+       let name = mkInternalName uq2 occName noSrcSpan   -- use mkSysLocal?
+       let var  = Id.mkLocalId name realWorldStatePrimTy
+       scrut <- 
+          if opt_Hpc 
+            then return (Var tick)
+            else do
+              let tickVar = Var tick
+              let tickType = mkFunTys (map idType vars) realWorldStatePrimTy 
+              let scrutApTy = App tickVar (Type tickType)
+              return (mkApps scrutApTy (map Var vars) :: Expr Id)
+       return $ Case scrut var ty [(DEFAULT,[],e)]
+  where
+     ty = exprType e
+
+mkBinaryTickBox :: Int -> Int -> CoreExpr -> DsM CoreExpr
+mkBinaryTickBox ixT ixF e = do
+       mod <- getModuleDs
+       uq <- newUnique         
+       mod <- getModuleDs
+       let bndr1 = mkSysLocal FSLIT("t1") uq boolTy 
+       falseBox <- mkTickBox ixF [] $ Var falseDataConId
+       trueBox  <- mkTickBox ixT [] $ Var trueDataConId
+       return $ Case e bndr1 boolTy
+                       [ (DataAlt falseDataCon, [], falseBox)
+                       , (DataAlt trueDataCon,  [], trueBox)
+                       ]
+\end{code}