[project @ 2000-03-08 17:48:24 by simonmar]
[ghc-hetmet.git] / ghc / compiler / deSugar / DsExpr.lhs
index 698b48a..bce1b1d 100644 (file)
@@ -26,7 +26,7 @@ import DsBinds                ( dsMonoBinds, AutoScc(..) )
 import DsGRHSs         ( dsGuarded )
 import DsCCall         ( dsCCall )
 import DsListComp      ( dsListComp )
-import DsUtils         ( mkErrorAppDs )
+import DsUtils         ( mkErrorAppDs, mkDsLets, mkConsExpr, mkNilExpr )
 import Match           ( matchWrapper, matchSimply )
 
 import CoreUtils       ( coreExprType )
@@ -36,15 +36,15 @@ import Id           ( Id, idType, recordSelectorFieldLabel )
 import Const           ( Con(..) )
 import DataCon         ( DataCon, dataConId, dataConTyCon, dataConArgTys, dataConFieldLabels )
 import Const           ( mkMachInt, Literal(..), mkStrLit )
-import PrelVals                ( rEC_CON_ERROR_ID, rEC_UPD_ERROR_ID, iRREFUT_PAT_ERROR_ID )
+import PrelInfo                ( rEC_CON_ERROR_ID, rEC_UPD_ERROR_ID, iRREFUT_PAT_ERROR_ID )
 import TyCon           ( isNewTyCon )
 import DataCon         ( isExistentialDataCon )
 import Type            ( splitFunTys, mkTyConApp,
-                         splitAlgTyConApp, splitTyConApp_maybe,
+                         splitAlgTyConApp, splitTyConApp_maybe, isNotUsgTy, unUsgTy,
                          splitAppTy, isUnLiftedType, Type
                        )
 import TysWiredIn      ( tupleCon, unboxedTupleCon,
-                         consDataCon, listTyCon, mkListTy,
+                         listTyCon, mkListTy,
                          charDataCon, charTy, stringTy
                        )
 import BasicTypes      ( RecFlag(..) )
@@ -60,14 +60,14 @@ import Outputable
 %*                                                                     *
 %************************************************************************
 
-@dsLet@ is a match-result transformer, taking the MatchResult for the body
+@dsLet@ is a match-result transformer, taking the @MatchResult@ for the body
 and transforming it into one for the let-bindings enclosing the body.
 
 This may seem a bit odd, but (source) let bindings can contain unboxed
 binds like
-
+\begin{verbatim}
        C x# = e
-
+\end{verbatim}
 This must be transformed to a case expression and, if the type has
 more than one constructor, may fail.
 
@@ -82,7 +82,9 @@ dsLet (ThenBinds b1 b2) body
     dsLet b1 body'
   
 -- Special case for bindings which bind unlifted variables
-dsLet (MonoBind (AbsBinds [] [] binder_triples (PatMonoBind pat grhss loc)) sigs is_rec) body
+-- Silently ignore INLINE pragmas...
+dsLet (MonoBind (AbsBinds [] [] binder_triples inlines
+                          (PatMonoBind pat grhss loc)) sigs is_rec) body
   | or [isUnLiftedType (idType g) | (_, g, l) <- binder_triples]
   = ASSERT (case is_rec of {NonRecursive -> True; other -> False})
     putSrcLocDs loc                    $
