X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FhsSyn%2FHsDecls.lhs;h=8c23d482bf0754be103d7b44046b5ca2309ffd92;hb=e38f57d95204bea6c322425af0da52cf8ce72d0e;hp=9de522df97126f2960c2eb20c8accd83b8a72b1c;hpb=57d07fb8c739fb50f957c25e8987632d04da3969;p=ghc-hetmet.git diff --git a/ghc/compiler/hsSyn/HsDecls.lhs b/ghc/compiler/hsSyn/HsDecls.lhs index 9de522d..8c23d48 100644 --- a/ghc/compiler/hsSyn/HsDecls.lhs +++ b/ghc/compiler/hsSyn/HsDecls.lhs @@ -1,31 +1,55 @@ % -% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996 +% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % \section[HsDecls]{Abstract syntax: global declarations} -Definitions for: @FixityDecl@, @TyDecl@ and @ConDecl@, @ClassDecl@, +Definitions for: @TyDecl@ and @oCnDecl@, @ClassDecl@, @InstDecl@, @DefaultDecl@ and @ForeignDecl@. \begin{code} -module HsDecls where +module HsDecls ( + HsDecl(..), LHsDecl, TyClDecl(..), LTyClDecl, + InstDecl(..), LInstDecl, NewOrData(..), + RuleDecl(..), LRuleDecl, RuleBndr(..), + DefaultDecl(..), LDefaultDecl, SpliceDecl(..), + ForeignDecl(..), LForeignDecl, ForeignImport(..), ForeignExport(..), + CImportSpec(..), FoType(..), + ConDecl(..), ResType(..), LConDecl, + DeprecDecl(..), LDeprecDecl, + HsGroup(..), emptyRdrGroup, emptyRnGroup, appendGroups, + tcdName, tyClDeclNames, tyClDeclTyVars, + isClassDecl, isSynDecl, isDataDecl, + countTyClDecls, + conDetailsTys, + collectRuleBndrSigTys, + ) where #include "HsVersions.h" -- friends: -import HsBinds ( HsBinds, MonoBinds, Sig, nullMonoBinds ) -import HsPragmas ( DataPragmas, ClassPragmas ) +import {-# SOURCE #-} HsExpr( HsExpr, pprExpr ) + -- Because Expr imports Decls via HsBracket + +import HsBinds ( HsValBinds(..), HsBind, LHsBinds, plusHsValBinds, + Sig(..), LSig, LFixitySig, pprLHsBinds, + emptyValBindsIn, emptyValBindsOut ) +import HsPat ( HsConDetails(..), hsConArgs ) +import HsImpExp ( pprHsVar ) import HsTypes -import HsCore ( UfExpr ) -import BasicTypes ( Fixity, NewOrData(..) ) -import IdInfo ( ArgUsageInfo, FBTypeInfo, ArityInfo, UpdateInfo ) -import Demand ( Demand ) -import CallConv ( CallConv, pprCallConv ) +import HscTypes ( DeprecTxt ) +import CoreSyn ( RuleName ) +import Kind ( Kind, pprKind ) +import BasicTypes ( Activation(..) ) +import ForeignCall ( CCallTarget(..), DNCallSpec, CCallConv, Safety, + CExportSpec(..), CLabelString ) -- others: -import Name ( getOccName, OccName, NamedThing(..) ) +import FunDeps ( pprFundeps ) +import Class ( FunDep ) import Outputable -import SrcLoc ( SrcLoc ) -import Util +import Util ( count ) +import SrcLoc ( Located(..), unLoc, noLoc ) +import FastString \end{code} @@ -36,130 +60,423 @@ import Util %************************************************************************ \begin{code} -data HsDecl flexi name pat - = TyD (TyDecl name) - | ClD (ClassDecl flexi name pat) - | InstD (InstDecl flexi name pat) - | DefD (DefaultDecl name) - | ValD (HsBinds flexi name pat) - | SigD (IfaceSig name) - | ForD (ForeignDecl name) +type LHsDecl id = Located (HsDecl id) + +data HsDecl id + = TyClD (TyClDecl id) + | InstD (InstDecl id) + | ValD (HsBind id) + | SigD (Sig id) + | DefD (DefaultDecl id) + | ForD (ForeignDecl id) + | DeprecD (DeprecDecl id) + | RuleD (RuleDecl id) + | SpliceD (SpliceDecl id) + +-- NB: all top-level fixity decls are contained EITHER +-- EITHER SigDs +-- OR in the ClassDecls in TyClDs +-- +-- The former covers +-- a) data constructors +-- b) class methods (but they can be also done in the +-- signatures of class decls) +-- c) imported functions (that have an IfacSig) +-- d) top level decls +-- +-- The latter is for class methods only + +-- A [HsDecl] is categorised into a HsGroup before being +-- fed to the renamer. +data HsGroup id + = HsGroup { + hs_valds :: HsValBinds id, + hs_tyclds :: [LTyClDecl id], + hs_instds :: [LInstDecl id], + + hs_fixds :: [LFixitySig id], + -- Snaffled out of both top-level fixity signatures, + -- and those in class declarations + + hs_defds :: [LDefaultDecl id], + hs_fords :: [LForeignDecl id], + hs_depds :: [LDeprecDecl id], + hs_ruleds :: [LRuleDecl id] + } + +emptyGroup, emptyRdrGroup, emptyRnGroup :: HsGroup a +emptyRdrGroup = emptyGroup { hs_valds = emptyValBindsIn } +emptyRnGroup = emptyGroup { hs_valds = emptyValBindsOut } + +emptyGroup = HsGroup { hs_tyclds = [], hs_instds = [], + hs_fixds = [], hs_defds = [], hs_fords = [], + hs_depds = [], hs_ruleds = [], + hs_valds = error "emptyGroup hs_valds: Can't happen" } + +appendGroups :: HsGroup a -> HsGroup a -> HsGroup a +appendGroups + HsGroup { + hs_valds = val_groups1, + hs_tyclds = tyclds1, + hs_instds = instds1, + hs_fixds = fixds1, + hs_defds = defds1, + hs_fords = fords1, + hs_depds = depds1, + hs_ruleds = rulds1 } + HsGroup { + hs_valds = val_groups2, + hs_tyclds = tyclds2, + hs_instds = instds2, + hs_fixds = fixds2, + hs_defds = defds2, + hs_fords = fords2, + hs_depds = depds2, + hs_ruleds = rulds2 } + = + HsGroup { + hs_valds = val_groups1 `plusHsValBinds` val_groups2, + hs_tyclds = tyclds1 ++ tyclds2, + hs_instds = instds1 ++ instds2, + hs_fixds = fixds1 ++ fixds2, + hs_defds = defds1 ++ defds2, + hs_fords = fords1 ++ fords2, + hs_depds = depds1 ++ depds2, + hs_ruleds = rulds1 ++ rulds2 } \end{code} \begin{code} -#ifdef DEBUG -hsDeclName :: (NamedThing name, Outputable name, Outputable pat) - => HsDecl flexi name pat -> name -#endif -hsDeclName (TyD (TyData _ _ name _ _ _ _ _)) = name -hsDeclName (TyD (TySynonym name _ _ _)) = name -hsDeclName (ClD (ClassDecl _ name _ _ _ _ _ _ _)) = name -hsDeclName (SigD (IfaceSig name _ _ _)) = name -hsDeclName (InstD (InstDecl _ _ _ (Just name) _)) = name -hsDeclName (ForD (ForeignDecl name _ _ _ _ _)) = name --- Others don't make sense -#ifdef DEBUG -hsDeclName x = pprPanic "HsDecls.hsDeclName" (ppr x) -#endif -\end{code} - -\begin{code} -instance (NamedThing name, Outputable name, Outputable pat) - => Outputable (HsDecl flexi name pat) where - - ppr (TyD td) = ppr td - ppr (ClD cd) = ppr cd - ppr (SigD sig) = ppr sig +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 - -#ifdef DEBUG --- hsDeclName needs more context when DEBUG is on -instance (NamedThing name, Outputable name, Outputable pat, Eq name) - => Eq (HsDecl flex name pat) where - d1 == d2 = hsDeclName d1 == hsDeclName d2 - -instance (NamedThing name, Outputable name, Outputable pat, Ord name) - => Ord (HsDecl flex name pat) where - d1 `compare` d2 = hsDeclName d1 `compare` hsDeclName d2 -#else -instance (Eq name) => Eq (HsDecl flex name pat) where - d1 == d2 = hsDeclName d1 == hsDeclName d2 - -instance (Ord name) => Ord (HsDecl flexi name pat) where - d1 `compare` d2 = hsDeclName d1 `compare` hsDeclName d2 -#endif + ppr (SigD sd) = ppr sd + ppr (RuleD rd) = ppr rd + ppr (DeprecD 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 }) + = 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] + where + ppr_ds [] = empty + ppr_ds ds = text "" $$ vcat (map ppr ds) + +data SpliceDecl id = SpliceDecl (Located (HsExpr id)) -- Top level splice + +instance OutputableBndr name => Outputable (SpliceDecl name) where + ppr (SpliceDecl e) = ptext SLIT("$") <> parens (pprExpr (unLoc e)) \end{code} %************************************************************************ %* * -\subsection[FixityDecl]{A fixity declaration} +\subsection[TyDecl]{@data@, @newtype@ or @type@ (synonym) type declaration} %* * %************************************************************************ -\begin{code} -data FixityDecl name = FixityDecl name Fixity SrcLoc + -------------------------------- + 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: + - Ensure they "point to" the parent data/class decl + when loading that decl from an interface file + (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 + +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 +~~~~~~~~~~~~~~~ + - 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 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) + 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 + -instance Outputable name => Outputable (FixityDecl name) where - ppr (FixityDecl name fixity loc) = sep [ppr fixity, ppr name] +\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 + +type LTyClDecl name = Located (TyClDecl name) + +data TyClDecl name + = ForeignType { + tcdLName :: Located name, + tcdExtName :: Maybe FastString, + tcdFoType :: FoType + } + + | TyData { tcdND :: NewOrData, + tcdCtxt :: LHsContext name, -- Context + tcdLName :: Located name, -- Type constructor + tcdTyVars :: [LHsTyVarBndr name], -- Type variables + tcdKindSig :: Maybe Kind, -- Optional kind sig; + -- (only for the 'where' form) + + tcdCons :: [LConDecl name], -- Data constructors + -- For data T a = T1 | T2 a the LConDecls all have ResTyH98 + -- For data T a where { T1 :: T a } the LConDecls all have ResTyGADT + + tcdDerivs :: Maybe [LHsType name] + -- Derivings; Nothing => not specified + -- Just [] => derive exactly what is asked + -- These "types" must be of form + -- forall ab. C ty1 ty2 + -- Typically the foralls and ty args are empty, but they + -- are non-empty for the newtype-deriving case + } + + | TySynonym { tcdLName :: Located name, -- type constructor + tcdTyVars :: [LHsTyVarBndr name], -- type variables + tcdSynRhs :: LHsType name -- synonym expansion + } + + | ClassDecl { tcdCtxt :: LHsContext name, -- Context... + tcdLName :: Located name, -- Name of the class + tcdTyVars :: [LHsTyVarBndr name], -- Class type variables + tcdFDs :: [Located (FunDep name)], -- Functional deps + tcdSigs :: [LSig name], -- Methods' signatures + tcdMeths :: LHsBinds name -- Default methods + } + +data NewOrData + = NewType -- "newtype Blah ..." + | DataType -- "data Blah ..." + deriving( Eq ) -- Needed because Demand derives Eq \end{code} +Simple classifiers -%************************************************************************ -%* * -\subsection[TyDecl]{@data@, @newtype@ or @type@ (synonym) type declaration} -%* * -%************************************************************************ +\begin{code} +isDataDecl, isSynDecl, isClassDecl :: TyClDecl name -> Bool + +isSynDecl (TySynonym {}) = True +isSynDecl other = False + +isDataDecl (TyData {}) = True +isDataDecl other = False + +isClassDecl (ClassDecl {}) = True +isClassDecl other = False +\end{code} + +Dealing with names \begin{code} -data TyDecl name - = TyData NewOrData - (Context name) -- context - name -- type constructor - [HsTyVar name] -- type variables - [ConDecl name] -- data constructors (empty if abstract) - (Maybe [name]) -- derivings; Nothing => not specified - -- (i.e., derive default); Just [] => derive - -- *nothing*; Just => as you would - -- expect... - (DataPragmas name) - SrcLoc - - | TySynonym name -- type constructor - [HsTyVar name] -- type variables - (HsType name) -- synonym expansion - SrcLoc +tcdName :: TyClDecl name -> name +tcdName decl = unLoc (tcdLName decl) + +tyClDeclNames :: Eq name => TyClDecl name -> [Located name] +-- 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 {tcdLName = name}) = [name] +tyClDeclNames (ForeignType {tcdLName = name}) = [name] + +tyClDeclNames (ClassDecl {tcdLName = cls_name, tcdSigs = sigs}) + = cls_name : [n | L _ (TypeSig n _) <- sigs] + +tyClDeclNames (TyData {tcdLName = tc_name, tcdCons = cons}) + = tc_name : conDeclsNames (map unLoc cons) + +tyClDeclTyVars (TySynonym {tcdTyVars = tvs}) = tvs +tyClDeclTyVars (TyData {tcdTyVars = tvs}) = tvs +tyClDeclTyVars (ClassDecl {tcdTyVars = tvs}) = tvs +tyClDeclTyVars (ForeignType {}) = [] +\end{code} + +\begin{code} +countTyClDecls :: [TyClDecl name] -> (Int, Int, Int, Int) + -- class, data, newtype, synonym decls +countTyClDecls decls + = (count isClassDecl decls, + count isSynDecl 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 (TyDecl name) where +instance OutputableBndr name + => Outputable (TyClDecl name) where - ppr (TySynonym tycon tyvars mono_ty src_loc) - = hang (pp_decl_head SLIT("type") empty tycon tyvars) + ppr (ForeignType {tcdLName = ltycon}) + = hsep [ptext SLIT("foreign import type dotnet"), ppr ltycon] + + ppr (TySynonym {tcdLName = ltycon, tcdTyVars = tyvars, tcdSynRhs = mono_ty}) + = hang (ptext SLIT("type") <+> pp_decl_head [] ltycon tyvars <+> equals) 4 (ppr mono_ty) - ppr (TyData new_or_data context tycon tyvars condecls derivings pragmas src_loc) - = pp_tydecl - (pp_decl_head keyword (pp_context_and_arrow context) tycon tyvars) + ppr (TyData {tcdND = new_or_data, tcdCtxt = context, tcdLName = ltycon, + tcdTyVars = tyvars, tcdKindSig = mb_sig, tcdCons = condecls, + tcdDerivs = derivings}) + = pp_tydecl (ppr new_or_data <+> pp_decl_head (unLoc context) ltycon tyvars <+> ppr_sig mb_sig) (pp_condecls condecls) derivings where - keyword = case new_or_data of - NewType -> SLIT("newtype") - DataType -> SLIT("data") + ppr_sig Nothing = empty + ppr_sig (Just kind) = dcolon <+> pprKind kind -pp_decl_head str pp_context tycon tyvars - = hsep [ptext str, pp_context, ppr tycon, - interppSP tyvars, ptext SLIT("=")] + ppr (ClassDecl {tcdCtxt = context, tcdLName = lclas, tcdTyVars = tyvars, tcdFDs = fds, + tcdSigs = sigs, tcdMeths = methods}) + | null sigs -- No "where" part + = top_matter -pp_condecls [] = empty -- Curious! -pp_condecls (c:cs) - = sep (ppr c : map (\ c -> (<>) (ptext SLIT("| ")) (ppr c)) cs) + | otherwise -- Laid out + = sep [hsep [top_matter, ptext SLIT("where {")], + nest 4 (sep [sep (map ppr_sig sigs), ppr methods, char '}'])] + where + top_matter = ptext SLIT("class") <+> pp_decl_head (unLoc context) lclas tyvars <+> pprFundeps (map unLoc fds) + ppr_sig sig = ppr sig <> semi + +pp_decl_head :: OutputableBndr name + => HsContext name + -> Located name + -> [LHsTyVarBndr name] + -> SDoc +pp_decl_head context thing tyvars + = hsep [pprHsContext context, ppr thing, interppSP tyvars] +pp_condecls cs@(L _ ConDecl{ con_res = ResTyGADT _ } : _) -- In GADT syntax + = hang (ptext SLIT("where")) 2 (vcat (map ppr cs)) +pp_condecls cs -- In H98 syntax + = equals <+> sep (punctuate (ptext SLIT(" |")) (map ppr cs)) pp_tydecl pp_head pp_decl_rhs derivings = hang pp_head 4 (sep [ @@ -169,27 +486,11 @@ pp_tydecl pp_head pp_decl_rhs derivings Just ds -> hsep [ptext SLIT("deriving"), parens (interpp'SP ds)] ]) -pp_context_and_arrow :: Outputable name => Context name -> SDoc -pp_context_and_arrow [] = empty -pp_context_and_arrow theta = hsep [pprContext theta, ptext SLIT("=>")] +instance Outputable NewOrData where + ppr NewType = ptext SLIT("newtype") + ppr DataType = ptext SLIT("data") \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 (NamedThing name, Outputable name) - => Outputable (SpecDataSig name) where - - ppr (SpecDataSig tycon ty _) - = hsep [text "{-# SPECIALIZE data", ppr ty, text "#-}"] -\end{code} %************************************************************************ %* * @@ -198,92 +499,86 @@ instance (NamedThing name, Outputable name) %************************************************************************ \begin{code} -data ConDecl name - = ConDecl name -- Constructor name - (Context name) -- Existential context for this constructor - (ConDetails name) - SrcLoc +type LConDecl name = Located (ConDecl name) -data ConDetails name - = VanillaCon -- prefix-style con decl - [BangType name] +-- data T b = forall a. Eq a => MkT a b +-- MkT :: forall b a. Eq a => MkT a b - | InfixCon -- infix-style con decl - (BangType name) - (BangType name) +-- data T b where +-- MkT1 :: Int -> T Int - | RecCon -- record-style con decl - [([name], BangType name)] -- list of "fields" +-- data T = Int `MkT` Int +-- | MkT2 - | NewCon -- newtype con decl - (HsType name) +-- data T a where +-- Int `MkT` Int :: T Int -data BangType name - = Banged (HsType name) -- HsType: to allow Haskell extensions - | Unbanged (HsType name) -- (MonoType only needed for straight Haskell) -\end{code} +data ConDecl name + = ConDecl + { con_name :: Located name -- Constructor name; this is used for the + -- DataCon itself, and for the user-callable wrapper Id -\begin{code} -instance (NamedThing name, Outputable name) => Outputable (ConDecl name) where - ppr (ConDecl con cxt con_details loc) - = pp_context_and_arrow cxt <+> ppr_con_details con con_details + , con_explicit :: HsExplicitForAll -- Is there an user-written forall? (cf. HStypes.HsForAllTy) -ppr_con_details con (InfixCon ty1 ty2) - = hsep [ppr_bang ty1, ppr con, ppr_bang ty2] + , con_qvars :: [LHsTyVarBndr name] -- ResTyH98: the constructor's existential type variables + -- ResTyGADT: all the constructor's quantified type variables -ppr_con_details con (VanillaCon tys) - = ppr con <+> hsep (map (ppr_bang) tys) + , con_cxt :: LHsContext name -- The context. This *does not* include the + -- "stupid theta" which lives only in the TyData decl -ppr_con_details con (NewCon ty) - = ppr con <+> pprParendHsType ty + , con_details :: HsConDetails name (LBangType name) -- The main payload -ppr_con_details con (RecCon fields) - = ppr con <+> braces (hsep (punctuate comma (map ppr_field fields))) - where - ppr_field (ns, ty) = hsep (map (ppr) ns) <+> - ptext SLIT("::") <+> - ppr_bang ty + , con_res :: ResType name -- Result type of the constructor + } -ppr_bang (Banged ty) = ptext SLIT("!") <> pprParendHsType ty -ppr_bang (Unbanged ty) = pprParendHsType ty +data ResType name + = ResTyH98 -- Constructor was declared using Haskell 98 syntax + | ResTyGADT (LHsType name) -- Constructor was declared using GADT-style syntax, + -- and here is its result type \end{code} -%************************************************************************ -%* * -\subsection[ClassDecl]{A class declaration} -%* * -%************************************************************************ - \begin{code} -data ClassDecl flexi name pat - = ClassDecl (Context name) -- context... - name -- name of the class - [HsTyVar name] -- the class type variables - [Sig name] -- methods' signatures - (MonoBinds flexi name pat) -- default methods - (ClassPragmas name) - name name -- The names of the tycon and datacon for this class - -- These are filled in by the renamer - SrcLoc +conDeclsNames :: Eq name => [ConDecl name] -> [Located name] + -- 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 { con_name = lname, con_details = RecCon flds }) + = (map unLoc new_flds ++ flds_seen, lname : [f | f <- new_flds] ++ acc) + where + new_flds = [ f | (f,_) <- flds, not (unLoc f `elem` flds_seen) ] + + do_one (flds_seen, acc) c + = (flds_seen, (con_name c):acc) + +conDetailsTys details = map getBangType (hsConArgs details) \end{code} + \begin{code} -instance (NamedThing name, Outputable name, Outputable pat) - => Outputable (ClassDecl flexi name pat) where +instance (OutputableBndr name) => Outputable (ConDecl name) where + ppr = pprConDecl - ppr (ClassDecl context clas tyvars sigs methods pragmas _ _ src_loc) - | null sigs -- No "where" part - = top_matter +pprConDecl (ConDecl con expl tvs cxt details ResTyH98) + = sep [pprHsForAll expl tvs cxt, ppr_details con details] + where + ppr_details con (InfixCon t1 t2) = hsep [ppr t1, pprHsVar con, ppr t2] + ppr_details con (PrefixCon tys) = hsep (pprHsVar con : map ppr tys) + ppr_details con (RecCon fields) = ppr con <+> ppr_fields fields - | otherwise -- Laid out - = sep [hsep [top_matter, ptext SLIT("where {")], - nest 4 (vcat [sep (map ppr_sig sigs), - ppr methods, - char '}'])] - where - top_matter = hsep [ptext SLIT("class"), pp_context_and_arrow context, - ppr clas, hsep (map (ppr) tyvars)] - ppr_sig sig = ppr sig <> semi +pprConDecl (ConDecl con expl tvs cxt details (ResTyGADT res_ty)) + = sep [pprHsForAll expl tvs cxt, ppr con <+> ppr_details details] + where + ppr_details (PrefixCon arg_tys) = dcolon <+> ppr (foldr mk_fun_ty res_ty arg_tys) + ppr_details (RecCon fields) = ppr fields <+> dcolon <+> ppr res_ty + ppr_details (PrefixCon _) = pprPanic "pprConDecl" (ppr con) + + mk_fun_ty a b = noLoc (HsFunTy a b) + +ppr_fields fields = braces (sep (punctuate comma (map ppr_field fields))) +ppr_field (n, ty) = ppr n <+> dcolon <+> ppr ty \end{code} %************************************************************************ @@ -293,35 +588,23 @@ instance (NamedThing name, Outputable name, Outputable pat) %************************************************************************ \begin{code} -data InstDecl flexi name pat - = InstDecl (HsType name) -- Context => Class Instance-type +type LInstDecl name = Located (InstDecl name) + +data InstDecl name + = InstDecl (LHsType name) -- Context => Class Instance-type -- Using a polytype means that the renamer conveniently -- figures out the quantified type variables for us. + (LHsBinds name) + [LSig name] -- User-supplied pragmatic info - (MonoBinds flexi name pat) - - [Sig name] -- User-supplied pragmatic info - - (Maybe name) -- Name for the dictionary function +instance (OutputableBndr name) => Outputable (InstDecl name) where - SrcLoc -\end{code} - -\begin{code} -instance (NamedThing name, Outputable name, Outputable pat) - => Outputable (InstDecl flexi name pat) where - - ppr (InstDecl inst_ty binds uprags dfun_name src_loc) - = getPprStyle $ \ sty -> - if ifaceStyle sty || (nullMonoBinds binds && null uprags) then - hsep [ptext SLIT("instance"), ppr inst_ty] - else - vcat [hsep [ptext SLIT("instance"), ppr inst_ty, ptext SLIT("where")], - nest 4 (ppr uprags), - nest 4 (ppr binds) ] + ppr (InstDecl inst_ty binds uprags) + = vcat [hsep [ptext SLIT("instance"), ppr inst_ty, ptext SLIT("where")], + nest 4 (ppr uprags), + nest 4 (pprLHsBinds binds) ] \end{code} - %************************************************************************ %* * \subsection[DefaultDecl]{A @default@ declaration} @@ -333,14 +616,15 @@ for the parser to check that; we pass them all through in the abstract syntax, and that restriction must be checked in the front end. \begin{code} +type LDefaultDecl name = Located (DefaultDecl name) + data DefaultDecl name - = DefaultDecl [HsType name] - SrcLoc + = DefaultDecl [LHsType name] -instance (NamedThing name, Outputable name) +instance (OutputableBndr name) => Outputable (DefaultDecl name) where - ppr (DefaultDecl tys src_loc) + ppr (DefaultDecl tys) = ptext SLIT("default") <+> parens (interpp'SP tys) \end{code} @@ -351,83 +635,160 @@ instance (NamedThing name, Outputable name) %************************************************************************ \begin{code} -data ForeignDecl name = - ForeignDecl - name - ForKind - (HsType name) - ExtName - CallConv - SrcLoc - -instance (NamedThing name, 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 <+> ptext SLIT("::") <+> 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 FAST_STRING (Maybe FAST_STRING) - -isDynamic :: ExtName -> Bool -isDynamic Dynamic = True -isDynamic _ = False - - -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) +-- 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 +-- +type LForeignDecl name = Located (ForeignDecl name) + +data ForeignDecl name + = ForeignImport (Located name) (LHsType name) ForeignImport Bool -- defines name + | ForeignExport (Located name) (LHsType name) ForeignExport Bool -- uses name + +-- 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.) + +-- 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 + + +-- pretty printing of foreign declarations +-- + +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 _ _ (CWrapper) = ptext SLIT("wrapper") + -- + pprLib lib | nullFS 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") \end{code} + %************************************************************************ %* * -\subsection{Signatures in interface files} +\subsection{Transformation rules} %* * %************************************************************************ \begin{code} -data IfaceSig name - = IfaceSig name - (HsType name) - [HsIdInfo name] - SrcLoc - -instance (NamedThing name, Outputable name) => Outputable (IfaceSig name) where - ppr (IfaceSig var ty _ _) - = hang (hsep [ppr var, ptext SLIT("::")]) - 4 (ppr ty) - -data HsIdInfo name - = HsArity ArityInfo - | HsStrictness (HsStrictnessInfo name) - | HsUnfold Bool (UfExpr name) -- True <=> INLINE pragma - | HsUpdate UpdateInfo - | HsArgUsage ArgUsageInfo - | HsFBType FBTypeInfo - | HsSpecialise [HsTyVar name] [HsType name] (UfExpr name) - - -data HsStrictnessInfo name - = HsStrictnessInfo [Demand] - (Maybe (name, [name])) -- Worker, if any - -- and needed constructors - | HsBottom +type LRuleDecl name = Located (RuleDecl name) + +data RuleDecl name + = HsRule -- Source rule + RuleName -- Rule name + Activation + [RuleBndr name] -- Forall'd vars; after typechecking this includes tyvars + (Located (HsExpr name)) -- LHS + (Located (HsExpr name)) -- RHS + +data RuleBndr name + = RuleBndr (Located name) + | RuleBndrSig (Located name) (LHsType name) + +collectRuleBndrSigTys :: [RuleBndr name] -> [LHsType name] +collectRuleBndrSigTys bndrs = [ty | RuleBndrSig _ ty <- bndrs] + +instance OutputableBndr name => Outputable (RuleDecl name) where + ppr (HsRule name act ns lhs rhs) + = sep [text "{-# RULES" <+> doubleQuotes (ftext name) <+> ppr act, + nest 4 (pp_forall <+> pprExpr (unLoc lhs)), + nest 4 (equals <+> pprExpr (unLoc rhs) <+> text "#-}") ] + where + pp_forall | null ns = empty + | otherwise = text "forall" <+> fsep (map ppr ns) <> dot + +instance OutputableBndr 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} +type LDeprecDecl name = Located (DeprecDecl name) + +data DeprecDecl name = Deprecation name DeprecTxt + +instance OutputableBndr name => Outputable (DeprecDecl name) where + ppr (Deprecation thing txt) + = hsep [text "{-# DEPRECATED", ppr thing, doubleQuotes (ppr txt), text "#-}"] \end{code}