Clean up for code conventions & add some comment
[ghc-hetmet.git] / compiler / ghci / RtClosureInspect.hs
index 7c144c0..bc6cc47 100644 (file)
@@ -22,7 +22,10 @@ module RtClosureInspect(
      isFullyEvaluated, 
      isPointed,
      isFullyEvaluatedTerm,
+     mapTermType,
+     termTyVars,
 --     unsafeDeepSeq, 
+     cvReconstructType
  ) where 
 
 #include "HsVersions.h"
@@ -34,7 +37,8 @@ import HscTypes         ( HscEnv )
 
 import DataCon          
 import Type             
-import TcRnMonad        ( TcM, initTcPrintErrors, ioToTcRn, recoverM, writeMutVar )
+import TcRnMonad        ( TcM, initTcPrintErrors, ioToTcRn, recoverM
+                        , writeMutVar )
 import TcType
 import TcMType
 import TcUnify
@@ -51,7 +55,7 @@ import TysPrim
 import PrelNames
 import TysWiredIn
 
-import Constants        ( wORD_SIZE )
+import Constants
 import Outputable
 import Maybes
 import Panic
@@ -59,17 +63,14 @@ import FiniteMap
 
 import GHC.Arr          ( Array(..) )
 import GHC.Ptr          ( Ptr(..), castPtr )
-import GHC.Exts         
-import GHC.Int          ( Int32(..),  Int64(..) )
-import GHC.Word         ( Word32(..), Word64(..) )
+import GHC.Exts
 
 import Control.Monad
 import Data.Maybe
 import Data.Array.Base
 import Data.List        ( partition, nub )
-import Foreign.Storable
-
-import IO
+import Foreign
+import System.IO.Unsafe
 
 ---------------------------------------------
 -- * A representation of semi evaluated Terms
