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,
+ isClassDecl, isSynDecl, isDataDecl, isIfaceSigDecl, isCoreDecl,
+ isTypeOrClassDecl, countTyClDecls,
mkClassDeclSysNames, isSourceInstDecl, ifaceRuleDeclName,
getClassDeclSysNames, conDetailsTys,
collectRuleBndrSigTys
)
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
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)
+ 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
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 decls
= (count isClassDecl decls,
count isSynDecl decls,
- count isIfaceSigDecl decls,
+ count (\ x -> isIfaceSigDecl x || isCoreDecl x) decls,
count isDataTy decls,
count isNewTy decls)
where
ppr (IfaceSig {tcdName = var, tcdType = ty, tcdIdInfo = info})
= getPprStyle $ \ sty ->
- hsep [ if ifaceStyle sty then ppr var else ppr_var var,
- dcolon, ppr ty, pprHsIdInfo info
- ]
+ hsep [ 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 [
\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
-- 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)))
=> 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}
instance (NamedThing name, Outputable name, Outputable pat)
=> Outputable (RuleDecl name pat) where
ppr (HsRule name act ns lhs rhs loc)
- = sep [text "{-# RULES" <+> doubleQuotes (ptext name) <+> ppr act,
+ = sep [text "{-# RULES" <+> doubleQuotes (ftext name) <+> ppr act,
pp_forall, ppr lhs, equals <+> ppr rhs,
text "#-}" ]
where
| 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 _)