X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Ftypecheck%2FTcModule.lhs;h=4fc393756534722b3939a0b44685e07a643f9539;hb=111cee3f1ad93816cb828e38b38521d85c3bcebb;hp=dccaab2a2e6961f8358241b73a2203be6d5b75f3;hpb=a77abe6a30ea2763cfa1c0ca83cdce9b7200ced2;p=ghc-hetmet.git diff --git a/ghc/compiler/typecheck/TcModule.lhs b/ghc/compiler/typecheck/TcModule.lhs index dccaab2..4fc3937 100644 --- a/ghc/compiler/typecheck/TcModule.lhs +++ b/ghc/compiler/typecheck/TcModule.lhs @@ -1,165 +1,202 @@ % -% (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, - TcResults(..), - TcResultBinds(..), - TcIfaceInfo(..), - TcLocalTyConsAndClasses(..), - TcSpecialiseRequests(..), - TcDDumpDeriv(..) + TcResults(..) ) where -import 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 ( opt_D_dump_tc ) +import HsSyn ( HsModule(..), HsBinds(..), MonoBinds(..), HsDecl(..) ) +import RnHsSyn ( RenamedHsModule ) +import TcHsSyn ( TcMonoBinds, TypecheckedMonoBinds, + TypecheckedForeignDecl, TypecheckedRuleDecl, + zonkTopBinds, zonkForeignExports, zonkRules ) -import RnHsSyn ( RenamedHsModule(..), RenamedFixityDecl(..) ) -import TcHsSyn ( TypecheckedHsBinds(..), TypecheckedHsExpr(..), - TcIdOcc(..), zonkBinds, zonkInst, zonkId ) import TcMonad -import Inst ( Inst, plusLIE ) -import TcBinds ( tcBindsAndThen ) -import TcClassDcl ( tcClassDecls2 ) +import Inst ( Inst, emptyLIE, plusLIE ) +import TcBinds ( tcTopBindsAndThen ) +import TcClassDcl ( tcClassDecls2, mkImplicitClassBinds ) import TcDefaults ( tcDefaults ) -import TcEnv ( tcExtendGlobalValEnv, getEnv_LocalIds, - getEnv_TyCons, getEnv_Classes, - tcLookupLocalValueByKey, tcLookupTyConByKey ) +import TcEnv ( tcExtendGlobalValEnv, tcExtendTypeEnv, + getEnvTyCons, getEnvClasses, tcLookupValueMaybe, + explicitLookupValueByKey, tcSetValueEnv, + tcLookupTyCon, initEnv, + ValueEnv, TcTyThing(..) + ) +import TcExpr ( tcId ) +import TcRules ( tcRules ) +import TcForeign ( tcForeignImports, tcForeignExports ) import TcIfaceSig ( tcInterfaceSigs ) import TcInstDcls ( tcInstDecls1, tcInstDecls2 ) -import TcInstUtil ( buildInstanceEnvs, InstInfo ) +import TcInstUtil ( buildInstanceEnvs, classDataCon, InstInfo ) import TcSimplify ( tcSimplifyTop ) -import TcTyClsDecls ( tcTyAndClassDecls1 ) - -import Bag ( listToBag ) -import Class ( GenClass ) -import ErrUtils ( Warning(..), Error(..) ) -import Id ( GenId, isDataCon, isMethodSelId, idType ) -import Maybes ( catMaybes ) -import Name ( isExported, isLocallyDefined ) -import PrelInfo ( unitTy, mkPrimIoTy ) -import Pretty -import RnUtils ( RnEnv(..) ) -import TyCon ( TyCon ) -import Type ( mkSynTy ) -import Unify ( unifyTauTy ) -import UniqFM ( lookupUFM_Directly, lookupWithDefaultUFM_Directly, - filterUFM, eltsUFM ) -import Unique ( iOTyConKey, mainIdKey, mainPrimIOIdKey ) +import TcTyClsDecls ( tcTyAndClassDecls ) +import TcTyDecls ( mkImplicitDataBinds ) +import TcType ( TcType, typeToTcType, + TcKind, kindToTcKind, + newTyVarTy + ) + +import RnMonad ( RnNameSupply, getIfaceFixities, Fixities, InterfaceDetails ) +import Bag ( isEmptyBag ) +import ErrUtils ( Message, printErrorsAndWarnings, dumpIfSet ) +import Id ( Id, idType ) +import Module ( pprModuleName ) +import Name ( Name, nameUnique, isLocallyDefined, NamedThing(..) ) +import TyCon ( TyCon, tyConKind ) +import Class ( Class, classSelIds, classTyCon ) +import Type ( mkTyConApp, mkForAllTy, + boxedTypeKind, getTyVar, Type ) +import TysWiredIn ( unitTy ) +import PrelMods ( mAIN_Name ) +import PrelInfo ( main_NAME, thinAirIdNames, setThinAirIds ) +import TcUnify ( unifyTauTy ) +import Unique ( Unique ) +import UniqSupply ( UniqSupply ) +import Maybes ( maybeToBool ) import Util +import Bag ( Bag, isEmptyBag ) +import Outputable -import FiniteMap ( emptyFM ) -tycon_specs = emptyFM +import IOExts \end{code} Outside-world interface: \begin{code} --- Convenient type synonyms first: -type TcResults - = (TcResultBinds, - TcIfaceInfo, - TcLocalTyConsAndClasses, - 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 TcLocalTyConsAndClasses -- things defined in this module - = ([TyCon], [Class]) - -- not sure the classes are used at all (ToDo) - -type TcSpecialiseRequests - = FiniteMap TyCon [(Bool, [Maybe Type])] - -- source tycon specialisation requests - -type TcDDumpDeriv - = PprStyle -> Pretty +-- Convenient type synonyms first: +data TcResults + = TcResults { + tc_binds :: TypecheckedMonoBinds, + tc_tycons :: [TyCon], + tc_classes :: [Class], + tc_insts :: Bag InstInfo, -- Instance declaration information + tc_fords :: [TypecheckedForeignDecl], -- Foreign import & exports. + tc_rules :: [TypecheckedRuleDecl], -- Transformation rules + tc_env :: ValueEnv, + tc_thinair :: [Id] -- The thin-air Ids + } --------------- typecheckModule :: UniqSupply - -> RnEnv -- for renaming derivings + -> RnNameSupply + -> InterfaceDetails -> 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) + -> IO (Maybe TcResults) + +typecheckModule us rn_name_supply iface_det mod + = initTc us initEnv (tcModule rn_name_supply (getIfaceFixities iface_det) mod) + >>= \ (maybe_result, warns, errs) -> + + printErrorsAndWarnings errs warns >> + + -- write the thin-air Id map + (case maybe_result of + Just results -> setThinAirIds (tc_thinair results) + Nothing -> return () + ) >> + + dumpIfSet opt_D_dump_tc "Typechecked" + (case maybe_result of + Just results -> ppr (tc_binds results) + $$ + pp_rules (tc_rules results) + Nothing -> text "Typecheck failed") >> + + return (if isEmptyBag errs then + maybe_result + else + Nothing) + +pp_rules [] = empty +pp_rules rs = vcat [ptext SLIT("{-# RULES"), + nest 4 (vcat (map ppr rs)), + ptext SLIT("#-}")] \end{code} The internal monster: \begin{code} -tcModule :: RnEnv -- for renaming derivings +tcModule :: RnNameSupply -- for renaming derivings + -> Fixities -- needed for Show/Read 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 +tcModule rn_name_supply fixities + (HsModule mod_name verion exports imports decls _ src_loc) + = 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 + fixTc (\ ~(unf_env ,_) -> + -- unf_env is used for type-checking interface 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, record_binds) -> - - -- 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, record_binds, inst_info, deriv_binds, ddump_deriv) - - ) `thenTc` \ (_, env, record_binds, inst_info, deriv_binds, ddump_deriv) -> - tcSetEnv env ( - - -- Default declarations - tcDefaults default_decls `thenTc` \ defaulting_tys -> - tcSetDefaultTys defaulting_tys ( -- for the iface sigs... + -- + -- unf_env is also used to get the pragam info + -- for imported dfuns and default methods + + -- 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 + tcTyAndClassDecls unf_env rec_inst_mapper decls `thenTc` \ env -> + + -- Typecheck the instance decls, includes deriving + tcSetEnv env ( + tcInstDecls1 unf_env decls mod_name fixities rn_name_supply + ) `thenTc` \ (inst_info, deriv_binds) -> + + buildInstanceEnvs inst_info `thenNF_Tc` \ inst_mapper -> + + returnTc (inst_mapper, env, inst_info, deriv_binds) + + -- End of inner fix loop + ) `thenTc` \ (_, env, inst_info, deriv_binds) -> + + tcSetEnv env ( + + -- Default declarations + tcDefaults decls `thenTc` \ defaulting_tys -> + tcSetDefaultTys defaulting_tys $ + + -- Create any necessary record selector Ids and their bindings + -- "Necessary" includes data and newtype declarations + -- We don't create bindings for dictionary constructors; + -- they are always fully applied, and the bindings are just there + -- to support partial applications + let + tycons = getEnvTyCons env + classes = getEnvClasses env + local_tycons = filter isLocallyDefined tycons + local_classes = filter isLocallyDefined classes + in + mkImplicitDataBinds tycons `thenTc` \ (data_ids, imp_data_binds) -> + mkImplicitClassBinds classes `thenNF_Tc` \ (cls_ids, imp_cls_binds) -> + + -- Extend the global value environment with + -- (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 $ + + -- Extend the TyCon envt with the tycons corresponding to + -- the classes. + -- They are mentioned in types in interface files. + tcExtendTypeEnv [ (getName tycon, (kindToTcKind (tyConKind tycon), Nothing, ATyCon tycon)) + | clas <- classes, + let tycon = classTyCon clas + ] $ -- Interface type signatures -- We tie a knot so that the Ids read out of interfaces are in scope @@ -167,128 +204,102 @@ tcModule rn_env -- 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 -> + tcInterfaceSigs unf_env decls `thenTc` \ sig_ids -> + tcExtendGlobalValEnv sig_ids $ - returnTc (env, inst_info, record_binds, deriv_binds, ddump_deriv, defaulting_tys, sig_ids) - - )))) `thenTc` \ (env, inst_info, record_binds, deriv_binds, ddump_deriv, defaulting_tys, _) -> - - tcSetEnv env ( -- to the end... - tcSetDefaultTys defaulting_tys ( -- ditto + -- foreign import declarations next. + tcForeignImports decls `thenTc` \ (fo_ids, foi_decls) -> + tcExtendGlobalValEnv fo_ids $ -- 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, + tcTopBindsAndThen + (\ is_rec binds1 (binds2, thing) -> (binds1 `AndMonoBinds` binds2, thing)) + (get_val_decls decls `ThenBinds` deriv_binds) + ( tcGetEnv `thenNF_Tc` \ env -> + tcGetUnique `thenNF_Tc` \ uniq -> + returnTc ((EmptyMonoBinds, env), emptyLIE) + ) `thenTc` \ ((val_binds, final_env), lie_valdecls) -> + tcSetEnv final_env $ + + -- foreign export declarations next. + tcForeignExports decls `thenTc` \ (lie_fodecls, foe_binds, foe_decls) -> + + -- Second pass over class and 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, _) -> - - checkTopLevelIds mod_name final_env `thenTc_` - - -- 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 -> - 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 - - exported_ids = [v | v <- localids, - isExported v && not (isDataCon v) && not (isMethodSelId v)] - in - -- 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. - zonkBinds record_binds `thenNF_Tc` \ record_binds' -> - zonkBinds val_binds `thenNF_Tc` \ val_binds' -> - zonkBinds inst_binds `thenNF_Tc` \ inst_binds' -> - zonkBinds cls_binds `thenNF_Tc` \ cls_binds' -> - mapNF_Tc zonkInst const_insts `thenNF_Tc` \ const_insts' -> - mapNF_Tc (zonkId.TcId) exported_ids `thenNF_Tc` \ exported_ids' -> - - -- FINISHED AT LAST - returnTc ( - (record_binds', cls_binds', inst_binds', val_binds', const_insts'), - - -- the next collection is just for mkInterface - (exported_ids', tycons, classes, inst_info), - - (local_tycons, local_classes), - - tycon_specs, - - ddump_deriv - ))) - where - ty_decls_bag = listToBag ty_decls - cls_decls_bag = listToBag cls_decls - inst_decls_bag = listToBag inst_decls - + tcInstDecls2 inst_info `thenNF_Tc` \ (lie_instdecls, inst_binds) -> + tcClassDecls2 decls `thenNF_Tc` \ (lie_clasdecls, cls_dm_binds) -> + tcRules decls `thenNF_Tc` \ (lie_rules, 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 -> + + -- Check that Main defines main + (if mod_name == mAIN_Name then + tcLookupValueMaybe main_NAME `thenNF_Tc` \ maybe_main -> + checkTc (maybeToBool maybe_main) noMainErr + else + returnTc () + ) `thenTc_` + + -- Backsubstitution. This must be done last. + -- Even tcSimplifyTop may do some unification. + let + all_binds = imp_data_binds `AndMonoBinds` + imp_cls_binds `AndMonoBinds` + val_binds `AndMonoBinds` + inst_binds `AndMonoBinds` + cls_dm_binds `AndMonoBinds` + const_inst_binds `AndMonoBinds` + foe_binds + in + zonkTopBinds all_binds `thenNF_Tc` \ (all_binds', really_final_env) -> + tcSetValueEnv really_final_env $ + zonkForeignExports foe_decls `thenNF_Tc` \ foe_decls' -> + zonkRules rules `thenNF_Tc` \ rules' -> + + let + thin_air_ids = map (explicitLookupValueByKey really_final_env . nameUnique) thinAirIdNames + -- When looking up the thin-air names we must use + -- a global env that includes the zonked locally-defined Ids too + -- Hence using really_final_env + in + returnTc (really_final_env, + (TcResults { tc_binds = all_binds', + tc_tycons = local_tycons, + tc_classes = local_classes, + tc_insts = inst_info, + tc_fords = foi_decls ++ foe_decls', + tc_rules = rules', + tc_env = really_final_env, + tc_thinair = thin_air_ids + })) + ) + + -- End of outer fix loop + ) `thenTc` \ (final_env, stuff) -> + returnTc stuff + +get_val_decls decls = foldr ThenBinds EmptyBinds [binds | ValD binds <- decls] \end{code} -%************************************************************************ -%* * -\subsection{Error checking code} -%* * -%************************************************************************ - - -checkTopLevelIds checks that Main.main or Main.mainPrimIO has correct type. - \begin{code} -checkTopLevelIds :: FAST_STRING -> TcEnv s -> TcM s () -checkTopLevelIds mod final_env - | mod /= SLIT("Main") - = returnTc () - - | otherwise - = tcSetEnv final_env ( - tcLookupLocalValueByKey mainIdKey `thenNF_Tc` \ maybe_main -> - tcLookupLocalValueByKey mainPrimIOIdKey `thenNF_Tc` \ maybe_prim -> - tcLookupTyConByKey iOTyConKey `thenNF_Tc` \ io_tc -> - - case (maybe_main, maybe_prim) of - (Just main, Nothing) -> tcAddErrCtxt mainCtxt $ - unifyTauTy (mkSynTy io_tc [unitTy]) - (idType main) - - (Nothing, Just prim) -> tcAddErrCtxt primCtxt $ - unifyTauTy (mkPrimIoTy unitTy) - (idType prim) - - (Just _ , Just _ ) -> failTc mainBothIdErr - (Nothing, Nothing) -> failTc mainNoneIdErr - ) - -mainCtxt sty - = ppStr "main should have type IO ()" - -primCtxt sty - = ppStr "mainPrimIO should have type PrimIO ()" - -mainBothIdErr sty - = ppStr "module Main contains definitions for both main and mainPrimIO" - -mainNoneIdErr sty - = ppStr "module Main does not contain a definition for main (or mainPrimIO)" +noMainErr + = hsep [ptext SLIT("Module"), quotes (pprModuleName mAIN_Name), + ptext SLIT("must include a definition for"), quotes (ppr main_NAME)] \end{code} +