X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FhsSyn%2FHsDecls.lhs;h=001d4f8ada9defc27fc93750568a25e343156f53;hb=f6c31c0fbf77b1c46c508fa56214361671ccfd05;hp=90a211f305085ec9de5aaea4cf1bb3c20230863c;hpb=c4854c781cdf7046fe6ec064c805fa838e31e933;p=ghc-hetmet.git diff --git a/ghc/compiler/hsSyn/HsDecls.lhs b/ghc/compiler/hsSyn/HsDecls.lhs index 90a211f..001d4f8 100644 --- a/ghc/compiler/hsSyn/HsDecls.lhs +++ b/ghc/compiler/hsSyn/HsDecls.lhs @@ -9,40 +9,47 @@ Definitions for: @TyDecl@ and @oCnDecl@, @ClassDecl@, \begin{code} module HsDecls ( HsDecl(..), TyClDecl(..), InstDecl(..), RuleDecl(..), RuleBndr(..), - DefaultDecl(..), - ForeignDecl(..), FoImport(..), FoExport(..), FoType(..), - ConDecl(..), ConDetails(..), + DefaultDecl(..), HsGroup(..), SpliceDecl(..), + ForeignDecl(..), ForeignImport(..), ForeignExport(..), + CImportSpec(..), FoType(..), + ConDecl(..), CoreDecl(..), BangType(..), getBangType, getBangStrictness, unbangedType, DeprecDecl(..), DeprecTxt, - hsDeclName, instDeclName, - tyClDeclName, tyClDeclNames, tyClDeclSysNames, tyClDeclTyVars, - isClassDecl, isSynDecl, isDataDecl, isIfaceSigDecl, countTyClDecls, - mkClassDeclSysNames, isIfaceRuleDecl, ifaceRuleDeclName, - getClassDeclSysNames, conDetailsTys + tyClDeclName, tyClDeclNames, tyClDeclTyVars, + isClassDecl, isSynDecl, isDataDecl, isIfaceSigDecl, + isTypeOrClassDecl, countTyClDecls, + isSourceInstDecl, instDeclDFun, ifaceRuleDeclName, + conDetailsTys, + collectRuleBndrSigTys, isSrcRule ) where #include "HsVersions.h" -- friends: -import HsBinds ( HsBinds, MonoBinds, Sig(..), FixitySig(..) ) -import HsExpr ( HsExpr ) -import HsImpExp ( ppr_var ) +import {-# SOURCE #-} HsExpr( HsExpr, pprExpr ) + -- Because Expr imports Decls via HsBracket + +import HsBinds ( HsBinds, MonoBinds, Sig(..) ) +import HsPat ( HsConDetails(..), hsConArgs ) +import HsImpExp ( pprHsVar ) import HsTypes import PprCore ( pprCoreRule ) import HsCore ( UfExpr, UfBinder, HsIdInfo, pprHsIdInfo, eq_ufBinders, eq_ufExpr, pprUfExpr ) import CoreSyn ( CoreRule(..), RuleName ) -import BasicTypes ( NewOrData(..), StrictnessMark(..), Activation(..) ) -import ForeignCall ( CExportSpec, CCallSpec, DNCallSpec, CCallConv ) +import BasicTypes ( NewOrData(..), StrictnessMark(..), Activation(..), FixitySig(..) ) +import ForeignCall ( CCallTarget(..), DNCallSpec, CCallConv, Safety, + CExportSpec(..)) -- others: import Name ( NamedThing ) import FunDeps ( pprFundeps ) +import TyCon ( DataConDetails(..), visibleDataCons ) import Class ( FunDep, DefMeth(..) ) import CStrings ( CLabelString ) import Outputable -import Util ( eqListBy ) +import Util ( eqListBy, count ) import SrcLoc ( SrcLoc ) import FastString @@ -57,18 +64,20 @@ import Maybe ( isNothing, fromJust ) %************************************************************************ \begin{code} -data HsDecl name pat - = TyClD (TyClDecl name pat) - | InstD (InstDecl name pat) - | DefD (DefaultDecl name) - | ValD (HsBinds name pat) - | ForD (ForeignDecl name) - | FixD (FixitySig name) - | DeprecD (DeprecDecl name) - | RuleD (RuleDecl name pat) +data HsDecl id + = TyClD (TyClDecl id) + | InstD (InstDecl id) + | ValD (MonoBinds id) + | SigD (Sig id) + | DefD (DefaultDecl id) + | ForD (ForeignDecl id) + | DeprecD (DeprecDecl id) + | RuleD (RuleDecl id) + | CoreD (CoreDecl id) + | SpliceD (SpliceDecl id) -- NB: all top-level fixity decls are contained EITHER --- EITHER FixDs +-- EITHER SigDs -- OR in the ClassDecls in TyClDs -- -- The former covers @@ -79,40 +88,68 @@ data HsDecl name pat -- d) top level decls -- -- The latter is for class methods only -\end{code} - -\begin{code} -#ifdef DEBUG -hsDeclName :: (NamedThing name, Outputable name, Outputable pat) - => HsDecl name pat -> name -#endif -hsDeclName (TyClD decl) = tyClDeclName decl -hsDeclName (InstD decl) = instDeclName decl -hsDeclName (ForD decl) = forDeclName decl -hsDeclName (FixD (FixitySig name _ _)) = name --- Others don't make sense -#ifdef DEBUG -hsDeclName x = pprPanic "HsDecls.hsDeclName" (ppr x) -#endif - - -instDeclName :: InstDecl name pat -> name -instDeclName (InstDecl _ _ _ (Just name) _) = name +-- A [HsDecl] is categorised into a HsGroup before being +-- fed to the renamer. +data HsGroup id + = HsGroup { + hs_valds :: HsBinds id, + -- Before the renamer, this is a single big MonoBinds, + -- with all the bindings, and all the signatures. + -- The renamer does dependency analysis, using ThenBinds + -- to give the structure + + hs_tyclds :: [TyClDecl id], + hs_instds :: [InstDecl id], + + hs_fixds :: [FixitySig id], + -- Snaffled out of both top-level fixity signatures, + -- and those in class declarations + + hs_defds :: [DefaultDecl id], + hs_fords :: [ForeignDecl id], + hs_depds :: [DeprecDecl id], + hs_ruleds :: [RuleDecl id], + hs_coreds :: [CoreDecl id] + } \end{code} \begin{code} -instance (NamedThing name, Outputable name, Outputable pat) - => Outputable (HsDecl name pat) where - +instance OutputableBndr name => Outputable (HsDecl name) where ppr (TyClD dcl) = ppr dcl ppr (ValD binds) = ppr binds ppr (DefD def) = ppr def ppr (InstD inst) = ppr inst ppr (ForD fd) = ppr fd - ppr (FixD fd) = ppr fd + ppr (SigD sd) = ppr sd ppr (RuleD rd) = ppr rd ppr (DeprecD dd) = ppr dd + ppr (CoreD dd) = ppr dd + ppr (SpliceD dd) = ppr dd + +instance OutputableBndr name => Outputable (HsGroup name) where + ppr (HsGroup { hs_valds = val_decls, + hs_tyclds = tycl_decls, + hs_instds = inst_decls, + hs_fixds = fix_decls, + hs_depds = deprec_decls, + hs_fords = foreign_decls, + hs_defds = default_decls, + hs_ruleds = rule_decls, + hs_coreds = core_decls }) + = vcat [ppr_ds fix_decls, ppr_ds default_decls, + ppr_ds deprec_decls, ppr_ds rule_decls, + ppr val_decls, + ppr_ds tycl_decls, ppr_ds inst_decls, + ppr_ds foreign_decls, ppr_ds core_decls] + where + ppr_ds [] = empty + ppr_ds ds = text "" $$ vcat (map ppr ds) + +data SpliceDecl id = SpliceDecl (HsExpr id) SrcLoc -- Top level splice + +instance OutputableBndr name => Outputable (SpliceDecl name) where + ppr (SpliceDecl e _) = ptext SLIT("$") <> parens (pprExpr e) \end{code} @@ -148,15 +185,16 @@ interface files, of course. Any such occurrence must haul in the relevant type or class decl. Plan of attack: - - Make up their occurrence names immediately - This is done in RdrHsSyn.mkClassDecl, mkTyDecl, mkConDecl - - Ensure they "point to" the parent data/class decl when loading that decl from an interface file - (See RnHiFiles.getTyClDeclSysNames) + (See RnHiFiles.getSysBinders) + + - When typechecking the decl, we build the implicit TyCons and Ids. + When doing so we look them up in the name cache (RnEnv.lookupSysName), + to ensure correct module and provenance is set - - When renaming the decl look them up in the name cache, - ensure correct module and provenance is set +These are the two places that we have to conjure up the magic derived +names. (The actual magic is in OccName.mkWorkerOcc, etc.) Default methods ~~~~~~~~~~~~~~~ @@ -173,6 +211,7 @@ Here's the deal. (We distinguish the two cases because source-code decls have (Just binds) in the tcdMeths field, whereas interface decls have Nothing. In *source-code* class declarations: + - When parsing, every ClassOpSig gets a DefMeth with a suitable RdrName This is done by RdrHsSyn.mkClassOpSigDM @@ -234,7 +273,7 @@ Source code: instance Foo [Bool] where ... These might both be dFooList - - The CoreTidy phase globalises the name, and ensures the occurrence name is + - The CoreTidy phase externalises the name, and ensures the occurrence name is unique (this isn't special to dict funs). So we'd get dFooList and dFooList1. - We can take this relaxed approach (changing the occurrence name later) @@ -258,7 +297,7 @@ Interface file code: -- for a module. That's why (despite the misnomer) IfaceSig and ForeignType -- are both in TyClDecl -data TyClDecl name pat +data TyClDecl name = IfaceSig { tcdName :: name, -- It may seem odd to classify an interface-file signature tcdType :: HsType name, -- as a 'TyClDecl', but it's very convenient. tcdIdInfo :: [HsIdInfo name], @@ -271,17 +310,19 @@ data TyClDecl name pat tcdLoc :: SrcLoc } | TyData { tcdND :: NewOrData, - tcdCtxt :: HsContext name, -- context - tcdName :: name, -- type constructor - tcdTyVars :: [HsTyVarBndr name], -- type variables - tcdCons :: [ConDecl name], -- data constructors (empty if abstract) - tcdNCons :: Int, -- Number of data constructors (valid even if type is abstract) - tcdDerivs :: Maybe [name], -- derivings; Nothing => not specified - -- (i.e., derive default); Just [] => derive - -- *nothing*; Just => as you would - -- expect... - tcdSysNames :: DataSysNames name, -- Generic converter functions - tcdLoc :: SrcLoc + tcdCtxt :: HsContext name, -- Context + tcdName :: name, -- Type constructor + tcdTyVars :: [HsTyVarBndr name], -- Type variables + tcdCons :: DataConDetails (ConDecl name), -- Data constructors + tcdDerivs :: Maybe (HsContext name), -- Derivings; Nothing => not specified + -- Just [] => derive exactly what is asked + tcdGeneric :: Maybe Bool, -- Nothing <=> source decl + -- Just x <=> interface-file decl; + -- x=True <=> generic converter functions available + -- We need this for imported data decls, since the + -- imported modules may have been compiled with + -- different flags to the current compilation unit + tcdLoc :: SrcLoc } | TySynonym { tcdName :: name, -- type constructor @@ -295,10 +336,9 @@ data TyClDecl name pat tcdTyVars :: [HsTyVarBndr name], -- The class type variables tcdFDs :: [FunDep name], -- Functional dependencies tcdSigs :: [Sig name], -- Methods' signatures - tcdMeths :: Maybe (MonoBinds name pat), -- Default methods - -- Nothing for imported class decls - -- Just bs for source class decls - tcdSysNames :: ClassSysNames name, + tcdMeths :: Maybe (MonoBinds name), -- Default methods + -- Nothing for imported class decls + -- Just bs for source class decls tcdLoc :: SrcLoc } \end{code} @@ -306,7 +346,7 @@ data TyClDecl name pat Simple classifiers \begin{code} -isIfaceSigDecl, isDataDecl, isSynDecl, isClassDecl :: TyClDecl name pat -> Bool +isIfaceSigDecl, isDataDecl, isSynDecl, isClassDecl :: TyClDecl name -> Bool isIfaceSigDecl (IfaceSig {}) = True isIfaceSigDecl other = False @@ -319,17 +359,23 @@ isDataDecl other = False isClassDecl (ClassDecl {}) = True isClassDecl other = False + +isTypeOrClassDecl (ClassDecl {}) = True +isTypeOrClassDecl (TyData {}) = True +isTypeOrClassDecl (TySynonym {}) = True +isTypeOrClassDecl (ForeignType {}) = True +isTypeOrClassDecl other = False \end{code} Dealing with names \begin{code} -------------------------------- -tyClDeclName :: TyClDecl name pat -> name +tyClDeclName :: TyClDecl name -> name tyClDeclName tycl_decl = tcdName tycl_decl -------------------------------- -tyClDeclNames :: Eq name => TyClDecl name pat -> [(name, SrcLoc)] +tyClDeclNames :: Eq name => TyClDecl name -> [(name, SrcLoc)] -- Returns all the *binding* names of the decl, along with their SrcLocs -- The first one is guaranteed to be the name of the decl -- For record fields, the first one counts as the SrcLoc @@ -351,44 +397,10 @@ tyClDeclTyVars (TyData {tcdTyVars = tvs}) = tvs tyClDeclTyVars (ClassDecl {tcdTyVars = tvs}) = tvs tyClDeclTyVars (ForeignType {}) = [] tyClDeclTyVars (IfaceSig {}) = [] - - --------------------------------- --- The "system names" are extra implicit names *bound* by the decl. --- They are kept in a list rather than a tuple --- to make the renamer easier. - -type ClassSysNames name = [name] --- For class decls they are: --- [tycon, datacon wrapper, datacon worker, --- superclass selector 1, ..., superclass selector n] - -type DataSysNames name = [name] --- For data decls they are --- [from, to] --- where from :: T -> Tring --- to :: Tring -> T - -tyClDeclSysNames :: TyClDecl name pat -> [(name, SrcLoc)] --- Similar to tyClDeclNames, but returns the "implicit" --- or "system" names of the declaration - -tyClDeclSysNames (ClassDecl {tcdSysNames = names, tcdLoc = loc}) - = [(n,loc) | n <- names] -tyClDeclSysNames (TyData {tcdCons = cons, tcdSysNames = names, tcdLoc = loc}) - = [(n,loc) | n <- names] ++ - [(wkr_name,loc) | ConDecl _ wkr_name _ _ _ loc <- cons] -tyClDeclSysNames decl = [] - - -mkClassDeclSysNames :: (name, name, name, [name]) -> [name] -getClassDeclSysNames :: [name] -> (name, name, name, [name]) -mkClassDeclSysNames (a,b,c,ds) = a:b:c:ds -getClassDeclSysNames (a:b:c:ds) = (a,b,c,ds) \end{code} \begin{code} -instance (NamedThing name, Ord name) => Eq (TyClDecl name pat) where +instance (NamedThing name, Ord name) => Eq (TyClDecl name) where -- Used only when building interface files (==) d1@(IfaceSig {}) d2@(IfaceSig {}) = tcdName d1 == tcdName d2 && @@ -404,7 +416,7 @@ instance (NamedThing name, Ord name) => Eq (TyClDecl name pat) where tcdND d1 == tcdND d2 && eqWithHsTyVars (tcdTyVars d1) (tcdTyVars d2) (\ env -> eq_hsContext env (tcdCtxt d1) (tcdCtxt d2) && - eqListBy (eq_ConDecl env) (tcdCons d1) (tcdCons d2) + eq_hsCD env (tcdCons d1) (tcdCons d2) ) (==) d1@(TySynonym {}) d2@(TySynonym {}) @@ -423,6 +435,11 @@ instance (NamedThing name, Ord name) => Eq (TyClDecl name pat) where (==) _ _ = False -- default case +eq_hsCD env (DataCons c1) (DataCons c2) = eqListBy (eq_ConDecl env) c1 c2 +eq_hsCD env Unknown Unknown = True +eq_hsCD env (HasCons n1) (HasCons n2) = n1 == n2 +eq_hsCD env d1 d2 = False + eq_hsFD env (ns1,ms1) (ns2,ms2) = eqListBy (eq_hsVar env) ns1 ns2 && eqListBy (eq_hsVar env) ms1 ms2 @@ -437,30 +454,32 @@ eq_cls_sig env (ClassOpSig n1 dm1 ty1 _) (ClassOpSig n2 dm2 ty2 _) GenDefMeth `eq_dm` GenDefMeth = True DefMeth _ `eq_dm` DefMeth _ = True dm1 `eq_dm` dm2 = False - - \end{code} \begin{code} -countTyClDecls :: [TyClDecl name pat] -> (Int, Int, Int, Int, Int) +countTyClDecls :: [TyClDecl name] -> (Int, Int, Int, Int, Int) -- class, data, newtype, synonym decls countTyClDecls decls - = (length [() | ClassDecl {} <- decls], - length [() | TySynonym {} <- decls], - length [() | IfaceSig {} <- decls], - length [() | TyData {tcdND = DataType} <- decls], - length [() | TyData {tcdND = NewType} <- decls]) + = (count isClassDecl decls, + count isSynDecl decls, + count isIfaceSigDecl decls, + count isDataTy decls, + count isNewTy decls) + where + isDataTy TyData{tcdND=DataType} = True + isDataTy _ = False + + isNewTy TyData{tcdND=NewType} = True + isNewTy _ = False \end{code} \begin{code} -instance (NamedThing name, Outputable name, Outputable pat) - => Outputable (TyClDecl name pat) where +instance OutputableBndr name + => Outputable (TyClDecl name) where ppr (IfaceSig {tcdName = var, tcdType = ty, tcdIdInfo = info}) = getPprStyle $ \ sty -> - hsep [ if ifaceStyle sty then ppr var else ppr_var var, - dcolon, ppr ty, pprHsIdInfo info - ] + hsep [ pprHsVar var, dcolon, ppr ty, pprHsIdInfo info ] ppr (ForeignType {tcdName = tycon}) = hsep [ptext SLIT("foreign import type dotnet"), ppr tycon] @@ -470,10 +489,10 @@ instance (NamedThing name, Outputable name, Outputable pat) 4 (ppr mono_ty) ppr (TyData {tcdND = new_or_data, tcdCtxt = context, tcdName = tycon, - tcdTyVars = tyvars, tcdCons = condecls, tcdNCons = ncons, + tcdTyVars = tyvars, tcdCons = condecls, tcdDerivs = derivings}) = pp_tydecl (ptext keyword <+> pp_decl_head context tycon tyvars) - (pp_condecls condecls ncons) + (pp_condecls condecls) derivings where keyword = case new_or_data of @@ -492,23 +511,23 @@ instance (NamedThing name, Outputable name, Outputable pat) top_matter = ptext SLIT("class") <+> pp_decl_head context clas tyvars <+> pprFundeps fds ppr_sig sig = ppr sig <> semi - pp_methods = getPprStyle $ \ sty -> - if ifaceStyle sty || isNothing methods + pp_methods = if isNothing methods then empty else ppr (fromJust methods) - -pp_decl_head :: Outputable name => HsContext name -> name -> [HsTyVarBndr name] -> SDoc + +pp_decl_head :: OutputableBndr name => HsContext name -> name -> [HsTyVarBndr name] -> SDoc pp_decl_head context thing tyvars = hsep [pprHsContext context, ppr thing, interppSP tyvars] -pp_condecls [] ncons = ptext SLIT("{- abstract with") <+> int ncons <+> ptext SLIT("constructors -}") -pp_condecls (c:cs) ncons = equals <+> sep (ppr c : map (\ c -> ptext SLIT("|") <+> ppr c) cs) +pp_condecls Unknown = ptext SLIT("{- abstract -}") +pp_condecls (HasCons n) = ptext SLIT("{- abstract with") <+> int n <+> ptext SLIT("constructors -}") +pp_condecls (DataCons cs) = equals <+> sep (punctuate (ptext SLIT(" |")) (map ppr cs)) pp_tydecl pp_head pp_decl_rhs derivings = hang pp_head 4 (sep [ pp_decl_rhs, case derivings of Nothing -> empty - Just ds -> hsep [ptext SLIT("deriving"), parens (interpp'SP ds)] + Just ds -> hsep [ptext SLIT("deriving"), ppr_hs_context ds] ]) \end{code} @@ -524,64 +543,42 @@ data ConDecl name = ConDecl name -- Constructor name; this is used for the -- DataCon itself, and for the user-callable wrapper Id - name -- Name of the constructor's 'worker Id' - -- Filled in as the ConDecl is built - [HsTyVarBndr name] -- Existentially quantified type variables (HsContext name) -- ...and context -- If both are empty then there are no existentials - (ConDetails name) + (HsConDetails name (BangType name)) SrcLoc - -data ConDetails name - = VanillaCon -- prefix-style con decl - [BangType name] - - | InfixCon -- infix-style con decl - (BangType name) - (BangType name) - - | RecCon -- record-style con decl - [([name], BangType name)] -- list of "fields" \end{code} \begin{code} -conDeclsNames :: Eq name => [ConDecl name] -> [(name,SrcLoc)] +conDeclsNames :: Eq name => DataConDetails (ConDecl name) -> [(name,SrcLoc)] -- See tyClDeclNames for what this does -- The function is boringly complicated because of the records -- And since we only have equality, we have to be a little careful conDeclsNames cons - = snd (foldl do_one ([], []) cons) + = snd (foldl do_one ([], []) (visibleDataCons cons)) where - do_one (flds_seen, acc) (ConDecl name _ _ _ details loc) - = do_details ((name,loc):acc) details + do_one (flds_seen, acc) (ConDecl name _ _ (RecCon flds) loc) + = (new_flds ++ flds_seen, (name,loc) : [(f,loc) | f <- new_flds] ++ acc) where - do_details acc (RecCon flds) = foldl do_fld (flds_seen, acc) flds - do_details acc other = (flds_seen, acc) - - do_fld acc (flds, _) = foldl do_fld1 acc flds + new_flds = [ f | (f,_) <- flds, not (f `elem` flds_seen) ] - do_fld1 (flds_seen, acc) fld - | fld `elem` flds_seen = (flds_seen,acc) - | otherwise = (fld:flds_seen, (fld,loc):acc) + do_one (flds_seen, acc) (ConDecl name _ _ _ loc) + = (flds_seen, (name,loc):acc) \end{code} \begin{code} -conDetailsTys :: ConDetails name -> [HsType name] -conDetailsTys (VanillaCon btys) = map getBangType btys -conDetailsTys (InfixCon bty1 bty2) = [getBangType bty1, getBangType bty2] -conDetailsTys (RecCon fields) = [getBangType bty | (_, bty) <- fields] - +conDetailsTys details = map getBangType (hsConArgs details) -eq_ConDecl env (ConDecl n1 _ tvs1 cxt1 cds1 _) - (ConDecl n2 _ tvs2 cxt2 cds2 _) +eq_ConDecl env (ConDecl n1 tvs1 cxt1 cds1 _) + (ConDecl n2 tvs2 cxt2 cds2 _) = n1 == n2 && (eq_hsTyVars env tvs1 tvs2 $ \ env -> eq_hsContext env cxt1 cxt2 && eq_ConDetails env cds1 cds2) -eq_ConDetails env (VanillaCon bts1) (VanillaCon bts2) +eq_ConDetails env (PrefixCon bts1) (PrefixCon bts2) = eqListBy (eq_btype env) bts1 bts2 eq_ConDetails env (InfixCon bta1 btb1) (InfixCon bta2 btb2) = eq_btype env bta1 bta2 && eq_btype env btb1 btb2 @@ -604,30 +601,26 @@ eq_btype env (BangType s1 t1) (BangType s2 t2) = s1==s2 && eq_hsType env t1 t2 \end{code} \begin{code} -instance (Outputable name) => Outputable (ConDecl name) where - ppr (ConDecl con _ tvs cxt con_details loc) +instance (OutputableBndr name) => Outputable (ConDecl name) where + ppr (ConDecl con tvs cxt con_details loc) = sep [pprHsForAll tvs cxt, ppr_con_details con con_details] ppr_con_details con (InfixCon ty1 ty2) = hsep [ppr_bang ty1, ppr con, ppr_bang ty2] --- ConDecls generated by MkIface.ifaceTyThing always have a VanillaCon, even +-- ConDecls generated by MkIface.ifaceTyThing always have a PrefixCon, even -- if the constructor is an infix one. This is because in an interface file -- we don't distinguish between the two. Hence when printing these for the -- user, we need to parenthesise infix constructor names. -ppr_con_details con (VanillaCon tys) - = getPprStyle $ \ sty -> - hsep ((if ifaceStyle sty then ppr con else ppr_var con) - : map (ppr_bang) tys) +ppr_con_details con (PrefixCon tys) + = hsep (pprHsVar con : map ppr_bang tys) ppr_con_details con (RecCon fields) = ppr con <+> braces (sep (punctuate comma (map ppr_field fields))) where - ppr_field (ns, ty) = hsep (map (ppr) ns) <+> - dcolon <+> - ppr_bang ty + ppr_field (n, ty) = ppr n <+> dcolon <+> ppr_bang ty -instance Outputable name => Outputable (BangType name) where +instance OutputableBndr name => Outputable (BangType name) where ppr = ppr_bang ppr_bang (BangType s ty) = ppr s <> pprParendHsType ty @@ -641,12 +634,12 @@ ppr_bang (BangType s ty) = ppr s <> pprParendHsType ty %************************************************************************ \begin{code} -data InstDecl name pat +data InstDecl name = InstDecl (HsType name) -- Context => Class Instance-type -- Using a polytype means that the renamer conveniently -- figures out the quantified type variables for us. - (MonoBinds name pat) + (MonoBinds name) [Sig name] -- User-supplied pragmatic info @@ -654,20 +647,21 @@ data InstDecl name pat -- Nothing for source-file instance decls SrcLoc + +isSourceInstDecl :: InstDecl name -> Bool +isSourceInstDecl (InstDecl _ _ _ maybe_dfun _) = isNothing maybe_dfun + +instDeclDFun :: InstDecl name -> Maybe name +instDeclDFun (InstDecl _ _ _ df _) = df -- A Maybe, but that's ok \end{code} \begin{code} -instance (Outputable name, Outputable pat) - => Outputable (InstDecl name pat) where +instance (OutputableBndr name) => Outputable (InstDecl name) where ppr (InstDecl inst_ty binds uprags maybe_dfun_name src_loc) - = getPprStyle $ \ sty -> - if ifaceStyle sty then - hsep [ptext SLIT("instance"), ppr inst_ty, equals, pp_dfun] - else - vcat [hsep [ptext SLIT("instance"), ppr inst_ty, ptext SLIT("where")], - nest 4 (ppr uprags), - nest 4 (ppr binds) ] + = vcat [hsep [ptext SLIT("instance"), ppr inst_ty, ptext SLIT("where")], + nest 4 (ppr uprags), + nest 4 (ppr binds) ] where pp_dfun = case maybe_dfun_name of Just df -> ppr df @@ -675,7 +669,7 @@ instance (Outputable name, Outputable pat) \end{code} \begin{code} -instance Ord name => Eq (InstDecl name pat) where +instance Ord name => Eq (InstDecl name) where -- Used for interface comparison only, so don't compare bindings (==) (InstDecl inst_ty1 _ _ dfun1 _) (InstDecl inst_ty2 _ _ dfun2 _) = inst_ty1 == inst_ty2 && dfun1 == dfun2 @@ -697,7 +691,7 @@ data DefaultDecl name = DefaultDecl [HsType name] SrcLoc -instance (Outputable name) +instance (OutputableBndr name) => Outputable (DefaultDecl name) where ppr (DefaultDecl tys src_loc) @@ -711,43 +705,110 @@ instance (Outputable name) %************************************************************************ \begin{code} + +-- foreign declarations are distinguished as to whether they define or use a +-- Haskell name +-- +-- * the Boolean value indicates whether the pre-standard deprecated syntax +-- has been used +-- data ForeignDecl name - = ForeignImport name (HsType name) FoImport SrcLoc - | ForeignExport name (HsType name) FoExport SrcLoc + = ForeignImport name (HsType name) ForeignImport Bool SrcLoc -- defines name + | ForeignExport name (HsType name) ForeignExport Bool SrcLoc -- uses name -forDeclName (ForeignImport n _ _ _) = n -forDeclName (ForeignExport n _ _ _) = n +-- yield the Haskell name defined or used in a foreign declaration +-- +foreignDeclName :: ForeignDecl name -> name +foreignDeclName (ForeignImport n _ _ _ _) = n +foreignDeclName (ForeignExport n _ _ _ _) = n -data FoImport - = LblImport CLabelString -- foreign label - | CImport CCallSpec -- foreign import - | CDynImport CCallConv -- foreign export dynamic - | DNImport DNCallSpec -- foreign import dotnet +-- specification of an imported external entity in dependence on the calling +-- convention +-- +data ForeignImport = -- import of a C entity + -- + -- * the two strings specifying a header file or library + -- may be empty, which indicates the absence of a + -- header or object specification (both are not used + -- in the case of `CWrapper' and when `CFunction' + -- has a dynamic target) + -- + -- * the calling convention is irrelevant for code + -- generation in the case of `CLabel', but is needed + -- for pretty printing + -- + -- * `Safety' is irrelevant for `CLabel' and `CWrapper' + -- + CImport CCallConv -- ccall or stdcall + Safety -- safe or unsafe + FastString -- name of C header + FastString -- name of library object + CImportSpec -- details of the C entity + + -- import of a .NET function + -- + | DNImport DNCallSpec + +-- details of an external C entity +-- +data CImportSpec = CLabel CLabelString -- import address of a C label + | CFunction CCallTarget -- static or dynamic function + | CWrapper -- wrapper to expose closures + -- (former f.e.d.) -data FoExport = CExport CExportSpec +-- specification of an externally exported entity in dependence on the calling +-- convention +-- +data ForeignExport = CExport CExportSpec -- contains the calling convention + | DNExport -- presently unused +-- abstract type imported from .NET +-- data FoType = DNType -- In due course we'll add subtype stuff - deriving( Eq ) -- Used for equality instance for TyClDecl + deriving (Eq) -- Used for equality instance for TyClDecl -instance Outputable name => Outputable (ForeignDecl name) where - ppr (ForeignImport nm ty (LblImport lbl) src_loc) - = ptext SLIT("foreign label") <+> ppr lbl <+> ppr nm <+> dcolon <+> ppr ty - ppr (ForeignImport nm ty decl src_loc) - = ptext SLIT("foreign import") <+> ppr decl <+> ppr nm <+> dcolon <+> ppr ty - ppr (ForeignExport nm ty decl src_loc) - = ptext SLIT("foreign export") <+> ppr decl <+> ppr nm <+> dcolon <+> ppr ty -instance Outputable FoImport where - ppr (CImport d) = ppr d - ppr (CDynImport conv) = text "dynamic" <+> ppr conv - ppr (DNImport d) = ptext SLIT("dotnet") <+> ppr d - ppr (LblImport l) = ptext SLIT("label") <+> ppr l +-- pretty printing of foreign declarations +-- -instance Outputable FoExport where - ppr (CExport d) = ppr d +instance OutputableBndr name => Outputable (ForeignDecl name) where + ppr (ForeignImport n ty fimport _ _) = + ptext SLIT("foreign import") <+> ppr fimport <+> + ppr n <+> dcolon <+> ppr ty + ppr (ForeignExport n ty fexport _ _) = + ptext SLIT("foreign export") <+> ppr fexport <+> + ppr n <+> dcolon <+> ppr ty + +instance Outputable ForeignImport where + ppr (DNImport spec) = + ptext SLIT("dotnet") <+> ppr spec + ppr (CImport cconv safety header lib spec) = + ppr cconv <+> ppr safety <+> + char '"' <> pprCEntity header lib spec <> char '"' + where + pprCEntity header lib (CLabel lbl) = + ptext SLIT("static") <+> ftext header <+> char '&' <> + pprLib lib <> ppr lbl + pprCEntity header lib (CFunction (StaticTarget lbl)) = + ptext SLIT("static") <+> ftext header <+> char '&' <> + pprLib lib <> ppr lbl + pprCEntity header lib (CFunction (DynamicTarget)) = + ptext SLIT("dynamic") + pprCEntity header lib (CFunction (CasmTarget _)) = + panic "HsDecls.pprCEntity: malformed C function target" + pprCEntity _ _ (CWrapper) = ptext SLIT("wrapper") + -- + pprLib lib | nullFastString lib = empty + | otherwise = char '[' <> ppr lib <> char ']' + +instance Outputable ForeignExport where + ppr (CExport (CExportStatic lbl cconv)) = + ppr cconv <+> char '"' <> ppr lbl <> char '"' + ppr (DNExport ) = + ptext SLIT("dotnet") <+> ptext SLIT("\"\"") instance Outputable FoType where - ppr DNType = ptext SLIT("type dotnet") + ppr DNType = ptext SLIT("type dotnet") \end{code} @@ -758,15 +819,13 @@ instance Outputable FoType where %************************************************************************ \begin{code} -data RuleDecl name pat +data RuleDecl name = HsRule -- Source rule RuleName -- Rule name Activation - [name] -- Forall'd tyvars, filled in by the renamer with - -- tyvars mentioned in sigs; then filled out by typechecker - [RuleBndr name] -- Forall'd term vars - (HsExpr name pat) -- LHS - (HsExpr name pat) -- RHS + [RuleBndr name] -- Forall'd vars; after typechecking this includes tyvars + (HsExpr name) -- LHS + (HsExpr name) -- RHS SrcLoc | IfaceRule -- One that's come in from an interface file; pre-typecheck @@ -782,40 +841,40 @@ data RuleDecl name pat name -- Head of LHS CoreRule -isIfaceRuleDecl :: RuleDecl name pat -> Bool -isIfaceRuleDecl (HsRule _ _ _ _ _ _ _) = False -isIfaceRuleDecl other = True +isSrcRule :: RuleDecl name -> Bool +isSrcRule (HsRule _ _ _ _ _ _) = True +isSrcRule other = False -ifaceRuleDeclName :: RuleDecl name pat -> name +ifaceRuleDeclName :: RuleDecl name -> name ifaceRuleDeclName (IfaceRule _ _ _ n _ _ _) = n ifaceRuleDeclName (IfaceRuleOut n r) = n -ifaceRuleDeclName (HsRule fs _ _ _ _ _ _) = pprPanic "ifaceRuleDeclName" (ppr fs) +ifaceRuleDeclName (HsRule fs _ _ _ _ _) = pprPanic "ifaceRuleDeclName" (ppr fs) data RuleBndr name = RuleBndr name | RuleBndrSig name (HsType name) -instance (NamedThing name, Ord name) => Eq (RuleDecl name pat) where +collectRuleBndrSigTys :: [RuleBndr name] -> [HsType name] +collectRuleBndrSigTys bndrs = [ty | RuleBndrSig _ ty <- bndrs] + +instance (NamedThing name, Ord name) => Eq (RuleDecl name) where -- Works for IfaceRules only; used when comparing interface file versions (IfaceRule n1 a1 bs1 f1 es1 rhs1 _) == (IfaceRule n2 a2 bs2 f2 es2 rhs2 _) = n1==n2 && f1 == f2 && a1==a2 && eq_ufBinders emptyEqHsEnv bs1 bs2 (\env -> eqListBy (eq_ufExpr env) (rhs1:es1) (rhs2:es2)) -instance (NamedThing name, Outputable name, Outputable pat) - => Outputable (RuleDecl name pat) where - ppr (HsRule name act tvs ns lhs rhs loc) - = sep [text "{-# RULES" <+> doubleQuotes (ptext name) <+> ppr act, - pp_forall, ppr lhs, equals <+> ppr rhs, +instance OutputableBndr name => Outputable (RuleDecl name) where + ppr (HsRule name act ns lhs rhs loc) + = sep [text "{-# RULES" <+> doubleQuotes (ftext name) <+> ppr act, + pp_forall, pprExpr lhs, equals <+> pprExpr rhs, text "#-}" ] where - pp_forall | null tvs && null ns = empty - | otherwise = text "forall" <+> - fsep (map ppr tvs ++ map ppr ns) - <> dot + pp_forall | null ns = empty + | otherwise = text "forall" <+> fsep (map ppr ns) <> dot ppr (IfaceRule name act tpl_vars fn tpl_args rhs loc) - = hsep [ doubleQuotes (ptext name), ppr act, + = hsep [ doubleQuotes (ftext name), ppr act, ptext SLIT("__forall") <+> braces (interppSP tpl_vars), ppr fn <+> sep (map (pprUfExpr parens) tpl_args), ptext SLIT("=") <+> ppr rhs @@ -823,7 +882,7 @@ instance (NamedThing name, Outputable name, Outputable pat) ppr (IfaceRuleOut fn rule) = pprCoreRule (ppr fn) rule -instance Outputable name => Outputable (RuleBndr name) where +instance OutputableBndr name => Outputable (RuleBndr name) where ppr (RuleBndr name) = ppr name ppr (RuleBndrSig name ty) = ppr name <> dcolon <> ppr ty \end{code} @@ -840,9 +899,29 @@ We use exported entities for things to deprecate. \begin{code} data DeprecDecl name = Deprecation name DeprecTxt SrcLoc -type DeprecTxt = FAST_STRING -- reason/explanation for deprecation +type DeprecTxt = FastString -- reason/explanation for deprecation -instance Outputable name => Outputable (DeprecDecl name) where +instance OutputableBndr name => Outputable (DeprecDecl name) where ppr (Deprecation thing txt _) = hsep [text "{-# DEPRECATED", ppr thing, doubleQuotes (ppr txt), text "#-}"] \end{code} + + +%************************************************************************ +%* * + External-core declarations +%* * +%************************************************************************ + +\begin{code} +data CoreDecl name -- a Core value binding (from 'external Core' input) + = CoreDecl name + (HsType name) + (UfExpr name) + SrcLoc + +instance OutputableBndr name => Outputable (CoreDecl name) where + ppr (CoreDecl var ty rhs loc) + = getPprStyle $ \ sty -> + hsep [ pprHsVar var, dcolon, ppr ty, ppr rhs ] +\end{code}