[project @ 2002-02-14 14:56:04 by simonpj]
[ghc-hetmet.git] / ghc / compiler / deSugar / DsExpr.lhs
index 2ce9440..45b02fb 100644 (file)
@@ -13,13 +13,18 @@ import HsSyn                ( failureFreePat,
                          HsExpr(..), OutPat(..), HsLit(..), ArithSeqInfo(..),
                          Stmt(..), HsMatchContext(..), HsDoContext(..), 
                          Match(..), HsBinds(..), MonoBinds(..), 
-                         mkSimpleMatch, isDoExpr
+                         mkSimpleMatch 
                        )
-import TcHsSyn         ( TypecheckedHsExpr, TypecheckedHsBinds,
-                         TypecheckedStmt, TypecheckedMatchContext
-                       )
-import TcType          ( tcSplitAppTy, tcSplitFunTys, tcSplitTyConApp_maybe, tcTyConAppArgs,
+import TcHsSyn         ( TypecheckedHsExpr, TypecheckedHsBinds, TypecheckedStmt, outPatType )
+
+-- NB: The desugarer, which straddles the source and Core worlds, sometimes
+--     needs to see source types (newtypes etc), and sometimes not
+--     So WATCH OUT; check each use of split*Ty functions.
+-- Sigh.  This is a pain.
+
+import TcType          ( tcSplitAppTy, tcSplitFunTys, tcTyConAppArgs,
                          isIntegerTy, tcSplitTyConApp, isUnLiftedType, Type )
+import Type            ( splitFunTys )
 import CoreSyn
 import CoreUtils       ( exprType, mkIfThenElse, bindNonRec )
 
@@ -27,8 +32,8 @@ import DsMonad
 import DsBinds         ( dsMonoBinds, AutoScc(..) )
 import DsGRHSs         ( dsGuarded )
 import DsCCall         ( dsCCall, resultWrapper )
-import DsListComp      ( dsListComp )
-import DsUtils         ( mkErrorAppDs, mkDsLets, mkStringLit, mkStringLitFS, 
+import DsListComp      ( dsListComp, dsPArrComp )
+import DsUtils         ( mkErrorAppDs, mkStringLit, mkStringLitFS, 
                          mkConsExpr, mkNilExpr, mkIntegerLit
                        )
 import Match           ( matchWrapper, matchSimply )
@@ -41,10 +46,10 @@ import DataCon              ( DataCon, dataConWrapId, dataConFieldLabels, dataConInstOrigArg
 import DataCon         ( isExistentialDataCon )
 import Literal         ( Literal(..) )
 import TyCon           ( tyConDataCons )
-import TysWiredIn      ( tupleCon, listTyCon, charDataCon, intDataCon )
-import BasicTypes      ( RecFlag(..), Boxity(..) )
+import TysWiredIn      ( tupleCon, charDataCon, intDataCon )
+import BasicTypes      ( RecFlag(..), Boxity(..), ipNameName )
 import Maybes          ( maybeToBool )
-import PrelNames       ( hasKey, ratioTyConKey )
+import PrelNames       ( hasKey, ratioTyConKey, toPName )
 import Util            ( zipEqual, zipWithEqual )
 import Outputable
 
@@ -80,31 +85,56 @@ dsLet (ThenBinds b1 b2) body
     dsLet b1 body'
   
 -- Special case for bindings which bind unlifted variables
+-- We need to do a case right away, rather than building
+-- a tuple and doing selections.
 -- 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]
+dsLet bind@(MonoBind (AbsBinds [] [] exports inlines binds) sigs is_rec) body
+  | or [isUnLiftedType (idType g) | (_, g, l) <- exports]
   = ASSERT (case is_rec of {NonRecursive -> True; other -> False})
-    putSrcLocDs loc                    $
-    dsGuarded grhss                    `thenDs` \ rhs ->
-    let
-       body' = foldr bind body binder_triples
-       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 ->
-    matchSimply rhs PatBindRhs pat body' error_expr
+       -- Unlifted bindings are always non-recursive
+       -- and are always a Fun or Pat monobind
+       --
+       -- ToDo: in some bizarre case it's conceivable that there
+       --       could be dict binds in the 'binds'.  (See the notes
+       --       below.  Then pattern-match would fail.  Urk.)
+    case binds of
+      FunMonoBind fun _ matches loc
+       -> putSrcLocDs loc                      $
+          matchWrapper (FunRhs fun) matches    `thenDs` \ (args, rhs) ->
+          ASSERT( null args )  -- Functions aren't lifted
+          returnDs (bindNonRec fun rhs body_w_exports)
+
+      PatMonoBind pat grhss loc
+       -> putSrcLocDs loc                      $
+          dsGuarded grhss                      `thenDs` \ rhs ->
+          mk_error_app pat                     `thenDs` \ error_expr ->
+          matchSimply rhs PatBindRhs pat body_w_exports error_expr
+
+      other -> pprPanic "dsLet: unlifted" (ppr bind $$ ppr body)
   where
-    result_ty = exprType body
+    body_w_exports              = foldr bind_export body exports
+    bind_export (tvs, g, l) body = ASSERT( null tvs )
+                                  bindNonRec g (Var l) body
+
+    mk_error_app pat = mkErrorAppDs iRREFUT_PAT_ERROR_ID
+                                   (exprType body)
+                                   (showSDoc (ppr pat))
 
 -- Ordinary case for bindings
 dsLet (MonoBind binds sigs is_rec) body
   = dsMonoBinds NoSccs binds []  `thenDs` \ prs ->
-    case is_rec of
-      Recursive    -> returnDs (Let (Rec prs) body)
-      NonRecursive -> returnDs (mkDsLets [NonRec b r | (b,r) <- prs] body)
-\end{code}
+    returnDs (Let (Rec prs) body)
+       -- Use a Rec regardless of is_rec. 
+       -- Why? Because it allows the MonoBinds to be all
+       -- mixed up, which is what happens in one rare case
+       -- Namely, for an AbsBind with no tyvars and no dicts,
+       --         but which does have dictionary bindings.
+       -- See notes with TcSimplify.inferLoop [NO TYVARS]
+       -- It turned out that wrapping a Rec here was the easiest solution
+       --
+       -- NB The previous case dealt with unlifted bindings, so we
+       --    only have to deal with lifted ones now; so Rec is ok
+\end{code}     
 
 %************************************************************************
 %*                                                                     *
@@ -115,9 +145,9 @@ dsLet (MonoBind binds sigs is_rec) body
 \begin{code}
 dsExpr :: TypecheckedHsExpr -> DsM CoreExpr
 
-dsExpr (HsVar var)      = returnDs (Var var)
-dsExpr (HsIPVar var)     = returnDs (Var var)
-dsExpr (HsLit lit)       = dsLit lit
+dsExpr (HsVar var)  = returnDs (Var var)
+dsExpr (HsIPVar ip) = returnDs (Var (ipNameName ip))
+dsExpr (HsLit lit)  = dsLit lit
 -- HsOverLit has been gotten rid of by the type checker
 
 dsExpr expr@(HsLam a_Match)
@@ -163,7 +193,9 @@ dsExpr (SectionL expr op)
   = dsExpr op                                          `thenDs` \ core_op ->
     -- for the type of y, we need the type of op's 2nd argument
     let
-       (x_ty:y_ty:_, _) = tcSplitFunTys (exprType core_op)
+       (x_ty:y_ty:_, _) = splitFunTys (exprType core_op)
+       -- Must look through an implicit-parameter type; 
+       -- newtype impossible; hence Type.splitFunTys
     in
     dsExpr expr                                `thenDs` \ x_core ->
     newSysLocalDs x_ty                 `thenDs` \ x_id ->
@@ -177,7 +209,8 @@ dsExpr (SectionR op expr)
   = dsExpr op                  `thenDs` \ core_op ->
     -- for the type of x, we need the type of op's 2nd argument
     let
-       (x_ty:y_ty:_, _) = tcSplitFunTys (exprType core_op)
+       (x_ty:y_ty:_, _) = splitFunTys (exprType core_op)
+       -- See comment with SectionL
     in
     dsExpr expr                                `thenDs` \ y_core ->
     newSysLocalDs x_ty                 `thenDs` \ x_id ->
@@ -208,7 +241,7 @@ dsExpr (HsCase discrim matches src_loc)
                returnDs (Case core_discrim bndr alts)
        _ -> panic ("dsExpr: tuple pattern:\n" ++ showSDoc (ppr matching_code))
   where
-    ubx_tuple_match (Match _ [TuplePat ps Unboxed] _ _) = True
+    ubx_tuple_match (Match [TuplePat ps Unboxed] _ _) = True
     ubx_tuple_match _ = False
 
 dsExpr (HsCase discrim matches src_loc)
@@ -227,29 +260,28 @@ dsExpr (HsWith expr binds)
     where
       dsIPBind body (n, e)
         = dsExpr e     `thenDs` \ e' ->
-         returnDs (Let (NonRec n e') body)
+         returnDs (Let (NonRec (ipNameName n) e') body)
 
-dsExpr (HsDoOut do_or_lc stmts return_id then_id fail_id result_ty src_loc)
-  | maybeToBool maybe_list_comp
+-- We need the `ListComp' form to use `deListComp' (rather than the "do" form)
+-- because the interpretation of `stmts' depends on what sort of thing it is.
+--
+dsExpr (HsDoOut ListComp stmts return_id then_id fail_id result_ty src_loc)
   =    -- Special case for list comprehensions
     putSrcLocDs src_loc $
     dsListComp stmts elt_ty
+  where
+    (_, [elt_ty]) = tcSplitTyConApp result_ty
 
-  | otherwise
+dsExpr (HsDoOut DoExpr   stmts return_id then_id fail_id result_ty src_loc)
   = putSrcLocDs src_loc $
-    dsDo do_or_lc stmts return_id then_id fail_id result_ty
+    dsDo DoExpr stmts return_id then_id fail_id result_ty
+
+dsExpr (HsDoOut PArrComp stmts return_id then_id fail_id result_ty src_loc)
+  =    -- Special case for array comprehensions
+    putSrcLocDs src_loc $
+    dsPArrComp stmts elt_ty
   where
-    maybe_list_comp 
-       = case (do_or_lc, tcSplitTyConApp_maybe result_ty) of
-           (ListComp, Just (tycon, [elt_ty]))
-                 | tycon == listTyCon
-                -> Just elt_ty
-           other -> Nothing
-       -- We need the ListComp form to use deListComp (rather than the "do" form)
-       -- because the interpretation of ExprStmt depends on what sort of thing
-       -- it is.
-
-    Just elt_ty = maybe_list_comp
+    (_, [elt_ty]) = tcSplitTyConApp result_ty
 
 dsExpr (HsIf guard_expr then_expr else_expr src_loc)
   = putSrcLocDs src_loc $
@@ -278,7 +310,7 @@ dsExpr (TyApp expr tys)
 \underline{\bf Various data construction things}
 %              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 \begin{code}
-dsExpr (ExplicitListOut ty xs)
+dsExpr (ExplicitList ty xs)
   = go xs
   where
     go []     = returnDs (mkNilExpr ty)
@@ -286,6 +318,21 @@ dsExpr (ExplicitListOut ty xs)
                go xs                                   `thenDs` \ core_xs ->
                returnDs (mkConsExpr ty core_x core_xs)
 
+-- we create a list from the array elements and convert them into a list using
+-- `PrelPArr.toP'
+--
+-- * the main disadvantage to this scheme is that `toP' traverses the list
+--   twice: once to determine the length and a second time to put to elements
+--   into the array; this inefficiency could be avoided by exposing some of
+--   the innards of `PrelPArr' to the compiler (ie, have a `PrelPArrBase') so
+--   that we can exploit the fact that we already know the length of the array
+--   here at compile time
+--
+dsExpr (ExplicitPArr ty xs)
+  = dsLookupGlobalValue toPName                                `thenDs` \toP      ->
+    dsExpr (ExplicitList ty xs)                                `thenDs` \coreList ->
+    returnDs (mkApps (Var toP) [Type ty, coreList])
+
 dsExpr (ExplicitTuple expr_list boxity)
   = mapDs dsExpr expr_list       `thenDs` \ core_exprs  ->
     returnDs (mkConApp (tupleCon boxity (length expr_list))
@@ -314,6 +361,24 @@ dsExpr (ArithSeqOut expr (FromThenTo from thn two))
     dsExpr thn           `thenDs` \ thn2 ->
     dsExpr two           `thenDs` \ two2 ->
     returnDs (mkApps expr2 [from2, thn2, two2])
+
+dsExpr (PArrSeqOut expr (FromTo from two))
+  = dsExpr expr                  `thenDs` \ expr2 ->
+    dsExpr from                  `thenDs` \ from2 ->
+    dsExpr two           `thenDs` \ two2 ->
+    returnDs (mkApps expr2 [from2, two2])
+
+dsExpr (PArrSeqOut expr (FromThenTo from thn two))
+  = dsExpr expr                  `thenDs` \ expr2 ->
+    dsExpr from                  `thenDs` \ from2 ->
+    dsExpr thn           `thenDs` \ thn2 ->
+    dsExpr two           `thenDs` \ two2 ->
+    returnDs (mkApps expr2 [from2, thn2, two2])
+
+dsExpr (PArrSeqOut expr _)
+  = panic "DsExpr.dsExpr: Infinite parallel array!"
+    -- the parser shouldn't have generated it and the renamer and typechecker
+    -- shouldn't have let it through
 \end{code}
 
 \noindent
@@ -342,6 +407,8 @@ dsExpr (RecordConOut data_con con_expr rbinds)
   = dsExpr con_expr    `thenDs` \ con_expr' ->
     let
        (arg_tys, _) = tcSplitFunTys (exprType con_expr')
+       -- A newtype in the corner should be opaque; 
+       -- hence TcType.tcSplitFunTys
 
        mk_arg (arg_ty, lbl)
          = case [rhs | (sel_id,rhs,_) <- rbinds,
@@ -384,10 +451,10 @@ might do some argument-evaluation first; and may have to throw away some
 dictionaries.
 
 \begin{code}
-dsExpr (RecordUpdOut record_expr record_out_ty dicts [])
+dsExpr (RecordUpdOut record_expr record_in_ty record_out_ty dicts [])
   = dsExpr record_expr
 
-dsExpr (RecordUpdOut record_expr record_out_ty dicts rbinds)
+dsExpr expr@(RecordUpdOut record_expr record_in_ty record_out_ty dicts rbinds)
   = getSrcLocDs                        `thenDs` \ src_loc ->
     dsExpr record_expr         `thenDs` \ record_expr' ->
 
@@ -395,9 +462,8 @@ dsExpr (RecordUpdOut record_expr record_out_ty dicts rbinds)
        -- necessary so that we don't lose sharing
 
     let
-       record_in_ty = exprType record_expr'
-       in_inst_tys  = tcTyConAppArgs record_in_ty
-       out_inst_tys = tcTyConAppArgs record_out_ty
+       in_inst_tys  = tcTyConAppArgs record_in_ty      -- Newtype opaque
+       out_inst_tys = tcTyConAppArgs record_out_ty     -- Newtype opaque
 
        mk_val_arg field old_arg_id 
          = case [rhs | (sel_id, rhs, _) <- rbinds, 
@@ -418,11 +484,13 @@ dsExpr (RecordUpdOut record_expr record_out_ty dicts rbinds)
            in
            returnDs (mkSimpleMatch [ConPat con record_in_ty [] [] (map VarPat arg_ids)]
                                    rhs
-                                   (Just record_out_ty)
+                                   record_out_ty
                                    src_loc)
     in
        -- Record stuff doesn't work for existentials
-    ASSERT( all (not . isExistentialDataCon) data_cons )
+       -- The type checker checks for this, but we need 
+       -- worry only about the constructors that are to be updated
+    ASSERT2( all (not . isExistentialDataCon) cons_to_upd, ppr expr )
 
        -- It's important to generate the match with matchWrapper,
        -- and the right hand sides with applications of the wrapper Id
@@ -476,9 +544,9 @@ dsExpr (DictApp expr dicts) -- becomes a curried application
 #ifdef DEBUG
 -- HsSyn constructs that just shouldn't be here:
 dsExpr (HsDo _ _ _)        = panic "dsExpr:HsDo"
-dsExpr (ExplicitList _)            = panic "dsExpr:ExplicitList"
 dsExpr (ExprWithTySig _ _)  = panic "dsExpr:ExprWithTySig"
 dsExpr (ArithSeqIn _)      = panic "dsExpr:ArithSeqIn"
+dsExpr (PArrSeqIn _)       = panic "dsExpr:PArrSeqIn"
 #endif
 
 \end{code}
@@ -501,9 +569,9 @@ dsDo do_or_lc stmts return_id then_id fail_id result_ty
        (_, b_ty) = tcSplitAppTy result_ty      -- result_ty must be of the form (m b)
        is_do     = case do_or_lc of
                        DoExpr   -> True
-                       ListComp -> False
+                       _        -> False
        
-       -- For ExprStmt, see the comments near HsExpr.HsStmt about 
+       -- For ExprStmt, see the comments near HsExpr.Stmt about 
        -- exactly what ExprStmts mean!
        --
        -- In dsDo we can only see DoStmt and ListComp (no gaurds)
@@ -513,13 +581,10 @@ dsDo do_or_lc stmts return_id then_id fail_id result_ty
          | otherwise = do_expr expr locn       `thenDs` \ expr2 ->
                        returnDs (mkApps (Var return_id) [Type b_ty, expr2])
 
-       go (ExprStmt expr locn : stmts)
+       go (ExprStmt expr a_ty locn : stmts)
          | is_do       -- Do expression
          = do_expr expr locn           `thenDs` \ expr2 ->
            go stmts                    `thenDs` \ rest  ->
-           let
-               (_, a_ty) = tcSplitAppTy (exprType expr2)  -- Must be of form (m a)
-           in
            newSysLocalDs a_ty          `thenDs` \ ignored_result_id ->
            returnDs (mkApps (Var then_id) [Type a_ty, Type b_ty, expr2, 
                                            Lam ignored_result_id rest])
@@ -542,19 +607,19 @@ dsDo do_or_lc stmts return_id then_id fail_id result_ty
          = putSrcLocDs locn $
            dsExpr expr            `thenDs` \ expr2 ->
            let
-               (_, a_ty)  = tcSplitAppTy (exprType expr2) -- Must be of form (m a)
+               a_ty       = outPatType pat
                fail_expr  = HsApp (TyApp (HsVar fail_id) [b_ty])
                                    (HsLit (HsString (_PK_ msg)))
                msg = "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)
-                                          (Just result_ty) locn
+                                          result_ty locn
                the_matches
                  | failureFreePat pat = [main_match]
                  | otherwise          =
                      [ main_match
-                     , mkSimpleMatch [WildPat a_ty] fail_expr (Just result_ty) locn
+                     , mkSimpleMatch [WildPat a_ty] fail_expr result_ty locn
                      ]
            in
            matchWrapper (DoCtxt do_or_lc) the_matches  `thenDs` \ (binders, matching_code) ->
@@ -615,6 +680,3 @@ dsLit (HsRat r ty)
                (tycon, [i_ty]) -> ASSERT(isIntegerTy i_ty && tycon `hasKey` ratioTyConKey)
                                   (head (tyConDataCons tycon), i_ty)
 \end{code}
-
-
-