@@ -92,7 +94,8 @@ dsLet (MonoBind (AbsBinds [] [] binder_triples (PatMonoBind pat grhss loc)) sigs
        bind (tyvars, g, l) body = ASSERT( null tyvars )
                                   bindNonRec g (Var l) body
     in
-    mkErrorAppDs iRREFUT_PAT_ERROR_ID result_ty (showSDoc (ppr pat))   `thenDs` \ error_expr ->
+    mkErrorAppDs iRREFUT_PAT_ERROR_ID result_ty (showSDoc (ppr pat))
+    `thenDs` \ error_expr ->
     matchSimply rhs PatBindMatch pat body' error_expr
   where
     result_ty = coreExprType body
@@ -102,9 +105,7 @@ dsLet (MonoBind binds sigs is_rec) body
   = dsMonoBinds NoSccs binds []  `thenDs` \ prs ->
     case is_rec of
       Recursive    -> returnDs (Let (Rec prs) body)
-      NonRecursive -> returnDs (foldr mk_let body prs)
-  where
-    mk_let (bndr,rhs) body = Let (NonRec bndr rhs) body
+      NonRecursive -> returnDs (mkDsLets [NonRec b r | (b,r) <- prs] body)
 \end{code}
 
 %************************************************************************
@@ -117,6 +118,7 @@ dsLet (MonoBind binds sigs is_rec) body
 dsExpr :: TypecheckedHsExpr -> DsM CoreExpr
 
 dsExpr e@(HsVar var) = returnDs (Var var)
+dsExpr e@(HsIPVar var) = returnDs (Var var)
 \end{code}
 
 %************************************************************************
@@ -125,17 +127,17 @@ dsExpr e@(HsVar var) = returnDs (Var var)
 %*                                                                     *
 %************************************************************************
 
-We give int/float literals type Integer and Rational, respectively.
+We give int/float literals type @Integer@ and @Rational@, respectively.
 The typechecker will (presumably) have put \tr{from{Integer,Rational}s}
 around them.
 
-ToDo: put in range checks for when converting "i"
+ToDo: put in range checks for when converting ``@i@''
 (or should that be in the typechecker?)
 
 For numeric literals, we try to detect there use at a standard type
-(Int, Float, etc.) are directly put in the right constructor.
+(@Int@, @Float@, etc.) are directly put in the right constructor.
 [NB: down with the @App@ conversion.]
-Otherwise, we punt, putting in a "NoRep" Core literal (where the
+Otherwise, we punt, putting in a @NoRep@ Core literal (where the
 representation decisions are delayed)...
 
 See also below where we look for @DictApps@ for \tr{plusInt}, etc.
@@ -149,39 +151,18 @@ dsExpr (HsLitOut (HsString s) _)
   = let
        the_char = mkConApp charDataCon [mkLit (MachChar (_HEAD_ s))]
        the_nil  = mkNilExpr charTy
-       the_cons = mkConApp consDataCon [Type charTy, the_char, the_nil]
+       the_cons = mkConsExpr charTy the_char the_nil
     in
     returnDs the_cons
 
 
 -- "_" => build (\ c n -> c 'c' n)     -- LATER
 
--- "str" ==> build (\ c n -> foldr charTy T c n "str")
-
-{- LATER:
-dsExpr (HsLitOut (HsString str) _)
-  = newTyVarsDs [alphaTyVar]           `thenDs` \ [new_tyvar] ->
-    let
-       new_ty = mkTyVarTy new_tyvar
-    in
-    newSysLocalsDs [
-               charTy `mkFunTy` (new_ty `mkFunTy` new_ty),
-               new_ty,
-                      mkForallTy [alphaTyVar]
-                              ((charTy `mkFunTy` (alphaTy `mkFunTy` alphaTy))
-                                       `mkFunTy` (alphaTy `mkFunTy` alphaTy))
-               ]                       `thenDs` \ [c,n,g] ->
-     returnDs (mkBuild charTy new_tyvar c n g (
-       foldl App
-         (CoTyApp (CoTyApp (Var foldrId) charTy) new_ty) *** ensure non-prim type ***
-         [VarArg c,VarArg n,LitArg (NoRepStr str)]))
--}
-
 -- otherwise, leave it as a NoRepStr;
 -- the Core-to-STG pass will wrap it in an application of "unpackCStringId".
 
 dsExpr (HsLitOut (HsString str) _)
-  = returnDs (mkLit (NoRepStr str stringTy))
+  = returnDs (mkStringLitFS str)
 
 dsExpr (HsLitOut (HsLitLit str) ty)
   | isUnLiftedType ty
@@ -277,9 +258,6 @@ will sort it out.
 dsExpr (OpApp e1 op _ e2)
   = dsExpr op                                          `thenDs` \ core_op ->
     -- for the type of y, we need the type of op's 2nd argument
-    let
-       (x_ty:y_ty:_, _) = splitFunTys (coreExprType core_op)
-    in
     dsExpr e1                          `thenDs` \ x_core ->
     dsExpr e2                          `thenDs` \ y_core ->
     returnDs (mkApps core_op [x_core, y_core])
@@ -311,38 +289,49 @@ dsExpr (SectionR op expr)
     returnDs (bindNonRec y_id y_core $
              Lam x_id (mkApps core_op [Var x_id, Var y_id]))
 
-dsExpr (CCall label args may_gc is_asm result_ty)
+dsExpr (CCall lbl args may_gc is_asm result_ty)
   = mapDs dsExpr args          `thenDs` \ core_args ->
-    dsCCall label core_args may_gc is_asm result_ty
+    dsCCall lbl core_args may_gc is_asm result_ty
        -- dsCCall does all the unboxification, etc.
 
 dsExpr (HsSCC cc expr)
   = dsExpr expr                        `thenDs` \ core_expr ->
-    getModuleAndGroupDs                `thenDs` \ (mod_name, group_name) ->
-    returnDs (Note (SCC (mkUserCC cc mod_name group_name)) core_expr)
+    getModuleDs                        `thenDs` \ mod_name ->
+    returnDs (Note (SCC (mkUserCC cc mod_name)) core_expr)
 
 -- special case to handle unboxed tuple patterns.
 
-dsExpr (HsCase discrim matches@[Match _ [TuplePat ps boxed] _ _] src_loc)
- | not boxed && all var_pat ps 
+dsExpr (HsCase discrim matches src_loc)
+ | all ubx_tuple_match matches
  =  putSrcLocDs src_loc $
-    dsExpr discrim                             `thenDs` \ core_discrim ->
-    matchWrapper CaseMatch matches "case"      `thenDs` \ ([discrim_var], matching_code) ->
+    dsExpr discrim                       `thenDs` \ core_discrim ->
+    matchWrapper CaseMatch matches "case" `thenDs` \ ([discrim_var], matching_code) ->
     case matching_code of
        Case (Var x) bndr alts | x == discrim_var -> 
                returnDs (Case core_discrim bndr alts)
        _ -> panic ("dsExpr: tuple pattern:\n" ++ showSDoc (ppr matching_code))
+  where
+    ubx_tuple_match (Match _ [TuplePat ps False{-unboxed-}] _ _) = True
+    ubx_tuple_match _ = False
 
 dsExpr (HsCase discrim matches src_loc)
   = putSrcLocDs src_loc $
-    dsExpr discrim                             `thenDs` \ core_discrim ->
-    matchWrapper CaseMatch matches "case"      `thenDs` \ ([discrim_var], matching_code) ->
+    dsExpr discrim                       `thenDs` \ core_discrim ->
+    matchWrapper CaseMatch matches "case" `thenDs` \ ([discrim_var], matching_code) ->
     returnDs (bindNonRec discrim_var core_discrim matching_code)
 
 dsExpr (HsLet binds body)
   = dsExpr body                `thenDs` \ body' ->
     dsLet binds body'
-    
+
+dsExpr (HsWith expr binds)
+  = dsExpr expr                `thenDs` \ expr' ->
+    foldlDs dsIPBind expr' binds
+    where
+      dsIPBind body (n, e)
+        = dsExpr e     `thenDs` \ e' ->
+         returnDs (Let (NonRec n e') body)
+
 dsExpr (HsDoOut do_or_lc stmts return_id then_id fail_id result_ty src_loc)
   | maybeToBool maybe_list_comp
   =    -- Special case for list comprehensions
@@ -374,8 +363,9 @@ dsExpr (HsIf guard_expr then_expr else_expr src_loc)
 \end{code}
 
 
-Type lambda and application
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+\noindent
+\underline{\bf Type lambda and application}
+%              ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 \begin{code}
 dsExpr (TyLam tyvars expr)
   = dsExpr expr `thenDs` \ core_expr ->
@@ -387,8 +377,9 @@ dsExpr (TyApp expr tys)
 \end{code}
 
 
-Various data construction things
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+\noindent
+\underline{\bf Various data construction things}
+%              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 \begin{code}
 dsExpr (ExplicitListOut ty xs)
   = go xs
@@ -398,25 +389,28 @@ dsExpr (ExplicitListOut ty xs)
     go []     = returnDs (mkNilExpr ty)
     go (x:xs) = dsExpr x                               `thenDs` \ core_x ->
                go xs                                   `thenDs` \ core_xs ->
-               returnDs (mkConApp consDataCon [Type ty, core_x, core_xs])
+                ASSERT( isNotUsgTy ty )
+               returnDs (mkConsExpr ty core_x core_xs)
 
 dsExpr (ExplicitTuple expr_list boxed)
   = mapDs dsExpr expr_list       `thenDs` \ core_exprs  ->
     returnDs (mkConApp ((if boxed 
                            then tupleCon 
                            else unboxedTupleCon) (length expr_list))
-               (map (Type . coreExprType) core_exprs ++ core_exprs))
+               (map (Type . unUsgTy . coreExprType) core_exprs ++ core_exprs))
+                -- the above unUsgTy is *required* -- KSW 1999-04-07
 
 dsExpr (HsCon con_id [ty] [arg])
   | isNewTyCon tycon
   = dsExpr arg              `thenDs` \ arg' ->
-    returnDs (Note (Coerce result_ty (coreExprType arg')) arg')
+    returnDs (Note (Coerce result_ty (unUsgTy (coreExprType arg'))) arg')
   where
     result_ty = mkTyConApp tycon [ty]
     tycon     = dataConTyCon con_id
 
 dsExpr (HsCon con_id tys args)
   = mapDs dsExpr args            `thenDs` \ args2  ->
+    ASSERT( all isNotUsgTy tys )
     returnDs (mkConApp con_id (map Type tys ++ args2))
 
 dsExpr (ArithSeqOut expr (From from))
@@ -444,22 +438,26 @@ dsExpr (ArithSeqOut expr (FromThenTo from thn two))
     returnDs (mkApps expr2 [from2, thn2, two2])
 \end{code}
 
-Record construction and update
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+\noindent
+\underline{\bf Record construction and update}
+%              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 For record construction we do this (assuming T has three arguments)
-
+\begin{verbatim}
        T { op2 = e }
 ==>
        let err = /\a -> recConErr a 
        T (recConErr t1 "M.lhs/230/op1") 
          e 
          (recConErr t1 "M.lhs/230/op3")
-
-recConErr then converts its arugment string into a proper message
+\end{verbatim}
+@recConErr@ then converts its arugment string into a proper message
 before printing it as
-
+\begin{verbatim}
        M.lhs, line 230: missing field op1 was evaluated
+\end{verbatim}
 
+We also handle @C{}@ as valid construction syntax for an unlabelled
+constructor @C@, setting all of @C@'s fields to bottom.
 
 \begin{code}
 dsExpr (RecordConOut data_con con_expr rbinds)
@@ -473,19 +471,27 @@ dsExpr (RecordConOut data_con con_expr rbinds)
              (rhs:rhss) -> ASSERT( null rhss )
                            dsExpr rhs
              []         -> mkErrorAppDs rEC_CON_ERROR_ID arg_ty (showSDoc (ppr lbl))
+       unlabelled_bottom arg_ty = mkErrorAppDs rEC_CON_ERROR_ID arg_ty ""
+
+       labels = dataConFieldLabels data_con
     in
-    mapDs mk_arg (zipEqual "dsExpr:RecordCon" arg_tys (dataConFieldLabels data_con)) `thenDs` \ con_args ->
+
+    (if null labels
+       then mapDs unlabelled_bottom arg_tys
+       else mapDs mk_arg (zipEqual "dsExpr:RecordCon" arg_tys labels))
+       `thenDs` \ con_args ->
+
     returnDs (mkApps con_expr' con_args)
 \end{code}
 
 Record update is a little harder. Suppose we have the decl:
-
+\begin{verbatim}
        data T = T1 {op1, op2, op3 :: Int}
               | T2 {op4, op2 :: Int}
               | T3
-
+\end{verbatim}
 Then we translate as follows:
-
+\begin{verbatim}
        r { op2 = e }
 ===>
        let op2 = e in
@@ -493,9 +499,9 @@ Then we translate as follows:
          T1 op1 _ op3 -> T1 op1 op2 op3
          T2 op4 _     -> T2 op4 op2
          other        -> recUpdError "M.lhs/230"
-
-It's important that we use the constructor Ids for T1, T2 etc on the
-RHSs, and do not generate a Core Con directly, because the constructor
+\end{verbatim}
+It's important that we use the constructor Ids for @T1@, @T2@ etc on the
+RHSs, and do not generate a Core @Con@ directly, because the constructor
 might do some argument-evaluation first; and may have to throw away some
 dictionaries.
 
@@ -528,6 +534,7 @@ dsExpr (RecordUpdOut record_expr record_out_ty dicts rbinds)
 
        mk_alt con
          = newSysLocalsDs (dataConArgTys con in_inst_tys)      `thenDs` \ arg_ids ->
+               -- This call to dataConArgTys won't work for existentials
            let 
                val_args = zipWithEqual "dsExpr:RecordUpd" mk_val_arg
                                        (dataConFieldLabels con) arg_ids
@@ -559,8 +566,10 @@ dsExpr (RecordUpdOut record_expr record_out_ty dicts rbinds)
        ok (sel_id, _, _) = recordSelectorFieldLabel sel_id `elem` con_fields
 \end{code}
 
-Dictionary lambda and application
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+\noindent
+\underline{\bf Dictionary lambda and application}
+%              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 @DictLam@ and @DictApp@ turn into the regular old things.
 (OLD:) @DictFunApp@ also becomes a curried application, albeit slightly more
 complicated; reminiscent of fully-applied constructors.
@@ -614,7 +623,8 @@ dsDo do_or_lc stmts return_id then_id fail_id result_ty
        go (GuardStmt expr locn : stmts)
          = do_expr expr locn                   `thenDs` \ expr2 ->
            go stmts                            `thenDs` \ rest ->
-           let msg = "Pattern match failure in do expression, " ++ showSDoc (ppr locn) in
+           let msg = ASSERT( isNotUsgTy b_ty )
+                 "Pattern match failure in do expression, " ++ showSDoc (ppr locn) in
            returnDs (mkIfThenElse expr2 
                                   rest 
                                   (App (App (Var fail_id) 
@@ -624,7 +634,7 @@ dsDo do_or_lc stmts return_id then_id fail_id result_ty
        go (ExprStmt expr locn : stmts)
          = do_expr expr locn           `thenDs` \ expr2 ->
            let
-               (_, a_ty) = splitAppTy (coreExprType expr2)     -- Must be of form (m a)
+               (_, a_ty) = splitAppTy (coreExprType expr2)  -- Must be of form (m a)
            in
            if null stmts then
                returnDs expr2
@@ -642,11 +652,15 @@ dsDo do_or_lc stmts return_id then_id fail_id result_ty
          = putSrcLocDs locn $
            dsExpr expr            `thenDs` \ expr2 ->
            let
-               (_, a_ty)  = splitAppTy (coreExprType expr2)    -- Must be of form (m a)
-               fail_expr  = HsApp (TyApp (HsVar fail_id) [b_ty]) (HsLitOut (HsString (_PK_ msg)) stringTy)
-               msg = "Pattern match failure in do expression, " ++ showSDoc (ppr locn)
+               (_, a_ty)  = splitAppTy (coreExprType expr2) -- Must be of form (m a)
+               fail_expr  = HsApp (TyApp (HsVar fail_id) [b_ty])
+                                   (HsLitOut (HsString (_PK_ msg)) stringTy)
+               msg = ASSERT2( isNotUsgTy a_ty, ppr a_ty )
+                      ASSERT2( isNotUsgTy b_ty, ppr b_ty )
+                      "Pattern match failure in do expression, " ++ showSDoc (ppr locn)
                main_match = mkSimpleMatch [pat] 
-                                          (HsDoOut do_or_lc stmts return_id then_id fail_id result_ty locn)
+                                          (HsDoOut do_or_lc stmts return_id then_id
+                                                    fail_id result_ty locn)
                                           (Just result_ty) locn
                the_matches
                  | failureFreePat pat = [main_match]