c7e951f343fa17a9d0e3de1bc9ae6fb87a9f2fca
[ghc-hetmet.git] / compiler / typecheck / TcRules.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1993-1998
3 %
4 \section[TcRules]{Typechecking transformation rules}
5
6 \begin{code}
7 module TcRules ( tcRules ) where
8
9 #include "HsVersions.h"
10
11 import HsSyn            ( RuleDecl(..), LRuleDecl, RuleBndr(..), mkHsDictLet )
12 import TcRnMonad
13 import TcSimplify       ( tcSimplifyRuleLhs, tcSimplifyInferCheck )
14 import TcMType          ( newFlexiTyVarTy, zonkQuantifiedTyVar, tcSkolSigTyVars )
15 import TcType           ( tyVarsOfTypes, openTypeKind, SkolemInfo(..), substTyWith, mkTyVarTys )
16 import TcHsType         ( UserTypeCtxt(..), tcHsPatSigType )
17 import TcExpr           ( tcMonoExpr )
18 import TcEnv            ( tcExtendIdEnv, tcExtendTyVarEnv )
19 import Inst             ( instToId )
20 import Id               ( idType, mkLocalId )
21 import Name             ( Name )
22 import SrcLoc           ( noLoc, unLoc )
23 import Outputable
24 \end{code}
25
26 \begin{code}
27 tcRules :: [LRuleDecl Name] -> TcM [LRuleDecl TcId]
28 tcRules decls = mappM (wrapLocM tcRule) decls
29
30 tcRule :: RuleDecl Name -> TcM (RuleDecl TcId)
31 tcRule (HsRule name act vars lhs fv_lhs rhs fv_rhs)
32   = addErrCtxt (ruleCtxt name)                  $
33     traceTc (ptext SLIT("---- Rule ------")
34                  <+> ppr name)                  `thenM_` 
35     newFlexiTyVarTy openTypeKind                `thenM` \ rule_ty ->
36
37         -- Deal with the tyvars mentioned in signatures
38     tcRuleBndrs vars (\ ids ->
39                 -- Now LHS and RHS
40         getLIE (tcMonoExpr lhs rule_ty) `thenM` \ (lhs', lhs_lie) ->
41         getLIE (tcMonoExpr rhs rule_ty) `thenM` \ (rhs', rhs_lie) ->
42         returnM (ids, lhs', rhs', lhs_lie, rhs_lie)
43     )                           `thenM` \ (ids, lhs', rhs', lhs_lie, rhs_lie) ->
44
45                 -- Check that LHS has no overloading at all
46     tcSimplifyRuleLhs lhs_lie   `thenM` \ (lhs_dicts, lhs_binds) ->
47
48         -- Gather the template variables and tyvars
49     let
50         tpl_ids = map instToId lhs_dicts ++ ids
51
52         -- IMPORTANT!  We *quantify* over any dicts that appear in the LHS
53         -- Reason: 
54         --      a) The particular dictionary isn't important, because its value
55         --         depends only on the type
56         --              e.g     gcd Int $fIntegralInt
57         --         Here we'd like to match against (gcd Int any_d) for any 'any_d'
58         --
59         --      b) We'd like to make available the dictionaries bound 
60         --         on the LHS in the RHS, so quantifying over them is good
61         --         See the 'lhs_dicts' in tcSimplifyAndCheck for the RHS
62
63         -- We initially quantify over any tyvars free in *either* the rule
64         --  *or* the bound variables.  The latter is important.  Consider
65         --      ss (x,(y,z)) = (x,z)
66         --      RULE:  forall v. fst (ss v) = fst v
67         -- The type of the rhs of the rule is just a, but v::(a,(b,c))
68         --
69         -- We also need to get the free tyvars of the LHS; but we do that
70         -- during zonking (see TcHsSyn.zonkRule)
71         --
72         forall_tvs = tyVarsOfTypes (rule_ty : map idType tpl_ids)
73     in
74         -- RHS can be a bit more lenient.  In particular,
75         -- we let constant dictionaries etc float outwards
76         --
77         -- NB: tcSimplifyInferCheck zonks the forall_tvs, and 
78         --     knocks out any that are constrained by the environment
79     tcSimplifyInferCheck (text "tcRule")
80                          forall_tvs
81                          lhs_dicts rhs_lie      `thenM` \ (forall_tvs1, rhs_binds) ->
82     mappM zonkQuantifiedTyVar forall_tvs1       `thenM` \ forall_tvs2 ->
83         -- This zonk is exactly the same as the one in TcBinds.tcBindWithSigs
84
85     returnM (HsRule name act
86                     (map (RuleBndr . noLoc) (forall_tvs2 ++ tpl_ids))   -- yuk
87                     (mkHsDictLet lhs_binds lhs') fv_lhs
88                     (mkHsDictLet rhs_binds rhs') fv_rhs)
89
90
91 tcRuleBndrs [] thing_inside = thing_inside []
92 tcRuleBndrs (RuleBndr var : vars) thing_inside
93   = do  { ty <- newFlexiTyVarTy openTypeKind
94         ; let id = mkLocalId (unLoc var) ty
95         ; tcExtendIdEnv [id] $
96           tcRuleBndrs vars (\ids -> thing_inside (id:ids)) }
97 tcRuleBndrs (RuleBndrSig var rn_ty : vars) thing_inside
98 --  e.g         x :: a->a
99 --  The tyvar 'a' is brought into scope first, just as if you'd written
100 --              a::*, x :: a->a
101   = do  { let ctxt = RuleSigCtxt (unLoc var)
102         ; (tyvars, ty) <- tcHsPatSigType ctxt rn_ty
103         ; let skol_tvs = tcSkolSigTyVars (SigSkol ctxt) tyvars
104               id_ty = substTyWith tyvars (mkTyVarTys skol_tvs) ty
105               id = mkLocalId (unLoc var) id_ty
106         ; tcExtendTyVarEnv skol_tvs $
107           tcExtendIdEnv [id] $
108           tcRuleBndrs vars (\ids -> thing_inside (id:ids)) }
109
110 ruleCtxt name = ptext SLIT("When checking the transformation rule") <+> 
111                 doubleQuotes (ftext name)
112 \end{code}
113
114
115
116