[project @ 2000-02-10 18:39:51 by lewie]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcImprove.lhs
index a730a9a..dfe35dd 100644 (file)
@@ -3,152 +3,161 @@ module TcImprove ( tcImprove ) where
 
 #include "HsVersions.h"
 
-import Type            ( tyVarsOfTypes )
-import Class           ( classInstEnv, classExtraBigSig )
-import Unify           ( matchTys )
+import Name            ( Name )
+import Type            ( Type, tyVarsOfTypes )
+import Class           ( className, classInstEnv, classExtraBigSig )
+import Unify           ( unifyTyListsX, matchTys )
 import Subst           ( mkSubst, substTy )
 import TcMonad
 import TcType          ( zonkTcType, zonkTcTypes )
 import TcUnify         ( unifyTauTyLists )
 import Inst            ( Inst, LookupInstResult(..),
-                         lookupInst, isDict, getDictClassTys, getFunDeps,
-                         zonkLIE {- for debugging -} )
-import VarSet          ( emptyVarSet )
+                         lookupInst, getFunDepsOfLIE, getIPsOfLIE,
+                         zonkLIE, zonkFunDeps {- for debugging -} )
+import InstEnv         ( InstEnv )             -- Reqd for 4.02; InstEnv is a synonym, and
+                                               -- 4.02 doesn't "see" it soon enough
+import VarSet          ( VarSet, emptyVarSet, unionVarSet )
 import VarEnv          ( emptyVarEnv )
 import FunDeps         ( instantiateFdClassTys )
-import Bag             ( bagToList )
 import Outputable
-import List            ( elemIndex )
-import Maybe           ( catMaybes )
+import List            ( elemIndex, nub )
 \end{code}
 
-Improvement goes here.
-
 \begin{code}
