[project @ 1997-07-25 22:43:29 by sof]
[ghc-hetmet.git] / ghc / compiler / simplCore / SimplCase.lhs
index 4318ec5..918b4a7 100644 (file)
@@ -1,4 +1,4 @@
-%
+`%
 % (c) The AQUA Project, Glasgow University, 1994-1996
 %
 \section[SimplCase]{Simplification of `case' expression}
@@ -11,19 +11,23 @@ Support code for @Simplify@.
 module SimplCase ( simplCase, bindLargeRhs ) where
 
 IMP_Ubiq(){-uitous-}
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 201
 IMPORT_DELOOPER(SmplLoop)              ( simplBind, simplExpr, MagicUnfoldingFun )
+#else
+import {-# SOURCE #-} Simplify ( simplBind, simplExpr )
+--import {-# SOURCE #-} MagicUFs ( MagicUnfoldingFun )
+#endif
 
 import BinderInfo      -- too boring to try to select things...
 import CmdLineOpts     ( SimplifierSwitch(..) )
 import CoreSyn
-import CoreUnfold      ( Unfolding(..), UnfoldingGuidance(..),
-                         SimpleUnfolding, FormSummary
-                       )
+import CoreUnfold      ( Unfolding, SimpleUnfolding )
 import CoreUtils       ( coreAltsType, nonErrorRHSs, maybeErrorApp,
-                         unTagBindersAlts
+                         unTagBindersAlts, unTagBinders, coreExprType
                        )
-import Id              ( idType, isDataCon, getIdDemandInfo,
-                         SYN_IE(DataCon), GenId{-instance Eq-}
+import Id              ( idType, isDataCon, getIdDemandInfo, dataConArgTys,
+                         SYN_IE(DataCon), GenId{-instance Eq-},
+                         SYN_IE(Id)
                        )
 import IdInfo          ( willBeDemanded, DemandInfo )
 import Literal         ( isNoRepLit, Literal{-instance Eq-} )
@@ -32,12 +36,13 @@ import PrelVals             ( voidId )
 import PrimOp          ( primOpOkForSpeculation, PrimOp{-instance Eq-} )
 import SimplEnv
 import SimplMonad
-import SimplUtils      ( mkValLamTryingEta )
-import Type            ( isPrimType, getAppDataTyConExpandingDicts, mkFunTy, mkFunTys, eqTy )
+import Type            ( isPrimType, maybeAppDataTyConExpandingDicts, getAppDataTyConExpandingDicts, mkFunTy, mkFunTys, eqTy )
+import TyCon           ( isDataTyCon )
 import TysPrim         ( voidTy )
 import Unique          ( Unique{-instance Eq-} )
 import Usage           ( GenUsage{-instance Eq-} )
-import Util            ( isIn, isSingleton, zipEqual, panic, assertPanic )
+import Util            ( SYN_IE(Eager), runEager, appEager,
+                         isIn, isSingleton, zipEqual, panic, assertPanic )
 \end{code}
 
 Float let out of case.
@@ -47,7 +52,7 @@ simplCase :: SimplEnv
          -> InExpr     -- Scrutinee
          -> InAlts     -- Alternatives
          -> (SimplEnv -> InExpr -> SmplM OutExpr)      -- Rhs handler
-         -> OutType                            -- Type of result expression
+         -> OutType                                    -- Type of result expression
          -> SmplM OutExpr
 
 simplCase env (Let bind body) alts rhs_c result_ty
@@ -112,7 +117,7 @@ simplCase env (Case inner_scrut inner_alts) outer_alts rhs_c result_ty
     else
        bindLargeAlts env outer_alts rhs_c result_ty    `thenSmpl` \ (extra_bindings, outer_alts') ->
        let
-          rhs_c' = \env rhs -> simplExpr env rhs []
+          rhs_c' = \env rhs -> simplExpr env rhs [] result_ty
        in
        simplCase env inner_scrut inner_alts
                  (\env rhs -> simplCase env rhs outer_alts' rhs_c' result_ty)
@@ -132,10 +137,12 @@ simplCase env scrut alts rhs_c result_ty
   | maybeToBool maybe_error_app
   =    -- Look for an application of an error id
     tick CaseOfError   `thenSmpl_`
-    rhs_c env retyped_error_app
+    simplExpr env retyped_error_app [] result_ty
+               -- Ignore rhs_c!
+               -- We must apply simplExpr because "rhs" isn't yet simplified.
+               -- The ice is a little thin because body_ty is an OutType; but it's ok really
   where
-    alts_ty               = coreAltsType (unTagBindersAlts alts)
-    maybe_error_app       = maybeErrorApp scrut (Just alts_ty)
+    maybe_error_app       = maybeErrorApp scrut (Just result_ty)
     Just retyped_error_app = maybe_error_app
 \end{code}
 
@@ -143,9 +150,18 @@ Finally the default case
 
 \begin{code}
 simplCase env other_scrut alts rhs_c result_ty
-  =    -- Float the let outside the case scrutinee
-    simplExpr env other_scrut []       `thenSmpl` \ scrut' ->
+  = simplTy env scrut_ty                       `appEager` \ scrut_ty' ->
+    simplExpr env' other_scrut [] scrut_ty     `thenSmpl` \ scrut' ->
     completeCase env scrut' alts rhs_c
+  where
+       -- When simplifying the scrutinee of a complete case that
+       -- has no default alternative
+    env' = case alts of
+               AlgAlts _ NoDefault  -> setCaseScrutinee env
+               PrimAlts _ NoDefault -> setCaseScrutinee env
+               other                -> env
+
+    scrut_ty = coreExprType (unTagBinders other_scrut)
 \end{code}
 
 
@@ -358,7 +374,7 @@ completeCase env scrut alts rhs_c
        -- the scrutinee.  Remember that the rhs is as yet unsimplified.
     rhs1_is_scrutinee = case (scrut, rhs1) of
                          (Var scrut_var, Var rhs_var)
-                               -> case lookupId env rhs_var of
+                               -> case (runEager $ lookupId env rhs_var) of
                                    VarArg rhs_var' -> rhs_var' == scrut_var
                                    other           -> False
                          other -> False
@@ -443,20 +459,19 @@ bindLargeRhs env args rhs_ty rhs_c
                App (Var prim_rhs_fun_id) (VarArg voidId))
 
   | otherwise
-  =    -- Make the new binding Id.  NB: it's an OutId
-    newId rhs_fun_ty           `thenSmpl` \ rhs_fun_id ->
-
-       -- Generate its rhs
+  =    -- Generate the rhs
     cloneIds env used_args     `thenSmpl` \ used_args' ->
     let
        new_env = extendIdEnvWithClones env used_args used_args'
+       rhs_fun_ty :: OutType
+       rhs_fun_ty = mkFunTys (map idType used_args') rhs_ty
     in
+
+       -- Make the new binding Id.  NB: it's an OutId
+    newId rhs_fun_ty           `thenSmpl` \ rhs_fun_id ->
     rhs_c new_env              `thenSmpl` \ rhs' ->
     let
-       final_rhs
-         = (if switchIsSet new_env SimplDoEtaReduction
-            then mkValLamTryingEta
-            else mkValLam) used_args' rhs'
+       final_rhs = mkValLam used_args' rhs'
     in
     returnSmpl (NonRec rhs_fun_id final_rhs,
                foldl App (Var rhs_fun_id) used_arg_atoms)
@@ -465,8 +480,6 @@ bindLargeRhs env args rhs_ty rhs_c
        -- it's processed the OutId won't be found in the environment, so it
        -- will be left unmodified.
   where
-    rhs_fun_ty :: OutType
-    rhs_fun_ty = mkFunTys [simplTy env (idType id) | (id,_) <- used_args] rhs_ty
 
     used_args      = [arg | arg@(_,usage) <- args, not (dead usage)]
     used_arg_atoms = [VarArg arg_id | (arg_id,_) <- used_args]
@@ -497,6 +510,27 @@ simplAlts :: SimplEnv
          -> InAlts
          -> (SimplEnv -> InExpr -> SmplM OutExpr)      -- Rhs handler
          -> SmplM OutAlts
+-- For single-constructor types
+--     case e of y -> b    ===>   case e of (a,b) -> let y = (a,b) in b
+
+simplAlts env scrut (AlgAlts [] (BindDefault bndr@(id,occ_info) rhs)) rhs_c
+  | maybeToBool maybe_data_ty && 
+    not (null cons) &&         -- Not an abstract type (can arise if we're pruning tydecl imports)
+    null other_cons
+  = ASSERT( isDataTyCon tycon )
+    newIds inst_con_arg_tys    `thenSmpl` \ new_bindees ->
+    let
+       new_args = [ (b, bad_occ_info) | b <- new_bindees ]
+       con_app  = mkCon con [] ty_args (map VarArg new_bindees)
+       new_rhs  = Let (NonRec bndr con_app) rhs
+    in
+    simplAlts env scrut (AlgAlts [(con,new_args,new_rhs)] NoDefault) rhs_c
+  where
+    maybe_data_ty              = maybeAppDataTyConExpandingDicts (idType id)
+    Just (tycon, ty_args, cons)        = maybe_data_ty
+    (con:other_cons)           = cons
+    inst_con_arg_tys           = dataConArgTys con ty_args
+    bad_occ_info               = ManyOcc 0     -- Non-committal!
 
 simplAlts env scrut (AlgAlts alts deflt) rhs_c
   = mapSmpl do_alt alts                                        `thenSmpl` \ alts' ->
@@ -511,8 +545,7 @@ simplAlts env scrut (AlgAlts alts deflt) rhs_c
            new_env = case scrut of
                       Var v -> extendEnvGivenNewRhs env1 v (Con con args)
                             where
-                               (_, ty_args, _) = --trace "SimplCase.getAppData..." $
-                                                 getAppDataTyConExpandingDicts (idType v)
+                               (_, ty_args, _) = getAppDataTyConExpandingDicts (idType v)
                                args = map TyArg ty_args ++ map VarArg con_args'
 
                       other -> env1
@@ -776,8 +809,7 @@ mkCoCase env scrut (AlgAlts outer_alts
         v | scrut_is_var = Var scrut_var
           | otherwise    = Con con (map TyArg arg_tys ++ map VarArg args)
 
-    arg_tys = --trace "SimplCase:getAppData...:2" $
-             case (getAppDataTyConExpandingDicts (idType deflt_var)) of
+    arg_tys = case (getAppDataTyConExpandingDicts (idType deflt_var)) of
                (_, arg_tys, _) -> arg_tys
 
 mkCoCase env scrut (PrimAlts