X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2FhsSyn%2FHsBinds.lhs;h=f8afd262fe5b4a5585b5d262e5428ec3fd09c7da;hp=5709e582386a7578befe1f76452bc8b9bff1cd3c;hb=d2ce0f52d42edf32bb9f13796e6ba6edba8bd516;hpb=0084ab49ab3c0123c4b7f9523d092af45bccfd41 diff --git a/compiler/hsSyn/HsBinds.lhs b/compiler/hsSyn/HsBinds.lhs index 5709e58..f8afd26 100644 --- a/compiler/hsSyn/HsBinds.lhs +++ b/compiler/hsSyn/HsBinds.lhs @@ -32,10 +32,13 @@ import BasicTypes import Outputable import SrcLoc import Util +import VarEnv import Var import Bag +import Unique import FastString +import Data.IORef( IORef ) import Data.Data hiding ( Fixity ) \end{code} @@ -77,10 +80,9 @@ data HsValBindsLR idL idR -- Value bindings (not implicit parameters) [LSig Name] deriving (Data, Typeable) -type LHsBinds id = Bag (LHsBind id) -type DictBinds id = LHsBinds id -- Used for dictionary or method bindings -type LHsBind id = Located (HsBind id) -type HsBind id = HsBindLR id id +type LHsBinds id = Bag (LHsBind id) +type LHsBind id = Located (HsBind id) +type HsBind id = HsBindLR id id type LHsBindLR idL idR = Located (HsBindLR idL idR) type LHsBindsLR idL idR = Bag (LHsBindLR idL idR) @@ -123,7 +125,7 @@ data HsBindLR idL idR -- Before renaming, and after typechecking, -- the field is unused; it's just an error thunk - fun_tick :: Maybe (Int,[idR]) -- ^ This is the (optional) module-local tick number. + fun_tick :: Maybe (Int,[Id]) -- ^ This is the (optional) module-local tick number. } | PatBind { -- The pattern is never a simple variable; @@ -141,17 +143,17 @@ data HsBindLR idL idR -- (used for implication constraints only) } - | AbsBinds { -- Binds abstraction; TRANSLATION + | AbsBinds { -- Binds abstraction; TRANSLATION abs_tvs :: [TyVar], - abs_dicts :: [DictId], -- Includes equality constraints + abs_ev_vars :: [EvVar], -- Includes equality constraints -- AbsBinds only gets used when idL = idR after renaming, -- but these need to be idL's for the collect... code in HsUtil to have -- the right type abs_exports :: [([TyVar], idL, idL, TcSpecPrags)], -- (tvs, poly_id, mono_id, prags) - abs_binds :: LHsBinds idL -- The dictionary bindings and typechecked user bindings - -- mixed up together; you can tell the dict bindings because - -- they are all VarBinds + + abs_ev_binds :: TcEvBinds, -- Evidence bindings + abs_binds :: LHsBinds idL -- Typechecked user bindings } deriving (Data, Typeable) -- Consider (AbsBinds tvs ds [(ftvs, poly_f, mono_f) binds] @@ -285,7 +287,7 @@ ppr_monobind (FunBind { fun_id = fun, fun_infix = inf, Just t -> text "-- tick id = " <> ppr t) $$ pprFunBind (unLoc fun) inf matches -ppr_monobind (AbsBinds { abs_tvs = tyvars, abs_dicts = dictvars, +ppr_monobind (AbsBinds { abs_tvs = tyvars, abs_ev_vars = dictvars, abs_exports = exports, abs_binds = val_binds }) = sep [ptext (sLit "AbsBinds"), brackets (interpp'SP tyvars), @@ -321,12 +323,12 @@ pprTicks pp_no_debug pp_when_debug data HsIPBinds id = IPBinds [LIPBind id] - (DictBinds id) -- Only in typechecker output; binds + TcEvBinds -- Only in typechecker output; binds -- uses of the implicit parameters deriving (Data, Typeable) isEmptyIPBinds :: HsIPBinds id -> Bool -isEmptyIPBinds (IPBinds is ds) = null is && isEmptyBag ds +isEmptyIPBinds (IPBinds is ds) = null is && isEmptyTcEvBinds ds type LIPBind id = Located (IPBind id) @@ -339,7 +341,7 @@ data IPBind id instance (OutputableBndr id) => Outputable (HsIPBinds id) where ppr (IPBinds bs ds) = pprDeeperList vcat (map ppr bs) - $$ pprLHsBinds ds + $$ ppr ds instance (OutputableBndr id) => Outputable (IPBind id) where ppr (IPBind id rhs) = pprBndr LetBind id <+> equals <+> pprExpr (unLoc rhs) @@ -359,65 +361,148 @@ instance (OutputableBndr id) => Outputable (IPBind id) where data HsWrapper = WpHole -- The identity coercion - | WpCompose HsWrapper HsWrapper -- (\a1..an. []) `WpCompose` (\x1..xn. []) - -- = (\a1..an \x1..xn. []) + | WpCompose HsWrapper HsWrapper + -- (wrap1 `WpCompse` wrap2)[e] = wrap1[ wrap2[ e ]] + -- + -- Hence (\a. []) `WpCompose` (\b. []) = (\a b. []) + -- But ([] a) `WpCompose` ([] b) = ([] b a) | WpCast Coercion -- A cast: [] `cast` co -- Guaranteed not the identity coercion - | WpApp Var -- [] d the 'd' is a type-class dictionary or coercion variable - - | WpTyApp Type -- [] t the 't' is a type or corecion - -- ToDo: it'd be tidier if 't' was always a type (not coercion), - -- but that is inconvenient in Inst.instCallDicts + -- Evidence abstraction and application + -- (both dictionaries and coercions) + | WpEvLam EvVar -- \d. [] the 'd' is an evidence variable + | WpEvApp EvTerm -- [] d the 'd' is evidence for a constraint - | WpLam Var -- \d. [] the 'd' is a type-class dictionary or coercion variable + -- Type abstraction and application | WpTyLam TyVar -- \a. [] the 'a' is a type variable (not coercion var) + | WpTyApp Type -- [] t the 't' is a type (not coercion) + - -- 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) + | WpLet TcEvBinds -- Non-empty (or possibly non-empty) evidence bindings, + -- so that the identity coercion is always exactly WpHole deriving (Data, Typeable) -instance Outputable HsWrapper where - ppr co_fn = pprHsWrapper (ptext (sLit "<>")) co_fn -pprHsWrapper :: SDoc -> HsWrapper -> SDoc -pprHsWrapper it wrap = - let - help it WpHole = it - help it (WpCompose f1 f2) = help (help it f2) f1 - help it (WpCast co) = sep [it, nest 2 (ptext (sLit "`cast`") <+> pprParendType co)] - help it (WpApp id) = sep [it, nest 2 (ppr id)] - help it (WpTyApp ty) = sep [it, ptext (sLit "@") <+> pprParendType ty] - help it (WpLam id) = sep [ptext (sLit "\\") <> pprBndr LambdaBind id <> dot, it] - help it (WpTyLam tv) = sep [ptext (sLit "/\\") <> pprBndr LambdaBind tv <> dot, it] - help it (WpLet binds) = sep [ptext (sLit "let") <+> braces (ppr binds), it] - in - -- in debug mode, print the wrapper - -- otherwise just print what's inside - getPprStyle (\ s -> if debugStyle s then (help it wrap) else it) +data TcEvBinds + = TcEvBinds -- Mutable evidence bindings + EvBindsVar -- Mutable because they are updated "later" + -- when an implication constraint is solved + + | EvBinds -- Immutable after zonking + (Bag EvBind) + + deriving( Typeable ) + +data EvBindsVar = EvBindsVar (IORef EvBindMap) Unique + -- The Unique is only for debug printing + +----------------- +type EvBindMap = VarEnv EvBind + +emptyEvBindMap :: EvBindMap +emptyEvBindMap = emptyVarEnv + +extendEvBinds :: EvBindMap -> EvVar -> EvTerm -> EvBindMap +extendEvBinds bs v t = extendVarEnv bs v (EvBind v t) + +lookupEvBind :: EvBindMap -> EvVar -> Maybe EvBind +lookupEvBind = lookupVarEnv + +evBindMapBinds :: EvBindMap -> Bag EvBind +evBindMapBinds = foldVarEnv consBag emptyBag + +----------------- +instance Data TcEvBinds where + -- Placeholder; we can't travers into TcEvBinds + toConstr _ = abstractConstr "TcEvBinds" + gunfold _ _ = error "gunfold" + dataTypeOf _ = mkNoRepType "TcEvBinds" + +-- All evidence is bound by EvBinds; no side effects +data EvBind = EvBind EvVar EvTerm + +data EvTerm + = EvId EvId -- Term-level variable-to-variable bindings + -- (no coercion variables! they come via EvCoercion) + + | EvCoercion Coercion -- Coercion bindings + + | EvCast EvVar Coercion -- d |> co + + | EvDFunApp DFunId -- Dictionary instance application + [Type] [EvVar] + | EvSuperClass DictId Int -- n'th superclass. Used for both equalities and + -- dictionaries, even though the former have no + -- selector Id. We count up from _0_ + + deriving( Data, Typeable) + +evVarTerm :: EvVar -> EvTerm +evVarTerm v | isCoVar v = EvCoercion (mkCoVarCoercion v) + | otherwise = EvId v +\end{code} + +Note [EvBinds/EvTerm] +~~~~~~~~~~~~~~~~~~~~~ +How evidence is created and updated. Bindings for dictionaries, +and coercions and implicit parameters are carried around in TcEvBinds +which during constraint generation and simplification is always of the +form (TcEvBinds ref). After constraint simplification is finished it +will be transformed to t an (EvBinds ev_bag). + +Evidence for coercions *SHOULD* be filled in using the TcEvBinds +However, all EvVars that correspond to *wanted* coercion terms in +an EvBind must be mutable variables so that they can be readily +inlined (by zonking) after constraint simplification is finished. + +Conclusion: a new wanted coercion variable should be made mutable. +[Notice though that evidence variables that bind coercion terms + from super classes will be "given" and hence rigid] + + +\begin{code} +emptyTcEvBinds :: TcEvBinds +emptyTcEvBinds = EvBinds emptyBag + +isEmptyTcEvBinds :: TcEvBinds -> Bool +isEmptyTcEvBinds (EvBinds b) = isEmptyBag b +isEmptyTcEvBinds (TcEvBinds {}) = panic "isEmptyTcEvBinds" + (<.>) :: 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) +mkWpTyApps tys = mk_co_app_fn WpTyApp tys + +mkWpEvApps :: [EvTerm] -> HsWrapper +mkWpEvApps args = mk_co_app_fn WpEvApp args -mkWpApps :: [Var] -> HsWrapper -mkWpApps ids = mk_co_fn WpApp (reverse ids) +mkWpEvVarApps :: [EvVar] -> HsWrapper +mkWpEvVarApps vs = mkWpEvApps (map evVarTerm vs) mkWpTyLams :: [TyVar] -> HsWrapper -mkWpTyLams ids = mk_co_fn WpTyLam ids +mkWpTyLams ids = mk_co_lam_fn WpTyLam ids mkWpLams :: [Var] -> HsWrapper -mkWpLams ids = mk_co_fn WpLam ids +mkWpLams ids = mk_co_lam_fn WpEvLam ids -mk_co_fn :: (a -> HsWrapper) -> [a] -> HsWrapper -mk_co_fn f as = foldr (WpCompose . f) WpHole as +mkWpLet :: TcEvBinds -> HsWrapper +-- This no-op is a quite a common case +mkWpLet (EvBinds b) | isEmptyBag b = WpHole +mkWpLet ev_binds = WpLet ev_binds + +mk_co_lam_fn :: (a -> HsWrapper) -> [a] -> HsWrapper +mk_co_lam_fn f as = foldr (\x wrap -> f x `WpCompose` wrap) WpHole as + +mk_co_app_fn :: (a -> HsWrapper) -> [a] -> HsWrapper +-- For applications, the *first* argument must +-- come *last* in the composition sequence +mk_co_app_fn f as = foldr (\x wrap -> wrap `WpCompose` f x) WpHole as idHsWrapper :: HsWrapper idHsWrapper = WpHole @@ -427,6 +512,45 @@ isIdHsWrapper WpHole = True isIdHsWrapper _ = False \end{code} +Pretty printing + +\begin{code} +instance Outputable HsWrapper where + ppr co_fn = pprHsWrapper (ptext (sLit "<>")) co_fn + +pprHsWrapper :: SDoc -> HsWrapper -> SDoc +-- In debug mode, print the wrapper +-- otherwise just print what's inside +pprHsWrapper it wrap + = getPprStyle (\ s -> if debugStyle s then (help it wrap) else it) + where + help it WpHole = it + help it (WpCompose f1 f2) = help (help it f2) f1 + help it (WpCast co) = sep [it, nest 2 (ptext (sLit "`cast`") <+> pprParendType co)] + help it (WpEvApp id) = sep [it, nest 2 (ppr id)] + help it (WpTyApp ty) = sep [it, ptext (sLit "@") <+> pprParendType ty] + help it (WpEvLam id) = sep [ptext (sLit "\\") <> pprBndr LambdaBind id <> dot, it] + help it (WpTyLam tv) = sep [ptext (sLit "/\\") <> pprBndr LambdaBind tv <> dot, it] + help it (WpLet binds) = sep [ptext (sLit "let") <+> braces (ppr binds), it] + +instance Outputable TcEvBinds where + ppr (TcEvBinds v) = ppr v + ppr (EvBinds bs) = ptext (sLit "EvBinds") <> braces (ppr bs) + +instance Outputable EvBindsVar where + ppr (EvBindsVar _ u) = ptext (sLit "EvBindsVar") <> angleBrackets (ppr u) + +instance Outputable EvBind where + ppr (EvBind v e) = ppr v <+> equals <+> ppr e + +instance Outputable EvTerm where + ppr (EvId v) = ppr v + ppr (EvCast v co) = ppr v <+> (ptext (sLit "`cast`")) <+> pprParendType co + ppr (EvCoercion co) = ppr co + ppr (EvSuperClass d n) = ptext (sLit "sc") <> parens (ppr (d,n)) + ppr (EvDFunApp df tys ts) = ppr df <+> sep [ char '@' <> ppr tys + , ppr ts ] +\end{code} %************************************************************************ %* *