-tcImprove lie
-  = let cfdss = catMaybes (map getFunDeps (bagToList lie)) in
-    iterImprove cfdss
-
+tcImprove lie =
+    if null cfdss then
+       returnTc ()
+    else
+       -- zonkCfdss cfdss `thenTc` \ cfdss' ->
+       -- pprTrace "tcI" (ppr cfdss') $
+       iterImprove nfdss
+    where
+       cfdss = getFunDepsOfLIE lie
+       clas_nfdss = map (\(c, fds) -> (emptyVarSet, className c, fds)) cfdss
+       classes = nub (map fst cfdss)
+       inst_nfdss = concatMap getInstNfdssOf classes
+       ips = getIPsOfLIE lie
+       ip_nfdss = map (\(n, ty) -> (emptyVarSet, n, [([], [ty])])) ips
+       nfdss = ip_nfdss ++ clas_nfdss ++ inst_nfdss
+
+getInstNfdssOf clas = nfdss
+    where
+       nm = className clas
+       ins = classInstEnv clas
+       mk_nfds (free, ts, i) = (free, nm, instantiateFdClassTys clas ts)
+       nfdss = map mk_nfds ins
+
+iterImprove :: [(VarSet, Name, [([Type],[Type])])] -> TcM s ()
+iterImprove [] = returnTc ()
 iterImprove cfdss
-  = instImprove cfdss                  `thenTc` \ change1 ->
+  = -- zonkCfdss cfdss `thenTc` \ cfdss' ->
+    -- pprTrace "iterI" (ppr cfdss') $
+    -- instImprove cfdss                       `thenTc` \ change1 ->
     selfImprove pairImprove cfdss      `thenTc` \ change2 ->
-    if change1 || change2 then
+    if {- change1 || -} change2 then
        iterImprove cfdss
     else
        returnTc ()
 
+-- ZZ debugging...
+zonkCfdss ((c, fds) : cfdss)
+  = zonkFunDeps fds `thenTc` \ fds' ->
+    zonkCfdss cfdss `thenTc` \ cfdss' ->
+    returnTc ((c, fds') : cfdss')
+zonkCfdss [] = returnTc []
+
+{-
 instImprove (cfds@(clas, fds) : cfdss)
-  = instImprove1 cfds ins
+  = instImprove1 cfds ins      `thenTc` \ changed ->
+    instImprove cfdss          `thenTc` \ rest_changed ->
+    returnTc (changed || rest_changed)
   where ins = classInstEnv clas
 instImprove [] = returnTc False
 
-instImprove1 cfds@(clas, fds1) ((free, ts, _) : ins)
-  = checkFds fds1 free fds2    `thenTc` \ changed ->
+instImprove1 cfds@(clas, fds1) ((free, ts, i) : ins)
+  = -- pprTrace "iI1" (ppr (free, ts, i)) $
+    checkFds fds1 free fds2    `thenTc` \ changed ->
     instImprove1 cfds ins      `thenTc` \ rest_changed ->
     returnTc (changed || rest_changed)
   where fds2 = instantiateFdClassTys clas ts
 instImprove1 _ _ = returnTc False
+-}
 
+-- ZZ this will do a lot of redundant checking wrt instances
+-- it would do to make this operate over two lists, the first
+-- with only clas_nfds and ip_nfds, and the second with everything
+-- control would otherwise mimic the current loop, so that the
+-- caller could control whether the redundant inst improvements
+-- were avoided
+-- you could then also use this to check for consistency of new instances
 selfImprove f [] = returnTc False
-selfImprove f (cfds : cfdss)
-  = mapTc (f cfds) cfdss       `thenTc` \ changes ->
-    orTc changes               `thenTc` \ changed ->
-    selfImprove f cfdss                `thenTc` \ rest_changed ->
+selfImprove f (nfds : nfdss)
+  = mapTc (f nfds) nfdss       `thenTc` \ changes ->
+    anyTc changes              `thenTc` \ changed ->
+    selfImprove f nfdss                `thenTc` \ rest_changed ->
     returnTc (changed || rest_changed)
 
-pairImprove (clas1, fds1) (clas2, fds2)
-  = if clas1 == clas2 then
-       checkFds fds1 emptyVarSet fds2
+pairImprove (free1, n1, fds1) (free2, n2, fds2)
+  = if n1 == n2 then
+       checkFds (free1 `unionVarSet` free2) fds1 fds2
     else
        returnTc False
 
-checkFds [] free [] = returnTc False
-checkFds (fd1 : fd1s) free (fd2 : fd2s) =
-    checkFd fd1 free fd2       `thenTc` \ change ->
-    checkFds fd1s free fd2s    `thenTc` \ changes ->
+checkFds free [] [] = returnTc False
+checkFds free (fd1 : fd1s) (fd2 : fd2s) =
+    checkFd free fd1 fd2       `thenTc` \ change ->
+    checkFds free fd1s fd2s    `thenTc` \ changes ->
     returnTc (change || changes)
 --checkFds _ _ = returnTc False
 
-checkFd (t_x, t_y) free (s_x, s_y)
+checkFd free (t_x, t_y) (s_x, s_y)
   -- we need to zonk each time because unification
   -- may happen at any time
-  = zonkMatchTys t_x free s_x `thenTc` \ msubst ->
+  = zonkUnifyTys free t_x s_x `thenTc` \ msubst ->
     case msubst of
       Just subst ->
-       let s_y' = map (substTy (mkSubst emptyVarEnv subst)) s_y in
-           zonkMatchTys t_y free s_y `thenTc` \ msubst2 ->
-               case msubst2 of
-                 Just _ ->
-                   -- they're the same, nothing changes
-                   returnTc False
-                 Nothing ->
-                   unifyTauTyLists t_y s_y' `thenTc_`
-                   -- if we get here, something must have unified
-                   returnTc True
+       let t_y' = map (substTy (mkSubst emptyVarEnv subst)) t_y
+           s_y' = map (substTy (mkSubst emptyVarEnv subst)) s_y
+       in
+           zonkEqTys t_y' s_y' `thenTc` \ eq ->
+           if eq then
+               -- they're the same, nothing changes...
+               returnTc False
+           else
+               -- ZZ what happens if two instance vars unify?
+               unifyTauTyLists t_y' s_y' `thenTc_`
+               -- if we get here, something must have unified
+               returnTc True
       Nothing ->
        returnTc False
 
+zonkEqTys ts1 ts2
+  = mapTc zonkTcType ts1 `thenTc` \ ts1' ->
+    mapTc zonkTcType ts2 `thenTc` \ ts2' ->
+    returnTc (ts1' == ts2')
+
 zonkMatchTys ts1 free ts2
   = mapTc zonkTcType ts1 `thenTc` \ ts1' ->
     mapTc zonkTcType ts2 `thenTc` \ ts2' ->
-    --returnTc (ts1' == ts2')
+    -- pprTrace "zMT" (ppr (ts1', free, ts2')) $
     case matchTys free ts2' ts1' of
-      Just (subst, []) -> returnTc (Just subst)
+      Just (subst, []) -> -- pprTrace "zMT match!" empty $
+                         returnTc (Just subst)
       Nothing -> returnTc Nothing
 
-{-
-instImprove clas fds =
-    pprTrace "class inst env" (ppr (clas, classInstEnv clas)) $
-    zonkFunDeps fds `thenTc` \ fds' ->
-    pprTrace "lIEFDs" (ppr (clas, fds')) $
-    case lookupInstEnvFDs clas fds' of
-      Nothing -> returnTc ()
-      Just (t_y, s_y) ->
-       pprTrace "lIEFDs result" (ppr (t_y, s_y)) $
-       unifyTauTyLists t_y s_y
-
-lookupInstEnvFDs clas fds
-  = find env
-  where
-    env = classInstEnv clas
-    (ctvs, fds, _, _, _, _) = classExtraBigSig clas
-    find [] = Nothing
-    find ((tpl_tyvars, tpl, val) : rest)
-      = let tplx = concatMap (\us -> thingy tpl us ctvs) (map fst fds)
-           tply = concatMap (\vs -> thingy tpl vs ctvs) (map snd fds)
-        in
-           case matchTys tpl_tyvars tplx tysx of
-             Nothing -> find rest
-             Just (tenv, leftovers) ->
-               let subst = mkSubst (tyVarsOfTypes tys) tenv
-               in
-                   -- this is the list of things that
-                   -- need to be unified
-                   Just (map (substTy subst) tply, tysy)
-    tysx = concatMap (\us -> thingy tys us ctvs) (map fst fds)
-    tysy = concatMap (\vs -> thingy tys vs ctvs) (map snd fds)
-    thingy f us ctvs
-      = map (f !!) is
-       where is = map (\u -> let Just i = elemIndex u ctvs in i) us
--}
-
-{-
-  = let (clas, tys) = getDictClassTys dict
-    in
-       -- first, do instance-based improvement
-       instImprove clas tys `thenTc_`
-       -- OK, now do pairwise stuff
-       mapTc (f clas tys) dicts `thenTc` \ changes ->
-       foldrTc (\a b -> returnTc (a || b)) False changes `thenTc` \ changed ->
-       allDictPairs f dicts `thenTc` \ rest_changed ->
-       returnTc (changed || rest_changed)
--}
-
+zonkUnifyTys free ts1 ts2
+  = mapTc zonkTcType ts1 `thenTc` \ ts1' ->
+    mapTc zonkTcType ts2 `thenTc` \ ts2' ->
+    -- pprTrace "zMT" (ppr (ts1', free, ts2')) $
+    case unifyTyListsX free ts2' ts1' of
+      Just subst {- (subst, []) -} -> -- pprTrace "zMT match!" empty $
+                         returnTc (Just subst)
+      Nothing -> returnTc Nothing
 \end{code}
 
 Utilities:
 
 A monadic version of the standard Prelude `or' function.
 \begin{code}
-orTc bs = foldrTc (\a b -> returnTc (a || b)) False bs
+anyTc bs = foldrTc (\a b -> returnTc (a || b)) False bs
 \end{code}