X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FhsSyn%2FHsDecls.lhs;h=375a35d4434092aa7111edae9946387d2e78ab44;hb=6858f7c15fcf9efe9e6fdf22de34d0791b0f0c08;hp=7fb207ee9a48f04e41c070a8fde0aa9ee6e2cc3e;hpb=495ef8bd9ef30bffe50ea399b91e3ba09646b59a;p=ghc-hetmet.git diff --git a/ghc/compiler/hsSyn/HsDecls.lhs b/ghc/compiler/hsSyn/HsDecls.lhs index 7fb207e..375a35d 100644 --- a/ghc/compiler/hsSyn/HsDecls.lhs +++ b/ghc/compiler/hsSyn/HsDecls.lhs @@ -3,44 +3,50 @@ % \section[HsDecls]{Abstract syntax: global declarations} -Definitions for: @TyDecl@ and @ConDecl@, @ClassDecl@, +Definitions for: @TyDecl@ and @oCnDecl@, @ClassDecl@, @InstDecl@, @DefaultDecl@ and @ForeignDecl@. \begin{code} module HsDecls ( HsDecl(..), TyClDecl(..), InstDecl(..), RuleDecl(..), RuleBndr(..), - DefaultDecl(..), ForeignDecl(..), ForKind(..), - ExtName(..), isDynamicExtName, extNameStatic, - ConDecl(..), ConDetails(..), BangType(..), - IfaceSig(..), SpecDataSig(..), + DefaultDecl(..), + ForeignDecl(..), FoImport(..), FoExport(..), FoType(..), + ConDecl(..), ConDetails(..), + BangType(..), getBangType, getBangStrictness, unbangedType, DeprecDecl(..), DeprecTxt, - hsDeclName, tyClDeclName, isClassDecl, isSynDecl, isDataDecl, countTyClDecls, toHsRule + hsDeclName, instDeclName, + tyClDeclName, tyClDeclNames, tyClDeclSysNames, tyClDeclTyVars, + isClassDecl, isSynDecl, isDataDecl, isIfaceSigDecl, countTyClDecls, + mkClassDeclSysNames, isIfaceRuleDecl, ifaceRuleDeclName, + getClassDeclSysNames, conDetailsTys ) 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 HsImpExp ( IE(..) ) +import HsImpExp ( ppr_var ) import HsTypes import PprCore ( pprCoreRule ) -import HsCore ( UfExpr(UfVar), UfBinder, IfaceSig(..), eq_ufBinders, eq_ufExpr, pprUfExpr, toUfExpr, toUfBndr ) -import CoreSyn ( CoreRule(..) ) -import BasicTypes ( Fixity, NewOrData(..) ) -import CallConv ( CallConv, pprCallConv ) -import Var ( TyVar, Id ) -import Name ( toRdrName ) +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 ) -- others: -import PprType +import Name ( NamedThing ) import FunDeps ( pprFundeps ) -import Class ( FunDep ) -import CStrings ( CLabelString, pprCLabelString ) +import Class ( FunDep, DefMeth(..) ) +import CStrings ( CLabelString ) import Outputable -import SrcLoc ( SrcLoc, noSrcLoc ) -import Util +import Util ( eqListBy ) +import SrcLoc ( SrcLoc ) +import FastString + +import Maybe ( isNothing, fromJust ) \end{code} @@ -57,7 +63,6 @@ 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) @@ -78,31 +83,29 @@ data HsDecl name pat \begin{code} #ifdef DEBUG -hsDeclName :: (Outputable name, Outputable pat) +hsDeclName :: (NamedThing name, 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 decl) = forDeclName decl +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} -instance (Outputable name, Outputable pat) +instance (NamedThing name, 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 @@ -112,14 +115,6 @@ instance (Outputable name, Outputable pat) 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 - (SigD s1) == (SigD s2) = s1 == s2 - (TyClD d1) == (TyClD d2) = d1 == d2 -\end{code} - %************************************************************************ %* * @@ -127,102 +122,357 @@ instance Ord name => Eq (HsDecl name pat) where %* * %************************************************************************ + -------------------------------- + THE NAMING STORY + -------------------------------- + +Here is the story about the implicit names that go with type, class, and instance +decls. It's a bit tricky, so pay attention! + +"Implicit" (or "system") binders +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 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 + 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) + + - When renaming the decl look them up in the name cache, + ensure correct module and provenance is set + +Default methods +~~~~~~~~~~~~~~~ + - Occurrence name is derived uniquely from the method name + E.g. $dmmax + + - If there is a default method name at all, it's recorded in + the ClassOpSig (in HsBinds), in the DefMeth field. + (DefMeth is defined in Class.lhs) + +Source-code class decls and interface-code class decls are treated subtly +differently, which has given me a great deal of confusion over the years. +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 + + - The renamer renames it to a Name + + - During typechecking, we generate a binding for each $dm for + which there's a programmer-supplied default method: + class Foo a where + op1 :: + op2 :: + op1 = ... + We generate a binding for $dmop1 but not for $dmop2. + The Class for Foo has a NoDefMeth for op2 and a DefMeth for op1. + The Name for $dmop2 is simply discarded. + +In *interface-file* class declarations: + - When parsing, we see if there's an explicit programmer-supplied default method + because there's an '=' sign to indicate it: + class Foo a where + op1 = :: -- NB the '=' + op2 :: + We use this info to generate a DefMeth with a suitable RdrName for op1, + and a NoDefMeth for op2 + - The interface file has a separate definition for $dmop1, with unfolding etc. + - The renamer renames it to a Name. + - The renamer treats $dmop1 as a free variable of the declaration, so that + the binding for $dmop1 will be sucked in. (See RnHsSyn.tyClDeclFVs) + This doesn't happen for source code class decls, because they *bind* the default method. + +Dictionary functions +~~~~~~~~~~~~~~~~~~~~ +Each instance declaration gives rise to one dictionary function binding. + +The type checker makes up new source-code instance declarations +(e.g. from 'deriving' or generic default methods --- see +TcInstDcls.tcInstDecls1). So we can't generate the names for +dictionary functions in advance (we don't know how many we need). + +On the other hand for interface-file instance declarations, the decl +specifies the name of the dictionary function, and it has a binding elsewhere +in the interface file: + instance {Eq Int} = dEqInt + dEqInt :: {Eq Int} + +So again we treat source code and interface file code slightly differently. + +Source code: + - Source code instance decls have a Nothing in the (Maybe name) field + (see data InstDecl below) + + - The typechecker makes up a Local name for the dict fun for any source-code + instance decl, whether it comes from a source-code instance decl, or whether + the instance decl is derived from some other construct (e.g. 'deriving'). + + - The occurrence name it chooses is derived from the instance decl (just for + documentation really) --- e.g. dNumInt. Two dict funs may share a common + occurrence name, but will have different uniques. E.g. + instance Foo [Int] where ... + instance Foo [Bool] where ... + These might both be dFooList + + - The CoreTidy phase globalises 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) + because dict fun Ids are not captured in a TyCon or Class (unlike default + methods, say). Instead, they are kept separately in the InstEnv. This + makes it easy to adjust them after compiling a module. (Once we've finished + compiling that module, they don't change any more.) + + +Interface file code: + - The instance decl gives the dict fun name, so the InstDecl has a (Just name) + in the (Maybe name) field. + + - RnHsSyn.instDeclFVs treats the dict fun name as free in the decl, so that we + suck in the dfun binding + + \begin{code} +-- TyClDecls are precisely the kind of declarations that can +-- appear in interface files; or (internally) in GHC's interface +-- for a module. That's why (despite the misnomer) IfaceSig and ForeignType +-- are both in TyClDecl + data TyClDecl name pat - = TyData NewOrData - (HsContext name) -- context - name -- type constructor - [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 + = 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], + tcdLoc :: SrcLoc + } + + | ForeignType { tcdName :: name, -- See remarks about IfaceSig above + tcdExtName :: Maybe FastString, + tcdFoType :: FoType, + 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... - (DataPragmas name) - SrcLoc + tcdSysNames :: DataSysNames name, -- Generic converter functions + tcdLoc :: SrcLoc + } + + | TySynonym { tcdName :: name, -- type constructor + tcdTyVars :: [HsTyVarBndr name], -- type variables + tcdSynRhs :: HsType name, -- synonym expansion + tcdLoc :: SrcLoc + } + + | ClassDecl { tcdCtxt :: HsContext name, -- Context... + tcdName :: name, -- Name of the class + 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, + tcdLoc :: SrcLoc + } +\end{code} - | TySynonym name -- type constructor - [HsTyVarBndr name] -- type variables - (HsType name) -- synonym expansion - SrcLoc +Simple classifiers - | ClassDecl (HsContext name) -- context... - name -- name of the class - [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. - SrcLoc +\begin{code} +isIfaceSigDecl, 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 + +isClassDecl (ClassDecl {}) = True +isClassDecl other = False +\end{code} -instance Ord name => Eq (TyClDecl name pat) where +Dealing with names + +\begin{code} +-------------------------------- +tyClDeclName :: TyClDecl name pat -> name +tyClDeclName tycl_decl = tcdName tycl_decl + +-------------------------------- +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 {tcdName = name, tcdLoc = loc}) = [(name,loc)] +tyClDeclNames (IfaceSig {tcdName = name, tcdLoc = loc}) = [(name,loc)] +tyClDeclNames (ForeignType {tcdName = name, tcdLoc = loc}) = [(name,loc)] + +tyClDeclNames (ClassDecl {tcdName = cls_name, tcdSigs = sigs, tcdLoc = loc}) + = (cls_name,loc) : [(n,loc) | ClassOpSig n _ _ loc <- sigs] + +tyClDeclNames (TyData {tcdName = tc_name, tcdCons = cons, tcdLoc = loc}) + = (tc_name,loc) : conDeclsNames cons + + +tyClDeclTyVars (TySynonym {tcdTyVars = tvs}) = tvs +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 -- Used only when building interface files - (==) (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 + (==) d1@(IfaceSig {}) d2@(IfaceSig {}) + = tcdName d1 == tcdName d2 && + tcdType d1 == tcdType d2 && + tcdIdInfo d1 == tcdIdInfo d2 + + (==) d1@(ForeignType {}) d2@(ForeignType {}) + = tcdName d1 == tcdName d2 && + tcdFoType d1 == tcdFoType d2 + + (==) d1@(TyData {}) d2@(TyData {}) + = tcdName d1 == tcdName d2 && + 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) + ) + + (==) d1@(TySynonym {}) d2@(TySynonym {}) + = tcdName d1 == tcdName d2 && + eqWithHsTyVars (tcdTyVars d1) (tcdTyVars d2) (\ env -> + eq_hsType env (tcdSynRhs d1) (tcdSynRhs d2) + ) + + (==) d1@(ClassDecl {}) d2@(ClassDecl {}) + = tcdName d1 == tcdName d2 && + eqWithHsTyVars (tcdTyVars d1) (tcdTyVars d2) (\ env -> + eq_hsContext env (tcdCtxt d1) (tcdCtxt d2) && + eqListBy (eq_hsFD env) (tcdFDs d1) (tcdFDs d2) && + eqListBy (eq_cls_sig env) (tcdSigs d1) (tcdSigs d2) ) + (==) _ _ = 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 _ b1 ty1 _) (ClassOpSig n2 _ b2 ty2 _) - = n1==n2 && b1==b2 && eq_hsType env ty1 ty2 +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 for (DefMeth id) + -- This is used for comparing declarations before putting + -- them into interface files, and the name of the default + -- method isn't relevant + NoDefMeth `eq_dm` NoDefMeth = True + 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) +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]) - -isDataDecl, isSynDecl, isClassDecl :: TyClDecl name pat -> Bool - -isSynDecl (TySynonym _ _ _ _) = True -isSynDecl other = False - -isDataDecl (TyData _ _ _ _ _ _ _ _ _) = True -isDataDecl other = False - -isClassDecl (ClassDecl _ _ _ _ _ _ _ _ _ _ _ _) = True -isClassDecl other = False + = (length [() | ClassDecl {} <- decls], + length [() | TySynonym {} <- decls], + length [() | IfaceSig {} <- decls], + length [() | TyData {tcdND = DataType} <- decls], + length [() | TyData {tcdND = NewType} <- decls]) \end{code} \begin{code} -instance (Outputable name, Outputable pat) +instance (NamedThing name, Outputable name, Outputable pat) => Outputable (TyClDecl name pat) where - ppr (TySynonym tycon tyvars mono_ty src_loc) + 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 + ] + + ppr (ForeignType {tcdName = tycon}) + = hsep [ptext SLIT("foreign import type dotnet"), ppr tycon] + + ppr (TySynonym {tcdName = tycon, tcdTyVars = tyvars, tcdSynRhs = mono_ty}) = hang (ptext SLIT("type") <+> pp_decl_head [] tycon tyvars <+> equals) 4 (ppr mono_ty) - ppr (TyData new_or_data context tycon tyvars condecls ncons derivings pragmas src_loc) - = pp_tydecl - (ptext keyword <+> pp_decl_head context tycon tyvars <+> equals) + ppr (TyData {tcdND = new_or_data, tcdCtxt = context, tcdName = tycon, + tcdTyVars = tyvars, tcdCons = condecls, tcdNCons = ncons, + tcdDerivs = derivings}) + = pp_tydecl (ptext keyword <+> pp_decl_head context tycon tyvars) (pp_condecls condecls ncons) derivings where @@ -230,7 +480,8 @@ instance (Outputable name, Outputable pat) NewType -> SLIT("newtype") DataType -> SLIT("data") - ppr (ClassDecl context clas tyvars fds sigs methods pragmas _ _ _ _ src_loc) + ppr (ClassDecl {tcdCtxt = context, tcdName = clas, tcdTyVars = tyvars, tcdFDs = fds, + tcdSigs = sigs, tcdMeths = methods}) | null sigs -- No "where" part = top_matter @@ -240,15 +491,17 @@ instance (Outputable name, Outputable pat) where 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 + if ifaceStyle sty || isNothing methods + then empty + else ppr (fromJust 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_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_condecls (c:cs) ncons = equals <+> sep (ppr c : map (\ c -> ptext SLIT("|") <+> ppr c) cs) pp_tydecl pp_head pp_decl_rhs derivings = hang pp_head 4 (sep [ @@ -259,22 +512,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} %************************************************************************ %* * @@ -290,7 +527,7 @@ data ConDecl name name -- Name of the constructor's 'worker Id' -- Filled in as the ConDecl is built - [HsTyVarBndr name] -- Existentially quantified type variables + [HsTyVarBndr name] -- Existentially quantified type variables (HsContext name) -- ...and context -- If both are empty then there are no existentials @@ -307,21 +544,40 @@ data ConDetails name | RecCon -- record-style con decl [([name], BangType name)] -- list of "fields" +\end{code} + +\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) - | NewCon -- newtype con decl, possibly with a labelled field. - (HsType name) - (Maybe name) -- Just x => labelled field 'x' + 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} -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. +\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] eq_ConDecl env (ConDecl n1 _ tvs1 cxt1 cds1 _) (ConDecl n2 _ tvs2 cxt2 cds2 _) = n1 == n2 && - (eqWithHsTyVars tvs1 tvs2 $ \ env -> + (eq_hsTyVars env tvs1 tvs2 $ \ env -> eq_hsContext env cxt1 cxt2 && eq_ConDetails env cds1 cds2) @@ -331,15 +587,20 @@ 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 (NewCon t1 mn1) (NewCon t2 mn2) - = eq_hsType env t1 t2 && mn1 == mn2 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 = BangType StrictnessMark (HsType name) + +getBangType (BangType _ ty) = ty +getBangStrictness (BangType s _) = s + +unbangedType ty = BangType NotMarkedStrict 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 (BangType s1 t1) (BangType s2 t2) = s1==s2 && eq_hsType env t1 t2 \end{code} \begin{code} @@ -350,19 +611,17 @@ instance (Outputable name) => Outputable (ConDecl name) where ppr_con_details con (InfixCon ty1 ty2) = hsep [ppr_bang ty1, ppr con, ppr_bang ty2] +-- ConDecls generated by MkIface.ifaceTyCls always have a VanillaCon, 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) - = ppr con <+> hsep (map (ppr_bang) tys) + = getPprStyle $ \ sty -> + hsep ((if ifaceStyle sty then ppr con else ppr_var con) + : 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))) + = ppr con <+> braces (sep (punctuate comma (map ppr_field fields))) where ppr_field (ns, ty) = hsep (map (ppr) ns) <+> dcolon <+> @@ -371,9 +630,7 @@ ppr_con_details con (RecCon fields) 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 +ppr_bang (BangType s ty) = ppr s <> pprParendHsType ty \end{code} @@ -393,7 +650,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} @@ -402,14 +660,18 @@ 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 then - hsep [ptext SLIT("instance"), ppr inst_ty, equals, ppr dfun_name] + 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} @@ -449,57 +711,46 @@ instance (Outputable name) %************************************************************************ \begin{code} -data ForeignDecl name = - ForeignDecl - name - ForKind - (HsType name) - ExtName - CallConv - SrcLoc - -instance (Outputable name) - => Outputable (ForeignDecl name) where - - ppr (ForeignDecl nm imp_exp ty ext_name cconv src_loc) - = ptext SLIT("foreign") <+> ppr_imp_exp <+> pprCallConv cconv <+> - ppr ext_name <+> ppr_unsafe <+> ppr nm <+> dcolon <+> ppr ty - where - (ppr_imp_exp, ppr_unsafe) = - case imp_exp of - FoLabel -> (ptext SLIT("label"), empty) - FoExport -> (ptext SLIT("export"), empty) - FoImport us - | us -> (ptext SLIT("import"), ptext SLIT("unsafe")) - | otherwise -> (ptext SLIT("import"), empty) - -data ForKind - = FoLabel - | FoExport - | FoImport Bool -- True => unsafe call. - -data ExtName - = Dynamic - | ExtName CLabelString -- The external name of the foreign thing, - (Maybe CLabelString) -- and optionally its DLL or module name - -- Both of these are completely unencoded; - -- we just print them as they are - -isDynamicExtName :: ExtName -> Bool -isDynamicExtName Dynamic = True -isDynamicExtName _ = False - -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 (pprCLabelString nm) +data ForeignDecl name + = ForeignImport name (HsType name) FoImport SrcLoc + | ForeignExport name (HsType name) FoExport SrcLoc + +forDeclName (ForeignImport n _ _ _) = n +forDeclName (ForeignExport n _ _ _) = n + +data FoImport + = LblImport CLabelString -- foreign label + | CImport CCallSpec -- foreign import + | CDynImport CCallConv -- foreign export dynamic + | DNImport DNCallSpec -- foreign import dotnet + +data FoExport = CExport CExportSpec + +data FoType = DNType -- In due course we'll add subtype stuff + 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 + +instance Outputable FoExport where + ppr (CExport d) = ppr d + +instance Outputable FoType where + ppr DNType = ptext SLIT("type dotnet") \end{code} + %************************************************************************ %* * \subsection{Transformation rules} @@ -509,7 +760,8 @@ instance Outputable ExtName where \begin{code} data RuleDecl name pat = HsRule -- Source rule - FAST_STRING -- Rule name + 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 @@ -518,7 +770,8 @@ data RuleDecl name pat SrcLoc | IfaceRule -- One that's come in from an interface file; pre-typecheck - FAST_STRING + RuleName + Activation [UfBinder name] -- Tyvars and term vars name -- Head of lhs [UfExpr name] -- Args of LHS @@ -529,22 +782,30 @@ data RuleDecl name pat name -- Head of LHS CoreRule +isIfaceRuleDecl :: RuleDecl name pat -> Bool +isIfaceRuleDecl (HsRule _ _ _ _ _ _ _) = False +isIfaceRuleDecl other = True + +ifaceRuleDeclName :: RuleDecl name pat -> name +ifaceRuleDeclName (IfaceRule _ _ _ n _ _ _) = n +ifaceRuleDeclName (IfaceRuleOut n r) = n +ifaceRuleDeclName (HsRule fs _ _ _ _ _ _) = pprPanic "ifaceRuleDeclName" (ppr fs) data RuleBndr name = RuleBndr name | RuleBndrSig name (HsType name) -instance Ord name => Eq (RuleDecl name pat) where +instance (NamedThing name, 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 && + (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 (Outputable name, Outputable pat) +instance (NamedThing name, Outputable name, Outputable pat) => Outputable (RuleDecl name pat) where - ppr (HsRule name tvs ns lhs rhs loc) - = sep [text "{-# RULES" <+> doubleQuotes (ptext name), + ppr (HsRule name act tvs ns lhs rhs loc) + = sep [text "{-# RULES" <+> doubleQuotes (ptext name) <+> ppr act, pp_forall, ppr lhs, equals <+> ppr rhs, text "#-}" ] where @@ -553,8 +814,8 @@ instance (Outputable name, Outputable pat) fsep (map ppr tvs ++ map ppr ns) <> dot - ppr (IfaceRule name tpl_vars fn tpl_args rhs loc) - = hsep [ doubleQuotes (ptext name), + ppr (IfaceRule name act tpl_vars fn tpl_args rhs loc) + = hsep [ doubleQuotes (ptext name), ppr act, ptext SLIT("__forall") <+> braces (interppSP tpl_vars), ppr fn <+> sep (map (pprUfExpr parens) tpl_args), ptext SLIT("=") <+> ppr rhs @@ -565,16 +826,6 @@ instance (Outputable name, Outputable pat) instance Outputable name => Outputable (RuleBndr name) where ppr (RuleBndr name) = ppr name ppr (RuleBndrSig name ty) = ppr name <> dcolon <> ppr ty - -toHsRule id (BuiltinRule _) - = pprTrace "toHsRule: builtin" (ppr id) (bogusIfaceRule id) - -toHsRule id (Rule name bndrs args rhs) - = IfaceRule name (map toUfBndr bndrs) (toRdrName id) - (map toUfExpr args) (toUfExpr rhs) noSrcLoc - -bogusIfaceRule id - = IfaceRule SLIT("bogus") [] (toRdrName id) [] (UfVar (toRdrName id)) noSrcLoc \end{code} @@ -584,17 +835,14 @@ bogusIfaceRule id %* * %************************************************************************ -We use exported entities for things to deprecate. Cunning trick (hack?): -`IEModuleContents undefined' is used for module deprecation. +We use exported entities for things to deprecate. \begin{code} -data DeprecDecl name = Deprecation (IE name) DeprecTxt SrcLoc +data DeprecDecl name = Deprecation name DeprecTxt SrcLoc type DeprecTxt = FAST_STRING -- reason/explanation for deprecation instance Outputable name => Outputable (DeprecDecl name) where - ppr (Deprecation (IEModuleContents _) txt _) - = hsep [text "{-# DEPRECATED", doubleQuotes (ppr txt), text "#-}"] - ppr (Deprecation thing txt _) + ppr (Deprecation thing txt _) = hsep [text "{-# DEPRECATED", ppr thing, doubleQuotes (ppr txt), text "#-}"] \end{code}