X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FhsSyn%2FHsDecls.lhs;h=54f993da7fc264931d5f99b89b79215354269cac;hb=47eef4b5780f0a5b5a37847097842daebd0f9285;hp=6b7b50965179a242a71ad9582e579b4604f074c8;hpb=111cee3f1ad93816cb828e38b38521d85c3bcebb;p=ghc-hetmet.git diff --git a/ghc/compiler/hsSyn/HsDecls.lhs b/ghc/compiler/hsSyn/HsDecls.lhs index 6b7b509..54f993d 100644 --- a/ghc/compiler/hsSyn/HsDecls.lhs +++ b/ghc/compiler/hsSyn/HsDecls.lhs @@ -11,30 +11,35 @@ module HsDecls ( HsDecl(..), TyClDecl(..), InstDecl(..), RuleDecl(..), RuleBndr(..), DefaultDecl(..), ForeignDecl(..), ForKind(..), ExtName(..), isDynamicExtName, extNameStatic, - ConDecl(..), ConDetails(..), BangType(..), - IfaceSig(..), SpecDataSig(..), - hsDeclName, tyClDeclName, isClassDecl, isSynDecl, isDataDecl, countTyClDecls + ConDecl(..), ConDetails(..), + BangType(..), getBangType, + DeprecDecl(..), DeprecTxt, + hsDeclName, instDeclName, tyClDeclName, tyClDeclNames, + isClassDecl, isSynDecl, isDataDecl, isIfaceSigDecl, countTyClDecls, + mkClassDeclSysNames, isIfaceRuleDecl, + getClassDeclSysNames ) where #include "HsVersions.h" -- friends: -import HsBinds ( HsBinds, MonoBinds, Sig, FixitySig(..), nullMonoBinds ) +import HsBinds ( HsBinds, MonoBinds, Sig(..), FixitySig(..) ) import HsExpr ( HsExpr ) -import HsPragmas ( DataPragmas, ClassPragmas ) import HsTypes -import HsCore ( UfExpr, UfBinder, IfaceSig(..), UfRuleBody ) -import BasicTypes ( Fixity, NewOrData(..) ) +import PprCore ( pprCoreRule ) +import HsCore ( UfExpr, UfBinder, HsIdInfo, pprHsIdInfo, + eq_ufBinders, eq_ufExpr, pprUfExpr + ) +import CoreSyn ( CoreRule(..) ) +import BasicTypes ( NewOrData(..) ) import CallConv ( CallConv, pprCallConv ) -import Var ( TyVar ) -- others: -import PprType -import {-# SOURCE #-} FunDeps ( pprFundeps ) -import CStrings ( CLabelString ) +import FunDeps ( pprFundeps ) +import Class ( FunDep ) +import CStrings ( CLabelString, pprCLabelString ) import Outputable import SrcLoc ( SrcLoc ) -import Util \end{code} @@ -51,8 +56,8 @@ data HsDecl name pat | DefD (DefaultDecl name) | ValD (HsBinds name pat) | ForD (ForeignDecl name) - | SigD (IfaceSig name) | FixD (FixitySig name) + | DeprecD (DeprecDecl name) | RuleD (RuleDecl name pat) -- NB: all top-level fixity decls are contained EITHER @@ -74,20 +79,19 @@ data HsDecl name pat hsDeclName :: (Outputable name, Outputable pat) => HsDecl name pat -> name #endif -hsDeclName (TyClD decl) = tyClDeclName decl -hsDeclName (SigD (IfaceSig name _ _ _)) = name -hsDeclName (InstD (InstDecl _ _ _ name _)) = name -hsDeclName (ForD (ForeignDecl name _ _ _ _ _)) = name -hsDeclName (FixD (FixitySig name _ _)) = name +hsDeclName (TyClD decl) = tyClDeclName decl +hsDeclName (InstD decl) = instDeclName decl +hsDeclName (ForD (ForeignDecl name _ _ _ _ _)) = name +hsDeclName (FixD (FixitySig name _ _)) = name -- Others don't make sense #ifdef DEBUG hsDeclName x = pprPanic "HsDecls.hsDeclName" (ppr x) #endif -tyClDeclName :: TyClDecl name pat -> name -tyClDeclName (TyData _ _ name _ _ _ _ _) = name -tyClDeclName (TySynonym name _ _ _) = name -tyClDeclName (ClassDecl _ name _ _ _ _ _ _ _ _ _ _) = name + +instDeclName :: InstDecl name pat -> name +instDeclName (InstDecl _ _ _ (Just name) _) = name + \end{code} \begin{code} @@ -95,13 +99,21 @@ instance (Outputable name, Outputable pat) => Outputable (HsDecl name pat) where ppr (TyClD dcl) = ppr dcl - ppr (SigD sig) = ppr sig 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 (RuleD rd) = ppr rd + ppr (DeprecD dd) = ppr dd +\end{code} + +\begin{code} +instance Ord name => Eq (HsDecl name pat) where + -- Used only when comparing interfaces, + -- at which time only signature and type/class decls + (TyClD d1) == (TyClD d2) = d1 == d2 + _ == _ = False \end{code} @@ -111,98 +123,238 @@ instance (Outputable name, Outputable pat) %* * %************************************************************************ +Type and class declarations carry 'implicit names'. In particular: + +Type A. +~~~~~~~ + Each data type decl defines + a worker name for each constructor + to-T and from-T convertors + Each class decl defines + a tycon for the class + a data constructor for that tycon + the worker for that constructor + a selector for each superclass + +All have occurrence names that are derived uniquely from their parent declaration. + +None of these get separate definitions in an interface file; they are +fully defined by the data or class decl. But they may *occur* in +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 + + - Ensure they "point to" the parent data/class decl + when loading that decl from an interface file + + - When renaming the decl look them up in the name cache, + ensure correct module and provenance is set + +Type B: Default methods and dictionary functions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Have their own binding in an interface file. + +Default methods : occurrence name is derived uniquely from the class decl. +Dict functions : occurrence name is derived from the instance decl, plus a unique number. + +Plan of attack: + - Do *not* make them point to the parent class decl + - Interface-file decls: treat just like Type A + - Source-file decls: the names aren't in the decl at all; + instead the typechecker makes them up + \begin{code} data TyClDecl name pat - = TyData NewOrData + = IfaceSig name -- It may seem odd to classify an interface-file signature + (HsType name) -- as a 'TyClDecl', but it's very convenient. These three + [HsIdInfo name] -- are the kind that appear in interface files. + SrcLoc + + | TyData NewOrData (HsContext name) -- context name -- type constructor - [HsTyVar name] -- type variables + [HsTyVarBndr name] -- type variables [ConDecl name] -- data constructors (empty if abstract) + Int -- Number of data constructors (valid even if type is abstract) (Maybe [name]) -- derivings; Nothing => not specified -- (i.e., derive default); Just [] => derive -- *nothing*; Just => as you would -- expect... - (DataPragmas name) SrcLoc + name -- generic converter functions + name -- generic converter functions - | TySynonym name -- type constructor - [HsTyVar name] -- type variables - (HsType name) -- synonym expansion + | TySynonym name -- type constructor + [HsTyVarBndr name] -- type variables + (HsType name) -- synonym expansion SrcLoc | ClassDecl (HsContext name) -- context... name -- name of the class - [HsTyVar name] -- the class type variables - [([name], [name])] -- functional dependencies + [HsTyVarBndr name] -- the class type variables + [FunDep name] -- functional dependencies [Sig name] -- methods' signatures (MonoBinds name pat) -- default methods - (ClassPragmas name) - name name name [name] -- The names of the tycon, datacon wrapper, datacon worker, - -- and superclass selectors for this class. - -- These are filled in as the ClassDecl is made. + (ClassDeclSysNames name) SrcLoc \end{code} +Simple classifiers + \begin{code} -countTyClDecls :: [TyClDecl name pat] -> (Int, Int, Int, Int) - -- class, data, newtype, synonym decls -countTyClDecls decls - = (length [() | ClassDecl _ _ _ _ _ _ _ _ _ _ _ _ <- decls], - length [() | TyData DataType _ _ _ _ _ _ _ <- decls], - length [() | TyData NewType _ _ _ _ _ _ _ <- decls], - length [() | TySynonym _ _ _ _ <- decls]) +isIfaceSigDecl, isDataDecl, isSynDecl, isClassDecl :: TyClDecl name pat -> Bool -isDataDecl, isSynDecl, isClassDecl :: TyClDecl name pat -> Bool +isIfaceSigDecl (IfaceSig _ _ _ _) = True +isIfaceSigDecl other = False isSynDecl (TySynonym _ _ _ _) = True isSynDecl other = False -isDataDecl (TyData _ _ _ _ _ _ _ _) = True -isDataDecl other = False +isDataDecl (TyData _ _ _ _ _ _ _ _ _ _) = True +isDataDecl other = False -isClassDecl (ClassDecl _ _ _ _ _ _ _ _ _ _ _ _) = True -isClassDecl other = False +isClassDecl (ClassDecl _ _ _ _ _ _ _ _ ) = True +isClassDecl other = False +\end{code} + +Dealing with names + +\begin{code} +tyClDeclName :: TyClDecl name pat -> name +tyClDeclName (IfaceSig name _ _ _) = name +tyClDeclName (TyData _ _ name _ _ _ _ _ _ _) = name +tyClDeclName (TySynonym name _ _ _) = name +tyClDeclName (ClassDecl _ name _ _ _ _ _ _) = name + + +tyClDeclNames :: Eq name => TyClDecl name pat -> [(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 +-- We use the equality to filter out duplicate field names + +tyClDeclNames (TySynonym name _ _ loc) + = [(name,loc)] + +tyClDeclNames (ClassDecl _ cls_name _ _ sigs _ _ loc) + = (cls_name,loc) : [(n,loc) | ClassOpSig n _ _ loc <- sigs] + +tyClDeclNames (TyData _ _ tc_name _ cons _ _ loc _ _) + = (tc_name,loc) : conDeclsNames cons + +tyClDeclNames (IfaceSig name _ _ loc) = [(name,loc)] + +type ClassDeclSysNames name = [name] + -- [tycon, datacon wrapper, datacon worker, + -- superclass selector 1, ..., superclass selector n] + -- They are kept in a list rather than a tuple to make the + -- renamer easier. + +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 Ord name => Eq (TyClDecl name pat) where + -- Used only when building interface files + (==) (IfaceSig n1 t1 i1 _) + (IfaceSig n2 t2 i2 _) = n1==n2 && t1==t2 && i1==i2 + + (==) (TyData nd1 cxt1 n1 tvs1 cons1 _ _ _ _ _) + (TyData nd2 cxt2 n2 tvs2 cons2 _ _ _ _ _) + = n1 == n2 && + nd1 == nd2 && + eqWithHsTyVars tvs1 tvs2 (\ env -> + eq_hsContext env cxt1 cxt2 && + eqListBy (eq_ConDecl env) cons1 cons2 + ) + + (==) (TySynonym n1 tvs1 ty1 _) + (TySynonym n2 tvs2 ty2 _) + = n1 == n2 && + eqWithHsTyVars tvs1 tvs2 (\ env -> eq_hsType env ty1 ty2) + + (==) (ClassDecl cxt1 n1 tvs1 fds1 sigs1 _ _ _ ) + (ClassDecl cxt2 n2 tvs2 fds2 sigs2 _ _ _ ) + = n1 == n2 && + eqWithHsTyVars tvs1 tvs2 (\ env -> + eq_hsContext env cxt1 cxt2 && + eqListBy (eq_hsFD env) fds1 fds2 && + eqListBy (eq_cls_sig env) sigs1 sigs2 + ) + + (==) _ _ = False -- default case + + +eq_hsFD env (ns1,ms1) (ns2,ms2) + = eqListBy (eq_hsVar env) ns1 ns2 && eqListBy (eq_hsVar env) ms1 ms2 + +eq_cls_sig env (ClassOpSig n1 dm1 ty1 _) (ClassOpSig n2 dm2 ty2 _) + = n1==n2 && dm1 `eq_dm` dm2 && eq_hsType env ty1 ty2 + where + -- Ignore the name of the default method. + -- This is used for comparing declarations before putting + -- them into interface files, and the name of the default + -- method isn't relevant + (Just (explicit_dm1)) `eq_dm` (Just (explicit_dm2)) = explicit_dm1 == explicit_dm2 + Nothing `eq_dm` Nothing = True + dm1 `eq_dm` dm2 = False +\end{code} + +\begin{code} +countTyClDecls :: [TyClDecl name pat] -> (Int, Int, Int, Int, Int) + -- class, data, newtype, synonym decls +countTyClDecls decls + = (length [() | ClassDecl _ _ _ _ _ _ _ _ <- decls], + length [() | TyData DataType _ _ _ _ _ _ _ _ _ <- decls], + length [() | TyData NewType _ _ _ _ _ _ _ _ _ <- decls], + length [() | TySynonym _ _ _ _ <- decls], + length [() | IfaceSig _ _ _ _ <- decls]) \end{code} \begin{code} instance (Outputable name, Outputable pat) => Outputable (TyClDecl name pat) where + ppr (IfaceSig var ty info _) = hsep [ppr var, dcolon, ppr ty, pprHsIdInfo info] + ppr (TySynonym tycon tyvars mono_ty src_loc) - = hang (pp_decl_head SLIT("type") empty tycon tyvars) + = hang (ptext SLIT("type") <+> pp_decl_head [] tycon tyvars <+> equals) 4 (ppr mono_ty) - ppr (TyData new_or_data context tycon tyvars condecls derivings pragmas src_loc) + ppr (TyData new_or_data context tycon tyvars condecls ncons + derivings src_loc gen_conv1 gen_conv2) -- The generic names are not printed out ATM = pp_tydecl - (pp_decl_head keyword (pprHsContext context) tycon tyvars) - (pp_condecls condecls) + (ptext keyword <+> pp_decl_head context tycon tyvars <+> equals) + (pp_condecls condecls ncons) derivings where keyword = case new_or_data of NewType -> SLIT("newtype") DataType -> SLIT("data") - ppr (ClassDecl context clas tyvars fds sigs methods pragmas _ _ _ _ src_loc) + ppr (ClassDecl context clas tyvars fds sigs methods _ src_loc) | null sigs -- No "where" part = top_matter | otherwise -- Laid out = sep [hsep [top_matter, ptext SLIT("where {")], - nest 4 (vcat [sep (map ppr_sig sigs), - ppr methods, - char '}'])] + nest 4 (sep [sep (map ppr_sig sigs), pp_methods, char '}'])] where - top_matter = hsep [ptext SLIT("class"), pprHsContext context, - ppr clas, hsep (map (ppr) tyvars), pprFundeps fds] + 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 then empty else ppr methods + +pp_decl_head :: Outputable name => HsContext name -> name -> [HsTyVarBndr name] -> SDoc +pp_decl_head context thing tyvars = hsep [pprHsContext context, ppr thing, interppSP tyvars] - -pp_decl_head str pp_context tycon tyvars - = hsep [ptext str, pp_context, ppr tycon, - interppSP tyvars, ptext SLIT("=")] - -pp_condecls [] = empty -- Curious! -pp_condecls (c:cs) = sep (ppr c : map (\ c -> ptext SLIT("|") <+> ppr c) cs) +pp_condecls [] ncons = ptext SLIT("{- abstract with") <+> int ncons <+> ptext SLIT("constructors -}") +pp_condecls (c:cs) ncons = sep (ppr c : map (\ c -> ptext SLIT("|") <+> ppr c) cs) pp_tydecl pp_head pp_decl_rhs derivings = hang pp_head 4 (sep [ @@ -213,22 +365,6 @@ pp_tydecl pp_head pp_decl_rhs derivings ]) \end{code} -A type for recording what types a datatype should be specialised to. -It's called a ``Sig'' because it's sort of like a ``type signature'' -for an datatype declaration. - -\begin{code} -data SpecDataSig name - = SpecDataSig name -- tycon to specialise - (HsType name) - SrcLoc - -instance (Outputable name) - => Outputable (SpecDataSig name) where - - ppr (SpecDataSig tycon ty _) - = hsep [text "{-# SPECIALIZE data", ppr ty, text "#-}"] -\end{code} %************************************************************************ %* * @@ -244,7 +380,7 @@ data ConDecl name name -- Name of the constructor's 'worker Id' -- Filled in as the ConDecl is built - [HsTyVar name] -- Existentially quantified type variables + [HsTyVarBndr name] -- Existentially quantified type variables (HsContext name) -- ...and context -- If both are empty then there are no existentials @@ -261,21 +397,68 @@ data ConDetails name | RecCon -- record-style con decl [([name], BangType name)] -- list of "fields" +\end{code} - | NewCon -- newtype con decl, possibly with a labelled field. - (HsType name) - (Maybe name) -- Just x => labelled field 'x' +\begin{code} +conDeclsNames :: Eq name => [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) + where + do_one (flds_seen, acc) (ConDecl name _ _ _ details loc) + = do_details ((name,loc):acc) details + 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 + + do_fld1 (flds_seen, acc) fld + | fld `elem` flds_seen = (flds_seen,acc) + | otherwise = (fld:flds_seen, (fld,loc):acc) +\end{code} + +\begin{code} +eq_ConDecl env (ConDecl n1 _ tvs1 cxt1 cds1 _) + (ConDecl n2 _ tvs2 cxt2 cds2 _) + = n1 == n2 && + (eqWithHsTyVars tvs1 tvs2 $ \ env -> + eq_hsContext env cxt1 cxt2 && + eq_ConDetails env cds1 cds2) + +eq_ConDetails env (VanillaCon bts1) (VanillaCon 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 +eq_ConDetails env (RecCon fs1) (RecCon fs2) + = eqListBy (eq_fld env) fs1 fs2 +eq_ConDetails env _ _ = False + +eq_fld env (ns1,bt1) (ns2, bt2) = ns1==ns2 && eq_btype env bt1 bt2 +\end{code} + +\begin{code} data BangType name = Banged (HsType name) -- HsType: to allow Haskell extensions | Unbanged (HsType name) -- (MonoType only needed for straight Haskell) | Unpacked (HsType name) -- Field is strict and to be unpacked if poss. + +getBangType (Banged ty) = ty +getBangType (Unbanged ty) = ty +getBangType (Unpacked ty) = ty + +eq_btype env (Banged t1) (Banged t2) = eq_hsType env t1 t2 +eq_btype env (Unbanged t1) (Unbanged t2) = eq_hsType env t1 t2 +eq_btype env (Unpacked t1) (Unpacked t2) = eq_hsType env t1 t2 +eq_btype env _ _ = False \end{code} \begin{code} instance (Outputable name) => Outputable (ConDecl name) where ppr (ConDecl con _ tvs cxt con_details loc) - = sep [pprForAll tvs, pprHsContext cxt, ppr_con_details con con_details] + = 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] @@ -283,14 +466,6 @@ ppr_con_details con (InfixCon ty1 ty2) ppr_con_details con (VanillaCon tys) = ppr con <+> hsep (map (ppr_bang) tys) -ppr_con_details con (NewCon ty Nothing) - = ppr con <+> pprParendHsType ty - -ppr_con_details con (NewCon ty (Just x)) - = ppr con <+> braces pp_field - where - pp_field = ppr x <+> dcolon <+> pprParendHsType ty - ppr_con_details con (RecCon fields) = ppr con <+> braces (hsep (punctuate comma (map ppr_field fields))) where @@ -298,6 +473,9 @@ ppr_con_details con (RecCon fields) dcolon <+> ppr_bang ty +instance Outputable name => Outputable (BangType name) where + ppr = ppr_bang + ppr_bang (Banged ty) = ptext SLIT("!") <> pprParendHsType ty ppr_bang (Unbanged ty) = pprParendHsType ty ppr_bang (Unpacked ty) = ptext SLIT("! !") <> pprParendHsType ty @@ -320,7 +498,8 @@ data InstDecl name pat [Sig name] -- User-supplied pragmatic info - name -- Name for the dictionary function + (Maybe name) -- Name for the dictionary function + -- Nothing for source-file instance decls SrcLoc \end{code} @@ -329,14 +508,25 @@ data InstDecl name pat instance (Outputable name, Outputable pat) => Outputable (InstDecl name pat) where - ppr (InstDecl inst_ty binds uprags dfun_name src_loc) + ppr (InstDecl inst_ty binds uprags maybe_dfun_name src_loc) = getPprStyle $ \ sty -> - if ifaceStyle sty || (nullMonoBinds binds && null uprags) then - hsep [ptext SLIT("instance"), ppr inst_ty] + 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) ] + where + pp_dfun = case maybe_dfun_name of + Just df -> ppr df + Nothing -> empty +\end{code} + +\begin{code} +instance Ord name => Eq (InstDecl name pat) 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 \end{code} @@ -413,13 +603,11 @@ extNameStatic :: ExtName -> CLabelString extNameStatic (ExtName f _) = f extNameStatic Dynamic = panic "staticExtName: Dynamic - shouldn't ever happen." - instance Outputable ExtName where ppr Dynamic = ptext SLIT("dynamic") ppr (ExtName nm mb_mod) = case mb_mod of { Nothing -> empty; Just m -> doubleQuotes (ptext m) } <+> - doubleQuotes (ptext nm) - + doubleQuotes (pprCLabelString nm) \end{code} %************************************************************************ @@ -430,7 +618,7 @@ instance Outputable ExtName where \begin{code} data RuleDecl name pat - = RuleDecl + = HsRule -- Source rule FAST_STRING -- Rule name [name] -- Forall'd tyvars, filled in by the renamer with -- tyvars mentioned in sigs; then filled out by typechecker @@ -439,18 +627,35 @@ data RuleDecl name pat (HsExpr name pat) -- RHS SrcLoc - | IfaceRuleDecl -- One that's come in from an interface file - name - (UfRuleBody name) + | IfaceRule -- One that's come in from an interface file; pre-typecheck + FAST_STRING + [UfBinder name] -- Tyvars and term vars + name -- Head of lhs + [UfExpr name] -- Args of LHS + (UfExpr name) -- Pre typecheck SrcLoc + | IfaceRuleOut -- Post typecheck + name -- Head of LHS + CoreRule + +isIfaceRuleDecl (HsRule _ _ _ _ _ _) = False +isIfaceRuleDecl other = True + data RuleBndr name = RuleBndr name | RuleBndrSig name (HsType name) +instance Ord name => Eq (RuleDecl name pat) where + -- Works for IfaceRules only; used when comparing interface file versions + (IfaceRule n1 bs1 f1 es1 rhs1 _) == (IfaceRule n2 bs2 f2 es2 rhs2 _) + = n1==n2 && f1 == f2 && + eq_ufBinders emptyEqHsEnv bs1 bs2 (\env -> + eqListBy (eq_ufExpr env) (rhs1:es1) (rhs2:es2)) + instance (Outputable name, Outputable pat) => Outputable (RuleDecl name pat) where - ppr (RuleDecl name tvs ns lhs rhs loc) + ppr (HsRule name tvs ns lhs rhs loc) = sep [text "{-# RULES" <+> doubleQuotes (ptext name), pp_forall, ppr lhs, equals <+> ppr rhs, text "#-}" ] @@ -459,9 +664,36 @@ instance (Outputable name, Outputable pat) | otherwise = text "forall" <+> fsep (map ppr tvs ++ map ppr ns) <> dot - ppr (IfaceRuleDecl var body loc) = text "An imported rule..." + + ppr (IfaceRule name tpl_vars fn tpl_args rhs loc) + = hsep [ doubleQuotes (ptext name), + ptext SLIT("__forall") <+> braces (interppSP tpl_vars), + ppr fn <+> sep (map (pprUfExpr parens) tpl_args), + ptext SLIT("=") <+> ppr rhs + ] <+> semi + + ppr (IfaceRuleOut fn rule) = pprCoreRule (ppr fn) rule instance Outputable name => Outputable (RuleBndr name) where ppr (RuleBndr name) = ppr name ppr (RuleBndrSig name ty) = ppr name <> dcolon <> ppr ty \end{code} + + +%************************************************************************ +%* * +\subsection[DeprecDecl]{Deprecations} +%* * +%************************************************************************ + +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 + +instance Outputable name => Outputable (DeprecDecl name) where + ppr (Deprecation thing txt _) + = hsep [text "{-# DEPRECATED", ppr thing, doubleQuotes (ppr txt), text "#-}"] +\end{code}