X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=ghc%2Fcompiler%2Ftypecheck%2FTcModule.lhs;h=9a747c143ee79bb19d1d2d29246780f197684d2e;hb=a7526448bb4d9836032352c05837efb42ccb227b;hp=ff885c704df731217b764a94cf9bc762db33c659;hpb=4161ba13916463f8e67259498eacf22744160e1f;p=ghc-hetmet.git diff --git a/ghc/compiler/typecheck/TcModule.lhs b/ghc/compiler/typecheck/TcModule.lhs index ff885c7..9a747c1 100644 --- a/ghc/compiler/typecheck/TcModule.lhs +++ b/ghc/compiler/typecheck/TcModule.lhs @@ -5,40 +5,43 @@ \begin{code} module TcModule ( - typecheckModule, - TcResults(..) + typecheckModule, typecheckExpr, TcResults(..) ) where #include "HsVersions.h" import CmdLineOpts ( DynFlag(..), DynFlags, opt_PprStyle_Debug ) -import HsSyn ( HsBinds(..), MonoBinds(..), HsDecl(..) ) +import HsSyn ( HsBinds(..), MonoBinds(..), HsDecl(..), + isIfaceRuleDecl, nullBinds, andMonoBindList + ) import HsTypes ( toHsType ) -import RnHsSyn ( RenamedHsDecl ) -import TcHsSyn ( TypecheckedMonoBinds, +import RnHsSyn ( RenamedHsBinds, RenamedHsDecl, RenamedHsExpr ) +import TcHsSyn ( TypecheckedMonoBinds, TypecheckedHsExpr, TypecheckedForeignDecl, TypecheckedRuleDecl, - zonkTopBinds, zonkForeignExports, zonkRules + zonkTopBinds, zonkForeignExports, zonkRules, mkHsLet, + zonkExpr ) + import TcMonad +import TcType ( newTyVarTy, zonkTcType ) import Inst ( plusLIE ) import TcBinds ( tcTopBinds ) -import TcClassDcl ( tcClassDecls2, mkImplicitClassBinds ) -import TcDefaults ( tcDefaults ) +import TcClassDcl ( tcClassDecls2 ) +import TcDefaults ( tcDefaults, defaultDefaultTys ) +import TcExpr ( tcMonoExpr ) import TcEnv ( TcEnv, InstInfo(iDFunId), tcExtendGlobalValEnv, - tcEnvTyCons, tcEnvClasses, isLocalThing, - tcSetEnv, tcSetInstEnv, initTcEnv, getTcGEnv + isLocalThing, tcSetEnv, tcSetInstEnv, initTcEnv, getTcGEnv ) -import TcRules ( tcRules ) +import TcRules ( tcIfaceRules, tcSourceRules ) import TcForeign ( tcForeignImports, tcForeignExports ) import TcIfaceSig ( tcInterfaceSigs ) import TcInstDcls ( tcInstDecls1, tcInstDecls2 ) import TcSimplify ( tcSimplifyTop ) import TcTyClsDecls ( tcTyAndClassDecls ) -import TcTyDecls ( mkImplicitDataBinds ) -import CoreUnfold ( unfoldingTemplate ) -import Type ( funResultTy, splitForAllTys ) +import CoreUnfold ( unfoldingTemplate, hasUnfolding ) +import Type ( funResultTy, splitForAllTys, openTypeKind ) import Bag ( isEmptyBag ) import ErrUtils ( printErrorsAndWarnings, dumpIfSet_dyn, showPass ) import Id ( idType, idUnfolding ) @@ -53,8 +56,9 @@ import Outputable import HscTypes ( PersistentCompilerState(..), HomeSymbolTable, PackageTypeEnv, DFunId, ModIface(..), TypeEnv, extendTypeEnvList, - TyThing(..), mkTypeEnv ) -import List ( partition ) + TyThing(..), implicitTyThingIds, + mkTypeEnv + ) \end{code} Outside-world interface: @@ -63,9 +67,6 @@ Outside-world interface: -- 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 @@ -77,33 +78,79 @@ data TcResults --------------- typecheckModule :: DynFlags - -> Module -> PersistentCompilerState -> HomeSymbolTable -> ModIface -- Iface for this module -> PrintUnqualified -- For error printing -> [RenamedHsDecl] - -> IO (Maybe TcResults) + -> IO (Maybe (PersistentCompilerState, TcResults)) + -- The new PCS is Augmented with imported information, + -- (but not stuff from this module) -typecheckModule dflags this_mod pcs hst mod_iface unqual decls - = do { showPass dflags "Typechecker"; + +typecheckModule dflags pcs hst mod_iface unqual decls + = do { maybe_tc_result <- typecheck dflags pcs hst unqual $ + tcModule pcs hst get_fixity this_mod decls + ; printTcDump dflags maybe_tc_result + ; return maybe_tc_result } + where + this_mod = mi_module mod_iface + fixity_env = mi_fixities mod_iface + + get_fixity :: Name -> Maybe Fixity + get_fixity nm = lookupNameEnv fixity_env nm + +--------------- +typecheckExpr :: DynFlags + -> PersistentCompilerState + -> HomeSymbolTable + -> PrintUnqualified -- For error printing + -> Module + -> (RenamedHsExpr, -- The expression itself + [RenamedHsDecl]) -- Plus extra decls it sucked in from interface files + -> IO (Maybe (PersistentCompilerState, TypecheckedHsExpr, TcType)) + +typecheckExpr dflags pcs hst unqual this_mod (expr, decls) + = typecheck dflags pcs hst unqual $ + + -- use the default default settings, i.e. [Integer, Double] + tcSetDefaultTys defaultDefaultTys $ + tcImports pcs hst get_fixity this_mod decls `thenTc` \ (env, new_pcs, local_inst_info, deriv_binds, local_rules) -> + 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 -> + returnTc (new_pcs, zonked_expr, zonked_ty) + where + get_fixity :: Name -> Maybe Fixity + get_fixity n = pprPanic "typecheckExpr" (ppr n) + +--------------- +typecheck :: DynFlags + -> PersistentCompilerState + -> HomeSymbolTable + -> PrintUnqualified -- For error printing + -> TcM r + -> IO (Maybe r) + +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 (tcModule pcs hst get_fixity this_mod decls) + ; (maybe_tc_result, (warns,errs)) <- initTc dflags env thing_inside ; 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: @@ -113,68 +160,12 @@ tcModule :: PersistentCompilerState -> (Name -> Maybe Fixity) -> Module -> [RenamedHsDecl] - -> TcM TcResults + -> TcM (PersistentCompilerState, 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 --- 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 - -- 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 - -- (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) -> - + = -- 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) -> + tcSetEnv env $ -- Foreign import declarations next @@ -188,8 +179,8 @@ tcModule pcs hst get_fixity this_mod decls -- 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) -> +-- traceTc (text "Tc5") `thenNF_Tc_` + tcTopBinds (val_binds `ThenBinds` deriv_binds) `thenTc` \ ((val_binds, env), lie_valdecls) -> tcSetEnv env $ -- Foreign export declarations next @@ -198,11 +189,9 @@ tcModule pcs hst get_fixity this_mod 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) -> + tcClassDecls2 this_mod tycl_decls `thenNF_Tc` \ (lie_clasdecls, cls_dm_binds) -> + tcSourceRules source_rules `thenNF_Tc` \ (lie_rules, more_local_rules) -> -- Deal with constant or ambiguous InstIds. How could -- there be ambiguous ones? They can only arise if a @@ -212,18 +201,17 @@ tcModule pcs hst get_fixity this_mod decls -- during the generalisation step.) let lie_alldecls = lie_valdecls `plusLIE` - lie_instdecls `plusLIE` - lie_clasdecls `plusLIE` - lie_fodecls `plusLIE` - lie_rules + 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` + all_binds = val_binds `AndMonoBinds` inst_binds `AndMonoBinds` cls_dm_binds `AndMonoBinds` const_inst_binds `AndMonoBinds` @@ -234,38 +222,111 @@ tcModule pcs hst get_fixity this_mod decls 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' -> - + zonkRules more_local_rules `thenNF_Tc` \ more_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 - } + let local_things = filter (isLocalThing this_mod) (nameEnvElts (getTcGEnv final_env)) + + -- Create any necessary "implicit" bindings (data constructors etc) + -- Should we create bindings for dictionary constructors? + -- They are always fully applied, and the bindings are just there + -- to support partial applications. But it's easier to let them through. + implicit_binds = andMonoBindList [ CoreMonoBind id (unfoldingTemplate unf) + | id <- implicitTyThingIds local_things + , let unf = idUnfolding id + , hasUnfolding unf + ] + + local_type_env :: TypeEnv + local_type_env = mkTypeEnv local_things + + all_local_rules = local_rules ++ more_local_rules' in -- traceTc (text "Tc10") `thenNF_Tc_` - returnTc (TcResults { tc_pcs = final_pcs, - tc_env = local_type_env, - tc_binds = all_binds', + 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 = local_rules' + tc_rules = all_local_rules } ) - -get_binds decls = foldr ThenBinds EmptyBinds [binds | ValD binds <- decls] + where + tycl_decls = [d | TyClD d <- decls] + val_binds = foldr ThenBinds EmptyBinds [binds | ValD binds <- decls] + source_rules = [d | RuleD d <- decls, not (isIfaceRuleDecl d)] \end{code} +\begin{code} +tcImports :: PersistentCompilerState + -> HomeSymbolTable + -> (Name -> Maybe Fixity) + -> Module + -> [RenamedHsDecl] + -> TcM (TcEnv, PersistentCompilerState, + [InstInfo], RenamedHsBinds, [TypecheckedRuleDecl]) + +-- tcImports is a slight mis-nomer. +-- It deals with everythign that could be an import: +-- type and class decls +-- interface signatures +-- instance decls +-- rule decls +-- These can occur in source code too, of course + +tcImports pcs hst get_fixity this_mod 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 tycl_decls `thenTc` \ env -> + tcSetEnv env $ + + -- Typecheck the instance decls, includes deriving +-- traceTc (text "Tc2") `thenNF_Tc_` + tcInstDecls1 (pcs_insts pcs) (pcs_PRS pcs) + hst unf_env get_fixity this_mod + 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 +-- traceTc (text "Tc3") `thenNF_Tc_` + tcInterfaceSigs unf_env tycl_decls `thenTc` \ sig_ids -> + tcExtendGlobalValEnv sig_ids $ + + + tcIfaceRules (pcs_rules pcs) this_mod iface_rules `thenNF_Tc` \ (new_pcs_rules, local_rules) -> + + tcGetEnv `thenTc` \ unf_env -> + let + imported_things = filter (not . isLocalThing this_mod) (nameEnvElts (getTcGEnv unf_env)) + + new_pte :: PackageTypeEnv + new_pte = extendTypeEnvList (pcs_PTE pcs) imported_things + + new_pcs :: PersistentCompilerState + new_pcs = pcs { pcs_PTE = new_pte, + pcs_insts = new_pcs_insts, + pcs_rules = new_pcs_rules + } + in + returnTc (unf_env, new_pcs, local_inst_info, deriv_binds, local_rules) + ) + where + tycl_decls = [d | TyClD d <- decls] + iface_rules = [d | RuleD d <- decls, isIfaceRuleDecl d] +\end{code} %************************************************************************ %* * @@ -275,7 +336,7 @@ get_binds decls = foldr ThenBinds EmptyBinds [binds | ValD binds <- decls] \begin{code} printTcDump dflags Nothing = return () -printTcDump dflags (Just results) +printTcDump dflags (Just (_, results)) = do dumpIfSet_dyn dflags Opt_D_dump_types "Type signatures" (dump_sigs results) dumpIfSet_dyn dflags Opt_D_dump_tc