[project @ 2001-01-29 08:42:54 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcModule.lhs
index 9a747c1..631167b 100644 (file)
@@ -11,10 +11,11 @@ module TcModule (
 #include "HsVersions.h"
 
 import CmdLineOpts     ( DynFlag(..), DynFlags, opt_PprStyle_Debug )
-import HsSyn           ( HsBinds(..), MonoBinds(..), HsDecl(..), 
+import HsSyn           ( HsBinds(..), MonoBinds(..), HsDecl(..), HsExpr(..),
                          isIfaceRuleDecl, nullBinds, andMonoBindList
                        )
 import HsTypes         ( toHsType )
+import PrelNames       ( mAIN_Name, mainName, ioTyConName, printName )
 import RnHsSyn         ( RenamedHsBinds, RenamedHsDecl, RenamedHsExpr )
 import TcHsSyn         ( TypecheckedMonoBinds, TypecheckedHsExpr,
                          TypecheckedForeignDecl, TypecheckedRuleDecl,
@@ -24,41 +25,44 @@ import TcHsSyn              ( TypecheckedMonoBinds, TypecheckedHsExpr,
 
 
 import TcMonad
-import TcType          ( newTyVarTy, zonkTcType )
+import TcType          ( newTyVarTy, zonkTcType, tcInstType )
+import TcUnify         ( unifyTauTy )
 import Inst            ( plusLIE )
+import VarSet          ( varSetElems )
 import TcBinds         ( tcTopBinds )
 import TcClassDcl      ( tcClassDecls2 )
 import TcDefaults      ( tcDefaults, defaultDefaultTys )
 import TcExpr          ( tcMonoExpr )
-import TcEnv           ( TcEnv, InstInfo(iDFunId), tcExtendGlobalValEnv, 
-                         isLocalThing, tcSetEnv, tcSetInstEnv, initTcEnv, getTcGEnv
+import TcEnv           ( TcEnv, InstInfo, tcExtendGlobalValEnv, tcLookup_maybe,
+                         isLocalThing, tcSetEnv, tcSetInstEnv, initTcEnv, getTcGEnv,
+                         TcTyThing(..), tcLookupTyCon
                        )
 import TcRules         ( tcIfaceRules, tcSourceRules )
 import TcForeign       ( tcForeignImports, tcForeignExports )
 import TcIfaceSig      ( tcInterfaceSigs )
 import TcInstDcls      ( tcInstDecls1, tcInstDecls2 )
-import TcSimplify      ( tcSimplifyTop )
+import TcSimplify      ( tcSimplifyTop, tcSimplifyInfer )
 import TcTyClsDecls    ( tcTyAndClassDecls )
 
 import CoreUnfold      ( unfoldingTemplate, hasUnfolding )
-import Type            ( funResultTy, splitForAllTys, openTypeKind )
-import Bag             ( isEmptyBag )
-import ErrUtils                ( printErrorsAndWarnings, dumpIfSet_dyn, showPass )
-import Id              ( idType, idUnfolding )
-import Module           ( Module )
-import Name            ( Name, toRdrName )
+import Type            ( funResultTy, splitForAllTys, mkForAllTys, mkFunTys,
+                         liftedTypeKind, openTypeKind, mkTyConApp, tyVarsOfType, tidyType )
+import ErrUtils                ( printErrorsAndWarnings, errorsFound, dumpIfSet_dyn, showPass )
+import Id              ( idType, idName, isLocalId, idUnfolding )
+import Module           ( Module, isHomeModule, moduleName )
+import Name            ( Name, toRdrName, isGlobalName )
 import Name            ( nameEnvElts, lookupNameEnv )
 import TyCon           ( tyConGenInfo )
 import Util
 import BasicTypes       ( EP(..), Fixity )
-import Bag             ( isEmptyBag )
 import Outputable
 import HscTypes                ( PersistentCompilerState(..), HomeSymbolTable, 
-                         PackageTypeEnv, DFunId, ModIface(..),
+                         PackageTypeEnv, ModIface(..),
                          TypeEnv, extendTypeEnvList, 
                          TyThing(..), implicitTyThingIds, 
                          mkTypeEnv
                        )
+import IOExts
 \end{code}
 
 Outside-world interface:
@@ -69,7 +73,6 @@ data TcResults
   = TcResults {
        -- All these fields have info *just for this module*
        tc_env     :: TypeEnv,                  -- The top level TypeEnv
-       tc_insts   :: [DFunId],                 -- Instances
        tc_binds   :: TypecheckedMonoBinds,     -- Bindings
        tc_fords   :: [TypecheckedForeignDecl], -- Foreign import & exports.
        tc_rules   :: [TypecheckedRuleDecl]     -- Transformation rules
@@ -102,6 +105,7 @@ typecheckModule dflags pcs hst mod_iface unqual decls
 
 ---------------
 typecheckExpr :: DynFlags
+             -> Bool                   -- True <=> wrap in 'print' to get a result of IO type
              -> PersistentCompilerState
              -> HomeSymbolTable
              -> PrintUnqualified       -- For error printing
@@ -110,7 +114,7 @@ typecheckExpr :: DynFlags
                  [RenamedHsDecl])      -- Plus extra decls it sucked in from interface files
              -> IO (Maybe (PersistentCompilerState, TypecheckedHsExpr, TcType))
 
-typecheckExpr dflags pcs hst unqual this_mod (expr, decls)
+typecheckExpr dflags wrap_io pcs hst unqual this_mod (expr, decls)
   = typecheck dflags pcs hst unqual $
 
         -- use the default default settings, i.e. [Integer, Double]
@@ -119,17 +123,48 @@ typecheckExpr dflags pcs hst unqual this_mod (expr, decls)
     ASSERT( null local_inst_info && nullBinds deriv_binds && null local_rules )
 
     tcSetEnv env                               $
-    newTyVarTy openTypeKind    `thenTc` \ ty ->
-    tcMonoExpr expr ty         `thenTc` \ (expr', lie) ->
-    tcSimplifyTop lie          `thenTc` \ binds ->
-    let all_expr = mkHsLet binds expr' in
-    zonkExpr all_expr          `thenNF_Tc` \ zonked_expr ->
-    zonkTcType ty              `thenNF_Tc` \ zonked_ty ->
+    tc_expr expr                                       `thenTc` \ (expr', lie, expr_ty) ->
+    tcSimplifyInfer smpl_doc 
+       (varSetElems (tyVarsOfType expr_ty)) lie        `thenTc` \ (qtvs, lie_free, dict_binds, dict_ids) ->
+    tcSimplifyTop lie_free                             `thenTc` \ const_binds ->
+    let all_expr = mkHsLet const_binds $
+                  TyLam qtvs           $
+                  DictLam dict_ids     $
+                  mkHsLet dict_binds   $
+                  expr'
+       all_expr_ty = mkForAllTys qtvs (mkFunTys (map idType dict_ids) expr_ty)
+    in
+    zonkExpr all_expr                                  `thenNF_Tc` \ zonked_expr ->
+    zonkTcType all_expr_ty                             `thenNF_Tc` \ zonked_ty ->
+    ioToTc (dumpIfSet_dyn dflags 
+               Opt_D_dump_tc "Typechecked" (ppr zonked_expr)) `thenNF_Tc_`
     returnTc (new_pcs, zonked_expr, zonked_ty) 
+
   where
     get_fixity :: Name -> Maybe Fixity
     get_fixity n = pprPanic "typecheckExpr" (ppr n)
 
+    smpl_doc = ptext SLIT("main expression")
+
+       -- Typecheck it, wrapping in 'print' if necessary to
+       -- get a result of type IO t.  Returns the result type
+       -- that is free in the result type
+    tc_expr e 
+       | wrap_io   = tryTc_ (tc_io_expr (HsApp (HsVar printName) e))   -- Recovery case
+                            (tc_io_expr e)                             -- Main case
+       | otherwise = newTyVarTy openTypeKind   `thenTc` \ ty ->
+                     tcMonoExpr e ty           `thenTc` \ (e', lie) ->
+                     returnTc (e', lie, ty)
+                     
+       where
+         tc_io_expr e = newTyVarTy openTypeKind        `thenTc` \ ty ->
+                        tcLookupTyCon ioTyConName      `thenNF_Tc` \ ioTyCon ->
+                        let
+                           res_ty = mkTyConApp ioTyCon [ty]
+                        in
+                        tcMonoExpr e res_ty    `thenTc` \ (e', lie) ->
+                        returnTc (e', lie, res_ty)
+
 ---------------
 typecheck :: DynFlags
          -> PersistentCompilerState
@@ -142,14 +177,14 @@ typecheck dflags pcs hst unqual thing_inside
  = do  { showPass dflags "Typechecker";
        ; env <- initTcEnv hst (pcs_PTE pcs)
 
-       ; (maybe_tc_result, (warns,errs)) <- initTc dflags env thing_inside
+       ; (maybe_tc_result, errs) <- initTc dflags env thing_inside
 
-       ; printErrorsAndWarnings unqual (errs,warns)
+       ; printErrorsAndWarnings unqual errs
 
-       ; if isEmptyBag errs then 
-             return maybe_tc_result
-           else 
+       ; if errorsFound errs then 
              return Nothing 
+           else 
+             return maybe_tc_result
        }
 \end{code}
 
@@ -164,7 +199,11 @@ tcModule :: PersistentCompilerState
 
 tcModule pcs hst get_fixity this_mod decls
   =    -- Type-check the type and class decls, and all imported decls
-    tcImports pcs hst get_fixity this_mod decls        `thenTc` \ (env, new_pcs, local_inst_info, deriv_binds, local_rules) ->
+       -- tcImports recovers internally, but if anything gave rise to
+       -- an error we'd better stop now, to avoid a cascade
+    checkNoErrsTc (
+       tcImports pcs hst get_fixity this_mod decls
+    )                                          `thenTc` \ (env, new_pcs, local_inst_info, deriv_binds, local_rules) ->
 
     tcSetEnv env                               $
 
@@ -207,6 +246,9 @@ tcModule pcs hst get_fixity this_mod decls
                       lie_rules
     in
     tcSimplifyTop lie_alldecls                 `thenTc` \ const_inst_binds ->
+
+       -- CHECK THAT main IS DEFINED WITH RIGHT TYPE, IF REQUIRED
+    tcCheckMain this_mod                       `thenTc_`
     
         -- Backsubstitution.    This must be done last.
         -- Even tcSimplifyTop may do some unification.
@@ -246,7 +288,6 @@ tcModule pcs hst get_fixity this_mod decls
     returnTc (new_pcs,
              TcResults { tc_env     = local_type_env,
                          tc_binds   = implicit_binds `AndMonoBinds` all_binds', 
-                         tc_insts   = map iDFunId local_inst_info,
                          tc_fords   = foi_decls ++ foe_decls',
                          tc_rules   = all_local_rules
                         }
@@ -307,10 +348,22 @@ tcImports pcs hst get_fixity this_mod decls
        
        
         tcIfaceRules (pcs_rules pcs) this_mod iface_rules      `thenNF_Tc` \ (new_pcs_rules, local_rules) ->
+               -- When relinking this module from its interface-file decls
+               -- we'll have IfaceRules that are in fact local to this module
+               -- That's the reason we we get any local_rules out here
 
        tcGetEnv                                                `thenTc` \ unf_env ->
        let
-           imported_things = filter (not . isLocalThing this_mod) (nameEnvElts (getTcGEnv unf_env))
+           all_things = nameEnvElts (getTcGEnv unf_env)
+
+            -- sometimes we're compiling in the context of a package module
+            -- (on the GHCi command line, for example).  In this case, we
+            -- want to treat everything we pulled in as an imported thing.
+           imported_things
+               | isHomeModule this_mod
+                       = filter (not . isLocalThing this_mod) all_things
+               | otherwise
+                       = all_things
 
            new_pte :: PackageTypeEnv
            new_pte = extendTypeEnvList (pcs_PTE pcs) imported_things
@@ -330,6 +383,58 @@ tcImports pcs hst get_fixity this_mod decls
 
 %************************************************************************
 %*                                                                     *
+\subsection{Checking the type of main}
+%*                                                                     *
+%************************************************************************
+
+We must check that in module Main,
+       a) main is defined
+       b) main :: forall a1...an. IO t,  for some type t
+
+If we have
+       main = error "Urk"
+then the type of main will be 
+       main :: forall a. a
+and that should pass the test too.  
+
+So we just instantiate the type and unify with IO t, and declare 
+victory if doing so succeeds.
+
+\begin{code}
+tcCheckMain :: Module -> TcM ()
+tcCheckMain this_mod
+  | not (moduleName this_mod == mAIN_Name )
+  = returnTc ()
+
+  | otherwise
+  =    -- First unify the main_id with IO t, for any old t
+    tcLookup_maybe mainName            `thenNF_Tc` \ maybe_thing ->
+    case maybe_thing of
+       Just (ATcId main_id) -> check_main_ty (idType main_id)
+       other                -> addErrTc noMainErr      
+  where
+    check_main_ty main_ty
+      = tcInstType main_ty             `thenNF_Tc` \ (tvs, theta, main_tau) ->
+       newTyVarTy liftedTypeKind       `thenNF_Tc` \ arg_ty ->
+       tcLookupTyCon ioTyConName       `thenNF_Tc` \ ioTyCon ->
+       tcAddErrCtxtM (mainTypeCtxt main_ty)    $
+       if not (null theta) then 
+               failWithTc empty        -- Context has the error message
+       else
+       unifyTauTy main_tau (mkTyConApp ioTyCon [arg_ty])
+
+mainTypeCtxt main_ty tidy_env 
+  = zonkTcType main_ty         `thenNF_Tc` \ main_ty' ->
+    returnNF_Tc (tidy_env, ptext SLIT("`main' has the illegal type") <+> 
+                                quotes (ppr (tidyType tidy_env main_ty')))
+
+noMainErr = hsep [ptext SLIT("Module") <+> quotes (ppr mAIN_Name), 
+                 ptext SLIT("must include a definition for") <+> quotes (ptext SLIT("main"))]
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
 \subsection{Dumping output}
 %*                                                                     *
 %************************************************************************
@@ -361,7 +466,11 @@ dump_sigs results  -- Print type signatures
     ppr_sig (n,t)        = ppr n <+> dcolon <+> ppr t
 
     want_sig id | opt_PprStyle_Debug = True
-               | otherwise          = True     -- For now
+               | otherwise          = isLocalId id && isGlobalName (idName id)
+       -- isLocalId ignores data constructors, records selectors etc
+       -- The isGlobalName ignores local dictionary and method bindings
+       -- that the type checker has invented.  User-defined things have
+       -- Global names.
 
 ppr_gen_tycons tcs = vcat [ptext SLIT("{-# Generic type constructor details"),
                           vcat (map ppr_gen_tycon tcs),