X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Ftypecheck%2FTcModule.lhs;h=ff885c704df731217b764a94cf9bc762db33c659;hb=4161ba13916463f8e67259498eacf22744160e1f;hp=9d7b16d83e27744d2993122bfb2d772d284030f9;hpb=573ef10b2afd99d3c6a36370a9367609716c97d2;p=ghc-hetmet.git diff --git a/ghc/compiler/typecheck/TcModule.lhs b/ghc/compiler/typecheck/TcModule.lhs index 9d7b16d..ff885c7 100644 --- a/ghc/compiler/typecheck/TcModule.lhs +++ b/ghc/compiler/typecheck/TcModule.lhs @@ -1,260 +1,329 @@ % -% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996 +% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % \section[TcModule]{Typechecking a whole module} \begin{code} -#include "HsVersions.h" - module TcModule ( typecheckModule, - SYN_IE(TcResults), - SYN_IE(TcResultBinds), - SYN_IE(TcIfaceInfo), - SYN_IE(TcSpecialiseRequests), - SYN_IE(TcDDumpDeriv) + TcResults(..) ) where -IMP_Ubiq(){-uitous-} +#include "HsVersions.h" -import HsSyn ( HsModule(..), HsBinds(..), Bind, HsExpr, - TyDecl, SpecDataSig, ClassDecl, InstDecl, - SpecInstSig, DefaultDecl, Sig, Fake, InPat, - FixityDecl, IE, ImportDecl +import CmdLineOpts ( DynFlag(..), DynFlags, opt_PprStyle_Debug ) +import HsSyn ( HsBinds(..), MonoBinds(..), HsDecl(..) ) +import HsTypes ( toHsType ) +import RnHsSyn ( RenamedHsDecl ) +import TcHsSyn ( TypecheckedMonoBinds, + TypecheckedForeignDecl, TypecheckedRuleDecl, + zonkTopBinds, zonkForeignExports, zonkRules ) -import RnHsSyn ( SYN_IE(RenamedHsModule), RenamedFixityDecl(..) ) -import TcHsSyn ( SYN_IE(TypecheckedHsBinds), SYN_IE(TypecheckedHsExpr), - TcIdOcc(..), zonkBinds, zonkDictBinds ) - -import TcMonad hiding ( rnMtoTcM ) -import Inst ( Inst, plusLIE ) -import TcBinds ( tcBindsAndThen ) -import TcClassDcl ( tcClassDecls2 ) + +import TcMonad +import Inst ( plusLIE ) +import TcBinds ( tcTopBinds ) +import TcClassDcl ( tcClassDecls2, mkImplicitClassBinds ) import TcDefaults ( tcDefaults ) -import TcEnv ( tcExtendGlobalValEnv, getEnv_LocalIds, - getEnv_TyCons, getEnv_Classes, - tcLookupLocalValueByKey, tcLookupTyConByKey ) +import TcEnv ( TcEnv, InstInfo(iDFunId), tcExtendGlobalValEnv, + tcEnvTyCons, tcEnvClasses, isLocalThing, + tcSetEnv, tcSetInstEnv, initTcEnv, getTcGEnv + ) +import TcRules ( tcRules ) +import TcForeign ( tcForeignImports, tcForeignExports ) import TcIfaceSig ( tcInterfaceSigs ) import TcInstDcls ( tcInstDecls1, tcInstDecls2 ) -import TcInstUtil ( buildInstanceEnvs, InstInfo ) import TcSimplify ( tcSimplifyTop ) -import TcTyClsDecls ( tcTyAndClassDecls1 ) -import TcTyDecls ( mkDataBinds ) - -import Bag ( listToBag ) -import Class ( GenClass, classSelIds ) -import ErrUtils ( SYN_IE(Warning), SYN_IE(Error) ) -import Id ( idType, isMethodSelId, isTopLevId, GenId, SYN_IE(IdEnv), nullIdEnv ) -import Maybes ( catMaybes ) -import Name ( isLocallyDefined ) -import Pretty -import RnUtils ( SYN_IE(RnEnv) ) -import TyCon ( TyCon ) -import Type ( applyTyCon ) -import TysWiredIn ( unitTy, mkPrimIoTy ) -import TyVar ( SYN_IE(TyVarEnv), nullTyVarEnv ) -import Unify ( unifyTauTy ) -import UniqFM ( lookupUFM_Directly, lookupWithDefaultUFM_Directly, - filterUFM, eltsUFM ) -import Unique ( iOTyConKey ) +import TcTyClsDecls ( tcTyAndClassDecls ) +import TcTyDecls ( mkImplicitDataBinds ) + +import CoreUnfold ( unfoldingTemplate ) +import Type ( funResultTy, splitForAllTys ) +import Bag ( isEmptyBag ) +import ErrUtils ( printErrorsAndWarnings, dumpIfSet_dyn, showPass ) +import Id ( idType, idUnfolding ) +import Module ( Module ) +import Name ( Name, toRdrName ) +import Name ( nameEnvElts, lookupNameEnv ) +import TyCon ( tyConGenInfo ) import Util - -import FiniteMap ( emptyFM, FiniteMap ) -tycon_specs = emptyFM +import BasicTypes ( EP(..), Fixity ) +import Bag ( isEmptyBag ) +import Outputable +import HscTypes ( PersistentCompilerState(..), HomeSymbolTable, + PackageTypeEnv, DFunId, ModIface(..), + TypeEnv, extendTypeEnvList, + TyThing(..), mkTypeEnv ) +import List ( partition ) \end{code} Outside-world interface: \begin{code} --- Convenient type synonyms first: -type TcResults - = (TcResultBinds, - TcIfaceInfo, - TcSpecialiseRequests, - TcDDumpDeriv) - -type TcResultBinds - = (TypecheckedHsBinds, -- record selector binds - TypecheckedHsBinds, -- binds from class decls; does NOT - -- include default-methods bindings - TypecheckedHsBinds, -- binds from instance decls; INCLUDES - -- class default-methods binds - TypecheckedHsBinds, -- binds from value decls - - [(Id, TypecheckedHsExpr)]) -- constant instance binds -type TcIfaceInfo -- things for the interface generator - = ([Id], [TyCon], [Class], Bag InstInfo) - -type TcSpecialiseRequests - = FiniteMap TyCon [(Bool, [Maybe Type])] - -- source tycon specialisation requests - -type TcDDumpDeriv - = PprStyle -> Pretty +-- Convenient type synonyms first: +data TcResults + = TcResults { + tc_pcs :: PersistentCompilerState, -- Augmented with imported information, + -- (but not stuff from this module) + + -- 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 + } --------------- typecheckModule - :: UniqSupply - -> RnEnv -- for renaming derivings - -> RenamedHsModule - -> MaybeErr - (TcResults, -- if all goes well... - Bag Warning) -- (we can still get warnings) - (Bag Error, -- if we had errors... - Bag Warning) - -typecheckModule us rn_env mod - = initTc us (tcModule rn_env mod) + :: DynFlags + -> Module + -> PersistentCompilerState + -> HomeSymbolTable + -> ModIface -- Iface for this module + -> PrintUnqualified -- For error printing + -> [RenamedHsDecl] + -> IO (Maybe TcResults) + +typecheckModule dflags this_mod pcs hst mod_iface unqual decls + = do { showPass dflags "Typechecker"; + ; env <- initTcEnv hst (pcs_PTE pcs) + + ; (maybe_tc_result, (warns,errs)) <- initTc dflags env (tcModule pcs hst get_fixity this_mod decls) + + ; printErrorsAndWarnings unqual (errs,warns) + ; printTcDump dflags maybe_tc_result + + ; if isEmptyBag errs then + return maybe_tc_result + else + return Nothing + } + where + fixity_env = mi_fixities mod_iface + + get_fixity :: Name -> Maybe Fixity + get_fixity nm = lookupNameEnv fixity_env nm \end{code} The internal monster: \begin{code} -tcModule :: RnEnv -- for renaming derivings - -> RenamedHsModule -- input - -> TcM s TcResults -- output - -tcModule rn_env - (HsModule mod_name verion exports imports fixities - ty_decls specdata_sigs cls_decls inst_decls specinst_sigs - default_decls val_decls sigs src_loc) - - = ASSERT(null imports) - - tcAddSrcLoc src_loc $ -- record where we're starting - - -- Tie the knot for inteface-file value declaration signatures - -- This info is only used inside the knot for type-checking the - -- pragmas, which is done lazily [ie failure just drops the pragma - -- without having any global-failure effect]. - - fixTc (\ ~(_, _, _, _, _, _, sig_ids) -> - tcExtendGlobalValEnv sig_ids ( - - -- The knot for instance information. This isn't used at all - -- till we type-check value declarations - fixTc ( \ ~(rec_inst_mapper, _, _, _, _) -> - - -- Type-check the type and class decls - --trace "tcTyAndClassDecls:" $ - tcTyAndClassDecls1 rec_inst_mapper ty_decls_bag cls_decls_bag - `thenTc` \ env -> - +tcModule :: PersistentCompilerState + -> HomeSymbolTable + -> (Name -> Maybe Fixity) + -> Module + -> [RenamedHsDecl] + -> TcM TcResults + +tcModule pcs hst get_fixity this_mod decls + = -- Type-check the type and class decls + fixTc (\ ~(unf_env, _, _, _, _) -> + -- (unf_env :: RecTcEnv) is used for type-checking interface pragmas + -- which is done lazily [ie failure just drops the pragma + -- without having any global-failure effect]. + -- + -- unf_env is also used to get the pragama info + -- for imported dfuns and default methods + +-- traceTc (text "Tc1") `thenNF_Tc_` + tcTyAndClassDecls unf_env decls `thenTc` \ env -> + tcSetEnv env $ + let + classes = tcEnvClasses env + tycons = tcEnvTyCons env -- INCLUDES tycons derived from classes + in + -- Typecheck the instance decls, includes deriving - tcSetEnv env ( - --trace "tcInstDecls:" $ - tcInstDecls1 inst_decls_bag specinst_sigs - mod_name rn_env fixities - ) `thenTc` \ (inst_info, deriv_binds, ddump_deriv) -> - - buildInstanceEnvs inst_info `thenTc` \ inst_mapper -> - - returnTc (inst_mapper, env, inst_info, deriv_binds, ddump_deriv) - - ) `thenTc` \ (_, env, inst_info, deriv_binds, ddump_deriv) -> - tcSetEnv env ( - - -- Default declarations - tcDefaults default_decls `thenTc` \ defaulting_tys -> - tcSetDefaultTys defaulting_tys ( -- for the iface sigs... - +-- traceTc (text "Tc2") `thenNF_Tc_` + tcInstDecls1 (pcs_insts pcs) (pcs_PRS pcs) + hst unf_env get_fixity this_mod + tycons decls `thenTc` \ (new_pcs_insts, inst_env, local_inst_info, deriv_binds) -> + tcSetInstEnv inst_env $ + + -- Interface type signatures + -- We tie a knot so that the Ids read out of interfaces are in scope + -- when we read their pragmas. + -- What we rely on is that pragmas are typechecked lazily; if + -- any type errors are found (ie there's an inconsistency) + -- we silently discard the pragma + -- We must do this before mkImplicitDataBinds (which comes next), since + -- the latter looks up unpackCStringId, for example, which is usually + -- imported +-- traceTc (text "Tc3") `thenNF_Tc_` + tcInterfaceSigs unf_env decls `thenTc` \ sig_ids -> + tcExtendGlobalValEnv sig_ids $ + -- Create any necessary record selector Ids and their bindings -- "Necessary" includes data and newtype declarations - let - tycons = getEnv_TyCons env - classes = getEnv_Classes env - in - mkDataBinds tycons `thenTc` \ (data_ids, data_binds) -> - + -- We don't create bindings for dictionary constructors; + -- they are always fully applied, and the bindings are just there + -- to support partial applications + mkImplicitDataBinds this_mod tycons `thenTc` \ (data_ids, imp_data_binds) -> + mkImplicitClassBinds this_mod classes `thenNF_Tc` \ (cls_ids, imp_cls_binds) -> + -- Extend the global value environment with - -- a) constructors - -- b) record selectors - -- c) class op selectors - tcExtendGlobalValEnv data_ids $ - tcExtendGlobalValEnv (concat (map classSelIds classes)) $ + -- (a) constructors + -- (b) record selectors + -- (c) class op selectors + -- (d) default-method ids... where? I can't see where these are + -- put into the envt, and I'm worried that the zonking phase + -- will find they aren't there and complain. + tcExtendGlobalValEnv data_ids $ + tcExtendGlobalValEnv cls_ids $ + tcGetEnv `thenTc` \ unf_env -> + returnTc (unf_env, new_pcs_insts, local_inst_info, deriv_binds, + imp_data_binds `AndMonoBinds` imp_cls_binds) + ) `thenTc` \ (env, new_pcs_insts, local_inst_info, deriv_binds, data_cls_binds) -> + + tcSetEnv env $ + + -- Foreign import declarations next +-- traceTc (text "Tc4") `thenNF_Tc_` + tcForeignImports decls `thenTc` \ (fo_ids, foi_decls) -> + tcExtendGlobalValEnv fo_ids $ + + -- Default declarations + tcDefaults decls `thenTc` \ defaulting_tys -> + tcSetDefaultTys defaulting_tys $ + + -- Value declarations next. + -- We also typecheck any extra binds that came out of the "deriving" process +-- traceTc (text "Tc5") `thenNF_Tc_` + tcTopBinds (get_binds decls `ThenBinds` deriv_binds) `thenTc` \ ((val_binds, env), lie_valdecls) -> + tcSetEnv env $ + + -- Foreign export declarations next +-- traceTc (text "Tc6") `thenNF_Tc_` + tcForeignExports decls `thenTc` \ (lie_fodecls, foe_binds, foe_decls) -> + + -- Second pass over class and instance declarations, + -- to compile the bindings themselves. +-- traceTc (text "Tc7") `thenNF_Tc_` + tcInstDecls2 local_inst_info `thenNF_Tc` \ (lie_instdecls, inst_binds) -> +-- traceTc (text "Tc8") `thenNF_Tc_` + tcClassDecls2 this_mod decls `thenNF_Tc` \ (lie_clasdecls, cls_dm_binds) -> + tcRules (pcs_rules pcs) this_mod decls `thenNF_Tc` \ (new_pcs_rules, lie_rules, local_rules) -> + + -- Deal with constant or ambiguous InstIds. How could + -- there be ambiguous ones? They can only arise if a + -- top-level decl falls under the monomorphism + -- restriction, and no subsequent decl instantiates its + -- type. (Usually, ambiguous type variables are resolved + -- during the generalisation step.) + let + lie_alldecls = lie_valdecls `plusLIE` + lie_instdecls `plusLIE` + lie_clasdecls `plusLIE` + lie_fodecls `plusLIE` + lie_rules + in + tcSimplifyTop lie_alldecls `thenTc` \ const_inst_binds -> + + -- Backsubstitution. This must be done last. + -- Even tcSimplifyTop may do some unification. + let + all_binds = data_cls_binds `AndMonoBinds` + val_binds `AndMonoBinds` + inst_binds `AndMonoBinds` + cls_dm_binds `AndMonoBinds` + const_inst_binds `AndMonoBinds` + foe_binds + in +-- traceTc (text "Tc9") `thenNF_Tc_` + zonkTopBinds all_binds `thenNF_Tc` \ (all_binds', final_env) -> + tcSetEnv final_env $ + -- zonkTopBinds puts all the top-level Ids into the tcGEnv + zonkForeignExports foe_decls `thenNF_Tc` \ foe_decls' -> + zonkRules local_rules `thenNF_Tc` \ local_rules' -> + + + let (local_things, imported_things) = partition (isLocalThing this_mod) + (nameEnvElts (getTcGEnv final_env)) + + local_type_env :: TypeEnv + local_type_env = mkTypeEnv local_things + + new_pte :: PackageTypeEnv + new_pte = extendTypeEnvList (pcs_PTE pcs) imported_things + + final_pcs :: PersistentCompilerState + final_pcs = pcs { pcs_PTE = new_pte, + pcs_insts = new_pcs_insts, + pcs_rules = new_pcs_rules + } + in +-- traceTc (text "Tc10") `thenNF_Tc_` + returnTc (TcResults { tc_pcs = final_pcs, + tc_env = local_type_env, + tc_binds = all_binds', + tc_insts = map iDFunId local_inst_info, + tc_fords = foi_decls ++ foe_decls', + tc_rules = local_rules' + } + ) + +get_binds decls = foldr ThenBinds EmptyBinds [binds | ValD binds <- decls] +\end{code} - -- Interface type signatures - -- We tie a knot so that the Ids read out of interfaces are in scope - -- when we read their pragmas. - -- What we rely on is that pragmas are typechecked lazily; if - -- any type errors are found (ie there's an inconsistency) - -- we silently discard the pragma - tcInterfaceSigs sigs `thenTc` \ sig_ids -> - tcGetEnv `thenNF_Tc` \ env -> - returnTc (env, inst_info, data_binds, deriv_binds, ddump_deriv, defaulting_tys, sig_ids) - )))) `thenTc` \ (env, inst_info, data_binds, deriv_binds, ddump_deriv, defaulting_tys, _) -> +%************************************************************************ +%* * +\subsection{Dumping output} +%* * +%************************************************************************ - tcSetEnv env ( -- to the end... - tcSetDefaultTys defaulting_tys ( -- ditto +\begin{code} +printTcDump dflags Nothing = return () +printTcDump dflags (Just results) + = do dumpIfSet_dyn dflags Opt_D_dump_types + "Type signatures" (dump_sigs results) + dumpIfSet_dyn dflags Opt_D_dump_tc + "Typechecked" (dump_tc results) + +dump_tc results + = vcat [ppr (tc_binds results), + pp_rules (tc_rules results), + ppr_gen_tycons [tc | ATyCon tc <- nameEnvElts (tc_env results)] + ] + +dump_sigs results -- Print type signatures + = -- Convert to HsType so that we get source-language style printing + -- And sort by RdrName + vcat $ map ppr_sig $ sortLt lt_sig $ + [ (toRdrName id, toHsType (idType id)) + | AnId id <- nameEnvElts (tc_env results), + want_sig id + ] + where + lt_sig (n1,_) (n2,_) = n1 < n2 + ppr_sig (n,t) = ppr n <+> dcolon <+> ppr t - -- Value declarations next. - -- We also typecheck any extra binds that came out of the "deriving" process - --trace "tcBinds:" $ - tcBindsAndThen - (\ binds1 (binds2, thing) -> (binds1 `ThenBinds` binds2, thing)) - (val_decls `ThenBinds` deriv_binds) - ( -- Second pass over instance declarations, - -- to compile the bindings themselves. - tcInstDecls2 inst_info `thenNF_Tc` \ (lie_instdecls, inst_binds) -> - tcClassDecls2 cls_decls_bag `thenNF_Tc` \ (lie_clasdecls, cls_binds) -> - tcGetEnv `thenNF_Tc` \ env -> - returnTc ( (EmptyBinds, (inst_binds, cls_binds, env)), - lie_instdecls `plusLIE` lie_clasdecls, - () )) - - `thenTc` \ ((val_binds, (inst_binds, cls_binds, final_env)), lie_alldecls, _) -> - - -- Deal with constant or ambiguous InstIds. How could - -- there be ambiguous ones? They can only arise if a - -- top-level decl falls under the monomorphism - -- restriction, and no subsequent decl instantiates its - -- type. (Usually, ambiguous type variables are resolved - -- during the generalisation step.) - tcSimplifyTop lie_alldecls `thenTc` \ const_insts -> - - -- Backsubstitution. Monomorphic top-level decls may have - -- been instantiated by subsequent decls, and the final - -- simplification step may have instantiated some - -- ambiguous types. So, sadly, we need to back-substitute - -- over the whole bunch of bindings. - -- - -- More horrible still, we have to do it in a careful order, so that - -- all the TcIds are in scope when we come across them. - -- - -- These bindings ought really to be bundled together in a huge - -- recursive group, but HsSyn doesn't have recursion among Binds, only - -- among MonoBinds. Sigh again. - zonkDictBinds nullTyVarEnv nullIdEnv const_insts `thenNF_Tc` \ (const_insts', ve1) -> - zonkBinds nullTyVarEnv ve1 val_binds `thenNF_Tc` \ (val_binds', ve2) -> - - zonkBinds nullTyVarEnv ve2 data_binds `thenNF_Tc` \ (data_binds', _) -> - zonkBinds nullTyVarEnv ve2 inst_binds `thenNF_Tc` \ (inst_binds', _) -> - zonkBinds nullTyVarEnv ve2 cls_binds `thenNF_Tc` \ (cls_binds', _) -> + want_sig id | opt_PprStyle_Debug = True + | otherwise = True -- For now - let - localids = getEnv_LocalIds final_env - tycons = getEnv_TyCons final_env - classes = getEnv_Classes final_env - - local_tycons = filter isLocallyDefined tycons - local_classes = filter isLocallyDefined classes - local_vals = [ v | v <- eltsUFM ve2, isLocallyDefined v && isTopLevId v ] - -- the isTopLevId is doubtful... - in - -- FINISHED AT LAST - returnTc ( - (data_binds', cls_binds', inst_binds', val_binds', const_insts'), +ppr_gen_tycons tcs = vcat [ptext SLIT("{-# Generic type constructor details"), + vcat (map ppr_gen_tycon tcs), + ptext SLIT("#-}") + ] - -- the next collection is just for mkInterface - (local_vals, local_tycons, local_classes, inst_info), +-- x&y are now Id's, not CoreExpr's +ppr_gen_tycon tycon + | Just ep <- tyConGenInfo tycon + = (ppr tycon <> colon) $$ nest 4 (ppr_ep ep) - tycon_specs, + | otherwise = ppr tycon <> colon <+> ptext SLIT("Not derivable") - ddump_deriv - ))) +ppr_ep (EP from to) + = vcat [ ptext SLIT("Rep type:") <+> ppr (funResultTy from_tau), + ptext SLIT("From:") <+> ppr (unfoldingTemplate (idUnfolding from)), + ptext SLIT("To:") <+> ppr (unfoldingTemplate (idUnfolding to)) + ] where - ty_decls_bag = listToBag ty_decls - cls_decls_bag = listToBag cls_decls - inst_decls_bag = listToBag inst_decls + (_,from_tau) = splitForAllTys (idType from) + +pp_rules [] = empty +pp_rules rs = vcat [ptext SLIT("{-# RULES"), + nest 4 (vcat (map ppr rs)), + ptext SLIT("#-}")] \end{code}