module HsDecls (
HsDecl(..), TyClDecl(..), InstDecl(..), RuleDecl(..), RuleBndr(..),
DefaultDecl(..),
- ForeignDecl(..), FoImport(..), FoExport(..), FoType(..),
+ ForeignDecl(..), ForeignImport(..), ForeignExport(..),
+ CImportSpec(..), FoType(..),
ConDecl(..), ConDetails(..),
BangType(..), getBangType, getBangStrictness, unbangedType,
DeprecDecl(..), DeprecTxt,
hsDeclName, instDeclName,
tyClDeclName, tyClDeclNames, tyClDeclSysNames, tyClDeclTyVars,
- isClassDecl, isSynDecl, isDataDecl, isIfaceSigDecl, countTyClDecls,
- mkClassDeclSysNames, isIfaceRuleDecl, ifaceRuleDeclName,
- getClassDeclSysNames, conDetailsTys
+ isClassDecl, isSynDecl, isDataDecl, isIfaceSigDecl, isCoreDecl,
+ isTypeOrClassDecl, countTyClDecls,
+ mkClassDeclSysNames, isSourceInstDecl, ifaceRuleDeclName,
+ getClassDeclSysNames, conDetailsTys,
+ collectRuleBndrSigTys
) where
#include "HsVersions.h"
)
import CoreSyn ( CoreRule(..), RuleName )
import BasicTypes ( NewOrData(..), StrictnessMark(..), Activation(..) )
-import ForeignCall ( CExportSpec, CCallSpec, DNCallSpec, CCallConv )
+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
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
+hsDeclName (TyClD decl) = tyClDeclName decl
+hsDeclName (InstD decl) = instDeclName decl
+hsDeclName (ForD decl) = foreignDeclName decl
+hsDeclName (FixD (FixitySig name _ _)) = name
-- Others don't make sense
#ifdef DEBUG
-hsDeclName x = pprPanic "HsDecls.hsDeclName" (ppr x)
+hsDeclName x = pprPanic "HsDecls.hsDeclName" (ppr x)
#endif
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)
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 <list> => as you would
- -- expect...
+ tcdCons :: DataConDetails (ConDecl name), -- data constructors (empty if abstract)
+ tcdDerivs :: Maybe (HsContext name), -- derivings; Nothing => not specified
+ -- Just [] => derive exactly what is asked
tcdSysNames :: DataSysNames name, -- Generic converter functions
tcdLoc :: SrcLoc
}
tcdSysNames :: ClassSysNames name,
tcdLoc :: SrcLoc
}
+ -- a Core value binding (coming from 'external Core' input.)
+ | CoreDecl { tcdName :: name,
+ tcdType :: HsType name,
+ tcdRhs :: UfExpr name,
+ tcdLoc :: SrcLoc
+ }
+
\end{code}
Simple classifiers
\begin{code}
-isIfaceSigDecl, isDataDecl, isSynDecl, isClassDecl :: TyClDecl name pat -> Bool
+isIfaceSigDecl, isCoreDecl, isDataDecl, isSynDecl, isClassDecl :: TyClDecl name pat -> Bool
isIfaceSigDecl (IfaceSig {}) = True
isIfaceSigDecl other = False
isClassDecl (ClassDecl {}) = True
isClassDecl other = False
+
+isTypeOrClassDecl (ClassDecl {}) = True
+isTypeOrClassDecl (TyData {}) = True
+isTypeOrClassDecl (TySynonym {}) = True
+isTypeOrClassDecl (ForeignType {}) = True
+isTypeOrClassDecl other = False
+
+isCoreDecl (CoreDecl {}) = True
+isCoreDecl other = False
+
\end{code}
Dealing with names
tyClDeclNames (TySynonym {tcdName = name, tcdLoc = loc}) = [(name,loc)]
tyClDeclNames (IfaceSig {tcdName = name, tcdLoc = loc}) = [(name,loc)]
+tyClDeclNames (CoreDecl {tcdName = name, tcdLoc = loc}) = [(name,loc)]
tyClDeclNames (ForeignType {tcdName = name, tcdLoc = loc}) = [(name,loc)]
tyClDeclNames (ClassDecl {tcdName = cls_name, tcdSigs = sigs, tcdLoc = loc})
tyClDeclTyVars (ClassDecl {tcdTyVars = tvs}) = tvs
tyClDeclTyVars (ForeignType {}) = []
tyClDeclTyVars (IfaceSig {}) = []
+tyClDeclTyVars (CoreDecl {}) = []
--------------------------------
tyClDeclSysNames (ClassDecl {tcdSysNames = names, tcdLoc = loc})
= [(n,loc) | n <- names]
-tyClDeclSysNames (TyData {tcdCons = cons, tcdSysNames = names, tcdLoc = loc})
+tyClDeclSysNames (TyData {tcdCons = DataCons cons, tcdSysNames = names, tcdLoc = loc})
= [(n,loc) | n <- names] ++
[(wkr_name,loc) | ConDecl _ wkr_name _ _ _ loc <- cons]
tyClDeclSysNames decl = []
tcdType d1 == tcdType d2 &&
tcdIdInfo d1 == tcdIdInfo d2
+ (==) d1@(CoreDecl {}) d2@(CoreDecl {})
+ = tcdName d1 == tcdName d2 &&
+ tcdType d1 == tcdType d2 &&
+ tcdRhs d1 == tcdRhs d2
+
(==) d1@(ForeignType {}) d2@(ForeignType {})
= tcdName d1 == tcdName d2 &&
tcdFoType d1 == tcdFoType 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)
+ eq_hsCD env (tcdCons d1) (tcdCons d2)
)
(==) d1@(TySynonym {}) d2@(TySynonym {})
(==) _ _ = 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
countTyClDecls :: [TyClDecl name pat] -> (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 (\ x -> isIfaceSigDecl x || isCoreDecl x) 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}
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 [ ppr_var var, dcolon, ppr ty, pprHsIdInfo info ]
ppr (ForeignType {tcdName = tycon})
= hsep [ptext SLIT("foreign import type dotnet"), ppr tycon]
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
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)
+ ppr (CoreDecl {tcdName = var, tcdType = ty, tcdRhs = rhs})
+ = getPprStyle $ \ sty ->
+ hsep [ ppr_var var, dcolon, ppr ty, ppr rhs ]
+
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 = 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}
\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
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
+-- ConDecls generated by MkIface.ifaceTyThing 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)
- = getPprStyle $ \ sty ->
- hsep ((if ifaceStyle sty then ppr con else ppr_var con)
- : map (ppr_bang) tys)
+ = hsep (ppr_var con : map (ppr_bang) tys)
ppr_con_details con (RecCon fields)
= ppr con <+> braces (sep (punctuate comma (map ppr_field fields)))
-- Nothing for source-file instance decls
SrcLoc
+
+isSourceInstDecl :: InstDecl name pat -> Bool
+isSourceInstDecl (InstDecl _ _ _ maybe_dfun _) = isNothing maybe_dfun
\end{code}
\begin{code}
=> Outputable (InstDecl name pat) 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
%************************************************************************
\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
+
+
+-- pretty printing of foreign declarations
+--
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
+ 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("\"<unused>\"")
instance Outputable FoType where
- ppr DNType = ptext SLIT("type dotnet")
+ ppr DNType = ptext SLIT("type dotnet")
\end{code}
= 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
+ [RuleBndr name] -- Forall'd vars; after typechecking this includes tyvars
(HsExpr name pat) -- LHS
(HsExpr name pat) -- RHS
SrcLoc
name -- Head of LHS
CoreRule
-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)
+ifaceRuleDeclName (HsRule fs _ _ _ _ _) = pprPanic "ifaceRuleDeclName" (ppr fs)
data RuleBndr name
= RuleBndr name
| RuleBndrSig name (HsType name)
+collectRuleBndrSigTys :: [RuleBndr name] -> [HsType name]
+collectRuleBndrSigTys bndrs = [ty | RuleBndrSig _ ty <- bndrs]
+
instance (NamedThing name, Ord name) => Eq (RuleDecl name pat) 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 _)
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,
+ ppr (HsRule name act ns lhs rhs loc)
+ = sep [text "{-# RULES" <+> doubleQuotes (ftext name) <+> ppr act,
pp_forall, ppr lhs, equals <+> ppr 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
\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
ppr (Deprecation thing txt _)