[project @ 1999-05-18 15:03:54 by simonpj]
[ghc-hetmet.git] / ghc / compiler / types / Unify.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section{Unify}
5
6 This module contains a unifier and a matcher, both of which
7 use an explicit substitution
8
9 \begin{code}
10 module Unify ( unifyTysX, unifyTyListsX,
11                match, matchTy, matchTys
12   ) where 
13
14 import Type     ( Type(..), funTyCon, typeKind, tyVarsOfType,
15                   splitAppTy_maybe
16                 )
17
18 import Var      ( TyVar, tyVarKind )
19 import VarSet
20 import VarEnv   ( TyVarSubstEnv, emptySubstEnv, lookupSubstEnv, extendSubstEnv, 
21                   SubstResult(..)
22                 )
23
24 import Unique   ( Uniquable(..) )
25 import Outputable( panic )
26 import Util     ( snocView )
27 \end{code}
28
29 %************************************************************************
30 %*                                                                      *
31 \subsection{Unification wih a explicit substitution}
32 %*                                                                      *
33 %************************************************************************
34
35 Unify types with an explicit substitution and no monad.
36
37 \begin{code}
38 type MySubst
39    = (TyVarSet,         -- Set of template tyvars
40       TyVarSubstEnv)    -- Not necessarily idempotent
41
42 unifyTysX :: TyVarSet           -- Template tyvars
43           -> Type
44           -> Type
45           -> Maybe TyVarSubstEnv
46 unifyTysX tmpl_tyvars ty1 ty2
47   = uTysX ty1 ty2 (\(_,s) -> Just s) (tmpl_tyvars, emptySubstEnv)
48
49 unifyTyListsX :: TyVarSet -> [Type] -> [Type]
50               -> Maybe TyVarSubstEnv
51 unifyTyListsX tmpl_tyvars tys1 tys2
52   = uTyListsX tys1 tys2 (\(_,s) -> Just s) (tmpl_tyvars, emptySubstEnv)
53
54
55 uTysX :: Type
56       -> Type
57       -> (MySubst -> Maybe result)
58       -> MySubst
59       -> Maybe result
60
61 uTysX (NoteTy _ ty1) ty2 k subst = uTysX ty1 ty2 k subst
62 uTysX ty1 (NoteTy _ ty2) k subst = uTysX ty1 ty2 k subst
63
64         -- Variables; go for uVar
65 uTysX (TyVarTy tyvar1) (TyVarTy tyvar2) k subst 
66   | tyvar1 == tyvar2
67   = k subst
68 uTysX (TyVarTy tyvar1) ty2 k subst@(tmpls,_)
69   | tyvar1 `elemVarSet` tmpls
70   = uVarX tyvar1 ty2 k subst
71 uTysX ty1 (TyVarTy tyvar2) k subst@(tmpls,_)
72   | tyvar2 `elemVarSet` tmpls
73   = uVarX tyvar2 ty1 k subst
74
75         -- Functions; just check the two parts
76 uTysX (FunTy fun1 arg1) (FunTy fun2 arg2) k subst
77   = uTysX fun1 fun2 (uTysX arg1 arg2 k) subst
78
79         -- Type constructors must match
80 uTysX (TyConApp con1 tys1) (TyConApp con2 tys2) k subst
81   | (con1 == con2 && length tys1 == length tys2)
82   = uTyListsX tys1 tys2 k subst
83
84         -- Applications need a bit of care!
85         -- They can match FunTy and TyConApp, so use splitAppTy_maybe
86         -- NB: we've already dealt with type variables and Notes,
87         -- so if one type is an App the other one jolly well better be too
88 uTysX (AppTy s1 t1) ty2 k subst
89   = case splitAppTy_maybe ty2 of
90       Just (s2, t2) -> uTysX s1 s2 (uTysX t1 t2 k) subst
91       Nothing       -> Nothing    -- Fail
92
93 uTysX ty1 (AppTy s2 t2) k subst
94   = case splitAppTy_maybe ty1 of
95       Just (s1, t1) -> uTysX s1 s2 (uTysX t1 t2 k) subst
96       Nothing       -> Nothing    -- Fail
97
98         -- Not expecting for-alls in unification
99 #ifdef DEBUG
100 uTysX (ForAllTy _ _) ty2 k subst = panic "Unify.uTysX subst:ForAllTy (1st arg)"
101 uTysX ty1 (ForAllTy _ _) k subst = panic "Unify.uTysX subst:ForAllTy (2nd arg)"
102 #endif
103
104         -- Anything else fails
105 uTysX ty1 ty2 k subst = Nothing
106
107
108 uTyListsX []         []         k subst = k subst
109 uTyListsX (ty1:tys1) (ty2:tys2) k subst = uTysX ty1 ty2 (uTyListsX tys1 tys2 k) subst
110 uTyListsX tys1       tys2       k subst = Nothing   -- Fail if the lists are different lengths
111 \end{code}
112
113 \begin{code}
114 -- Invariant: tv1 is a unifiable variable
115 uVarX tv1 ty2 k subst@(tmpls, env)
116   = case lookupSubstEnv env tv1 of
117       Just (DoneTy ty1) ->    -- Already bound
118                      uTysX ty1 ty2 k subst
119
120       Nothing        -- Not already bound
121                |  typeKind ty2 == tyVarKind tv1
122                && occur_check_ok ty2
123                ->     -- No kind mismatch nor occur check
124                   k (tmpls, extendSubstEnv env tv1 (DoneTy ty2))
125
126                | otherwise -> Nothing   -- Fail if kind mis-match or occur check
127   where
128     occur_check_ok ty = all occur_check_ok_tv (varSetElems (tyVarsOfType ty))
129     occur_check_ok_tv tv | tv1 == tv = False
130                          | otherwise = case lookupSubstEnv env tv of
131                                          Nothing           -> True
132                                          Just (DoneTy ty)  -> occur_check_ok ty
133 \end{code}
134
135
136
137 %************************************************************************
138 %*                                                                      *
139 \subsection{Matching on types}
140 %*                                                                      *
141 %************************************************************************
142
143 Matching is a {\em unidirectional} process, matching a type against a
144 template (which is just a type with type variables in it).  The
145 matcher assumes that there are no repeated type variables in the
146 template, so that it simply returns a mapping of type variables to
147 types.  It also fails on nested foralls.
148
149 @matchTys@ matches corresponding elements of a list of templates and
150 types.
151
152 \begin{code}
153 matchTy :: TyVarSet                     -- Template tyvars
154         -> Type                         -- Template
155         -> Type                         -- Proposed instance of template
156         -> Maybe TyVarSubstEnv          -- Matching substitution
157                                         
158
159 matchTys :: TyVarSet                    -- Template tyvars
160          -> [Type]                      -- Templates
161          -> [Type]                      -- Proposed instance of template
162          -> Maybe (TyVarSubstEnv,               -- Matching substitution
163                    [Type])              -- Left over instance types
164
165 matchTy tmpls ty1 ty2 = match ty1 ty2 tmpls (\ senv -> Just senv) emptySubstEnv
166
167 matchTys tmpls tys1 tys2 = match_list tys1 tys2 tmpls 
168                                       (\ (senv,tys) -> Just (senv,tys))
169                                       emptySubstEnv
170 \end{code}
171
172 @match@ is the main function.
173
174 \begin{code}
175 match :: Type -> Type                           -- Current match pair
176       -> TyVarSet                               -- Template vars
177       -> (TyVarSubstEnv -> Maybe result)        -- Continuation
178       -> TyVarSubstEnv                          -- Current subst
179       -> Maybe result
180
181 -- When matching against a type variable, see if the variable
182 -- has already been bound.  If so, check that what it's bound to
183 -- is the same as ty; if not, bind it and carry on.
184
185 match (TyVarTy v) ty tmpls k senv
186   | v `elemVarSet` tmpls
187   =     -- v is a template variable
188     case lookupSubstEnv senv v of
189         Nothing -> k (extendSubstEnv senv v (DoneTy ty))
190         Just (DoneTy ty')  | ty' == ty         -> k senv   -- Succeeds
191                            | otherwise         -> Nothing  -- Fails
192
193   | otherwise
194   =     -- v is not a template variable; ty had better match
195         -- Can't use (==) because types differ
196     case ty of
197         TyVarTy v' | v == v' -> k senv    -- Success
198         other                -> Nothing   -- Failure
199
200 match (FunTy arg1 res1) (FunTy arg2 res2) tmpls k senv
201   = match arg1 arg2 tmpls (match res1 res2 tmpls k) senv
202
203 match (AppTy fun1 arg1) ty2 tmpls k senv 
204   = case splitAppTy_maybe ty2 of
205         Just (fun2,arg2) -> match fun1 fun2 tmpls (match arg1 arg2 tmpls k) senv
206         Nothing          -> Nothing     -- Fail
207
208 match (TyConApp tc1 tys1) (TyConApp tc2 tys2) tmpls k senv
209   | tc1 == tc2
210   = match_list tys1 tys2 tmpls k' senv
211   where
212     k' (senv', tys2') | null tys2' = k senv'    -- Succeed
213                       | otherwise  = Nothing    -- Fail 
214
215         -- With type synonyms, we have to be careful for the exact
216         -- same reasons as in the unifier.  Please see the
217         -- considerable commentary there before changing anything
218         -- here! (WDP 95/05)
219 match (NoteTy _ ty1) ty2            tmpls k senv = match ty1 ty2 tmpls k senv
220 match ty1            (NoteTy _ ty2) tmpls k senv = match ty1 ty2 tmpls k senv
221
222 -- Catch-all fails
223 match _ _ _ _ _ = Nothing
224
225 match_list []         tys2       tmpls k senv = k (senv, tys2)
226 match_list (ty1:tys1) []         tmpls k senv = Nothing -- Not enough arg tys => failure
227 match_list (ty1:tys1) (ty2:tys2) tmpls k senv = match ty1 ty2 tmpls (match_list tys1 tys2 tmpls k) senv
228 \end{code}
229