%
+% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
\section[HsBinds]{Abstract syntax: top-level bindings and signatures}
GRHSs, pprPatBind )
import {-# SOURCE #-} HsPat ( LPat )
-import HsTypes ( LHsType, PostTcType )
-import PprCore ( {- instances -} )
-import Coercion ( Coercion )
-import Type ( Type, pprParendType )
-import Name ( Name )
-import NameSet ( NameSet, elemNameSet )
-import BasicTypes ( IPName, RecFlag(..), InlineSpec(..), Fixity )
+import HsTypes
+import PprCore ()
+import Coercion
+import Type
+import Name
+import NameSet
+import BasicTypes
import Outputable
-import SrcLoc ( Located(..), SrcSpan, unLoc )
-import Util ( sortLe )
-import Var ( TyVar, DictId, Id )
-import Bag ( Bag, emptyBag, isEmptyBag, bagToList, unionBags, unionManyBags )
+import SrcLoc
+import Util
+import Var
+import Bag
\end{code}
%************************************************************************
-- Recursive by default
| ValBindsOut -- After renaming
- [(RecFlag, LHsBinds id)] -- Dependency analysed
+ [(RecFlag, LHsBinds id)] -- Dependency analysed, later bindings
+ -- in the list may depend on earlier
+ -- ones.
[LSig Name]
type LHsBinds id = Bag (LHsBind id)
fun_matches :: MatchGroup id, -- The payload
- fun_co_fn :: ExprCoFn, -- Coercion from the type of the MatchGroup to the type of
+ fun_co_fn :: HsWrapper, -- Coercion from the type of the MatchGroup to the type of
-- the Id. Example:
-- f :: Int -> forall a. a -> a
-- f x y = y
-- (with a free type variable a'). The coercion will take
-- a CoreExpr of this type and convert it to a CoreExpr of
-- type Int -> forall a'. a' -> a'
- -- Notice that the coercion captures the free a'. That's
- -- why coercions are (CoreExpr -> CoreExpr), rather than
- -- just CoreExpr (with a functional type)
+ -- Notice that the coercion captures the free a'.
- bind_fvs :: NameSet -- After the renamer, this contains a superset of the
+ bind_fvs :: NameSet, -- After the renamer, this contains a superset of the
-- Names of the other binders in this binding group that
-- are free in the RHS of the defn
-- Before renaming, and after typechecking,
-- the field is unused; it's just an error thunk
+
+ fun_tick :: Maybe (Int,[id]) -- This is the (optional) module-local tick number.
}
| PatBind { -- The pattern is never a simple variable;
| AbsBinds { -- Binds abstraction; TRANSLATION
abs_tvs :: [TyVar],
abs_dicts :: [DictId],
- abs_exports :: [([TyVar], id, id, [Prag])], -- (tvs, poly_id, mono_id, prags)
+ abs_exports :: [([TyVar], id, id, [LPrag])], -- (tvs, poly_id, mono_id, prags)
abs_binds :: LHsBinds id -- The dictionary bindings and typechecked user bindings
-- mixed up together; you can tell the dict bindings because
-- they are all VarBinds
ppr_monobind (PatBind { pat_lhs = pat, pat_rhs = grhss }) = pprPatBind pat grhss
ppr_monobind (VarBind { var_id = var, var_rhs = rhs }) = ppr var <+> equals <+> pprExpr (unLoc rhs)
-ppr_monobind (FunBind { fun_id = fun, fun_matches = matches }) = pprFunBind (unLoc fun) matches
+ppr_monobind (FunBind { fun_id = fun,
+ fun_matches = matches,
+ fun_tick = tick }) =
+ (case tick of
+ Nothing -> empty
+ Just t -> text "-- tick id = " <> ppr t
+ ) $$ pprFunBind (unLoc fun) matches
-- ToDo: print infix if appropriate
ppr_monobind (AbsBinds { abs_tvs = tyvars, abs_dicts = dictvars,
%************************************************************************
\begin{code}
--- A ExprCoFn is an expression with a hole in it
+-- A HsWrapper is an expression with a hole in it
-- We need coercions to have concrete form so that we can zonk them
-data ExprCoFn
- = CoHole -- The identity coercion
+data HsWrapper
+ = WpHole -- The identity coercion
- | CoCompose ExprCoFn ExprCoFn -- (\a1..an. []) `CoCompose` (\x1..xn. [])
+ | WpCompose HsWrapper HsWrapper -- (\a1..an. []) `WpCompose` (\x1..xn. [])
-- = (\a1..an \x1..xn. [])
- | ExprCoFn Coercion -- A cast: [] `cast` co
+ | WpCo Coercion -- A cast: [] `cast` co
-- Guaranteedn not the identity coercion
- -- Non-empty list in all of these, so that the identity coercion
- -- is always exactly CoHole, not, say, (CoTyLams [])
- | CoApps [Var] -- [] x1 .. xn; the xi are dicts or coercions
- | CoTyApps [Type] -- [] t1 .. tn
- | CoLams [Id] -- \x1..xn. []; the xi are dicts or coercions
- | CoTyLams [TyVar] -- \a1..an. []
- | CoLet (LHsBinds Id) -- let binds in []
- -- (ould be nicer to be core bindings)
-
-instance Outputable ExprCoFn where
- ppr CoHole = ptext SLIT("<>")
- ppr (ExprCoFn co) = ppr co
- ppr (CoApps ids) = ppr CoHole <+> interppSP ids
- ppr (CoTyApps tys) = ppr CoHole <+> hsep (map pprParendType tys)
- ppr (CoTyLams tvs) = sep [ptext SLIT("/\\") <> hsep (map (pprBndr LambdaBind) tvs),
- ptext SLIT("->") <+> ppr CoHole]
- ppr (CoLams ids) = sep [ptext SLIT("\\") <> hsep (map (pprBndr LambdaBind) ids),
- ptext SLIT("->") <+> ppr CoHole]
- ppr (CoLet binds) = sep [ptext SLIT("let") <+> braces (ppr binds),
- ppr CoHole]
- ppr (CoCompose co1 co2) = sep [ppr co1, ptext SLIT("<.>"), ppr co2]
-
-(<.>) :: ExprCoFn -> ExprCoFn -> ExprCoFn
-CoHole <.> c = c
-c <.> CoHole = c
-c1 <.> c2 = c1 `CoCompose` c2
-
-idCoercion :: ExprCoFn
-idCoercion = CoHole
-
-isIdCoercion :: ExprCoFn -> Bool
-isIdCoercion CoHole = True
-isIdCoercion other = False
+ | WpApp Var -- [] d the 'd' is a type-class dictionary
+ | WpTyApp Type -- [] t the 't' is a type or corecion
+ | WpLam Id -- \d. [] the 'd' is a type-class dictionary
+ | WpTyLam TyVar -- \a. [] the 'a' is a type or coercion variable
+
+ -- Non-empty bindings, so that the identity coercion
+ -- is always exactly WpHole
+ | WpLet (LHsBinds Id) -- let binds in []
+ -- (would be nicer to be core bindings)
+
+instance Outputable HsWrapper where
+ ppr co_fn = pprHsWrapper (ptext SLIT("<>")) co_fn
+
+pprHsWrapper :: SDoc -> HsWrapper -> SDoc
+pprHsWrapper it WpHole = it
+pprHsWrapper it (WpCompose f1 f2) = pprHsWrapper (pprHsWrapper it f2) f1
+pprHsWrapper it (WpCo co) = it <+> ptext SLIT("`cast`") <+> pprParendType co
+pprHsWrapper it (WpApp id) = it <+> ppr id
+pprHsWrapper it (WpTyApp ty) = it <+> ptext SLIT("@") <+> pprParendType ty
+pprHsWrapper it (WpLam id) = ptext SLIT("\\") <> pprBndr LambdaBind id <> dot <+> it
+pprHsWrapper it (WpTyLam tv) = ptext SLIT("/\\") <> pprBndr LambdaBind tv <> dot <+> it
+pprHsWrapper it (WpLet binds) = sep [ptext SLIT("let") <+> braces (ppr binds), it]
+
+(<.>) :: HsWrapper -> HsWrapper -> HsWrapper
+WpHole <.> c = c
+c <.> WpHole = c
+c1 <.> c2 = c1 `WpCompose` c2
+
+mkWpTyApps :: [Type] -> HsWrapper
+mkWpTyApps tys = mk_co_fn WpTyApp (reverse tys)
+
+mkWpApps :: [Id] -> HsWrapper
+mkWpApps ids = mk_co_fn WpApp (reverse ids)
+
+mkWpTyLams :: [TyVar] -> HsWrapper
+mkWpTyLams ids = mk_co_fn WpTyLam ids
+
+mkWpLams :: [Id] -> HsWrapper
+mkWpLams ids = mk_co_fn WpLam ids
+
+mk_co_fn :: (a -> HsWrapper) -> [a] -> HsWrapper
+mk_co_fn f as = foldr (WpCompose . f) WpHole as
+
+idHsWrapper :: HsWrapper
+idHsWrapper = WpHole
+
+isIdHsWrapper :: HsWrapper -> Bool
+isIdHsWrapper WpHole = True
+isIdHsWrapper other = False
\end{code}
\begin{code}
type LSig name = Located (Sig name)
-data Sig name
- = TypeSig (Located name) -- A bog-std type signature
+data Sig name -- Signatures and pragmas
+ = -- An ordinary type signature
+ -- f :: Num a => a -> a
+ TypeSig (Located name) -- A bog-std type signature
(LHsType name)
- | SpecSig (Located name) -- Specialise a function or datatype ...
- (LHsType name) -- ... to these types
- InlineSpec
+ -- An ordinary fixity declaration
+ -- infixl *** 8
+ | FixSig (FixitySig name) -- Fixity declaration
+ -- An inline pragma
+ -- {#- INLINE f #-}
| InlineSig (Located name) -- Function name
InlineSpec
+ -- A specialisation pragma
+ -- {-# SPECIALISE f :: Int -> Int #-}
+ | SpecSig (Located name) -- Specialise a function or datatype ...
+ (LHsType name) -- ... to these types
+ InlineSpec
+
+ -- A specialisation pragma for instance declarations only
+ -- {-# SPECIALISE instance Eq [Int] #-}
| SpecInstSig (LHsType name) -- (Class tys); should be a specialisation of the
-- current instance decl
- | FixSig (FixitySig name) -- Fixity declaration
type LFixitySig name = Located (FixitySig name)
data FixitySig name = FixitySig (Located name) Fixity
-- A Prag conveys pragmas from the type checker to the desugarer
+type LPrag = Located Prag
data Prag
= InlinePrag
InlineSpec
(HsExpr Id) -- An expression, of the given specialised type, which
PostTcType -- specialises the polymorphic function
[Id] -- Dicts mentioned free in the expression
+ -- Apr07: I think this is pretty useless
+ -- see Note [Const rule dicts] in DsBinds
InlineSpec -- Inlining spec for the specialised function
isInlinePrag (InlinePrag _) = True
isInlinePrag prag = False
-isSpecPrag (SpecPrag _ _ _ _) = True
-isSpecPrag prag = False
+isSpecPrag (SpecPrag {}) = True
+isSpecPrag prag = False
\end{code}
\begin{code}
Just n -> n `elemNameSet` ns
sigName :: LSig name -> Maybe name
-sigName (L _ sig) = f sig
- where
- f (TypeSig n _) = Just (unLoc n)
- f (SpecSig n _ _) = Just (unLoc n)
- f (InlineSig n _) = Just (unLoc n)
- f (FixSig (FixitySig n _)) = Just (unLoc n)
- f other = Nothing
+sigName (L _ sig) = sigNameNoLoc sig
+
+sigNameNoLoc :: Sig name -> Maybe name
+sigNameNoLoc (TypeSig n _) = Just (unLoc n)
+sigNameNoLoc (SpecSig n _ _) = Just (unLoc n)
+sigNameNoLoc (InlineSig n _) = Just (unLoc n)
+sigNameNoLoc (FixSig (FixitySig n _)) = Just (unLoc n)
+sigNameNoLoc other = Nothing
isFixityLSig :: LSig name -> Bool
isFixityLSig (L _ (FixSig {})) = True
pprSpec :: (Outputable id, Outputable ty) => id -> ty -> InlineSpec -> SDoc
pprSpec var ty inl = sep [ptext SLIT("SPECIALIZE") <+> ppr inl <+> pprVarSig var ty]
-pprPrag :: Outputable id => id -> Prag -> SDoc
-pprPrag var (InlinePrag inl) = ppr inl <+> ppr var
-pprPrag var (SpecPrag expr ty _ inl) = pprSpec var ty inl
+pprPrag :: Outputable id => id -> LPrag -> SDoc
+pprPrag var (L _ (InlinePrag inl)) = ppr inl <+> ppr var
+pprPrag var (L _ (SpecPrag expr ty _ inl)) = pprSpec var ty inl
\end{code}