[project @ 2001-05-18 08:46:18 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcExpr.lhs
index 59730b2..006983d 100644 (file)
@@ -9,7 +9,7 @@ module TcExpr ( tcApp, tcExpr, tcMonoExpr, tcPolyExpr, tcId ) where
 #include "HsVersions.h"
 
 import HsSyn           ( HsExpr(..), HsLit(..), ArithSeqInfo(..), 
-                         StmtCtxt(..), mkMonoBind
+                         HsMatchContext(..), mkMonoBind
                        )
 import RnHsSyn         ( RenamedHsExpr, RenamedRecordBinds )
 import TcHsSyn         ( TcExpr, TcRecordBinds, mkHsLet )
@@ -20,13 +20,12 @@ import BasicTypes   ( RecFlag(..) )
 import Inst            ( InstOrigin(..), 
                          LIE, mkLIE, emptyLIE, unitLIE, plusLIE, plusLIEs,
                          newOverloadedLit, newMethod, newIPDict,
-                         newDicts, newClassDicts,
+                         newDicts, 
                          instToId, tcInstId
                        )
 import TcBinds         ( tcBindsAndThen )
-import TcEnv           ( TcTyThing(..), 
-                         tcLookupClass, tcLookupGlobalId, tcLookupGlobal_maybe,
-                         tcLookupTyCon, tcLookupDataCon, tcLookup,
+import TcEnv           ( tcLookupClass, tcLookupGlobalId, tcLookupGlobal_maybe,
+                         tcLookupTyCon, tcLookupDataCon, tcLookupId,
                          tcExtendGlobalTyVars, tcLookupSyntaxName
                        )
 import TcMatches       ( tcMatchesCase, tcMatchLambda, tcStmts )
@@ -37,22 +36,23 @@ import TcType               ( TcType, TcTauType,
                          tcInstTyVars, tcInstType, 
                          newTyVarTy, newTyVarTys, zonkTcType )
 
-import FieldLabel      ( fieldLabelName, fieldLabelType, fieldLabelTyCon )
+import FieldLabel      ( FieldLabel, fieldLabelName, fieldLabelType, fieldLabelTyCon )
 import Id              ( idType, recordSelectorFieldLabel, isRecordSelector )
 import DataCon         ( dataConFieldLabels, dataConSig, 
-                         dataConStrictMarks, StrictnessMark(..)
+                         dataConStrictMarks
                        )
+import Demand          ( isMarkedStrict )
 import Name            ( Name )
 import Type            ( mkFunTy, mkAppTy, mkTyConTy,
                          splitFunTy_maybe, splitFunTys,
-                         mkTyConApp, splitSigmaTy, 
+                         mkTyConApp, splitSigmaTy, mkClassPred,
                          isTauTy, tyVarsOfType, tyVarsOfTypes, 
                          isSigmaTy, splitAlgTyConApp, splitAlgTyConApp_maybe,
                          liftedTypeKind, openTypeKind, mkArrowKind,
                          tidyOpenType
                        )
 import TyCon           ( TyCon, tyConTyVars )
-import Subst           ( mkTopTyVarSubst, substClasses, substTy )
+import Subst           ( mkTopTyVarSubst, substTheta, substTy )
 import VarSet          ( elemVarSet )
 import TysWiredIn      ( boolTy, mkListTy, listTyCon )
 import TcUnify         ( unifyTauTy, unifyFunTy, unifyListTy, unifyTupleTy )
@@ -63,7 +63,7 @@ import PrelNames      ( cCallableClassName,
                          thenMName, failMName, returnMName, ioTyConName
                        )
 import Outputable
-import Maybes          ( maybeToBool, mapMaybe )
+import Maybes          ( maybeToBool )
 import ListSetOps      ( minusList )
 import Util
 import CmdLineOpts
@@ -269,8 +269,8 @@ tcMonoExpr (HsCCall lbl args may_gc is_asm ignored_fake_result_ty) res_ty
     tcLookupTyCon ioTyConName          `thenNF_Tc` \ ioTyCon ->
     let
        new_arg_dict (arg, arg_ty)
-         = newClassDicts (CCallOrigin (_UNPK_ lbl) (Just arg))
-                         [(cCallableClass, [arg_ty])]  `thenNF_Tc` \ arg_dicts ->
+         = newDicts (CCallOrigin (_UNPK_ lbl) (Just arg))
+                    [mkClassPred cCallableClass [arg_ty]]      `thenNF_Tc` \ arg_dicts ->
            returnNF_Tc arg_dicts       -- Actually a singleton bag
 
        result_origin = CCallOrigin (_UNPK_ lbl) Nothing {- Not an arg -}
@@ -296,7 +296,7 @@ tcMonoExpr (HsCCall lbl args may_gc is_asm ignored_fake_result_ty) res_ty
        -- Construct the extra insts, which encode the
        -- constraints on the argument and result types.
     mapNF_Tc new_arg_dict (zipEqual "tcMonoExpr:CCall" args arg_tys)   `thenNF_Tc` \ ccarg_dicts_s ->
-    newClassDicts result_origin [(cReturnableClass, [result_ty])]      `thenNF_Tc` \ ccres_dict ->
+    newDicts result_origin [mkClassPred cReturnableClass [result_ty]]  `thenNF_Tc` \ ccres_dict ->
     returnTc (HsCCall lbl args' may_gc is_asm io_result_ty,
              mkLIE (ccres_dict ++ concat ccarg_dicts_s) `plusLIE` args_lie)
 \end{code}
@@ -401,14 +401,11 @@ tcMonoExpr expr@(RecordCon con_name rbinds) res_ty
     tcRecordBinds tycon ty_args rbinds         `thenTc` \ (rbinds', rbinds_lie) ->
     
     let
-      missing_s_fields = missingStrictFields rbinds data_con
+      (missing_s_fields, missing_fields) = missingFields rbinds data_con
     in
     checkTcM (null missing_s_fields)
        (mapNF_Tc (addErrTc . missingStrictFieldCon con_name) missing_s_fields `thenNF_Tc_`
         returnNF_Tc ())  `thenNF_Tc_`
-    let
-      missing_fields = missingFields rbinds data_con
-    in
     doptsTc Opt_WarnMissingFields `thenNF_Tc` \ warn ->
     checkTcM (not (warn && not (null missing_fields)))
        (mapNF_Tc ((warnTc True) . missingFieldCon con_name) missing_fields `thenNF_Tc_`
@@ -533,9 +530,9 @@ tcMonoExpr expr@(RecordUpd record_expr rbinds) res_ty
     let
        (tyvars, theta, _, _, _, _) = dataConSig (head data_cons)
        inst_env = mkTopTyVarSubst tyvars result_inst_tys
-       theta'   = substClasses inst_env theta
+       theta'   = substTheta inst_env theta
     in
-    newClassDicts RecordUpdOrigin theta'       `thenNF_Tc` \ dicts ->
+    newDicts RecordUpdOrigin theta'    `thenNF_Tc` \ dicts ->
 
        -- Phew!
     returnTc (RecordUpdOut record_expr' result_record_ty (map instToId dicts) rbinds', 
@@ -630,7 +627,10 @@ Implicit Parameter bindings.
 tcMonoExpr (HsWith expr binds) res_ty
   = tcMonoExpr expr res_ty                     `thenTc` \ (expr', expr_lie) ->
     mapAndUnzipTc tcIPBind binds               `thenTc` \ (pairs, bind_lies) ->
-    tcSimplifyIPs (map fst binds) expr_lie     `thenTc` \ (expr_lie', dict_binds) ->
+
+       -- If the binding binds ?x = E, we  must now 
+       -- discharge any ?x constraints in expr_lie
+    tcSimplifyIPs (map fst pairs) expr_lie     `thenTc` \ (expr_lie', dict_binds) ->
     let
        binds' = [(instToId ip, rhs) | (ip,rhs) <- pairs]
        expr'' = HsLet (mkMonoBind dict_binds [] Recursive) expr'
@@ -645,22 +645,6 @@ tcIPBind (name, expr)
     returnTc ((ip, expr'), lie)
 \end{code}
 
-Typecheck expression which in most cases will be an Id.
-
-\begin{code}
-tcExpr_id :: RenamedHsExpr
-           -> TcM (TcExpr,
-                    LIE,
-                    TcType)
-tcExpr_id id_expr
- = case id_expr of
-       HsVar name -> tcId name                 `thenNF_Tc` \ stuff -> 
-                     returnTc stuff
-       other      -> newTyVarTy openTypeKind   `thenNF_Tc` \ id_ty ->
-                     tcMonoExpr id_expr id_ty  `thenTc`    \ (id_expr', lie_id) ->
-                     returnTc (id_expr', lie_id, id_ty) 
-\end{code}
-
 %************************************************************************
 %*                                                                     *
 \subsection{@tcApp@ typchecks an application}
@@ -753,15 +737,22 @@ tcArg the_fun (arg, expected_arg_ty, arg_no)
 
 \begin{code}
 tcId :: Name -> NF_TcM (TcExpr, LIE, TcType)
+tcId name      -- Look up the Id and instantiate its type
+  = tcLookupId name                    `thenNF_Tc` \ id ->
+    tcInstId id
+\end{code}
+
+Typecheck expression which in most cases will be an Id.
 
-tcId name
-  =    -- Look up the Id and instantiate its type
-    tcLookup name                      `thenNF_Tc` \ thing ->
-    case thing of
-       ATcId tc_id       -> tcInstId tc_id
-       AGlobal (AnId id) -> tcInstId id
+\begin{code}
+tcExpr_id :: RenamedHsExpr -> TcM (TcExpr, LIE, TcType)
+tcExpr_id (HsVar name) = tcId name
+tcExpr_id expr         = newTyVarTy openTypeKind       `thenNF_Tc` \ id_ty ->
+                        tcMonoExpr expr id_ty  `thenTc`    \ (expr', lie_id) ->
+                        returnTc (expr', lie_id, id_ty) 
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
 \subsection{@tcDoStmts@ typechecks a {\em list} of do statements}
@@ -875,35 +866,32 @@ badFields rbinds data_con
   where
     field_names = map fieldLabelName (dataConFieldLabels data_con)
 
-missingStrictFields rbinds data_con
-  = [ fn | fn <- strict_field_names,
-                not (fn `elem` field_names_used)
-    ]
-  where
-    field_names_used = [ field_name | (field_name, _, _) <- rbinds ]
-    strict_field_names = mapMaybe isStrict field_info
-
-    isStrict (fl, MarkedStrict) = Just (fieldLabelName fl)
-    isStrict _                 = Nothing
-
-    field_info = zip (dataConFieldLabels data_con)
-                    (dataConStrictMarks data_con)
-
 missingFields rbinds data_con
-  = [ fn | fn <- non_strict_field_names, not (fn `elem` field_names_used) ]
+  | null field_labels = ([], [])       -- Not declared as a record;
+                                       -- But C{} is still valid
+  | otherwise  
+  = (missing_strict_fields, other_missing_fields)
   where
-    field_names_used = [ field_name | (field_name, _, _) <- rbinds ]
-
-     -- missing strict fields have already been flagged as 
-     -- being so, so leave them out here.
-    non_strict_field_names = mapMaybe isn'tStrict field_info
-
-    isn'tStrict (fl, MarkedStrict) = Nothing
-    isn'tStrict (fl, _)            = Just (fieldLabelName fl)
-
-    field_info = zip (dataConFieldLabels data_con)
-                    (dataConStrictMarks data_con)
+    missing_strict_fields
+       = [ fl | (fl, str) <- field_info,
+                isMarkedStrict str,
+                not (fieldLabelName fl `elem` field_names_used)
+         ]
+    other_missing_fields
+       = [ fl | (fl, str) <- field_info,
+                not (isMarkedStrict str),
+                not (fieldLabelName fl `elem` field_names_used)
+         ]
 
+    field_names_used = [ field_name | (field_name, _, _) <- rbinds ]
+    field_labels     = dataConFieldLabels data_con
+
+    field_info = zipEqual "missingFields"
+                         field_labels
+                         (drop (length ex_theta) (dataConStrictMarks data_con))
+       -- The 'drop' is because dataConStrictMarks
+       -- includes the existential dictionaries
+    (_, _, _, ex_theta, _, _) = dataConSig data_con
 \end{code}
 
 %************************************************************************
@@ -935,8 +923,8 @@ Overloaded literals.
 tcLit :: HsLit -> TcType -> TcM (TcExpr, LIE)
 tcLit (HsLitLit s _) res_ty
   = tcLookupClass cCallableClassName                   `thenNF_Tc` \ cCallableClass ->
-    newClassDicts (LitLitOrigin (_UNPK_ s))
-                 [(cCallableClass,[res_ty])]           `thenNF_Tc` \ dicts ->
+    newDicts (LitLitOrigin (_UNPK_ s))
+            [mkClassPred cCallableClass [res_ty]]      `thenNF_Tc` \ dicts ->
     returnTc (HsLit (HsLitLit s res_ty), mkLIE dicts)
 
 tcLit lit res_ty 
@@ -953,11 +941,6 @@ tcLit lit res_ty
 
 Mini-utils:
 
-\begin{code}
-pp_nest_hang :: String -> SDoc -> SDoc
-pp_nest_hang lbl stuff = nest 2 (hang (text lbl) 4 stuff)
-\end{code}
-
 Boring and alphabetical:
 \begin{code}
 arithSeqCtxt expr
@@ -1020,12 +1003,12 @@ recordConCtxt expr = ptext SLIT("In the record construction:") <+> ppr expr
 notSelector field
   = hsep [quotes (ppr field), ptext SLIT("is not a record selector")]
 
-missingStrictFieldCon :: Name -> Name -> SDoc
+missingStrictFieldCon :: Name -> FieldLabel -> SDoc
 missingStrictFieldCon con field
   = hsep [ptext SLIT("Constructor") <+> quotes (ppr con),
          ptext SLIT("does not have the required strict field"), quotes (ppr field)]
 
-missingFieldCon :: Name -> Name -> SDoc
+missingFieldCon :: Name -> FieldLabel -> SDoc
 missingFieldCon con field
   = hsep [ptext SLIT("Field") <+> quotes (ppr field),
          ptext SLIT("is not initialised")]