@@ -92,7 +93,7 @@ data Term = Term { ty        :: Type
                  , subTerms  :: [Term] }
 
           | Prim { ty        :: Type
-                 , value     :: String }
+                 , value     :: [Word] }
 
           | Suspension { ctype    :: ClosureType
                        , mb_ty    :: Maybe Type
@@ -136,7 +137,7 @@ data Closure = Closure { tipe         :: ClosureType
                        , infoPtr      :: Ptr ()
                        , infoTable    :: StgInfoTable
                        , ptrs         :: Array Int HValue
-                       , nonPtrs      :: ByteArray# 
+                       , nonPtrs      :: [Word]
                        }
 
 instance Outputable ClosureType where
@@ -157,7 +158,10 @@ getClosureData a =
            let tipe = readCType (BCI.tipe itbl)
                elems = BCI.ptrs itbl 
                ptrsList = Array 0 (fromIntegral$ elems) ptrs
-           ptrsList `seq` return (Closure tipe (Ptr iptr) itbl ptrsList nptrs)
+               nptrs_data = [W# (indexWordArray# nptrs i)
+                              | I# i <- [0.. fromIntegral (BCI.nptrs itbl)] ]
+           ptrsList `seq` 
+            return (Closure tipe (Ptr iptr) itbl ptrsList nptrs_data)
 
 readCType :: Integral a => a -> ClosureType
 readCType i
@@ -203,7 +207,7 @@ amap' f (Array i0 i arr#) = map (\(I# i#) -> case indexArray# arr# i# of
 unsafeDeepSeq :: a -> b -> b
 unsafeDeepSeq = unsafeDeepSeq1 2
  where unsafeDeepSeq1 0 a b = seq a $! b
-       unsafeDeepSeq1 i a b                -- 1st case avoids infinite loops for non reducible thunks
+       unsafeDeepSeq1 i a b   -- 1st case avoids infinite loops for non reducible thunks
         | not (isConstr tipe) = seq a $! unsafeDeepSeq1 (i-1) a b     
      -- | unsafePerformIO (isFullyEvaluated a) = b
         | otherwise = case unsafePerformIO (getClosureData a) of
@@ -211,59 +215,31 @@ unsafeDeepSeq = unsafeDeepSeq1 2
         where tipe = unsafePerformIO (getClosureType a)
 -}
 isPointed :: Type -> Bool
-isPointed t | Just (t, _) <- splitTyConApp_maybe t = not$ isUnliftedTypeKind (tyConKind t)
+isPointed t | Just (t, _) <- splitTyConApp_maybe t 
+            = not$ isUnliftedTypeKind (tyConKind t)
 isPointed _ = True
 
-#define MKDECODER(offset,cons,builder) (offset, show$ cons (builder addr 0#))
-
-extractUnboxed  :: [Type] -> ByteArray# -> [String]
-extractUnboxed tt ba = helper tt (byteArrayContents# ba)
-   where helper :: [Type] -> Addr# -> [String]
-         helper (t:tt) addr 
-          | Just ( tycon,_) <- splitTyConApp_maybe t 
-          =  let (offset, txt) = decode tycon addr
-                 (I# word_offset)   = offset*wORD_SIZE
-             in txt : helper tt (plusAddr# addr word_offset)
-          | otherwise 
-          = -- ["extractUnboxed.helper: Urk. I got a " ++ showSDoc (ppr t)]
-            panic$ "extractUnboxed.helper: Urk. I got a " ++ showSDoc (ppr t)
-         helper [] addr = []
-         decode :: TyCon -> Addr# -> (Int, String)
-         decode t addr                             
-           | t == charPrimTyCon   = MKDECODER(1,C#,indexCharOffAddr#)
-           | t == intPrimTyCon    = MKDECODER(1,I#,indexIntOffAddr#)
-           | t == wordPrimTyCon   = MKDECODER(1,W#,indexWordOffAddr#)
-           | t == floatPrimTyCon  = MKDECODER(1,F#,indexFloatOffAddr#)
-           | t == doublePrimTyCon = MKDECODER(2,D#,indexDoubleOffAddr#)
-           | t == int32PrimTyCon  = MKDECODER(1,I32#,indexInt32OffAddr#)
-           | t == word32PrimTyCon = MKDECODER(1,W32#,indexWord32OffAddr#)
-           | t == int64PrimTyCon  = MKDECODER(2,I64#,indexInt64OffAddr#)
-           | t == word64PrimTyCon = MKDECODER(2,W64#,indexWord64OffAddr#)
-           | t == addrPrimTyCon   = MKDECODER(1,I#,(\x off-> addr2Int# (indexAddrOffAddr# x off)))  --OPT Improve the presentation of addresses
-           | t == stablePtrPrimTyCon  = (1, "<stablePtr>")
-           | t == stableNamePrimTyCon = (1, "<stableName>")
-           | t == statePrimTyCon      = (1, "<statethread>")
-           | t == realWorldTyCon      = (1, "<realworld>")
-           | t == threadIdPrimTyCon   = (1, "<ThreadId>")
-           | t == weakPrimTyCon       = (1, "<Weak>")
-           | t == arrayPrimTyCon      = (1,"<array>")
-           | t == byteArrayPrimTyCon  = (1,"<bytearray>")
-           | t == mutableArrayPrimTyCon = (1, "<mutableArray>")
-           | t == mutableByteArrayPrimTyCon = (1, "<mutableByteArray>")
-           | t == mutVarPrimTyCon= (1, "<mutVar>")
-           | t == mVarPrimTyCon  = (1, "<mVar>")
-           | t == tVarPrimTyCon  = (1, "<tVar>")
-           | otherwise = (1, showSDoc (char '<' <> ppr t <> char '>')) 
-                 -- We cannot know the right offset in the otherwise case, so 1 is just a wild dangerous guess!
-           -- TODO: Improve the offset handling in decode (make it machine dependant)
+extractUnboxed  :: [Type] -> Closure -> [[Word]]
+extractUnboxed tt clos = go tt (nonPtrs clos)
+   where sizeofType t
+           | Just (tycon,_) <- splitTyConApp_maybe t
+           = ASSERT (isPrimTyCon tycon) sizeofTyCon tycon
+           | otherwise = pprPanic "Expected a TcTyCon" (ppr t)
+         go [] _ = []
+         go (t:tt) xx 
+           | (x, rest) <- splitAt (sizeofType t `div` wORD_SIZE) xx 
+           = x : go tt rest
+
+sizeofTyCon = sizeofPrimRep . tyConPrimRep
 
 -----------------------------------
 -- * Traversals for Terms
 -----------------------------------
 
 data TermFold a = TermFold { fTerm :: Type -> DataCon -> HValue -> [a] -> a
-                           , fPrim :: Type -> String -> a
-                           , fSuspension :: ClosureType -> Maybe Type -> HValue -> Maybe Name -> a
+                           , fPrim :: Type -> [Word] -> a
+                           , fSuspension :: ClosureType -> Maybe Type -> HValue
+                                           -> Maybe Name -> a
                            }
 
 foldTerm :: TermFold a -> Term -> a
@@ -284,6 +260,18 @@ idTermFoldM = TermFold {
               fSuspension = (((return.).).). Suspension
                        }
 
+mapTermType f = foldTerm idTermFold {
+          fTerm       = \ty dc hval tt -> Term (f ty) dc hval tt,
+          fSuspension = \ct mb_ty hval n ->
+                          Suspension ct (fmap f mb_ty) hval n }
+
+termTyVars = foldTerm TermFold {
+            fTerm       = \ty _ _ tt   -> 
+                          tyVarsOfType ty `plusVarEnv` concatVarEnv tt,
+            fSuspension = \_ mb_ty _ _ -> 
+                          maybe emptyVarEnv tyVarsOfType mb_ty,
+            fPrim       = \ _ _ -> emptyVarEnv }
+    where concatVarEnv = foldr plusVarEnv emptyVarEnv
 ----------------------------------
 -- Pretty printing of terms
 ----------------------------------
@@ -305,7 +293,7 @@ pprTerm p Term{dc=dc, subTerms=tt}
 
 pprTerm _ t = pprTerm1 t
 
-pprTerm1 Prim{value=value} = text value 
+pprTerm1 Prim{value=words, ty=ty} = text$ repPrim (tyConAppTyCon ty) words
 pprTerm1 t@Term{} = pprTerm 0 t 
 pprTerm1 Suspension{bound_to=Nothing} =  char '_' -- <> ppr ct <> char '_'
 pprTerm1 Suspension{mb_ty=Just ty, bound_to=Just n}
@@ -313,7 +301,8 @@ pprTerm1 Suspension{mb_ty=Just ty, bound_to=Just n}
   | otherwise = parens$ ppr n <> text "::" <> ppr ty 
 
 
-cPprTerm :: forall m. Monad m => ((Int->Term->m SDoc)->[Int->Term->m (Maybe SDoc)]) -> Term -> m SDoc
+cPprTerm :: forall m. Monad m => 
+           ((Int->Term->m SDoc)->[Int->Term->m (Maybe SDoc)]) -> Term -> m SDoc
 cPprTerm custom = go 0 where
   go prec t@Term{subTerms=tt, dc=dc} = do
     let mb_customDocs = map (($t) . ($prec)) (custom go) :: [m (Maybe SDoc)]    
@@ -341,7 +330,8 @@ cPprTermBase pprP =
   , ifTerm (isDC doubleDataCon) (coerceShow$ \(a::Double)->a)
   , ifTerm isIntegerDC          (coerceShow$ \(a::Integer)->a)
   ] 
-     where ifTerm pred f p t = if pred t then liftM Just (f p t) else return Nothing
+     where ifTerm pred f p t = if pred t then liftM Just (f p t) 
+                                         else return Nothing
            isIntegerDC Term{dc=dc} = 
               dataConName dc `elem` [ smallIntegerDataConName
                                     , largeIntegerDataConName] 
@@ -365,26 +355,231 @@ cPprTermBase pprP =
                       getListTerms t@Suspension{}       = [t]
                       getListTerms t = pprPanic "getListTerms" (ppr t)
 
+repPrim :: TyCon -> [Word] -> String
+repPrim t = rep where 
+   rep x
+    | t == charPrimTyCon   = show (build x :: Char)
+    | t == intPrimTyCon    = show (build x :: Int)
+    | t == wordPrimTyCon   = show (build x :: Word)
+    | t == floatPrimTyCon  = show (build x :: Float)
+    | t == doublePrimTyCon = show (build x :: Double)
+    | t == int32PrimTyCon  = show (build x :: Int32)
+    | t == word32PrimTyCon = show (build x :: Word32)
+    | t == int64PrimTyCon  = show (build x :: Int64)
+    | t == word64PrimTyCon = show (build x :: Word64)
+    | t == addrPrimTyCon   = show (nullPtr `plusPtr` build x)
+    | t == stablePtrPrimTyCon  = "<stablePtr>"
+    | t == stableNamePrimTyCon = "<stableName>"
+    | t == statePrimTyCon      = "<statethread>"
+    | t == realWorldTyCon      = "<realworld>"
+    | t == threadIdPrimTyCon   = "<ThreadId>"
+    | t == weakPrimTyCon       = "<Weak>"
+    | t == arrayPrimTyCon      = "<array>"
+    | t == byteArrayPrimTyCon  = "<bytearray>"
+    | t == mutableArrayPrimTyCon = "<mutableArray>"
+    | t == mutableByteArrayPrimTyCon = "<mutableByteArray>"
+    | t == mutVarPrimTyCon= "<mutVar>"
+    | t == mVarPrimTyCon  = "<mVar>"
+    | t == tVarPrimTyCon  = "<tVar>"
+    | otherwise = showSDoc (char '<' <> ppr t <> char '>')
+    where build ww = unsafePerformIO $ withArray ww (peek . castPtr) 
+--   This ^^^ relies on the representation of Haskell heap values being 
+--   the same as in a C array. 
+
 -----------------------------------
 -- Type Reconstruction
 -----------------------------------
+{-
+Type Reconstruction is type inference done on heap closures.
+The algorithm walks the heap generating a set of equations, which
+are solved with syntactic unification.
+A type reconstruction equation looks like:
+
+  <datacon reptype>  =  <actual heap contents> 
+
+The full equation set is generated by traversing all the subterms, starting
+from a given term.
+
+The only difficult part is that newtypes are only found in the lhs of equations.
+Right hand sides are missing them. We can either (a) drop them from the lhs, or 
+(b) reconstruct them in the rhs when possible. 
+
+The function congruenceNewtypes takes a shot at (b)
+-}
 
 -- The Type Reconstruction monad
 type TR a = TcM a
 
-runTR :: HscEnv -> TR Term -> IO Term
+runTR :: HscEnv -> TR a -> IO a
 runTR hsc_env c = do 
-  mb_term <- initTcPrintErrors hsc_env iNTERACTIVE (c >>= zonkTerm)
+  mb_term <- initTcPrintErrors hsc_env iNTERACTIVE c
   case mb_term of 
     Nothing -> panic "Can't unify"
-    Just term -> return term
+    Just x -> return x
 
 trIO :: IO a -> TR a 
 trIO = liftTcM . ioToTcRn
 
+liftTcM = id
+
+newVar :: Kind -> TR TcTyVar
+newVar = liftTcM . newFlexiTyVar
+
+-- | Returns the instantiated type scheme ty', and the substitution sigma 
+--   such that sigma(ty') = ty 
+instScheme :: Type -> TR (TcType, TvSubst)
+instScheme ty | (tvs, rho) <- tcSplitForAllTys ty = liftTcM$ do
+   (tvs',theta,ty') <- tcInstType (mapM tcInstTyVar) ty
+   return (ty', zipTopTvSubst tvs' (mkTyVarTys tvs))
+
+-- Adds a constraint of the form t1 == t2
+-- t1 is expected to come from walking the heap
+-- t2 is expected to come from a datacon signature
+-- Before unification, congruenceNewtypes needs to
+-- do its magic.
 addConstraint :: TcType -> TcType -> TR ()
 addConstraint t1 t2  = congruenceNewtypes t1 t2 >>= uncurry unifyType 
 
+
+
+-- Type & Term reconstruction 
+cvObtainTerm :: HscEnv -> Bool -> Maybe Type -> HValue -> IO Term
+cvObtainTerm hsc_env force mb_ty hval = runTR hsc_env $ do
+   tv <- liftM mkTyVarTy (newVar argTypeKind)
+   case mb_ty of
+     Nothing -> go tv tv hval >>= zonkTerm
+     Just ty | isMonomorphic ty -> go ty ty hval >>= zonkTerm
+     Just ty -> do 
+              (ty',rev_subst) <- instScheme (sigmaType ty)
+              addConstraint tv ty'
+              term <- go tv tv hval >>= zonkTerm
+              --restore original Tyvars
+              return$ mapTermType (substTy rev_subst) term
+    where 
+  go tv ty a = do 
+    let monomorphic = not(isTyVarTy tv)   
+    -- This ^^^ is a convention. The ancestor tests for
+    -- monomorphism and passes a type instead of a tv
+    clos <- trIO $ getClosureData a
+    case tipe clos of
+-- Thunks we may want to force
+-- NB. this won't attempt to force a BLACKHOLE.  Even with :force, we never
+-- force blackholes, because it would almost certainly result in deadlock,
+-- and showing the '_' is more useful.
+      t | isThunk t && force -> seq a $ go tv ty a
+-- We always follow indirections 
+      Indirection _ -> go tv ty $! (ptrs clos ! 0)
+ -- The interesting case
+      Constr -> do
+        m_dc <- trIO$ tcRnRecoverDataCon hsc_env (infoPtr clos)
+        case m_dc of
+          Nothing -> panic "Can't find the DataCon for a term"
+          Just dc -> do 
+            let extra_args = length(dataConRepArgTys dc) - 
+                             length(dataConOrigArgTys dc)
+                subTtypes  = matchSubTypes dc ty
+                (subTtypesP, subTtypesNP) = partition isPointed subTtypes
+            subTermTvs <- sequence
+                 [ if isMonomorphic t then return t 
+                                      else (mkTyVarTy `fmap` newVar k)
+                   | (t,k) <- zip subTtypesP (map typeKind subTtypesP)]
+            -- It is vital for newtype reconstruction that the unification step
+            --  is done right here, _before_ the subterms are RTTI reconstructed
+            when (not monomorphic) $ do
+                  let myType = mkFunTys (reOrderTerms subTermTvs 
+                                                      subTtypesNP 
+                                                      subTtypes) 
+                                        tv
+                  (signatureType,_) <- instScheme(dataConRepType dc) 
+                  addConstraint myType signatureType
+            subTermsP <- sequence $ drop extra_args 
+                                 -- ^^^  all extra arguments are pointed
+                  [ appArr (go tv t) (ptrs clos) i
+                   | (i,tv,t) <- zip3 [0..] subTermTvs subTtypesP]
+            let unboxeds   = extractUnboxed subTtypesNP clos
+                subTermsNP = map (uncurry Prim) (zip subTtypesNP unboxeds)      
+                subTerms   = reOrderTerms subTermsP subTermsNP 
+                                (drop extra_args subTtypes)
+            return (Term tv dc a subTerms)
+-- The otherwise case: can be a Thunk,AP,PAP,etc.
+      otherwise -> 
+         return (Suspension (tipe clos) (Just tv) a Nothing)
+
+  matchSubTypes dc ty
+    | Just (_,ty_args) <- splitTyConApp_maybe (repType ty) 
+    , null (dataConExTyVars dc)  --TODO case of extra existential tyvars
+    = dataConInstArgTys dc ty_args
+
+    | otherwise = dataConRepArgTys dc
+
+-- This is used to put together pointed and nonpointed subterms in the 
+--  correct order.
+  reOrderTerms _ _ [] = []
+  reOrderTerms pointed unpointed (ty:tys) 
+   | isPointed ty = ASSERT2(not(null pointed)
+                            , ptext SLIT("reOrderTerms") $$ 
+                                        (ppr pointed $$ ppr unpointed))
+                    head pointed : reOrderTerms (tail pointed) unpointed tys
+   | otherwise    = ASSERT2(not(null unpointed)
+                           , ptext SLIT("reOrderTerms") $$ 
+                                       (ppr pointed $$ ppr unpointed))
+                    head unpointed : reOrderTerms pointed (tail unpointed) tys
+
+
+
+-- Fast, breadth-first Type reconstruction
+
+cvReconstructType :: HscEnv -> Bool -> Maybe Type -> HValue -> IO Type
+cvReconstructType hsc_env force mb_ty hval = runTR hsc_env $ do
+   tv <- liftM mkTyVarTy (newVar argTypeKind)
+   case mb_ty of
+     Nothing -> do search (isMonomorphic `fmap` zonkTcType tv) 
+                       (uncurry go) 
+                       [(tv, hval)]  
+                   zonkTcType tv  -- TODO untested!
+     Just ty | isMonomorphic ty -> return ty
+     Just ty -> do 
+              (ty',rev_subst) <- instScheme (sigmaType ty)
+              addConstraint tv ty'
+              search (isMonomorphic `fmap` zonkTcType tv) 
+                     (uncurry go) 
+                     [(tv, hval)]
+              substTy rev_subst `fmap` zonkTcType tv
+    where 
+--  search :: m Bool -> ([a] -> [a] -> [a]) -> [a] -> m ()
+  search stop expand []     = return ()
+  search stop expand  (x:xx) = do new <- expand x 
+                                  unlessM stop $ search stop expand (xx ++ new)
+
+   -- returns unification tasks,since we are going to want a breadth-first search
+  go :: Type -> HValue -> TR [(Type, HValue)]
+  go tv a = do 
+    clos <- trIO $ getClosureData a
+    case tipe clos of
+      Indirection _ -> go tv $! (ptrs clos ! 0)
+      Constr -> do
+        m_dc <- trIO$ tcRnRecoverDataCon hsc_env (infoPtr clos)
+        case m_dc of
+          Nothing -> panic "Can't find the DataCon for a term"
+          Just dc -> do 
+            let extra_args = length(dataConRepArgTys dc) - 
+                             length(dataConOrigArgTys dc)
+            subTtypes <- mapMif (not . isMonomorphic)
+                                (\t -> mkTyVarTy `fmap` newVar (typeKind t))
+                                (dataConRepArgTys dc)
+            -- It is vital for newtype reconstruction that the unification step
+            -- is done right here, _before_ the subterms are RTTI reconstructed
+            let myType = mkFunTys subTtypes tv
+            signatureType <- instScheme(dataConRepType dc) 
+            addConstraint myType signatureType
+            return $ map (\(I# i#,t) -> case ptrs clos of 
+                             (Array _ _ ptrs#) -> case indexArray# ptrs# i# of 
+                                                       (# e #) -> (t,e))
+                        (drop extra_args $ zip [0..] subTtypes)
+      otherwise -> return []
+
+
+-- Dealing with newtypes
 {-
    A parallel fold over two Type values, 
  compensating for missing newtypes on both sides. 
@@ -445,10 +640,13 @@ congruenceNewtypes = go True
       let (tycon_l',args_l') = if isNewTyCon tycon_r && not(isNewTyCon tycon_l)
                                 then (tycon_r, rewrite tycon_r lhs)
                                 else (tycon_l, args_l)
-          (tycon_r',args_r') = if rewriteRHS && isNewTyCon tycon_l && not(isNewTyCon tycon_r)
+          (tycon_r',args_r') = if rewriteRHS && isNewTyCon tycon_l && 
+                                    not(isNewTyCon tycon_r)
                                 then (tycon_l, rewrite tycon_l rhs)
                                 else (tycon_r, args_r)
-      (args_l'', args_r'') <- unzip `liftM` zipWithM (go rewriteRHS) args_l' args_r'
+      (args_l'', args_r'') <- unzip `liftM` zipWithM (go rewriteRHS) 
+                                                     args_l' 
+                                                     args_r'
       return (mkTyConApp tycon_l' args_l'', mkTyConApp tycon_r' args_r'') 
 
     | otherwise = return (lhs,rhs)
@@ -459,97 +657,22 @@ congruenceNewtypes = go True
                Just subst -> substTys subst (map mkTyVarTy tvs)
                otherwise  -> panic "congruenceNewtypes: Can't unify a newtype"
 
-newVar :: Kind -> TR TcTyVar
-newVar = liftTcM . newFlexiTyVar
-
-liftTcM = id
-
--- | Returns the instantiated type scheme ty', and the substitution sigma 
---   such that sigma(ty') = ty 
-instScheme :: Type -> TR (TcType, TvSubst)
-instScheme ty | (tvs, rho) <- tcSplitForAllTys ty = liftTcM$ do
-   (tvs',theta,ty') <- tcInstType (mapM tcInstTyVar) ty
-   return (ty', zipTopTvSubst tvs' (mkTyVarTys tvs))
-
-cvObtainTerm :: HscEnv -> Bool -> Maybe Type -> HValue -> IO Term
-cvObtainTerm hsc_env force mb_ty hval = runTR hsc_env $ do
-   tv <- liftM mkTyVarTy (newVar argTypeKind)
-   case mb_ty of
-     Nothing -> go tv tv hval
-     Just ty | isMonomorphic ty -> go ty ty hval
-     Just ty -> do 
-              (ty',rev_subst) <- instScheme (sigmaType ty)
-              addConstraint tv ty'
-              term <- go tv tv hval
-              --restore original Tyvars
-              return$ flip foldTerm term idTermFold {
-                fTerm = \ty dc hval tt -> Term (substTy rev_subst ty) dc hval tt,
-                fSuspension = \ct mb_ty hval n -> 
-                          Suspension ct (substTy rev_subst `fmap` mb_ty) hval n}
-    where 
-  go tv ty a = do 
-    let monomorphic = not(isTyVarTy tv)   -- This is a convention. The ancestor tests for
-                                         -- monomorphism and passes a type instead of a tv
-    clos <- trIO $ getClosureData a
-    case tipe clos of
--- Thunks we may want to force
-      t | isThunk t && force -> seq a $ go tv ty a
--- We always follow indirections 
-      Indirection _ -> go tv ty $! (ptrs clos ! 0)
- -- The interesting case
-      Constr -> do
-        m_dc <- trIO$ tcRnRecoverDataCon hsc_env (infoPtr clos)
-        case m_dc of
-          Nothing -> panic "Can't find the DataCon for a term"
-          Just dc -> do 
-            let extra_args = length(dataConRepArgTys dc) - length(dataConOrigArgTys dc)
-                subTtypes  = matchSubTypes dc ty
-                (subTtypesP, subTtypesNP) = partition isPointed subTtypes
-            subTermTvs <- sequence
-                 [ if isMonomorphic t then return t else (mkTyVarTy `fmap` newVar k)
-                   | (t,k) <- zip subTtypesP (map typeKind subTtypesP)]
-            -- It is vital for newtype reconstruction that the unification step is done
-            --     right here, _before_ the subterms are RTTI reconstructed.
-            when (not monomorphic) $ do
-                  let myType = mkFunTys (reOrderTerms subTermTvs subTtypesNP subTtypes) tv
-                  instScheme(dataConRepType dc) >>= addConstraint myType . fst
-            subTermsP <- sequence $ drop extra_args -- all extra arguments are pointed
-                  [ appArr (go tv t) (ptrs clos) i
-                   | (i,tv,t) <- zip3 [0..] subTermTvs subTtypesP]
-            let unboxeds   = extractUnboxed subTtypesNP (nonPtrs clos)
-                subTermsNP = map (uncurry Prim) (zip subTtypesNP unboxeds)      
-                subTerms   = reOrderTerms subTermsP subTermsNP (drop extra_args subTtypes)
-            return (Term tv dc a subTerms)
--- The otherwise case: can be a Thunk,AP,PAP,etc.
-      otherwise -> 
-         return (Suspension (tipe clos) (Just tv) a Nothing)
 
--- Access the array of pointers and recurse down. Needs to be done with
--- care of no introducing a thunk! or go will fail to do its job 
-  appArr f arr (I# i#) = case arr of 
-                 (Array _ _ ptrs#) -> case indexArray# ptrs# i# of 
-                       (# e #) -> f e
+--------------------------------------------------------------------------------
 
-  matchSubTypes dc ty
-    | Just (_,ty_args) <- splitTyConApp_maybe (repType ty) 
-    , null (dataConExTyVars dc)  --TODO Handle the case of extra existential tyvars
-    = dataConInstArgTys dc ty_args
+isMonomorphic ty | (tvs, ty') <- splitForAllTys ty
+                 = null tvs && (isEmptyVarSet . tyVarsOfType) ty'
 
-    | otherwise = dataConRepArgTys dc
+mapMif :: Monad m => (a -> Bool) -> (a -> m a) -> [a] -> m [a]
+mapMif pred f xx = sequence $ mapMif_ pred f xx
+mapMif_ pred f []     = []
+mapMif_ pred f (x:xx) = (if pred x then f x else return x) : mapMif_ pred f xx
 
--- This is used to put together pointed and nonpointed subterms in the 
---  correct order.
-  reOrderTerms _ _ [] = []
-  reOrderTerms pointed unpointed (ty:tys) 
-   | isPointed ty = ASSERT2(not(null pointed)
-                           , ptext SLIT("reOrderTerms") $$ (ppr pointed $$ ppr unpointed))
-                    head pointed : reOrderTerms (tail pointed) unpointed tys
-   | otherwise    = ASSERT2(not(null unpointed)
-                           , ptext SLIT("reOrderTerms") $$ (ppr pointed $$ ppr unpointed))
-                    head unpointed : reOrderTerms pointed (tail unpointed) tys
+unlessM condM acc = condM >>= \c -> unless c acc
 
-isMonomorphic ty | isForAllTy ty = False
-isMonomorphic ty = (isEmptyVarSet . tyVarsOfType) ty
+-- Strict application of f at index i
+appArr f (Array _ _ ptrs#) (I# i#) = case indexArray# ptrs# i# of 
+                                       (# e #) -> f e
 
 zonkTerm :: Term -> TcM Term
 zonkTerm = foldTerm idTermFoldM {
@@ -564,53 +687,4 @@ zonkTerm = foldTerm idTermFoldM {
 -- Generalize the type: find all free tyvars and wrap in the appropiate ForAll.
 sigmaType ty = mkForAllTys (varSetElems$ tyVarsOfType (dropForAlls ty)) ty
 
-{-
-Example of Type Reconstruction
---------------------------------
-Suppose we have an existential type such as
-
-data Opaque = forall a. Opaque a
-
-And we have a term built as:
-
-t = Opaque (map Just [[1,1],[2,2]])
-
-The type of t as far as the typechecker goes is t :: Opaque
-If we seq the head of t, we obtain:
-
-t - O (_1::a) 
-
-seq _1 ()
-
-t - O ( (_3::b) : (_4::[b]) ) 
-
-seq _3 ()
-
-t - O ( (Just (_5::c)) : (_4::[b]) ) 
-
-At this point, we know that b = (Maybe c)
-
-seq _5 ()
 
-t - O ( (Just ((_6::d) : (_7::[d]) )) : (_4::[b]) )
-
-At this point, we know that c = [d]
-
-seq _6 ()
-
-t - O ( (Just (1 : (_7::[d]) )) : (_4::[b]) )
-
-At this point, we know that d = Integer
-
-The fully reconstructed expressions, with propagation, would be:
-
-t - O ( (Just (_5::c)) : (_4::[Maybe c]) ) 
-t - O ( (Just ((_6::d) : (_7::[d]) )) : (_4::[Maybe [d]]) )
-t - O ( (Just (1 : (_7::[Integer]) )) : (_4::[Maybe [Integer]]) )
-
-
-For reference, the type of the thing inside the opaque is 
-map Just [[1,1],[2,2]] :: [Maybe [Integer]]
-
-NOTE: (Num t) contexts have been manually replaced by Integer for clarity
--}