{-# LANGUAGE BangPatterns, CPP, ScopedTypeVariables, MagicHash #-}

-----------------------------------------------------------------------------
--
-- GHC Interactive support for inspecting arbitrary closures at runtime
--
-- Pepe Iborra (supported by Google SoC) 2006
--
-----------------------------------------------------------------------------
module RtClosureInspect(
     -- * Entry points and types
     cvObtainTerm,
     cvReconstructType,
     improveRTTIType,
     Term(..),

     -- * Utils
     isFullyEvaluatedTerm,
     termType, mapTermType, termTyCoVars,
     foldTerm, TermFold(..),
     cPprTerm, cPprTermBase,

     constrClosToName -- exported to use in test T4891
 ) where

#include "HsVersions.h"

import GhcPrelude

import GHCi
import GHCi.RemoteTypes
import HscTypes

import DataCon
import Type
import RepType
import qualified Unify as U
import Var
import TcRnMonad
import TcType
import TcMType
import TcHsSyn ( zonkTcTypeToTypeX, mkEmptyZonkEnv, ZonkFlexi( RuntimeUnkFlexi ) )
import TcUnify
import TcEnv

import TyCon
import Name
import OccName
import Module
import IfaceEnv
import Util
import VarSet
import BasicTypes       ( Boxity(..) )
import TysPrim
import PrelNames
import TysWiredIn
import DynFlags
import Outputable as Ppr
import GHC.Char
import GHC.Exts.Heap
import SMRep ( roundUpTo )

import Control.Monad
import Data.Maybe
import Data.List ((\\))
#if defined(INTEGER_GMP)
import GHC.Exts
import Data.Array.Base
import GHC.Integer.GMP.Internals
#elif defined(INTEGER_SIMPLE)
import GHC.Exts
import GHC.Integer.Simple.Internals
#endif
import qualified Data.Sequence as Seq
import Data.Sequence (viewl, ViewL(..))
import Foreign
import System.IO.Unsafe


---------------------------------------------
-- * A representation of semi evaluated Terms
---------------------------------------------

data Term = Term { Term -> RttiType
ty        :: RttiType
                 , Term -> Either String DataCon
dc        :: Either String DataCon
                               -- Carries a text representation if the datacon is
                               -- not exported by the .hi file, which is the case
                               -- for private constructors in -O0 compiled libraries
                 , Term -> ForeignHValue
val       :: ForeignHValue
                 , Term -> [Term]
subTerms  :: [Term] }

          | Prim { ty        :: RttiType
                 , Term -> [Word]
valRaw    :: [Word] }

          | Suspension { Term -> ClosureType
ctype    :: ClosureType
                       , ty       :: RttiType
                       , val      :: ForeignHValue
                       , Term -> Maybe Name
bound_to :: Maybe Name   -- Useful for printing
                       }
          | NewtypeWrap{       -- At runtime there are no newtypes, and hence no
                               -- newtype constructors. A NewtypeWrap is just a
                               -- made-up tag saying "heads up, there used to be
                               -- a newtype constructor here".
                         ty           :: RttiType
                       , dc           :: Either String DataCon
                       , Term -> Term
wrapped_term :: Term }
          | RefWrap    {       -- The contents of a reference
                         ty           :: RttiType
                       , wrapped_term :: Term }

termType :: Term -> RttiType
termType :: Term -> RttiType
termType Term
t = Term -> RttiType
ty Term
t

isFullyEvaluatedTerm :: Term -> Bool
isFullyEvaluatedTerm :: Term -> Bool
isFullyEvaluatedTerm Term {subTerms :: Term -> [Term]
subTerms=[Term]
tt} = (Term -> Bool) -> [Term] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Term -> Bool
isFullyEvaluatedTerm [Term]
tt
isFullyEvaluatedTerm Prim {}            = Bool
True
isFullyEvaluatedTerm NewtypeWrap{wrapped_term :: Term -> Term
wrapped_term=Term
t} = Term -> Bool
isFullyEvaluatedTerm Term
t
isFullyEvaluatedTerm RefWrap{wrapped_term :: Term -> Term
wrapped_term=Term
t}     = Term -> Bool
isFullyEvaluatedTerm Term
t
isFullyEvaluatedTerm Term
_                  = Bool
False

instance Outputable (Term) where
 ppr :: Term -> SDoc
ppr Term
t | Just SDoc
doc <- CustomTermPrinter Maybe -> Term -> Maybe SDoc
forall (m :: * -> *).
Monad m =>
CustomTermPrinter m -> Term -> m SDoc
cPprTerm CustomTermPrinter Maybe
forall (m :: * -> *). Monad m => CustomTermPrinter m
cPprTermBase Term
t = SDoc
doc
       | Bool
otherwise = String -> SDoc
forall a. String -> a
panic String
"Outputable Term instance"

----------------------------------------
-- Runtime Closure information functions
----------------------------------------

isThunk :: GenClosure a -> Bool
isThunk :: GenClosure a -> Bool
isThunk ThunkClosure{} = Bool
True
isThunk APClosure{} = Bool
True
isThunk APStackClosure{} = Bool
True
isThunk GenClosure a
_             = Bool
False

-- Lookup the name in a constructor closure
constrClosToName :: HscEnv -> GenClosure a -> IO (Either String Name)
constrClosToName :: HscEnv -> GenClosure a -> IO (Either String Name)
constrClosToName HscEnv
hsc_env ConstrClosure{pkg :: forall b. GenClosure b -> String
pkg=String
pkg,modl :: forall b. GenClosure b -> String
modl=String
mod,name :: forall b. GenClosure b -> String
name=String
occ} = do
   let occName :: OccName
occName = NameSpace -> String -> OccName
mkOccName NameSpace
OccName.dataName String
occ
       modName :: Module
modName = UnitId -> ModuleName -> Module
mkModule (String -> UnitId
stringToUnitId String
pkg) (String -> ModuleName
mkModuleName String
mod)
   Name -> Either String Name
forall a b. b -> Either a b
Right (Name -> Either String Name) -> IO Name -> IO (Either String Name)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` HscEnv -> Module -> OccName -> IO Name
lookupOrigIO HscEnv
hsc_env Module
modName OccName
occName
constrClosToName HscEnv
_hsc_env GenClosure a
clos =
   Either String Name -> IO (Either String Name)
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String Name
forall a b. a -> Either a b
Left (String
"conClosToName: Expected ConstrClosure, got " String -> String -> String
forall a. [a] -> [a] -> [a]
++ GenClosure () -> String
forall a. Show a => a -> String
show ((a -> ()) -> GenClosure a -> GenClosure ()
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (() -> a -> ()
forall a b. a -> b -> a
const ()) GenClosure a
clos)))

-----------------------------------
-- * Traversals for Terms
-----------------------------------
type TermProcessor a b = RttiType -> Either String DataCon -> ForeignHValue -> [a] -> b

data TermFold a = TermFold { TermFold a -> TermProcessor a a
fTerm        :: TermProcessor a a
                           , TermFold a -> RttiType -> [Word] -> a
fPrim        :: RttiType -> [Word] -> a
                           , TermFold a
-> ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> a
fSuspension  :: ClosureType -> RttiType -> ForeignHValue
                                            -> Maybe Name -> a
                           , TermFold a -> RttiType -> Either String DataCon -> a -> a
fNewtypeWrap :: RttiType -> Either String DataCon
                                            -> a -> a
                           , TermFold a -> RttiType -> a -> a
fRefWrap     :: RttiType -> a -> a
                           }


data TermFoldM m a =
                   TermFoldM {TermFoldM m a -> TermProcessor a (m a)
fTermM        :: TermProcessor a (m a)
                            , TermFoldM m a -> RttiType -> [Word] -> m a
fPrimM        :: RttiType -> [Word] -> m a
                            , TermFoldM m a
-> ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> m a
fSuspensionM  :: ClosureType -> RttiType -> ForeignHValue
                                             -> Maybe Name -> m a
                            , TermFoldM m a -> RttiType -> Either String DataCon -> a -> m a
fNewtypeWrapM :: RttiType -> Either String DataCon
                                            -> a -> m a
                            , TermFoldM m a -> RttiType -> a -> m a
fRefWrapM     :: RttiType -> a -> m a
                           }

foldTerm :: TermFold a -> Term -> a
foldTerm :: TermFold a -> Term -> a
foldTerm TermFold a
tf (Term RttiType
ty Either String DataCon
dc ForeignHValue
v [Term]
tt) = TermFold a -> TermProcessor a a
forall a. TermFold a -> TermProcessor a a
fTerm TermFold a
tf RttiType
ty Either String DataCon
dc ForeignHValue
v ((Term -> a) -> [Term] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (TermFold a -> Term -> a
forall a. TermFold a -> Term -> a
foldTerm TermFold a
tf) [Term]
tt)
foldTerm TermFold a
tf (Prim RttiType
ty    [Word]
v   ) = TermFold a -> RttiType -> [Word] -> a
forall a. TermFold a -> RttiType -> [Word] -> a
fPrim TermFold a
tf RttiType
ty [Word]
v
foldTerm TermFold a
tf (Suspension ClosureType
ct RttiType
ty ForeignHValue
v Maybe Name
b) = TermFold a
-> ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> a
forall a.
TermFold a
-> ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> a
fSuspension TermFold a
tf ClosureType
ct RttiType
ty ForeignHValue
v Maybe Name
b
foldTerm TermFold a
tf (NewtypeWrap RttiType
ty Either String DataCon
dc Term
t)  = TermFold a -> RttiType -> Either String DataCon -> a -> a
forall a. TermFold a -> RttiType -> Either String DataCon -> a -> a
fNewtypeWrap TermFold a
tf RttiType
ty Either String DataCon
dc (TermFold a -> Term -> a
forall a. TermFold a -> Term -> a
foldTerm TermFold a
tf Term
t)
foldTerm TermFold a
tf (RefWrap RttiType
ty Term
t)         = TermFold a -> RttiType -> a -> a
forall a. TermFold a -> RttiType -> a -> a
fRefWrap TermFold a
tf RttiType
ty (TermFold a -> Term -> a
forall a. TermFold a -> Term -> a
foldTerm TermFold a
tf Term
t)


foldTermM :: Monad m => TermFoldM m a -> Term -> m a
foldTermM :: TermFoldM m a -> Term -> m a
foldTermM TermFoldM m a
tf (Term RttiType
ty Either String DataCon
dc ForeignHValue
v [Term]
tt) = (Term -> m a) -> [Term] -> m [a]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (TermFoldM m a -> Term -> m a
forall (m :: * -> *) a. Monad m => TermFoldM m a -> Term -> m a
foldTermM TermFoldM m a
tf) [Term]
tt m [a] -> ([a] -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= TermFoldM m a -> TermProcessor a (m a)
forall (m :: * -> *) a. TermFoldM m a -> TermProcessor a (m a)
fTermM TermFoldM m a
tf RttiType
ty Either String DataCon
dc ForeignHValue
v
foldTermM TermFoldM m a
tf (Prim RttiType
ty    [Word]
v   ) = TermFoldM m a -> RttiType -> [Word] -> m a
forall (m :: * -> *) a. TermFoldM m a -> RttiType -> [Word] -> m a
fPrimM TermFoldM m a
tf RttiType
ty [Word]
v
foldTermM TermFoldM m a
tf (Suspension ClosureType
ct RttiType
ty ForeignHValue
v Maybe Name
b) = TermFoldM m a
-> ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> m a
forall (m :: * -> *) a.
TermFoldM m a
-> ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> m a
fSuspensionM TermFoldM m a
tf ClosureType
ct RttiType
ty ForeignHValue
v Maybe Name
b
foldTermM TermFoldM m a
tf (NewtypeWrap RttiType
ty Either String DataCon
dc Term
t)  = TermFoldM m a -> Term -> m a
forall (m :: * -> *) a. Monad m => TermFoldM m a -> Term -> m a
foldTermM TermFoldM m a
tf Term
t m a -> (a -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=  TermFoldM m a -> RttiType -> Either String DataCon -> a -> m a
forall (m :: * -> *) a.
TermFoldM m a -> RttiType -> Either String DataCon -> a -> m a
fNewtypeWrapM TermFoldM m a
tf RttiType
ty Either String DataCon
dc
foldTermM TermFoldM m a
tf (RefWrap RttiType
ty Term
t)         = TermFoldM m a -> Term -> m a
forall (m :: * -> *) a. Monad m => TermFoldM m a -> Term -> m a
foldTermM TermFoldM m a
tf Term
t m a -> (a -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= TermFoldM m a -> RttiType -> a -> m a
forall (m :: * -> *) a. TermFoldM m a -> RttiType -> a -> m a
fRefWrapM TermFoldM m a
tf RttiType
ty

idTermFold :: TermFold Term
idTermFold :: TermFold Term
idTermFold = TermFold :: forall a.
TermProcessor a a
-> (RttiType -> [Word] -> a)
-> (ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> a)
-> (RttiType -> Either String DataCon -> a -> a)
-> (RttiType -> a -> a)
-> TermFold a
TermFold {
              fTerm :: TermProcessor Term Term
fTerm = TermProcessor Term Term
Term,
              fPrim :: RttiType -> [Word] -> Term
fPrim = RttiType -> [Word] -> Term
Prim,
              fSuspension :: ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
fSuspension  = ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
Suspension,
              fNewtypeWrap :: RttiType -> Either String DataCon -> Term -> Term
fNewtypeWrap = RttiType -> Either String DataCon -> Term -> Term
NewtypeWrap,
              fRefWrap :: RttiType -> Term -> Term
fRefWrap = RttiType -> Term -> Term
RefWrap
                      }

mapTermType :: (RttiType -> Type) -> Term -> Term
mapTermType :: (RttiType -> RttiType) -> Term -> Term
mapTermType RttiType -> RttiType
f = TermFold Term -> Term -> Term
forall a. TermFold a -> Term -> a
foldTerm TermFold Term
idTermFold {
          fTerm :: TermProcessor Term Term
fTerm       = \RttiType
ty Either String DataCon
dc ForeignHValue
hval [Term]
tt -> TermProcessor Term Term
Term (RttiType -> RttiType
f RttiType
ty) Either String DataCon
dc ForeignHValue
hval [Term]
tt,
          fSuspension :: ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
fSuspension = \ClosureType
ct RttiType
ty ForeignHValue
hval Maybe Name
n ->
                          ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
Suspension ClosureType
ct (RttiType -> RttiType
f RttiType
ty) ForeignHValue
hval Maybe Name
n,
          fNewtypeWrap :: RttiType -> Either String DataCon -> Term -> Term
fNewtypeWrap= \RttiType
ty Either String DataCon
dc Term
t -> RttiType -> Either String DataCon -> Term -> Term
NewtypeWrap (RttiType -> RttiType
f RttiType
ty) Either String DataCon
dc Term
t,
          fRefWrap :: RttiType -> Term -> Term
fRefWrap    = \RttiType
ty Term
t -> RttiType -> Term -> Term
RefWrap (RttiType -> RttiType
f RttiType
ty) Term
t}

mapTermTypeM :: Monad m =>  (RttiType -> m Type) -> Term -> m Term
mapTermTypeM :: (RttiType -> m RttiType) -> Term -> m Term
mapTermTypeM RttiType -> m RttiType
f = TermFoldM m Term -> Term -> m Term
forall (m :: * -> *) a. Monad m => TermFoldM m a -> Term -> m a
foldTermM TermFoldM :: forall (m :: * -> *) a.
TermProcessor a (m a)
-> (RttiType -> [Word] -> m a)
-> (ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> m a)
-> (RttiType -> Either String DataCon -> a -> m a)
-> (RttiType -> a -> m a)
-> TermFoldM m a
TermFoldM {
          fTermM :: TermProcessor Term (m Term)
fTermM       = \RttiType
ty Either String DataCon
dc ForeignHValue
hval [Term]
tt -> RttiType -> m RttiType
f RttiType
ty m RttiType -> (RttiType -> m Term) -> m Term
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \RttiType
ty' -> Term -> m Term
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> m Term) -> Term -> m Term
forall a b. (a -> b) -> a -> b
$ TermProcessor Term Term
Term RttiType
ty'  Either String DataCon
dc ForeignHValue
hval [Term]
tt,
          fPrimM :: RttiType -> [Word] -> m Term
fPrimM       = (Term -> m Term
forall (m :: * -> *) a. Monad m => a -> m a
return(Term -> m Term) -> ([Word] -> Term) -> [Word] -> m Term
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) (([Word] -> Term) -> [Word] -> m Term)
-> (RttiType -> [Word] -> Term) -> RttiType -> [Word] -> m Term
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RttiType -> [Word] -> Term
Prim,
          fSuspensionM :: ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> m Term
fSuspensionM = \ClosureType
ct RttiType
ty ForeignHValue
hval Maybe Name
n ->
                          RttiType -> m RttiType
f RttiType
ty m RttiType -> (RttiType -> m Term) -> m Term
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \RttiType
ty' -> Term -> m Term
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> m Term) -> Term -> m Term
forall a b. (a -> b) -> a -> b
$ ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
Suspension ClosureType
ct RttiType
ty' ForeignHValue
hval Maybe Name
n,
          fNewtypeWrapM :: RttiType -> Either String DataCon -> Term -> m Term
fNewtypeWrapM= \RttiType
ty Either String DataCon
dc Term
t -> RttiType -> m RttiType
f RttiType
ty m RttiType -> (RttiType -> m Term) -> m Term
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \RttiType
ty' -> Term -> m Term
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> m Term) -> Term -> m Term
forall a b. (a -> b) -> a -> b
$ RttiType -> Either String DataCon -> Term -> Term
NewtypeWrap RttiType
ty' Either String DataCon
dc Term
t,
          fRefWrapM :: RttiType -> Term -> m Term
fRefWrapM    = \RttiType
ty Term
t -> RttiType -> m RttiType
f RttiType
ty m RttiType -> (RttiType -> m Term) -> m Term
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \RttiType
ty' -> Term -> m Term
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> m Term) -> Term -> m Term
forall a b. (a -> b) -> a -> b
$ RttiType -> Term -> Term
RefWrap RttiType
ty' Term
t}

termTyCoVars :: Term -> TyCoVarSet
termTyCoVars :: Term -> TyCoVarSet
termTyCoVars = TermFold TyCoVarSet -> Term -> TyCoVarSet
forall a. TermFold a -> Term -> a
foldTerm TermFold :: forall a.
TermProcessor a a
-> (RttiType -> [Word] -> a)
-> (ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> a)
-> (RttiType -> Either String DataCon -> a -> a)
-> (RttiType -> a -> a)
-> TermFold a
TermFold {
            fTerm :: TermProcessor TyCoVarSet TyCoVarSet
fTerm       = \RttiType
ty Either String DataCon
_ ForeignHValue
_ [TyCoVarSet]
tt   ->
                          RttiType -> TyCoVarSet
tyCoVarsOfType RttiType
ty TyCoVarSet -> TyCoVarSet -> TyCoVarSet
`unionVarSet` [TyCoVarSet] -> TyCoVarSet
concatVarEnv [TyCoVarSet]
tt,
            fSuspension :: ClosureType
-> RttiType -> ForeignHValue -> Maybe Name -> TyCoVarSet
fSuspension = \ClosureType
_ RttiType
ty ForeignHValue
_ Maybe Name
_ -> RttiType -> TyCoVarSet
tyCoVarsOfType RttiType
ty,
            fPrim :: RttiType -> [Word] -> TyCoVarSet
fPrim       = \ RttiType
_ [Word]
_ -> TyCoVarSet
emptyVarSet,
            fNewtypeWrap :: RttiType -> Either String DataCon -> TyCoVarSet -> TyCoVarSet
fNewtypeWrap= \RttiType
ty Either String DataCon
_ TyCoVarSet
t -> RttiType -> TyCoVarSet
tyCoVarsOfType RttiType
ty TyCoVarSet -> TyCoVarSet -> TyCoVarSet
`unionVarSet` TyCoVarSet
t,
            fRefWrap :: RttiType -> TyCoVarSet -> TyCoVarSet
fRefWrap    = \RttiType
ty TyCoVarSet
t -> RttiType -> TyCoVarSet
tyCoVarsOfType RttiType
ty TyCoVarSet -> TyCoVarSet -> TyCoVarSet
`unionVarSet` TyCoVarSet
t}
    where concatVarEnv :: [TyCoVarSet] -> TyCoVarSet
concatVarEnv = (TyCoVarSet -> TyCoVarSet -> TyCoVarSet)
-> TyCoVarSet -> [TyCoVarSet] -> TyCoVarSet
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr TyCoVarSet -> TyCoVarSet -> TyCoVarSet
unionVarSet TyCoVarSet
emptyVarSet

----------------------------------
-- Pretty printing of terms
----------------------------------

type Precedence        = Int
type TermPrinterM m    = Precedence -> Term -> m SDoc

app_prec,cons_prec, max_prec ::Int
max_prec :: Int
max_prec  = Int
10
app_prec :: Int
app_prec  = Int
max_prec
cons_prec :: Int
cons_prec = Int
5 -- TODO Extract this info from GHC itself

pprTermM, ppr_termM, pprNewtypeWrap :: Monad m => TermPrinterM m -> TermPrinterM m
pprTermM :: TermPrinterM m -> TermPrinterM m
pprTermM TermPrinterM m
y Int
p Term
t = SDoc -> SDoc
pprDeeper (SDoc -> SDoc) -> m SDoc -> m SDoc
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` TermPrinterM m -> TermPrinterM m
forall (m :: * -> *). Monad m => TermPrinterM m -> TermPrinterM m
ppr_termM TermPrinterM m
y Int
p Term
t

ppr_termM :: TermPrinterM m -> TermPrinterM m
ppr_termM TermPrinterM m
y Int
p Term{dc :: Term -> Either String DataCon
dc=Left String
dc_tag, subTerms :: Term -> [Term]
subTerms=[Term]
tt} = do
  [SDoc]
tt_docs <- (Term -> m SDoc) -> [Term] -> m [SDoc]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (TermPrinterM m
y Int
app_prec) [Term]
tt
  SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> m SDoc) -> SDoc -> m SDoc
forall a b. (a -> b) -> a -> b
$ Bool -> SDoc -> SDoc
cparen (Bool -> Bool
not ([Term] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Term]
tt) Bool -> Bool -> Bool
&& Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
app_prec)
                  (String -> SDoc
text String
dc_tag SDoc -> SDoc -> SDoc
<+> ([SDoc] -> SDoc) -> [SDoc] -> SDoc
pprDeeperList [SDoc] -> SDoc
fsep [SDoc]
tt_docs)

ppr_termM TermPrinterM m
y Int
p Term{dc :: Term -> Either String DataCon
dc=Right DataCon
dc, subTerms :: Term -> [Term]
subTerms=[Term]
tt}
{-  | dataConIsInfix dc, (t1:t2:tt') <- tt  --TODO fixity
  = parens (ppr_term1 True t1 <+> ppr dc <+> ppr_term1 True ppr t2)
    <+> hsep (map (ppr_term1 True) tt)
-} -- TODO Printing infix constructors properly
  = do { [SDoc]
tt_docs' <- (Term -> m SDoc) -> [Term] -> m [SDoc]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (TermPrinterM m
y Int
app_prec) [Term]
tt
       ; SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> m SDoc) -> SDoc -> m SDoc
forall a b. (a -> b) -> a -> b
$ SDoc -> SDoc -> SDoc
ifPprDebug ([SDoc] -> SDoc
show_tm [SDoc]
tt_docs')
                             ([SDoc] -> SDoc
show_tm ([RttiType] -> [SDoc] -> [SDoc]
forall b a. [b] -> [a] -> [a]
dropList (DataCon -> [RttiType]
dataConTheta DataCon
dc) [SDoc]
tt_docs'))
                  -- Don't show the dictionary arguments to
                  -- constructors unless -dppr-debug is on
       }
  where
    show_tm :: [SDoc] -> SDoc
show_tm [SDoc]
tt_docs
      | [SDoc] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [SDoc]
tt_docs = DataCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr DataCon
dc
      | Bool
otherwise    = Bool -> SDoc -> SDoc
cparen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
app_prec) (SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$
                       [SDoc] -> SDoc
sep [DataCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr DataCon
dc, Int -> SDoc -> SDoc
nest Int
2 (([SDoc] -> SDoc) -> [SDoc] -> SDoc
pprDeeperList [SDoc] -> SDoc
fsep [SDoc]
tt_docs)]

ppr_termM TermPrinterM m
y Int
p t :: Term
t@NewtypeWrap{} = TermPrinterM m -> TermPrinterM m
forall (m :: * -> *). Monad m => TermPrinterM m -> TermPrinterM m
pprNewtypeWrap TermPrinterM m
y Int
p Term
t
ppr_termM TermPrinterM m
y Int
p RefWrap{wrapped_term :: Term -> Term
wrapped_term=Term
t}  = do
  SDoc
contents <- TermPrinterM m
y Int
app_prec Term
t
  SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return(SDoc -> m SDoc) -> SDoc -> m SDoc
forall a b. (a -> b) -> a -> b
$ Bool -> SDoc -> SDoc
cparen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
app_prec) (String -> SDoc
text String
"GHC.Prim.MutVar#" SDoc -> SDoc -> SDoc
<+> SDoc
contents)
  -- The constructor name is wired in here ^^^ for the sake of simplicity.
  -- I don't think mutvars are going to change in a near future.
  -- In any case this is solely a presentation matter: MutVar# is
  -- a datatype with no constructors, implemented by the RTS
  -- (hence there is no way to obtain a datacon and print it).
ppr_termM TermPrinterM m
_ Int
_ Term
t = Term -> m SDoc
forall (m :: * -> *). Monad m => Term -> m SDoc
ppr_termM1 Term
t


ppr_termM1 :: Monad m => Term -> m SDoc
ppr_termM1 :: Term -> m SDoc
ppr_termM1 Prim{valRaw :: Term -> [Word]
valRaw=[Word]
words, ty :: Term -> RttiType
ty=RttiType
ty} =
    SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> m SDoc) -> SDoc -> m SDoc
forall a b. (a -> b) -> a -> b
$ TyCon -> [Word] -> SDoc
repPrim (RttiType -> TyCon
tyConAppTyCon RttiType
ty) [Word]
words
ppr_termM1 Suspension{ty :: Term -> RttiType
ty=RttiType
ty, bound_to :: Term -> Maybe Name
bound_to=Maybe Name
Nothing} =
    SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return (Char -> SDoc
char Char
'_' SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
whenPprDebug (String -> SDoc
text String
"::" SDoc -> SDoc -> SDoc
<> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
ty))
ppr_termM1 Suspension{ty :: Term -> RttiType
ty=RttiType
ty, bound_to :: Term -> Maybe Name
bound_to=Just Name
n}
--  | Just _ <- splitFunTy_maybe ty = return$ ptext (sLit("<function>")
  | Bool
otherwise = SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return(SDoc -> m SDoc) -> SDoc -> m SDoc
forall a b. (a -> b) -> a -> b
$ SDoc -> SDoc
parens(SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$ Name -> SDoc
forall a. Outputable a => a -> SDoc
ppr Name
n SDoc -> SDoc -> SDoc
<> String -> SDoc
text String
"::" SDoc -> SDoc -> SDoc
<> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
ty
ppr_termM1 Term{}        = String -> m SDoc
forall a. String -> a
panic String
"ppr_termM1 - Term"
ppr_termM1 RefWrap{}     = String -> m SDoc
forall a. String -> a
panic String
"ppr_termM1 - RefWrap"
ppr_termM1 NewtypeWrap{} = String -> m SDoc
forall a. String -> a
panic String
"ppr_termM1 - NewtypeWrap"

pprNewtypeWrap :: TermPrinterM m -> TermPrinterM m
pprNewtypeWrap TermPrinterM m
y Int
p NewtypeWrap{ty :: Term -> RttiType
ty=RttiType
ty, wrapped_term :: Term -> Term
wrapped_term=Term
t}
  | Just (TyCon
tc,[RttiType]
_) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
ty
  , ASSERT(isNewTyCon tc) True
  , Just DataCon
new_dc <- TyCon -> Maybe DataCon
tyConSingleDataCon_maybe TyCon
tc = do
             SDoc
real_term <- TermPrinterM m
y Int
max_prec Term
t
             SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> m SDoc) -> SDoc -> m SDoc
forall a b. (a -> b) -> a -> b
$ Bool -> SDoc -> SDoc
cparen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
app_prec) (DataCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr DataCon
new_dc SDoc -> SDoc -> SDoc
<+> SDoc
real_term)
pprNewtypeWrap TermPrinterM m
_ Int
_ Term
_ = String -> m SDoc
forall a. String -> a
panic String
"pprNewtypeWrap"

-------------------------------------------------------
-- Custom Term Pretty Printers
-------------------------------------------------------

-- We can want to customize the representation of a
--  term depending on its type.
-- However, note that custom printers have to work with
--  type representations, instead of directly with types.
-- We cannot use type classes here, unless we employ some
--  typerep trickery (e.g. Weirich's RepLib tricks),
--  which I didn't. Therefore, this code replicates a lot
--  of what type classes provide for free.

type CustomTermPrinter m = TermPrinterM m
                         -> [Precedence -> Term -> (m (Maybe SDoc))]

-- | Takes a list of custom printers with a explicit recursion knot and a term,
-- and returns the output of the first successful printer, or the default printer
cPprTerm :: Monad m => CustomTermPrinter m -> Term -> m SDoc
cPprTerm :: CustomTermPrinter m -> Term -> m SDoc
cPprTerm CustomTermPrinter m
printers_ = TermPrinterM m
go Int
0 where
  printers :: [Int -> Term -> m (Maybe SDoc)]
printers = CustomTermPrinter m
printers_ TermPrinterM m
go
  go :: TermPrinterM m
go Int
prec Term
t = do
    let default_ :: m (Maybe SDoc)
default_ = SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (SDoc -> Maybe SDoc) -> m SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` TermPrinterM m -> TermPrinterM m
forall (m :: * -> *). Monad m => TermPrinterM m -> TermPrinterM m
pprTermM TermPrinterM m
go Int
prec Term
t
        mb_customDocs :: [m (Maybe SDoc)]
mb_customDocs = [Int -> Term -> m (Maybe SDoc)
pp Int
prec Term
t | Int -> Term -> m (Maybe SDoc)
pp <- [Int -> Term -> m (Maybe SDoc)]
printers] [m (Maybe SDoc)] -> [m (Maybe SDoc)] -> [m (Maybe SDoc)]
forall a. [a] -> [a] -> [a]
++ [m (Maybe SDoc)
default_]
    Maybe SDoc
mdoc <- [m (Maybe SDoc)] -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => [m (Maybe a)] -> m (Maybe a)
firstJustM [m (Maybe SDoc)]
mb_customDocs
    case Maybe SDoc
mdoc of
      Maybe SDoc
Nothing -> String -> m SDoc
forall a. String -> a
panic String
"cPprTerm"
      Just SDoc
doc -> SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> m SDoc) -> SDoc -> m SDoc
forall a b. (a -> b) -> a -> b
$ Bool -> SDoc -> SDoc
cparen (Int
precInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>Int
app_precInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) SDoc
doc

  firstJustM :: [m (Maybe a)] -> m (Maybe a)
firstJustM (m (Maybe a)
mb:[m (Maybe a)]
mbs) = m (Maybe a)
mb m (Maybe a) -> (Maybe a -> m (Maybe a)) -> m (Maybe a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m (Maybe a) -> (a -> m (Maybe a)) -> Maybe a -> m (Maybe a)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([m (Maybe a)] -> m (Maybe a)
firstJustM [m (Maybe a)]
mbs) (Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m (Maybe a)) -> (a -> Maybe a) -> a -> m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe a
forall a. a -> Maybe a
Just)
  firstJustM [] = Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing

-- Default set of custom printers. Note that the recursion knot is explicit
cPprTermBase :: forall m. Monad m => CustomTermPrinter m
cPprTermBase :: CustomTermPrinter m
cPprTermBase TermPrinterM m
y =
  [ (Term -> Bool) -> TermPrinterM m -> Int -> Term -> m (Maybe SDoc)
ifTerm (RttiType -> Bool
isTupleTy(RttiType -> Bool) -> (Term -> RttiType) -> Term -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Term -> RttiType
ty) (\Int
_p -> ([SDoc] -> SDoc) -> m [SDoc] -> m SDoc
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (SDoc -> SDoc
parens (SDoc -> SDoc) -> ([SDoc] -> SDoc) -> [SDoc] -> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [SDoc] -> SDoc
hcat ([SDoc] -> SDoc) -> ([SDoc] -> [SDoc]) -> [SDoc] -> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SDoc -> [SDoc] -> [SDoc]
punctuate SDoc
comma)
                                      (m [SDoc] -> m SDoc) -> (Term -> m [SDoc]) -> Term -> m SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Term -> m SDoc) -> [Term] -> m [SDoc]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (TermPrinterM m
y (-Int
1))
                                      ([Term] -> m [SDoc]) -> (Term -> [Term]) -> Term -> m [SDoc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term -> [Term]
subTerms)
  , (Term -> Bool) -> TermPrinterM m -> Int -> Term -> m (Maybe SDoc)
ifTerm (\Term
t -> TyCon -> RttiType -> Bool
isTyCon TyCon
listTyCon (Term -> RttiType
ty Term
t) Bool -> Bool -> Bool
&& Term -> [Term]
subTerms Term
t [Term] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIs` Int
2)
           TermPrinterM m
ppr_list
  , (Term -> Bool)
-> (Int -> Term -> m (Maybe SDoc)) -> Int -> Term -> m (Maybe SDoc)
ifTerm' (TyCon -> RttiType -> Bool
isTyCon TyCon
intTyCon    (RttiType -> Bool) -> (Term -> RttiType) -> Term -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term -> RttiType
ty) Int -> Term -> m (Maybe SDoc)
ppr_int
  , (Term -> Bool)
-> (Int -> Term -> m (Maybe SDoc)) -> Int -> Term -> m (Maybe SDoc)
ifTerm' (TyCon -> RttiType -> Bool
isTyCon TyCon
charTyCon   (RttiType -> Bool) -> (Term -> RttiType) -> Term -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term -> RttiType
ty) Int -> Term -> m (Maybe SDoc)
ppr_char
  , (Term -> Bool)
-> (Int -> Term -> m (Maybe SDoc)) -> Int -> Term -> m (Maybe SDoc)
ifTerm' (TyCon -> RttiType -> Bool
isTyCon TyCon
floatTyCon  (RttiType -> Bool) -> (Term -> RttiType) -> Term -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term -> RttiType
ty) Int -> Term -> m (Maybe SDoc)
ppr_float
  , (Term -> Bool)
-> (Int -> Term -> m (Maybe SDoc)) -> Int -> Term -> m (Maybe SDoc)
ifTerm' (TyCon -> RttiType -> Bool
isTyCon TyCon
doubleTyCon (RttiType -> Bool) -> (Term -> RttiType) -> Term -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term -> RttiType
ty) Int -> Term -> m (Maybe SDoc)
ppr_double
  , (Term -> Bool)
-> (Int -> Term -> m (Maybe SDoc)) -> Int -> Term -> m (Maybe SDoc)
ifTerm' (RttiType -> Bool
isIntegerTy         (RttiType -> Bool) -> (Term -> RttiType) -> Term -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term -> RttiType
ty) Int -> Term -> m (Maybe SDoc)
ppr_integer
  ]
 where
   ifTerm :: (Term -> Bool)
          -> (Precedence -> Term -> m SDoc)
          -> Precedence -> Term -> m (Maybe SDoc)
   ifTerm :: (Term -> Bool) -> TermPrinterM m -> Int -> Term -> m (Maybe SDoc)
ifTerm Term -> Bool
pred TermPrinterM m
f = (Term -> Bool)
-> (Int -> Term -> m (Maybe SDoc)) -> Int -> Term -> m (Maybe SDoc)
ifTerm' Term -> Bool
pred (\Int
prec Term
t -> SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (SDoc -> Maybe SDoc) -> m SDoc -> m (Maybe SDoc)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TermPrinterM m
f Int
prec Term
t)

   ifTerm' :: (Term -> Bool)
          -> (Precedence -> Term -> m (Maybe SDoc))
          -> Precedence -> Term -> m (Maybe SDoc)
   ifTerm' :: (Term -> Bool)
-> (Int -> Term -> m (Maybe SDoc)) -> Int -> Term -> m (Maybe SDoc)
ifTerm' Term -> Bool
pred Int -> Term -> m (Maybe SDoc)
f Int
prec t :: Term
t@Term{}
       | Term -> Bool
pred Term
t    = Int -> Term -> m (Maybe SDoc)
f Int
prec Term
t
   ifTerm' Term -> Bool
_ Int -> Term -> m (Maybe SDoc)
_ Int
_ Term
_  = Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe SDoc
forall a. Maybe a
Nothing

   isTupleTy :: RttiType -> Bool
isTupleTy RttiType
ty    = Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
False (Maybe Bool -> Bool) -> Maybe Bool -> Bool
forall a b. (a -> b) -> a -> b
$ do
     (TyCon
tc,[RttiType]
_) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
ty
     Bool -> Maybe Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (TyCon -> Bool
isBoxedTupleTyCon TyCon
tc)

   isTyCon :: TyCon -> RttiType -> Bool
isTyCon TyCon
a_tc RttiType
ty = Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
False (Maybe Bool -> Bool) -> Maybe Bool -> Bool
forall a b. (a -> b) -> a -> b
$ do
     (TyCon
tc,[RttiType]
_) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
ty
     Bool -> Maybe Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (TyCon
a_tc TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
tc)

   isIntegerTy :: RttiType -> Bool
isIntegerTy RttiType
ty = Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
False (Maybe Bool -> Bool) -> Maybe Bool -> Bool
forall a b. (a -> b) -> a -> b
$ do
     (TyCon
tc,[RttiType]
_) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
ty
     Bool -> Maybe Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (TyCon -> Name
tyConName TyCon
tc Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
integerTyConName)

   ppr_int, ppr_char, ppr_float, ppr_double
      :: Precedence -> Term -> m (Maybe SDoc)
   ppr_int :: Int -> Term -> m (Maybe SDoc)
ppr_int Int
_ Term{subTerms :: Term -> [Term]
subTerms=[Prim{valRaw :: Term -> [Word]
valRaw=[Word
w]}]} =
      Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (Int -> SDoc
Ppr.int (Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
w)))
   ppr_int Int
_ Term
_ = Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe SDoc
forall a. Maybe a
Nothing

   ppr_char :: Int -> Term -> m (Maybe SDoc)
ppr_char Int
_ Term{subTerms :: Term -> [Term]
subTerms=[Prim{valRaw :: Term -> [Word]
valRaw=[Word
w]}]} =
      Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (Char -> SDoc
Ppr.pprHsChar (Int -> Char
chr (Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
w))))
   ppr_char Int
_ Term
_ = Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe SDoc
forall a. Maybe a
Nothing

   ppr_float :: Int -> Term -> m (Maybe SDoc)
ppr_float   Int
_ Term{subTerms :: Term -> [Term]
subTerms=[Prim{valRaw :: Term -> [Word]
valRaw=[Word
w]}]} = do
      let f :: Float
f = IO Float -> Float
forall a. IO a -> a
unsafeDupablePerformIO (IO Float -> Float) -> IO Float -> Float
forall a b. (a -> b) -> a -> b
$
                (Ptr Word -> IO Float) -> IO Float
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr Word -> IO Float) -> IO Float)
-> (Ptr Word -> IO Float) -> IO Float
forall a b. (a -> b) -> a -> b
$ \Ptr Word
p -> Ptr Word -> Word -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word
p Word
w IO () -> IO Float -> IO Float
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr Float -> IO Float
forall a. Storable a => Ptr a -> IO a
peek (Ptr Word -> Ptr Float
forall a b. Ptr a -> Ptr b
castPtr Ptr Word
p)
      Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (Float -> SDoc
Ppr.float Float
f))
   ppr_float Int
_ Term
_ = Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe SDoc
forall a. Maybe a
Nothing

   ppr_double :: Int -> Term -> m (Maybe SDoc)
ppr_double  Int
_ Term{subTerms :: Term -> [Term]
subTerms=[Prim{valRaw :: Term -> [Word]
valRaw=[Word
w]}]} = do
      let f :: Double
f = IO Double -> Double
forall a. IO a -> a
unsafeDupablePerformIO (IO Double -> Double) -> IO Double -> Double
forall a b. (a -> b) -> a -> b
$
                (Ptr Word -> IO Double) -> IO Double
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr Word -> IO Double) -> IO Double)
-> (Ptr Word -> IO Double) -> IO Double
forall a b. (a -> b) -> a -> b
$ \Ptr Word
p -> Ptr Word -> Word -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word
p Word
w IO () -> IO Double -> IO Double
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr Double -> IO Double
forall a. Storable a => Ptr a -> IO a
peek (Ptr Word -> Ptr Double
forall a b. Ptr a -> Ptr b
castPtr Ptr Word
p)
      Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (Double -> SDoc
Ppr.double Double
f))
   -- let's assume that if we get two words, we're on a 32-bit
   -- machine. There's no good way to get a DynFlags to check the word
   -- size here.
   ppr_double  Int
_ Term{subTerms :: Term -> [Term]
subTerms=[Prim{valRaw :: Term -> [Word]
valRaw=[Word
w1,Word
w2]}]} = do
      let f :: Double
f = IO Double -> Double
forall a. IO a -> a
unsafeDupablePerformIO (IO Double -> Double) -> IO Double -> Double
forall a b. (a -> b) -> a -> b
$
                (Ptr Word32 -> IO Double) -> IO Double
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr Word32 -> IO Double) -> IO Double)
-> (Ptr Word32 -> IO Double) -> IO Double
forall a b. (a -> b) -> a -> b
$ \Ptr Word32
p -> do
                  Ptr Word32 -> Word32 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word32
p (Word -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
w1 :: Word32)
                  Ptr Word32 -> Word32 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr Word32
p Ptr Word32 -> Int -> Ptr Word32
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
4) (Word -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
w2 :: Word32)
                  Ptr Double -> IO Double
forall a. Storable a => Ptr a -> IO a
peek (Ptr Word32 -> Ptr Double
forall a b. Ptr a -> Ptr b
castPtr Ptr Word32
p)
      Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (Double -> SDoc
Ppr.double Double
f))
   ppr_double Int
_ Term
_ = Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe SDoc
forall a. Maybe a
Nothing

   ppr_integer :: Precedence -> Term -> m (Maybe SDoc)
#if defined(INTEGER_GMP)
   -- Reconstructing Integers is a bit of a pain. This depends deeply
   -- on the integer-gmp representation, so it'll break if that
   -- changes (but there are several tests in
   -- tests/ghci.debugger/scripts that will tell us if this is wrong).
   --
   --   data Integer
   --     = S# Int#
   --     | Jp# {-# UNPACK #-} !BigNat
   --     | Jn# {-# UNPACK #-} !BigNat
   --
   --   data BigNat = BN# ByteArray#
   --
   ppr_integer _ Term{subTerms=[Prim{valRaw=[W# w]}]} =
      return (Just (Ppr.integer (S# (word2Int# w))))
   ppr_integer _ Term{dc=Right con,
                      subTerms=[Term{subTerms=[Prim{valRaw=ws}]}]} = do
      -- We don't need to worry about sizes that are not an integral
      -- number of words, because luckily GMP uses arrays of words
      -- (see GMP_LIMB_SHIFT).
      let
        !(UArray _ _ _ arr#) = listArray (0,length ws-1) ws
        constr
          | "Jp#" <- getOccString (dataConName con) = Jp#
          | otherwise = Jn#
      return (Just (Ppr.integer (constr (BN# arr#))))
#elif defined(INTEGER_SIMPLE)
   -- As with the GMP case, this depends deeply on the integer-simple
   -- representation.
   --
   -- @
   -- data Integer = Positive !Digits | Negative !Digits | Naught
   --
   -- data Digits = Some !Word# !Digits
   --             | None
   -- @
   --
   -- NB: the above has some type synonyms expanded out for the sake of brevity
   ppr_integer _ Term{subTerms=[]} =
      return (Just (Ppr.integer Naught))
   ppr_integer _ Term{dc=Right con, subTerms=[digitTerm]}
        | Just digits <- get_digits digitTerm
        = return (Just (Ppr.integer (constr digits)))
      where
        get_digits :: Term -> Maybe Digits
        get_digits Term{subTerms=[]} = Just None
        get_digits Term{subTerms=[Prim{valRaw=[W# w]},t]}
          = Some w <$> get_digits t
        get_digits _ = Nothing

        constr
          | "Positive" <- getOccString (dataConName con) = Positive
          | otherwise = Negative
#endif
   ppr_integer :: Int -> Term -> m (Maybe SDoc)
ppr_integer Int
_ Term
_ = Maybe SDoc -> m (Maybe SDoc)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe SDoc
forall a. Maybe a
Nothing

   --Note pprinting of list terms is not lazy
   ppr_list :: Precedence -> Term -> m SDoc
   ppr_list :: TermPrinterM m
ppr_list Int
p (Term{subTerms :: Term -> [Term]
subTerms=[Term
h,Term
t]}) = do
       let elems :: [Term]
elems      = Term
h Term -> [Term] -> [Term]
forall a. a -> [a] -> [a]
: Term -> [Term]
getListTerms Term
t
           isConsLast :: Bool
isConsLast = Bool -> Bool
not (Term -> RttiType
termType ([Term] -> Term
forall a. [a] -> a
last [Term]
elems) RttiType -> RttiType -> Bool
`eqType` Term -> RttiType
termType Term
h)
           is_string :: Bool
is_string  = (Term -> Bool) -> [Term] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (RttiType -> Bool
isCharTy (RttiType -> Bool) -> (Term -> RttiType) -> Term -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term -> RttiType
ty) [Term]
elems
           chars :: String
chars = [ Int -> Char
chr (Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
w)
                   | Term{subTerms :: Term -> [Term]
subTerms=[Prim{valRaw :: Term -> [Word]
valRaw=[Word
w]}]} <- [Term]
elems ]

       [SDoc]
print_elems <- (Term -> m SDoc) -> [Term] -> m [SDoc]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (TermPrinterM m
y Int
cons_prec) [Term]
elems
       if Bool
is_string
        then SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> SDoc
Ppr.doubleQuotes (String -> SDoc
Ppr.text String
chars))
        else if Bool
isConsLast
        then SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> m SDoc) -> SDoc -> m SDoc
forall a b. (a -> b) -> a -> b
$ Bool -> SDoc -> SDoc
cparen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
cons_prec)
                    (SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$ ([SDoc] -> SDoc) -> [SDoc] -> SDoc
pprDeeperList [SDoc] -> SDoc
fsep
                    ([SDoc] -> SDoc) -> [SDoc] -> SDoc
forall a b. (a -> b) -> a -> b
$ SDoc -> [SDoc] -> [SDoc]
punctuate (SDoc
spaceSDoc -> SDoc -> SDoc
<>SDoc
colon) [SDoc]
print_elems
        else SDoc -> m SDoc
forall (m :: * -> *) a. Monad m => a -> m a
return (SDoc -> m SDoc) -> SDoc -> m SDoc
forall a b. (a -> b) -> a -> b
$ SDoc -> SDoc
brackets
                    (SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$ ([SDoc] -> SDoc) -> [SDoc] -> SDoc
pprDeeperList [SDoc] -> SDoc
fcat
                    ([SDoc] -> SDoc) -> [SDoc] -> SDoc
forall a b. (a -> b) -> a -> b
$ SDoc -> [SDoc] -> [SDoc]
punctuate SDoc
comma [SDoc]
print_elems

        where getListTerms :: Term -> [Term]
getListTerms Term{subTerms :: Term -> [Term]
subTerms=[Term
h,Term
t]} = Term
h Term -> [Term] -> [Term]
forall a. a -> [a] -> [a]
: Term -> [Term]
getListTerms Term
t
              getListTerms Term{subTerms :: Term -> [Term]
subTerms=[]}    = []
              getListTerms t :: Term
t@Suspension{}       = [Term
t]
              getListTerms Term
t = String -> SDoc -> [Term]
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"getListTerms" (Term -> SDoc
forall a. Outputable a => a -> SDoc
ppr Term
t)
   ppr_list Int
_ Term
_ = String -> m SDoc
forall a. String -> a
panic String
"doList"


repPrim :: TyCon -> [Word] -> SDoc
repPrim :: TyCon -> [Word] -> SDoc
repPrim TyCon
t = [Word] -> SDoc
forall a. Storable a => [a] -> SDoc
rep where
   rep :: [a] -> SDoc
rep [a]
x
    -- Char# uses native machine words, whereas Char's Storable instance uses
    -- Int32, so we have to read it as an Int.
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
charPrimTyCon             = String -> SDoc
text (String -> SDoc) -> String -> SDoc
forall a b. (a -> b) -> a -> b
$ Char -> String
forall a. Show a => a -> String
show (Int -> Char
chr ([a] -> Int
forall a a. (Storable a, Storable a) => [a] -> a
build [a]
x :: Int))
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
intPrimTyCon              = String -> SDoc
text (String -> SDoc) -> String -> SDoc
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show ([a] -> Int
forall a a. (Storable a, Storable a) => [a] -> a
build [a]
x :: Int)
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
wordPrimTyCon             = String -> SDoc
text (String -> SDoc) -> String -> SDoc
forall a b. (a -> b) -> a -> b
$ Word -> String
forall a. Show a => a -> String
show ([a] -> Word
forall a a. (Storable a, Storable a) => [a] -> a
build [a]
x :: Word)
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
floatPrimTyCon            = String -> SDoc
text (String -> SDoc) -> String -> SDoc
forall a b. (a -> b) -> a -> b
$ Float -> String
forall a. Show a => a -> String
show ([a] -> Float
forall a a. (Storable a, Storable a) => [a] -> a
build [a]
x :: Float)
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
doublePrimTyCon           = String -> SDoc
text (String -> SDoc) -> String -> SDoc
forall a b. (a -> b) -> a -> b
$ Double -> String
forall a. Show a => a -> String
show ([a] -> Double
forall a a. (Storable a, Storable a) => [a] -> a
build [a]
x :: Double)
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
int32PrimTyCon            = String -> SDoc
text (String -> SDoc) -> String -> SDoc
forall a b. (a -> b) -> a -> b
$ Int32 -> String
forall a. Show a => a -> String
show ([a] -> Int32
forall a a. (Storable a, Storable a) => [a] -> a
build [a]
x :: Int32)
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
word32PrimTyCon           = String -> SDoc
text (String -> SDoc) -> String -> SDoc
forall a b. (a -> b) -> a -> b
$ Word32 -> String
forall a. Show a => a -> String
show ([a] -> Word32
forall a a. (Storable a, Storable a) => [a] -> a
build [a]
x :: Word32)
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
int64PrimTyCon            = String -> SDoc
text (String -> SDoc) -> String -> SDoc
forall a b. (a -> b) -> a -> b
$ Int64 -> String
forall a. Show a => a -> String
show ([a] -> Int64
forall a a. (Storable a, Storable a) => [a] -> a
build [a]
x :: Int64)
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
word64PrimTyCon           = String -> SDoc
text (String -> SDoc) -> String -> SDoc
forall a b. (a -> b) -> a -> b
$ Word64 -> String
forall a. Show a => a -> String
show ([a] -> Word64
forall a a. (Storable a, Storable a) => [a] -> a
build [a]
x :: Word64)
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
addrPrimTyCon             = String -> SDoc
text (String -> SDoc) -> String -> SDoc
forall a b. (a -> b) -> a -> b
$ Ptr Any -> String
forall a. Show a => a -> String
show (Ptr Any
forall a. Ptr a
nullPtr Ptr Any -> Int -> Ptr Any
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` [a] -> Int
forall a a. (Storable a, Storable a) => [a] -> a
build [a]
x)
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
stablePtrPrimTyCon        = String -> SDoc
text String
"<stablePtr>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
stableNamePrimTyCon       = String -> SDoc
text String
"<stableName>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
statePrimTyCon            = String -> SDoc
text String
"<statethread>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
proxyPrimTyCon            = String -> SDoc
text String
"<proxy>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
realWorldTyCon            = String -> SDoc
text String
"<realworld>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
threadIdPrimTyCon         = String -> SDoc
text String
"<ThreadId>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
weakPrimTyCon             = String -> SDoc
text String
"<Weak>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
arrayPrimTyCon            = String -> SDoc
text String
"<array>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
smallArrayPrimTyCon       = String -> SDoc
text String
"<smallArray>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
byteArrayPrimTyCon        = String -> SDoc
text String
"<bytearray>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
mutableArrayPrimTyCon     = String -> SDoc
text String
"<mutableArray>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
smallMutableArrayPrimTyCon = String -> SDoc
text String
"<smallMutableArray>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
mutableByteArrayPrimTyCon = String -> SDoc
text String
"<mutableByteArray>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
mutVarPrimTyCon           = String -> SDoc
text String
"<mutVar>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
mVarPrimTyCon             = String -> SDoc
text String
"<mVar>"
    | TyCon
t TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
tVarPrimTyCon             = String -> SDoc
text String
"<tVar>"
    | Bool
otherwise                      = Char -> SDoc
char Char
'<' SDoc -> SDoc -> SDoc
<> TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
t SDoc -> SDoc -> SDoc
<> Char -> SDoc
char Char
'>'
    where build :: [a] -> a
build [a]
ww = IO a -> a
forall a. IO a -> a
unsafePerformIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ [a] -> (Ptr a -> IO a) -> IO a
forall a b. Storable a => [a] -> (Ptr a -> IO b) -> IO b
withArray [a]
ww (Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek (Ptr a -> IO a) -> (Ptr a -> Ptr a) -> Ptr a -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr a -> Ptr a
forall a b. Ptr a -> Ptr b
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)
-}


-- A (non-mutable) tau type containing
-- existentially quantified tyvars.
--    (since GHC type language currently does not support
--     existentials, we leave these variables unquantified)
type RttiType = Type

-- An incomplete type as stored in GHCi:
--  no polymorphism: no quantifiers & all tyvars are skolem.
type GhciType = Type


-- The Type Reconstruction monad
--------------------------------
type TR a = TcM a

runTR :: HscEnv -> TR a -> IO a
runTR :: HscEnv -> TR a -> IO a
runTR HscEnv
hsc_env TR a
thing = do
  Maybe a
mb_val <- HscEnv -> TR a -> IO (Maybe a)
forall a. HscEnv -> TR a -> IO (Maybe a)
runTR_maybe HscEnv
hsc_env TR a
thing
  case Maybe a
mb_val of
    Maybe a
Nothing -> String -> IO a
forall a. HasCallStack => String -> a
error String
"unable to :print the term"
    Just a
x  -> a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x

runTR_maybe :: HscEnv -> TR a -> IO (Maybe a)
runTR_maybe :: HscEnv -> TR a -> IO (Maybe a)
runTR_maybe HscEnv
hsc_env TR a
thing_inside
  = do { (Messages
_errs, Maybe a
res) <- HscEnv -> TR a -> IO (Messages, Maybe a)
forall a. HscEnv -> TcM a -> IO (Messages, Maybe a)
initTcInteractive HscEnv
hsc_env TR a
thing_inside
       ; Maybe a -> IO (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
res }

-- | Term Reconstruction trace
traceTR :: SDoc -> TR ()
traceTR :: SDoc -> TR ()
traceTR = TR () -> TR ()
forall a. TcM a -> TcM a
liftTcM (TR () -> TR ()) -> (SDoc -> TR ()) -> SDoc -> TR ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DumpFlag -> SDoc -> TR ()
traceOptTcRn DumpFlag
Opt_D_dump_rtti


-- Semantically different to recoverM in TcRnMonad
-- recoverM retains the errors in the first action,
--  whereas recoverTc here does not
recoverTR :: TR a -> TR a -> TR a
recoverTR :: TR a -> TR a -> TR a
recoverTR = TR a -> TR a -> TR a
forall r. TcM r -> TcM r -> TcM r
tryTcDiscardingErrs

trIO :: IO a -> TR a
trIO :: IO a -> TR a
trIO = TR a -> TR a
forall a. TcM a -> TcM a
liftTcM (TR a -> TR a) -> (IO a -> TR a) -> IO a -> TR a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> TR a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO

liftTcM :: TcM a -> TR a
liftTcM :: TcM a -> TcM a
liftTcM = TcM a -> TcM a
forall a. a -> a
id

newVar :: Kind -> TR TcType
newVar :: RttiType -> TR RttiType
newVar = TR RttiType -> TR RttiType
forall a. TcM a -> TcM a
liftTcM (TR RttiType -> TR RttiType)
-> (RttiType -> TR RttiType) -> RttiType -> TR RttiType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RttiType -> TR RttiType
newFlexiTyVarTy

newOpenVar :: TR TcType
newOpenVar :: TR RttiType
newOpenVar = TR RttiType -> TR RttiType
forall a. TcM a -> TcM a
liftTcM TR RttiType
newOpenFlexiTyVarTy

instTyVars :: [TyVar] -> TR (TCvSubst, [TcTyVar])
-- Instantiate fresh mutable type variables from some TyVars
-- This function preserves the print-name, which helps error messages
instTyVars :: [TyVar] -> TR (TCvSubst, [TyVar])
instTyVars [TyVar]
tvs
  = TR (TCvSubst, [TyVar]) -> TR (TCvSubst, [TyVar])
forall a. TcM a -> TcM a
liftTcM (TR (TCvSubst, [TyVar]) -> TR (TCvSubst, [TyVar]))
-> TR (TCvSubst, [TyVar]) -> TR (TCvSubst, [TyVar])
forall a b. (a -> b) -> a -> b
$ ((TCvSubst, [TyVar]), WantedConstraints) -> (TCvSubst, [TyVar])
forall a b. (a, b) -> a
fst (((TCvSubst, [TyVar]), WantedConstraints) -> (TCvSubst, [TyVar]))
-> IOEnv
     (Env TcGblEnv TcLclEnv) ((TCvSubst, [TyVar]), WantedConstraints)
-> TR (TCvSubst, [TyVar])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TR (TCvSubst, [TyVar])
-> IOEnv
     (Env TcGblEnv TcLclEnv) ((TCvSubst, [TyVar]), WantedConstraints)
forall a. TcM a -> TcM (a, WantedConstraints)
captureConstraints ([TyVar] -> TR (TCvSubst, [TyVar])
newMetaTyVars [TyVar]
tvs)

type RttiInstantiation = [(TcTyVar, TyVar)]
   -- Associates the typechecker-world meta type variables
   -- (which are mutable and may be refined), to their
   -- debugger-world RuntimeUnk counterparts.
   -- If the TcTyVar has not been refined by the runtime type
   -- elaboration, then we want to turn it back into the
   -- original RuntimeUnk

-- | Returns the instantiated type scheme ty', and the
--   mapping from new (instantiated) -to- old (skolem) type variables
instScheme :: QuantifiedType -> TR (TcType, RttiInstantiation)
instScheme :: QuantifiedType -> TR (RttiType, RttiInstantiation)
instScheme ([TyVar]
tvs, RttiType
ty)
  = do { (TCvSubst
subst, [TyVar]
tvs') <- [TyVar] -> TR (TCvSubst, [TyVar])
instTyVars [TyVar]
tvs
       ; let rtti_inst :: RttiInstantiation
rtti_inst = [(TyVar
tv',TyVar
tv) | (TyVar
tv',TyVar
tv) <- [TyVar]
tvs' [TyVar] -> [TyVar] -> RttiInstantiation
forall a b. [a] -> [b] -> [(a, b)]
`zip` [TyVar]
tvs]
       ; (RttiType, RttiInstantiation) -> TR (RttiType, RttiInstantiation)
forall (m :: * -> *) a. Monad m => a -> m a
return (HasCallStack => TCvSubst -> RttiType -> RttiType
TCvSubst -> RttiType -> RttiType
substTy TCvSubst
subst RttiType
ty, RttiInstantiation
rtti_inst) }

applyRevSubst :: RttiInstantiation -> TR ()
-- Apply the *reverse* substitution in-place to any un-filled-in
-- meta tyvars.  This recovers the original debugger-world variable
-- unless it has been refined by new information from the heap
applyRevSubst :: RttiInstantiation -> TR ()
applyRevSubst RttiInstantiation
pairs = TR () -> TR ()
forall a. TcM a -> TcM a
liftTcM (((TyVar, TyVar) -> TR ()) -> RttiInstantiation -> TR ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (TyVar, TyVar) -> TR ()
do_pair RttiInstantiation
pairs)
  where
    do_pair :: (TyVar, TyVar) -> TR ()
do_pair (TyVar
tc_tv, TyVar
rtti_tv)
      = do { RttiType
tc_ty <- TyVar -> TR RttiType
zonkTcTyVar TyVar
tc_tv
           ; case RttiType -> Maybe TyVar
tcGetTyVar_maybe RttiType
tc_ty of
               Just TyVar
tv | TyVar -> Bool
isMetaTyVar TyVar
tv -> TyVar -> RttiType -> TR ()
writeMetaTyVar TyVar
tv (TyVar -> RttiType
mkTyVarTy TyVar
rtti_tv)
               Maybe TyVar
_                        -> () -> TR ()
forall (m :: * -> *) a. Monad m => a -> m a
return () }

-- 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 :: RttiType -> RttiType -> TR ()
addConstraint RttiType
actual RttiType
expected = do
    SDoc -> TR ()
traceTR (String -> SDoc
text String
"add constraint:" SDoc -> SDoc -> SDoc
<+> [SDoc] -> SDoc
fsep [RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
actual, SDoc
equals, RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
expected])
    TR () -> TR () -> TR ()
forall r. TcM r -> TcM r -> TcM r
recoverTR (SDoc -> TR ()
traceTR (SDoc -> TR ()) -> SDoc -> TR ()
forall a b. (a -> b) -> a -> b
$ [SDoc] -> SDoc
fsep [String -> SDoc
text String
"Failed to unify", RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
actual,
                                    String -> SDoc
text String
"with", RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
expected]) (TR () -> TR ()) -> TR () -> TR ()
forall a b. (a -> b) -> a -> b
$
      TcM (TcCoercionN, WantedConstraints) -> TR ()
forall a. TcM a -> TR ()
discardResult (TcM (TcCoercionN, WantedConstraints) -> TR ())
-> TcM (TcCoercionN, WantedConstraints) -> TR ()
forall a b. (a -> b) -> a -> b
$
      TcM TcCoercionN -> TcM (TcCoercionN, WantedConstraints)
forall a. TcM a -> TcM (a, WantedConstraints)
captureConstraints (TcM TcCoercionN -> TcM (TcCoercionN, WantedConstraints))
-> TcM TcCoercionN -> TcM (TcCoercionN, WantedConstraints)
forall a b. (a -> b) -> a -> b
$
      do { (RttiType
ty1, RttiType
ty2) <- RttiType -> RttiType -> TR (RttiType, RttiType)
congruenceNewtypes RttiType
actual RttiType
expected
         ; Maybe (HsExpr GhcRn) -> RttiType -> RttiType -> TcM TcCoercionN
unifyType Maybe (HsExpr GhcRn)
forall a. Maybe a
Nothing RttiType
ty1 RttiType
ty2 }
     -- TOMDO: what about the coercion?
     -- we should consider family instances


-- | Term reconstruction
--
-- Given a pointer to a heap object (`HValue`) and its type, build a `Term`
-- representation of the object. Subterms (objects in the payload) are also
-- built up to the given `max_depth`. After `max_depth` any subterms will appear
-- as `Suspension`s. Any thunks found while traversing the object will be forced
-- based on `force` parameter.
--
-- Types of terms will be refined based on constructors we find during term
-- reconstruction. See `cvReconstructType` for an overview of how type
-- reconstruction works.
--
cvObtainTerm
    :: HscEnv
    -> Int      -- ^ How many times to recurse for subterms
    -> Bool     -- ^ Force thunks
    -> RttiType -- ^ Type of the object to reconstruct
    -> ForeignHValue   -- ^ Object to reconstruct
    -> IO Term
cvObtainTerm :: HscEnv -> Int -> Bool -> RttiType -> ForeignHValue -> IO Term
cvObtainTerm HscEnv
hsc_env Int
max_depth Bool
force RttiType
old_ty ForeignHValue
hval = HscEnv -> TR Term -> IO Term
forall a. HscEnv -> TR a -> IO a
runTR HscEnv
hsc_env (TR Term -> IO Term) -> TR Term -> IO Term
forall a b. (a -> b) -> a -> b
$ do
  -- we quantify existential tyvars as universal,
  -- as this is needed to be able to manipulate
  -- them properly
   let quant_old_ty :: QuantifiedType
quant_old_ty@([TyVar]
old_tvs, RttiType
old_tau) = RttiType -> QuantifiedType
quantifyType RttiType
old_ty
       sigma_old_ty :: RttiType
sigma_old_ty = [TyVar] -> RttiType -> RttiType
mkInvForAllTys [TyVar]
old_tvs RttiType
old_tau
   SDoc -> TR ()
traceTR (String -> SDoc
text String
"Term reconstruction started with initial type " SDoc -> SDoc -> SDoc
<> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
old_ty)
   Term
term <-
     if [TyVar] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TyVar]
old_tvs
      then do
        Term
term  <- Int -> RttiType -> RttiType -> ForeignHValue -> TR Term
go Int
max_depth RttiType
sigma_old_ty RttiType
sigma_old_ty ForeignHValue
hval
        Term
term' <- Term -> TR Term
zonkTerm Term
term
        Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> TR Term) -> Term -> TR Term
forall a b. (a -> b) -> a -> b
$ Term -> Term
fixFunDictionaries (Term -> Term) -> Term -> Term
forall a b. (a -> b) -> a -> b
$ Term -> Term
expandNewtypes Term
term'
      else do
              (RttiType
old_ty', RttiInstantiation
rev_subst) <- QuantifiedType -> TR (RttiType, RttiInstantiation)
instScheme QuantifiedType
quant_old_ty
              RttiType
my_ty <- TR RttiType
newOpenVar
              Bool -> TR () -> TR ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (QuantifiedType -> Bool
check1 QuantifiedType
quant_old_ty) (SDoc -> TR ()
traceTR (String -> SDoc
text String
"check1 passed") TR () -> TR () -> TR ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
                                          RttiType -> RttiType -> TR ()
addConstraint RttiType
my_ty RttiType
old_ty')
              Term
term  <- Int -> RttiType -> RttiType -> ForeignHValue -> TR Term
go Int
max_depth RttiType
my_ty RttiType
sigma_old_ty ForeignHValue
hval
              RttiType
new_ty <- RttiType -> TR RttiType
zonkTcType (Term -> RttiType
termType Term
term)
              if RttiType -> Bool
isMonomorphic RttiType
new_ty Bool -> Bool -> Bool
|| QuantifiedType -> QuantifiedType -> Bool
check2 (RttiType -> QuantifiedType
quantifyType RttiType
new_ty) QuantifiedType
quant_old_ty
                 then do
                      SDoc -> TR ()
traceTR (String -> SDoc
text String
"check2 passed")
                      RttiType -> RttiType -> TR ()
addConstraint RttiType
new_ty RttiType
old_ty'
                      RttiInstantiation -> TR ()
applyRevSubst RttiInstantiation
rev_subst
                      Term
zterm' <- Term -> TR Term
zonkTerm Term
term
                      Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return ((Term -> Term
fixFunDictionaries (Term -> Term) -> (Term -> Term) -> Term -> Term
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Term -> Term
expandNewtypes) Term
zterm')
                 else do
                      SDoc -> TR ()
traceTR (String -> SDoc
text String
"check2 failed" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
parens
                                       (Term -> SDoc
forall a. Outputable a => a -> SDoc
ppr Term
term SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"::" SDoc -> SDoc -> SDoc
<+> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
new_ty))
                      -- we have unsound types. Replace constructor types in
                      -- subterms with tyvars
                      Term
zterm' <- (RttiType -> TR RttiType) -> Term -> TR Term
forall (m :: * -> *).
Monad m =>
(RttiType -> m RttiType) -> Term -> m Term
mapTermTypeM
                                 (\RttiType
ty -> case HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
ty of
                                           Just (TyCon
tc, RttiType
_:[RttiType]
_) | TyCon
tc TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
/= TyCon
funTyCon
                                               -> TR RttiType
newOpenVar
                                           Maybe (TyCon, [RttiType])
_   -> RttiType -> TR RttiType
forall (m :: * -> *) a. Monad m => a -> m a
return RttiType
ty)
                                 Term
term
                      Term -> TR Term
zonkTerm Term
zterm'
   SDoc -> TR ()
traceTR (String -> SDoc
text String
"Term reconstruction completed." SDoc -> SDoc -> SDoc
$$
            String -> SDoc
text String
"Term obtained: " SDoc -> SDoc -> SDoc
<> Term -> SDoc
forall a. Outputable a => a -> SDoc
ppr Term
term SDoc -> SDoc -> SDoc
$$
            String -> SDoc
text String
"Type obtained: " SDoc -> SDoc -> SDoc
<> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Term -> RttiType
termType Term
term))
   Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return Term
term
    where
  go :: Int -> Type -> Type -> ForeignHValue -> TcM Term
   -- I believe that my_ty should not have any enclosing
   -- foralls, nor any free RuntimeUnk skolems;
   -- that is partly what the quantifyType stuff achieved
   --
   -- [SPJ May 11] I don't understand the difference between my_ty and old_ty

  go :: Int -> RttiType -> RttiType -> ForeignHValue -> TR Term
go Int
0 RttiType
my_ty RttiType
_old_ty ForeignHValue
a = do
    SDoc -> TR ()
traceTR (String -> SDoc
text String
"Gave up reconstructing a term after" SDoc -> SDoc -> SDoc
<>
                  Int -> SDoc
int Int
max_depth SDoc -> SDoc -> SDoc
<> String -> SDoc
text String
" steps")
    GenClosure ForeignHValue
clos <- IO (GenClosure ForeignHValue) -> TR (GenClosure ForeignHValue)
forall a. IO a -> TR a
trIO (IO (GenClosure ForeignHValue) -> TR (GenClosure ForeignHValue))
-> IO (GenClosure ForeignHValue) -> TR (GenClosure ForeignHValue)
forall a b. (a -> b) -> a -> b
$ HscEnv -> ForeignHValue -> IO (GenClosure ForeignHValue)
GHCi.getClosure HscEnv
hsc_env ForeignHValue
a
    Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return (ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
Suspension (StgInfoTable -> ClosureType
tipe (GenClosure ForeignHValue -> StgInfoTable
forall b. GenClosure b -> StgInfoTable
info GenClosure ForeignHValue
clos)) RttiType
my_ty ForeignHValue
a Maybe Name
forall a. Maybe a
Nothing)
  go !Int
max_depth RttiType
my_ty RttiType
old_ty ForeignHValue
a = do
    let monomorphic :: Bool
monomorphic = Bool -> Bool
not(RttiType -> Bool
isTyVarTy RttiType
my_ty)
    -- This ^^^ is a convention. The ancestor tests for
    -- monomorphism and passes a type instead of a tv
    GenClosure ForeignHValue
clos <- IO (GenClosure ForeignHValue) -> TR (GenClosure ForeignHValue)
forall a. IO a -> TR a
trIO (IO (GenClosure ForeignHValue) -> TR (GenClosure ForeignHValue))
-> IO (GenClosure ForeignHValue) -> TR (GenClosure ForeignHValue)
forall a b. (a -> b) -> a -> b
$ HscEnv -> ForeignHValue -> IO (GenClosure ForeignHValue)
GHCi.getClosure HscEnv
hsc_env ForeignHValue
a
    case GenClosure ForeignHValue
clos of
-- Thunks we may want to force
      GenClosure ForeignHValue
t | GenClosure ForeignHValue -> Bool
forall a. GenClosure a -> Bool
isThunk GenClosure ForeignHValue
t Bool -> Bool -> Bool
&& Bool
force -> do
         SDoc -> TR ()
traceTR (String -> SDoc
text String
"Forcing a " SDoc -> SDoc -> SDoc
<> String -> SDoc
text (GenClosure () -> String
forall a. Show a => a -> String
show ((ForeignHValue -> ()) -> GenClosure ForeignHValue -> GenClosure ()
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (() -> ForeignHValue -> ()
forall a b. a -> b -> a
const ()) GenClosure ForeignHValue
t)))
         IO () -> TR ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> TR ()) -> IO () -> TR ()
forall a b. (a -> b) -> a -> b
$ HscEnv -> ForeignHValue -> IO ()
GHCi.seqHValue HscEnv
hsc_env ForeignHValue
a
         Int -> RttiType -> RttiType -> ForeignHValue -> TR Term
go (Int -> Int
forall a. Enum a => a -> a
pred Int
max_depth) RttiType
my_ty RttiType
old_ty ForeignHValue
a
-- Blackholes are indirections iff the payload is not TSO or BLOCKING_QUEUE. If
-- the indirection is a TSO or BLOCKING_QUEUE, we return the BLACKHOLE itself as
-- the suspension so that entering it in GHCi will enter the BLACKHOLE instead
-- of entering the TSO or BLOCKING_QUEUE (which leads to runtime panic).
      BlackholeClosure{indirectee :: forall b. GenClosure b -> b
indirectee=ForeignHValue
ind} -> do
         SDoc -> TR ()
traceTR (String -> SDoc
text String
"Following a BLACKHOLE")
         GenClosure ForeignHValue
ind_clos <- IO (GenClosure ForeignHValue) -> TR (GenClosure ForeignHValue)
forall a. IO a -> TR a
trIO (HscEnv -> ForeignHValue -> IO (GenClosure ForeignHValue)
GHCi.getClosure HscEnv
hsc_env ForeignHValue
ind)
         let return_bh_value :: TR Term
return_bh_value = Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return (ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
Suspension ClosureType
BLACKHOLE RttiType
my_ty ForeignHValue
a Maybe Name
forall a. Maybe a
Nothing)
         case GenClosure ForeignHValue
ind_clos of
           -- TSO and BLOCKING_QUEUE cases
           BlockingQueueClosure{} -> TR Term
return_bh_value
           OtherClosure StgInfoTable
info [ForeignHValue]
_ [Word]
_
             | StgInfoTable -> ClosureType
tipe StgInfoTable
info ClosureType -> ClosureType -> Bool
forall a. Eq a => a -> a -> Bool
== ClosureType
TSO -> TR Term
return_bh_value
           UnsupportedClosure StgInfoTable
info
             | StgInfoTable -> ClosureType
tipe StgInfoTable
info ClosureType -> ClosureType -> Bool
forall a. Eq a => a -> a -> Bool
== ClosureType
TSO -> TR Term
return_bh_value
           -- Otherwise follow the indirectee
           -- (NOTE: This code will break if we support TSO in ghc-heap one day)
           GenClosure ForeignHValue
_ -> Int -> RttiType -> RttiType -> ForeignHValue -> TR Term
go Int
max_depth RttiType
my_ty RttiType
old_ty ForeignHValue
ind
-- We always follow indirections
      IndClosure{indirectee :: forall b. GenClosure b -> b
indirectee=ForeignHValue
ind} -> do
         SDoc -> TR ()
traceTR (String -> SDoc
text String
"Following an indirection" )
         Int -> RttiType -> RttiType -> ForeignHValue -> TR Term
go Int
max_depth RttiType
my_ty RttiType
old_ty ForeignHValue
ind
-- We also follow references
      MutVarClosure{var :: forall b. GenClosure b -> b
var=ForeignHValue
contents}
         | Just (TyCon
tycon,[RttiType
world,RttiType
contents_ty]) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
old_ty
             -> do
                  -- Deal with the MutVar# primitive
                  -- It does not have a constructor at all,
                  -- so we simulate the following one
                  -- MutVar# :: contents_ty -> MutVar# s contents_ty
         SDoc -> TR ()
traceTR (String -> SDoc
text String
"Following a MutVar")
         RttiType
contents_tv <- RttiType -> TR RttiType
newVar RttiType
liftedTypeKind
         MASSERT(isUnliftedType my_ty)
         (RttiType
mutvar_ty,RttiInstantiation
_) <- QuantifiedType -> TR (RttiType, RttiInstantiation)
instScheme (QuantifiedType -> TR (RttiType, RttiInstantiation))
-> QuantifiedType -> TR (RttiType, RttiInstantiation)
forall a b. (a -> b) -> a -> b
$ RttiType -> QuantifiedType
quantifyType (RttiType -> QuantifiedType) -> RttiType -> QuantifiedType
forall a b. (a -> b) -> a -> b
$ RttiType -> RttiType -> RttiType
mkVisFunTy
                            RttiType
contents_ty (TyCon -> [RttiType] -> RttiType
mkTyConApp TyCon
tycon [RttiType
world,RttiType
contents_ty])
         RttiType -> RttiType -> TR ()
addConstraint (RttiType -> RttiType -> RttiType
mkVisFunTy RttiType
contents_tv RttiType
my_ty) RttiType
mutvar_ty
         Term
x <- Int -> RttiType -> RttiType -> ForeignHValue -> TR Term
go (Int -> Int
forall a. Enum a => a -> a
pred Int
max_depth) RttiType
contents_tv RttiType
contents_ty ForeignHValue
contents
         Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return (RttiType -> Term -> Term
RefWrap RttiType
my_ty Term
x)

 -- The interesting case
      ConstrClosure{ptrArgs :: forall b. GenClosure b -> [b]
ptrArgs=[ForeignHValue]
pArgs,dataArgs :: forall b. GenClosure b -> [Word]
dataArgs=[Word]
dArgs} -> do
        SDoc -> TR ()
traceTR (String -> SDoc
text String
"entering a constructor " SDoc -> SDoc -> SDoc
<> [Word] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Word]
dArgs SDoc -> SDoc -> SDoc
<+>
                      if Bool
monomorphic
                        then SDoc -> SDoc
parens (String -> SDoc
text String
"already monomorphic: " SDoc -> SDoc -> SDoc
<> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
my_ty)
                        else SDoc
Ppr.empty)
        Right Name
dcname <- IO (Either String Name)
-> IOEnv (Env TcGblEnv TcLclEnv) (Either String Name)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either String Name)
 -> IOEnv (Env TcGblEnv TcLclEnv) (Either String Name))
-> IO (Either String Name)
-> IOEnv (Env TcGblEnv TcLclEnv) (Either String Name)
forall a b. (a -> b) -> a -> b
$ HscEnv -> GenClosure ForeignHValue -> IO (Either String Name)
forall a. HscEnv -> GenClosure a -> IO (Either String Name)
constrClosToName HscEnv
hsc_env GenClosure ForeignHValue
clos
        (Maybe DataCon
mb_dc, Messages
_)   <- TcRn DataCon -> TcRn (Maybe DataCon, Messages)
forall a. TcRn a -> TcRn (Maybe a, Messages)
tryTc (Name -> TcRn DataCon
tcLookupDataCon Name
dcname)
        case Maybe DataCon
mb_dc of
          Maybe DataCon
Nothing -> do -- This can happen for private constructors compiled -O0
                        -- where the .hi descriptor does not export them
                        -- In such case, we return a best approximation:
                        --  ignore the unpointed args, and recover the pointeds
                        -- This preserves laziness, and should be safe.
                       SDoc -> TR ()
traceTR (String -> SDoc
text String
"Not constructor" SDoc -> SDoc -> SDoc
<+> Name -> SDoc
forall a. Outputable a => a -> SDoc
ppr Name
dcname)
                       let dflags :: DynFlags
dflags = HscEnv -> DynFlags
hsc_dflags HscEnv
hsc_env
                           tag :: String
tag = DynFlags -> Name -> String
forall a. Outputable a => DynFlags -> a -> String
showPpr DynFlags
dflags Name
dcname
                       [RttiType]
vars     <- Int -> TR RttiType -> IOEnv (Env TcGblEnv TcLclEnv) [RttiType]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM ([ForeignHValue] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ForeignHValue]
pArgs)
                                              (RttiType -> TR RttiType
newVar RttiType
liftedTypeKind)
                       [Term]
subTerms <- [TR Term] -> IOEnv (Env TcGblEnv TcLclEnv) [Term]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([TR Term] -> IOEnv (Env TcGblEnv TcLclEnv) [Term])
-> [TR Term] -> IOEnv (Env TcGblEnv TcLclEnv) [Term]
forall a b. (a -> b) -> a -> b
$ (ForeignHValue -> RttiType -> TR Term)
-> [ForeignHValue] -> [RttiType] -> [TR Term]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\ForeignHValue
x RttiType
tv ->
                           Int -> RttiType -> RttiType -> ForeignHValue -> TR Term
go (Int -> Int
forall a. Enum a => a -> a
pred Int
max_depth) RttiType
tv RttiType
tv ForeignHValue
x) [ForeignHValue]
pArgs [RttiType]
vars
                       Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return (TermProcessor Term Term
Term RttiType
my_ty (String -> Either String DataCon
forall a b. a -> Either a b
Left (Char
'<' Char -> String -> String
forall a. a -> [a] -> [a]
: String
tag String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
">")) ForeignHValue
a [Term]
subTerms)
          Just DataCon
dc -> do
            SDoc -> TR ()
traceTR (String -> SDoc
text String
"Is constructor" SDoc -> SDoc -> SDoc
<+> (DataCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr DataCon
dc SDoc -> SDoc -> SDoc
$$ RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
my_ty))
            [RttiType]
subTtypes <- DataCon -> RttiType -> IOEnv (Env TcGblEnv TcLclEnv) [RttiType]
getDataConArgTys DataCon
dc RttiType
my_ty
            [Term]
subTerms <- (RttiType -> ForeignHValue -> TR Term)
-> GenClosure ForeignHValue
-> [RttiType]
-> IOEnv (Env TcGblEnv TcLclEnv) [Term]
extractSubTerms (\RttiType
ty -> Int -> RttiType -> RttiType -> ForeignHValue -> TR Term
go (Int -> Int
forall a. Enum a => a -> a
pred Int
max_depth) RttiType
ty RttiType
ty) GenClosure ForeignHValue
clos [RttiType]
subTtypes
            Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return (TermProcessor Term Term
Term RttiType
my_ty (DataCon -> Either String DataCon
forall a b. b -> Either a b
Right DataCon
dc) ForeignHValue
a [Term]
subTerms)

      -- This is to support printing of Integers. It's not a general
      -- mechanism by any means; in particular we lose the size in
      -- bytes of the array.
      ArrWordsClosure{bytes :: forall b. GenClosure b -> Word
bytes=Word
b, arrWords :: forall b. GenClosure b -> [Word]
arrWords=[Word]
ws} -> do
         SDoc -> TR ()
traceTR (String -> SDoc
text String
"ByteArray# closure, size " SDoc -> SDoc -> SDoc
<> Word -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word
b)
         Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return (TermProcessor Term Term
Term RttiType
my_ty (String -> Either String DataCon
forall a b. a -> Either a b
Left String
"ByteArray#") ForeignHValue
a [RttiType -> [Word] -> Term
Prim RttiType
my_ty [Word]
ws])

-- The otherwise case: can be a Thunk,AP,PAP,etc.
      GenClosure ForeignHValue
_ -> do
         SDoc -> TR ()
traceTR (String -> SDoc
text String
"Unknown closure:" SDoc -> SDoc -> SDoc
<+>
                  String -> SDoc
text (GenClosure () -> String
forall a. Show a => a -> String
show ((ForeignHValue -> ()) -> GenClosure ForeignHValue -> GenClosure ()
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (() -> ForeignHValue -> ()
forall a b. a -> b -> a
const ()) GenClosure ForeignHValue
clos)))
         Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return (ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
Suspension (StgInfoTable -> ClosureType
tipe (GenClosure ForeignHValue -> StgInfoTable
forall b. GenClosure b -> StgInfoTable
info GenClosure ForeignHValue
clos)) RttiType
my_ty ForeignHValue
a Maybe Name
forall a. Maybe a
Nothing)

  -- insert NewtypeWraps around newtypes
  expandNewtypes :: Term -> Term
expandNewtypes = TermFold Term -> Term -> Term
forall a. TermFold a -> Term -> a
foldTerm TermFold Term
idTermFold { fTerm :: TermProcessor Term Term
fTerm = TermProcessor Term Term
worker } where
   worker :: TermProcessor Term Term
worker RttiType
ty Either String DataCon
dc ForeignHValue
hval [Term]
tt
     | Just (TyCon
tc, [RttiType]
args) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
ty
     , TyCon -> Bool
isNewTyCon TyCon
tc
     , RttiType
wrapped_type    <- TyCon -> [RttiType] -> RttiType
newTyConInstRhs TyCon
tc [RttiType]
args
     , Just DataCon
dc'        <- TyCon -> Maybe DataCon
tyConSingleDataCon_maybe TyCon
tc
     , Term
t'              <- TermProcessor Term Term
worker RttiType
wrapped_type Either String DataCon
dc ForeignHValue
hval [Term]
tt
     = RttiType -> Either String DataCon -> Term -> Term
NewtypeWrap RttiType
ty (DataCon -> Either String DataCon
forall a b. b -> Either a b
Right DataCon
dc') Term
t'
     | Bool
otherwise = TermProcessor Term Term
Term RttiType
ty Either String DataCon
dc ForeignHValue
hval [Term]
tt


   -- Avoid returning types where predicates have been expanded to dictionaries.
  fixFunDictionaries :: Term -> Term
fixFunDictionaries = TermFold Term -> Term -> Term
forall a. TermFold a -> Term -> a
foldTerm TermFold Term
idTermFold {fSuspension :: ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
fSuspension = ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
worker} where
      worker :: ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
worker ClosureType
ct RttiType
ty ForeignHValue
hval Maybe Name
n | RttiType -> Bool
isFunTy RttiType
ty = ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
Suspension ClosureType
ct (RttiType -> RttiType
dictsView RttiType
ty) ForeignHValue
hval Maybe Name
n
                          | Bool
otherwise  = ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
Suspension ClosureType
ct RttiType
ty ForeignHValue
hval Maybe Name
n

extractSubTerms :: (Type -> ForeignHValue -> TcM Term)
                -> GenClosure ForeignHValue -> [Type] -> TcM [Term]
extractSubTerms :: (RttiType -> ForeignHValue -> TR Term)
-> GenClosure ForeignHValue
-> [RttiType]
-> IOEnv (Env TcGblEnv TcLclEnv) [Term]
extractSubTerms RttiType -> ForeignHValue -> TR Term
recurse GenClosure ForeignHValue
clos = ((Int, Int, [Term]) -> [Term])
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
-> IOEnv (Env TcGblEnv TcLclEnv) [Term]
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Int, Int, [Term]) -> [Term]
forall a b c. (a, b, c) -> c
thdOf3 (IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
 -> IOEnv (Env TcGblEnv TcLclEnv) [Term])
-> ([RttiType] -> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term]))
-> [RttiType]
-> IOEnv (Env TcGblEnv TcLclEnv) [Term]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int
-> Int
-> [RttiType]
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
go Int
0 Int
0
  where
    array :: [Word]
array = GenClosure ForeignHValue -> [Word]
forall b. GenClosure b -> [Word]
dataArgs GenClosure ForeignHValue
clos

    go :: Int
-> Int
-> [RttiType]
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
go Int
ptr_i Int
arr_i [] = (Int, Int, [Term])
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
ptr_i, Int
arr_i, [])
    go Int
ptr_i Int
arr_i (RttiType
ty:[RttiType]
tys)
      | Just (TyCon
tc, [RttiType]
elem_tys) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
ty
      , TyCon -> Bool
isUnboxedTupleTyCon TyCon
tc
                -- See Note [Unboxed tuple RuntimeRep vars] in TyCon
      = do (Int
ptr_i, Int
arr_i, [Term]
terms0) <-
               Int
-> Int
-> [RttiType]
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
go Int
ptr_i Int
arr_i ([RttiType] -> [RttiType]
dropRuntimeRepArgs [RttiType]
elem_tys)
           (Int
ptr_i, Int
arr_i, [Term]
terms1) <- Int
-> Int
-> [RttiType]
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
go Int
ptr_i Int
arr_i [RttiType]
tys
           (Int, Int, [Term])
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
ptr_i, Int
arr_i, RttiType -> [Term] -> Term
unboxedTupleTerm RttiType
ty [Term]
terms0 Term -> [Term] -> [Term]
forall a. a -> [a] -> [a]
: [Term]
terms1)
      | Bool
otherwise
      = case HasDebugCallStack => RttiType -> [PrimRep]
RttiType -> [PrimRep]
typePrimRepArgs RttiType
ty of
          [PrimRep
rep_ty] ->  do
            (Int
ptr_i, Int
arr_i, Term
term0)  <- Int
-> Int
-> RttiType
-> PrimRep
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, Term)
go_rep Int
ptr_i Int
arr_i RttiType
ty PrimRep
rep_ty
            (Int
ptr_i, Int
arr_i, [Term]
terms1) <- Int
-> Int
-> [RttiType]
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
go Int
ptr_i Int
arr_i [RttiType]
tys
            (Int, Int, [Term])
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
ptr_i, Int
arr_i, Term
term0 Term -> [Term] -> [Term]
forall a. a -> [a] -> [a]
: [Term]
terms1)
          [PrimRep]
rep_tys -> do
           (Int
ptr_i, Int
arr_i, [Term]
terms0) <- Int
-> Int
-> [PrimRep]
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
go_unary_types Int
ptr_i Int
arr_i [PrimRep]
rep_tys
           (Int
ptr_i, Int
arr_i, [Term]
terms1) <- Int
-> Int
-> [RttiType]
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
go Int
ptr_i Int
arr_i [RttiType]
tys
           (Int, Int, [Term])
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
ptr_i, Int
arr_i, RttiType -> [Term] -> Term
unboxedTupleTerm RttiType
ty [Term]
terms0 Term -> [Term] -> [Term]
forall a. a -> [a] -> [a]
: [Term]
terms1)

    go_unary_types :: Int
-> Int
-> [PrimRep]
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
go_unary_types Int
ptr_i Int
arr_i [] = (Int, Int, [Term])
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
ptr_i, Int
arr_i, [])
    go_unary_types Int
ptr_i Int
arr_i (PrimRep
rep_ty:[PrimRep]
rep_tys) = do
      RttiType
tv <- RttiType -> TR RttiType
newVar RttiType
liftedTypeKind
      (Int
ptr_i, Int
arr_i, Term
term0)  <- Int
-> Int
-> RttiType
-> PrimRep
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, Term)
go_rep Int
ptr_i Int
arr_i RttiType
tv PrimRep
rep_ty
      (Int
ptr_i, Int
arr_i, [Term]
terms1) <- Int
-> Int
-> [PrimRep]
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
go_unary_types Int
ptr_i Int
arr_i [PrimRep]
rep_tys
      (Int, Int, [Term])
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, [Term])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
ptr_i, Int
arr_i, Term
term0 Term -> [Term] -> [Term]
forall a. a -> [a] -> [a]
: [Term]
terms1)

    go_rep :: Int
-> Int
-> RttiType
-> PrimRep
-> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, Term)
go_rep Int
ptr_i Int
arr_i RttiType
ty PrimRep
rep
      | PrimRep -> Bool
isGcPtrRep PrimRep
rep = do
          Term
t <- RttiType -> ForeignHValue -> TR Term
recurse RttiType
ty (ForeignHValue -> TR Term) -> ForeignHValue -> TR Term
forall a b. (a -> b) -> a -> b
$ (GenClosure ForeignHValue -> [ForeignHValue]
forall b. GenClosure b -> [b]
ptrArgs GenClosure ForeignHValue
clos)[ForeignHValue] -> Int -> ForeignHValue
forall a. [a] -> Int -> a
!!Int
ptr_i
          (Int, Int, Term) -> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, Term)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
ptr_i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, Int
arr_i, Term
t)
      | Bool
otherwise = do
          -- This is a bit involved since we allow packing multiple fields
          -- within a single word. See also
          -- GHC.StgToCmm.Layout.mkVirtHeapOffsetsWithPadding
          DynFlags
dflags <- IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
          let word_size :: Int
word_size = DynFlags -> Int
wORD_SIZE DynFlags
dflags
              big_endian :: Bool
big_endian = DynFlags -> Bool
wORDS_BIGENDIAN DynFlags
dflags
              size_b :: Int
size_b = DynFlags -> PrimRep -> Int
primRepSizeB DynFlags
dflags PrimRep
rep
              -- Align the start offset (eg, 2-byte value should be 2-byte
              -- aligned). But not more than to a word. The offset calculation
              -- should be the same with the offset calculation in
              -- GHC.StgToCmm.Layout.mkVirtHeapOffsetsWithPadding.
              !aligned_idx :: Int
aligned_idx = Int -> Int -> Int
roundUpTo Int
arr_i (Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
word_size Int
size_b)
              !new_arr_i :: Int
new_arr_i = Int
aligned_idx Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
size_b
              ws :: [Word]
ws | Int
size_b Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
word_size =
                     [Int -> Int -> Int -> Bool -> Word
index Int
size_b Int
aligned_idx Int
word_size Bool
big_endian]
                 | Bool
otherwise =
                     let (Int
q, Int
r) = Int
size_b Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int
word_size
                     in ASSERT( r == 0 )
                        [ [Word]
array[Word] -> Int -> Word
forall a. [a] -> Int -> a
!!Int
i
                        | Int
o <- [Int
0.. Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
                        , let i :: Int
i = (Int
aligned_idx Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
word_size) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
o
                        ]
          (Int, Int, Term) -> IOEnv (Env TcGblEnv TcLclEnv) (Int, Int, Term)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
ptr_i, Int
new_arr_i, RttiType -> [Word] -> Term
Prim RttiType
ty [Word]
ws)

    unboxedTupleTerm :: RttiType -> [Term] -> Term
unboxedTupleTerm RttiType
ty [Term]
terms
      = TermProcessor Term Term
Term RttiType
ty (DataCon -> Either String DataCon
forall a b. b -> Either a b
Right (Boxity -> Int -> DataCon
tupleDataCon Boxity
Unboxed ([Term] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Term]
terms)))
                (String -> ForeignHValue
forall a. HasCallStack => String -> a
error String
"unboxedTupleTerm: no HValue for unboxed tuple") [Term]
terms

    -- Extract a sub-word sized field from a word
    index :: Int -> Int -> Int -> Bool -> Word
index Int
item_size_b Int
index_b Int
word_size Bool
big_endian =
        (Word
word Word -> Word -> Word
forall a. Bits a => a -> a -> a
.&. (Word
mask Word -> Int -> Word
forall a. Bits a => a -> Int -> a
`shiftL` Int
moveBytes)) Word -> Int -> Word
forall a. Bits a => a -> Int -> a
`shiftR` Int
moveBytes
      where
        mask :: Word
        mask :: Word
mask = case Int
item_size_b of
            Int
1 -> Word
0xFF
            Int
2 -> Word
0xFFFF
            Int
4 -> Word
0xFFFFFFFF
            Int
_ -> String -> Word
forall a. String -> a
panic (String
"Weird byte-index: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
index_b)
        (Int
q,Int
r) = Int
index_b Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int
word_size
        word :: Word
word = [Word]
array[Word] -> Int -> Word
forall a. [a] -> Int -> a
!!Int
q
        moveBytes :: Int
moveBytes = if Bool
big_endian
                    then Int
word_size Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
item_size_b) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8
                    else Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8


-- | Fast, breadth-first Type reconstruction
--
-- Given a heap object (`HValue`) and its (possibly polymorphic) type (usually
-- obtained in GHCi), try to reconstruct a more monomorphic type of the object.
-- This is used for improving type information in debugger. For example, if we
-- have a polymorphic function:
--
--     sumNumList :: Num a => [a] -> a
--     sumNumList [] = 0
--     sumNumList (x : xs) = x + sumList xs
--
-- and add a breakpoint to it:
--
--     ghci> break sumNumList
--     ghci> sumNumList ([0 .. 9] :: [Int])
--
-- ghci shows us more precise types than just `a`s:
--
--     Stopped in Main.sumNumList, debugger.hs:3:23-39
--     _result :: Int = _
--     x :: Int = 0
--     xs :: [Int] = _
--
cvReconstructType
    :: HscEnv
    -> Int       -- ^ How many times to recurse for subterms
    -> GhciType  -- ^ Type to refine
    -> ForeignHValue  -- ^ Refine the type using this value
    -> IO (Maybe Type)
cvReconstructType :: HscEnv -> Int -> RttiType -> ForeignHValue -> IO (Maybe RttiType)
cvReconstructType HscEnv
hsc_env Int
max_depth RttiType
old_ty ForeignHValue
hval = HscEnv -> TR RttiType -> IO (Maybe RttiType)
forall a. HscEnv -> TR a -> IO (Maybe a)
runTR_maybe HscEnv
hsc_env (TR RttiType -> IO (Maybe RttiType))
-> TR RttiType -> IO (Maybe RttiType)
forall a b. (a -> b) -> a -> b
$ do
   SDoc -> TR ()
traceTR (String -> SDoc
text String
"RTTI started with initial type " SDoc -> SDoc -> SDoc
<> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
old_ty)
   let sigma_old_ty :: QuantifiedType
sigma_old_ty@([TyVar]
old_tvs, RttiType
_) = RttiType -> QuantifiedType
quantifyType RttiType
old_ty
   RttiType
new_ty <-
       if [TyVar] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TyVar]
old_tvs
        then RttiType -> TR RttiType
forall (m :: * -> *) a. Monad m => a -> m a
return RttiType
old_ty
        else do
          (RttiType
old_ty', RttiInstantiation
rev_subst) <- QuantifiedType -> TR (RttiType, RttiInstantiation)
instScheme QuantifiedType
sigma_old_ty
          RttiType
my_ty <- TR RttiType
newOpenVar
          Bool -> TR () -> TR ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (QuantifiedType -> Bool
check1 QuantifiedType
sigma_old_ty) (SDoc -> TR ()
traceTR (String -> SDoc
text String
"check1 passed") TR () -> TR () -> TR ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
                                      RttiType -> RttiType -> TR ()
addConstraint RttiType
my_ty RttiType
old_ty')
          IOEnv (Env TcGblEnv TcLclEnv) Bool
-> ((RttiType, ForeignHValue)
    -> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)])
-> Seq (RttiType, ForeignHValue)
-> Int
-> TR ()
forall a t.
(Eq a, Num a, Enum a) =>
IOEnv (Env TcGblEnv TcLclEnv) Bool
-> (t -> IOEnv (Env TcGblEnv TcLclEnv) [t]) -> Seq t -> a -> TR ()
search (RttiType -> Bool
isMonomorphic (RttiType -> Bool)
-> TR RttiType -> IOEnv (Env TcGblEnv TcLclEnv) Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` RttiType -> TR RttiType
zonkTcType RttiType
my_ty)
                 (\(RttiType
ty,ForeignHValue
a) -> RttiType
-> ForeignHValue
-> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)]
go RttiType
ty ForeignHValue
a)
                 ((RttiType, ForeignHValue) -> Seq (RttiType, ForeignHValue)
forall a. a -> Seq a
Seq.singleton (RttiType
my_ty, ForeignHValue
hval))
                 Int
max_depth
          RttiType
new_ty <- RttiType -> TR RttiType
zonkTcType RttiType
my_ty
          if RttiType -> Bool
isMonomorphic RttiType
new_ty Bool -> Bool -> Bool
|| QuantifiedType -> QuantifiedType -> Bool
check2 (RttiType -> QuantifiedType
quantifyType RttiType
new_ty) QuantifiedType
sigma_old_ty
            then do
                 SDoc -> TR ()
traceTR (String -> SDoc
text String
"check2 passed" SDoc -> SDoc -> SDoc
<+> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
old_ty SDoc -> SDoc -> SDoc
$$ RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
new_ty)
                 RttiType -> RttiType -> TR ()
addConstraint RttiType
my_ty RttiType
old_ty'
                 RttiInstantiation -> TR ()
applyRevSubst RttiInstantiation
rev_subst
                 RttiType -> TR RttiType
zonkRttiType RttiType
new_ty
            else SDoc -> TR ()
traceTR (String -> SDoc
text String
"check2 failed" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
parens (RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
new_ty)) TR () -> TR RttiType -> TR RttiType
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
                 RttiType -> TR RttiType
forall (m :: * -> *) a. Monad m => a -> m a
return RttiType
old_ty
   SDoc -> TR ()
traceTR (String -> SDoc
text String
"RTTI completed. Type obtained:" SDoc -> SDoc -> SDoc
<+> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
new_ty)
   RttiType -> TR RttiType
forall (m :: * -> *) a. Monad m => a -> m a
return RttiType
new_ty
    where
--  search :: m Bool -> ([a] -> [a] -> [a]) -> [a] -> m ()
  search :: IOEnv (Env TcGblEnv TcLclEnv) Bool
-> (t -> IOEnv (Env TcGblEnv TcLclEnv) [t]) -> Seq t -> a -> TR ()
search IOEnv (Env TcGblEnv TcLclEnv) Bool
_ t -> IOEnv (Env TcGblEnv TcLclEnv) [t]
_ Seq t
_ a
0 = SDoc -> TR ()
traceTR (String -> SDoc
text String
"Failed to reconstruct a type after " SDoc -> SDoc -> SDoc
<>
                                Int -> SDoc
int Int
max_depth SDoc -> SDoc -> SDoc
<> String -> SDoc
text String
" steps")
  search IOEnv (Env TcGblEnv TcLclEnv) Bool
stop t -> IOEnv (Env TcGblEnv TcLclEnv) [t]
expand Seq t
l a
d =
    case Seq t -> ViewL t
forall a. Seq a -> ViewL a
viewl Seq t
l of
      ViewL t
EmptyL  -> () -> TR ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      t
x :< Seq t
xx -> IOEnv (Env TcGblEnv TcLclEnv) Bool -> TR () -> TR ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM IOEnv (Env TcGblEnv TcLclEnv) Bool
stop (TR () -> TR ()) -> TR () -> TR ()
forall a b. (a -> b) -> a -> b
$ do
                  [t]
new <- t -> IOEnv (Env TcGblEnv TcLclEnv) [t]
expand t
x
                  IOEnv (Env TcGblEnv TcLclEnv) Bool
-> (t -> IOEnv (Env TcGblEnv TcLclEnv) [t]) -> Seq t -> a -> TR ()
search IOEnv (Env TcGblEnv TcLclEnv) Bool
stop t -> IOEnv (Env TcGblEnv TcLclEnv) [t]
expand (Seq t
xx Seq t -> Seq t -> Seq t
forall a. Monoid a => a -> a -> a
`mappend` [t] -> Seq t
forall a. [a] -> Seq a
Seq.fromList [t]
new) (a -> TR ()) -> a -> TR ()
forall a b. (a -> b) -> a -> b
$! (a -> a
forall a. Enum a => a -> a
pred a
d)

   -- returns unification tasks,since we are going to want a breadth-first search
  go :: Type -> ForeignHValue -> TR [(Type, ForeignHValue)]
  go :: RttiType
-> ForeignHValue
-> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)]
go RttiType
my_ty ForeignHValue
a = do
    SDoc -> TR ()
traceTR (String -> SDoc
text String
"go" SDoc -> SDoc -> SDoc
<+> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
my_ty)
    GenClosure ForeignHValue
clos <- IO (GenClosure ForeignHValue) -> TR (GenClosure ForeignHValue)
forall a. IO a -> TR a
trIO (IO (GenClosure ForeignHValue) -> TR (GenClosure ForeignHValue))
-> IO (GenClosure ForeignHValue) -> TR (GenClosure ForeignHValue)
forall a b. (a -> b) -> a -> b
$ HscEnv -> ForeignHValue -> IO (GenClosure ForeignHValue)
GHCi.getClosure HscEnv
hsc_env ForeignHValue
a
    case GenClosure ForeignHValue
clos of
      BlackholeClosure{indirectee :: forall b. GenClosure b -> b
indirectee=ForeignHValue
ind} -> RttiType
-> ForeignHValue
-> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)]
go RttiType
my_ty ForeignHValue
ind
      IndClosure{indirectee :: forall b. GenClosure b -> b
indirectee=ForeignHValue
ind} -> RttiType
-> ForeignHValue
-> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)]
go RttiType
my_ty ForeignHValue
ind
      MutVarClosure{var :: forall b. GenClosure b -> b
var=ForeignHValue
contents} -> do
         RttiType
tv'   <- RttiType -> TR RttiType
newVar RttiType
liftedTypeKind
         RttiType
world <- RttiType -> TR RttiType
newVar RttiType
liftedTypeKind
         RttiType -> RttiType -> TR ()
addConstraint RttiType
my_ty (TyCon -> [RttiType] -> RttiType
mkTyConApp TyCon
mutVarPrimTyCon [RttiType
world,RttiType
tv'])
         [(RttiType, ForeignHValue)]
-> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)]
forall (m :: * -> *) a. Monad m => a -> m a
return [(RttiType
tv', ForeignHValue
contents)]
      ConstrClosure{ptrArgs :: forall b. GenClosure b -> [b]
ptrArgs=[ForeignHValue]
pArgs} -> do
        Right Name
dcname <- IO (Either String Name)
-> IOEnv (Env TcGblEnv TcLclEnv) (Either String Name)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either String Name)
 -> IOEnv (Env TcGblEnv TcLclEnv) (Either String Name))
-> IO (Either String Name)
-> IOEnv (Env TcGblEnv TcLclEnv) (Either String Name)
forall a b. (a -> b) -> a -> b
$ HscEnv -> GenClosure ForeignHValue -> IO (Either String Name)
forall a. HscEnv -> GenClosure a -> IO (Either String Name)
constrClosToName HscEnv
hsc_env GenClosure ForeignHValue
clos
        SDoc -> TR ()
traceTR (String -> SDoc
text String
"Constr1" SDoc -> SDoc -> SDoc
<+> Name -> SDoc
forall a. Outputable a => a -> SDoc
ppr Name
dcname)
        (Maybe DataCon
mb_dc, Messages
_) <- TcRn DataCon -> TcRn (Maybe DataCon, Messages)
forall a. TcRn a -> TcRn (Maybe a, Messages)
tryTc (Name -> TcRn DataCon
tcLookupDataCon Name
dcname)
        case Maybe DataCon
mb_dc of
          Maybe DataCon
Nothing-> do
            [ForeignHValue]
-> (ForeignHValue
    -> IOEnv (Env TcGblEnv TcLclEnv) (RttiType, ForeignHValue))
-> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [ForeignHValue]
pArgs ((ForeignHValue
  -> IOEnv (Env TcGblEnv TcLclEnv) (RttiType, ForeignHValue))
 -> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)])
-> (ForeignHValue
    -> IOEnv (Env TcGblEnv TcLclEnv) (RttiType, ForeignHValue))
-> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)]
forall a b. (a -> b) -> a -> b
$ \ForeignHValue
x -> do
              RttiType
tv <- RttiType -> TR RttiType
newVar RttiType
liftedTypeKind
              (RttiType, ForeignHValue)
-> IOEnv (Env TcGblEnv TcLclEnv) (RttiType, ForeignHValue)
forall (m :: * -> *) a. Monad m => a -> m a
return (RttiType
tv, ForeignHValue
x)

          Just DataCon
dc -> do
            [RttiType]
arg_tys <- DataCon -> RttiType -> IOEnv (Env TcGblEnv TcLclEnv) [RttiType]
getDataConArgTys DataCon
dc RttiType
my_ty
            (Int
_, [(Int, RttiType)]
itys) <- Int -> [RttiType] -> TR (Int, [(Int, RttiType)])
findPtrTyss Int
0 [RttiType]
arg_tys
            SDoc -> TR ()
traceTR (String -> SDoc
text String
"Constr2" SDoc -> SDoc -> SDoc
<+> Name -> SDoc
forall a. Outputable a => a -> SDoc
ppr Name
dcname SDoc -> SDoc -> SDoc
<+> [RttiType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [RttiType]
arg_tys)
            [(RttiType, ForeignHValue)]
-> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([(RttiType, ForeignHValue)]
 -> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)])
-> [(RttiType, ForeignHValue)]
-> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)]
forall a b. (a -> b) -> a -> b
$ ((Int, RttiType) -> ForeignHValue -> (RttiType, ForeignHValue))
-> [(Int, RttiType)]
-> [ForeignHValue]
-> [(RttiType, ForeignHValue)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\(Int
_,RttiType
ty) ForeignHValue
x -> (RttiType
ty, ForeignHValue
x)) [(Int, RttiType)]
itys [ForeignHValue]
pArgs
      GenClosure ForeignHValue
_ -> [(RttiType, ForeignHValue)]
-> IOEnv (Env TcGblEnv TcLclEnv) [(RttiType, ForeignHValue)]
forall (m :: * -> *) a. Monad m => a -> m a
return []

findPtrTys :: Int  -- Current pointer index
           -> Type -- Type
           -> TR (Int, [(Int, Type)])
findPtrTys :: Int -> RttiType -> TR (Int, [(Int, RttiType)])
findPtrTys Int
i RttiType
ty
  | Just (TyCon
tc, [RttiType]
elem_tys) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
ty
  , TyCon -> Bool
isUnboxedTupleTyCon TyCon
tc
  = Int -> [RttiType] -> TR (Int, [(Int, RttiType)])
findPtrTyss Int
i [RttiType]
elem_tys

  | Bool
otherwise
  = case HasDebugCallStack => RttiType -> [PrimRep]
RttiType -> [PrimRep]
typePrimRep RttiType
ty of
      [PrimRep
rep] | PrimRep -> Bool
isGcPtrRep PrimRep
rep -> (Int, [(Int, RttiType)]) -> TR (Int, [(Int, RttiType)])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, [(Int
i, RttiType
ty)])
            | Bool
otherwise      -> (Int, [(Int, RttiType)]) -> TR (Int, [(Int, RttiType)])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
i,     [])
      [PrimRep]
prim_reps              ->
        ((Int, [(Int, RttiType)])
 -> PrimRep -> TR (Int, [(Int, RttiType)]))
-> (Int, [(Int, RttiType)])
-> [PrimRep]
-> TR (Int, [(Int, RttiType)])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (\(Int
i, [(Int, RttiType)]
extras) PrimRep
prim_rep ->
                if PrimRep -> Bool
isGcPtrRep PrimRep
prim_rep
                  then RttiType -> TR RttiType
newVar RttiType
liftedTypeKind TR RttiType
-> (RttiType -> TR (Int, [(Int, RttiType)]))
-> TR (Int, [(Int, RttiType)])
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \RttiType
tv -> (Int, [(Int, RttiType)]) -> TR (Int, [(Int, RttiType)])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1, [(Int, RttiType)]
extras [(Int, RttiType)] -> [(Int, RttiType)] -> [(Int, RttiType)]
forall a. [a] -> [a] -> [a]
++ [(Int
i, RttiType
tv)])
                  else (Int, [(Int, RttiType)]) -> TR (Int, [(Int, RttiType)])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
i, [(Int, RttiType)]
extras))
              (Int
i, []) [PrimRep]
prim_reps

findPtrTyss :: Int
            -> [Type]
            -> TR (Int, [(Int, Type)])
findPtrTyss :: Int -> [RttiType] -> TR (Int, [(Int, RttiType)])
findPtrTyss Int
i [RttiType]
tys = ((Int, [(Int, RttiType)])
 -> RttiType -> TR (Int, [(Int, RttiType)]))
-> (Int, [(Int, RttiType)])
-> [RttiType]
-> TR (Int, [(Int, RttiType)])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (Int, [(Int, RttiType)]) -> RttiType -> TR (Int, [(Int, RttiType)])
step (Int
i, []) [RttiType]
tys
  where step :: (Int, [(Int, RttiType)]) -> RttiType -> TR (Int, [(Int, RttiType)])
step (Int
i, [(Int, RttiType)]
discovered) RttiType
elem_ty = do
          (Int
i, [(Int, RttiType)]
extras) <- Int -> RttiType -> TR (Int, [(Int, RttiType)])
findPtrTys Int
i RttiType
elem_ty
          (Int, [(Int, RttiType)]) -> TR (Int, [(Int, RttiType)])
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
i, [(Int, RttiType)]
discovered [(Int, RttiType)] -> [(Int, RttiType)] -> [(Int, RttiType)]
forall a. [a] -> [a] -> [a]
++ [(Int, RttiType)]
extras)


-- Compute the difference between a base type and the type found by RTTI
-- improveType <base_type> <rtti_type>
-- The types can contain skolem type variables, which need to be treated as normal vars.
-- In particular, we want them to unify with things.
improveRTTIType :: HscEnv -> RttiType -> RttiType -> Maybe TCvSubst
improveRTTIType :: HscEnv -> RttiType -> RttiType -> Maybe TCvSubst
improveRTTIType HscEnv
_ RttiType
base_ty RttiType
new_ty = RttiType -> RttiType -> Maybe TCvSubst
U.tcUnifyTyKi RttiType
base_ty RttiType
new_ty

getDataConArgTys :: DataCon -> Type -> TR [Type]
-- Given the result type ty of a constructor application (D a b c :: ty)
-- return the types of the arguments.  This is RTTI-land, so 'ty' might
-- not be fully known.  Moreover, the arg types might involve existentials;
-- if so, make up fresh RTTI type variables for them
--
-- I believe that con_app_ty should not have any enclosing foralls
getDataConArgTys :: DataCon -> RttiType -> IOEnv (Env TcGblEnv TcLclEnv) [RttiType]
getDataConArgTys DataCon
dc RttiType
con_app_ty
  = do { let rep_con_app_ty :: RttiType
rep_con_app_ty = RttiType -> RttiType
unwrapType RttiType
con_app_ty
       ; SDoc -> TR ()
traceTR (String -> SDoc
text String
"getDataConArgTys 1" SDoc -> SDoc -> SDoc
<+> (RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
con_app_ty SDoc -> SDoc -> SDoc
$$ RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
rep_con_app_ty
                   SDoc -> SDoc -> SDoc
$$ Maybe (TyCon, [RttiType]) -> SDoc
forall a. Outputable a => a -> SDoc
ppr (HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
rep_con_app_ty)))
       ; ASSERT( all isTyVar ex_tvs ) return ()
                 -- ex_tvs can only be tyvars as data types in source
                 -- Haskell cannot mention covar yet (Aug 2018)
       ; (TCvSubst
subst, [TyVar]
_) <- [TyVar] -> TR (TCvSubst, [TyVar])
instTyVars ([TyVar]
univ_tvs [TyVar] -> [TyVar] -> [TyVar]
forall a. [a] -> [a] -> [a]
++ [TyVar]
ex_tvs)
       ; RttiType -> RttiType -> TR ()
addConstraint RttiType
rep_con_app_ty (HasCallStack => TCvSubst -> RttiType -> RttiType
TCvSubst -> RttiType -> RttiType
substTy TCvSubst
subst (DataCon -> RttiType
dataConOrigResTy DataCon
dc))
              -- See Note [Constructor arg types]
       ; let con_arg_tys :: [RttiType]
con_arg_tys = HasCallStack => TCvSubst -> [RttiType] -> [RttiType]
TCvSubst -> [RttiType] -> [RttiType]
substTys TCvSubst
subst (DataCon -> [RttiType]
dataConRepArgTys DataCon
dc)
       ; SDoc -> TR ()
traceTR (String -> SDoc
text String
"getDataConArgTys 2" SDoc -> SDoc -> SDoc
<+> (RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
rep_con_app_ty SDoc -> SDoc -> SDoc
$$ [RttiType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [RttiType]
con_arg_tys SDoc -> SDoc -> SDoc
$$ TCvSubst -> SDoc
forall a. Outputable a => a -> SDoc
ppr TCvSubst
subst))
       ; [RttiType] -> IOEnv (Env TcGblEnv TcLclEnv) [RttiType]
forall (m :: * -> *) a. Monad m => a -> m a
return [RttiType]
con_arg_tys }
  where
    univ_tvs :: [TyVar]
univ_tvs = DataCon -> [TyVar]
dataConUnivTyVars DataCon
dc
    ex_tvs :: [TyVar]
ex_tvs   = DataCon -> [TyVar]
dataConExTyCoVars DataCon
dc

{- Note [Constructor arg types]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider a GADT (cf #7386)
   data family D a b
   data instance D [a] a where
     MkT :: a -> D [a] (Maybe a)
     ...

In getDataConArgTys
* con_app_ty is the known type (from outside) of the constructor application,
  say D [Int] Int

* The data constructor MkT has a (representation) dataConTyCon = DList,
  say where
    data DList a where
      MkT :: a -> DList a (Maybe a)
      ...

So the dataConTyCon of the data constructor, DList, differs from
the "outside" type, D. So we can't straightforwardly decompose the
"outside" type, and we end up in the "_" branch of the case.

Then we match the dataConOrigResTy of the data constructor against the
outside type, hoping to get a substitution that tells how to instantiate
the *representation* type constructor.   This looks a bit delicate to
me, but it seems to work.
-}

-- Soundness checks
--------------------
{-
This is not formalized anywhere, so hold to your seats!
RTTI in the presence of newtypes can be a tricky and unsound business.

Example:
~~~~~~~~~
Suppose we are doing RTTI for a partially evaluated
closure t, the real type of which is t :: MkT Int, for

   newtype MkT a = MkT [Maybe a]

The table below shows the results of RTTI and the improvement
calculated for different combinations of evaluatedness and :type t.
Regard the two first columns as input and the next two as output.

  # |     t     |  :type t  | rtti(t)  | improv.    | result
    ------------------------------------------------------------
  1 |     _     |    t b    |    a     | none       | OK
  2 |     _     |   MkT b   |    a     | none       | OK
  3 |     _     |   t Int   |    a     | none       | OK

  If t is not evaluated at *all*, we are safe.

  4 |  (_ : _)  |    t b    |   [a]    | t = []     | UNSOUND
  5 |  (_ : _)  |   MkT b   |  MkT a   | none       | OK (compensating for the missing newtype)
  6 |  (_ : _)  |   t Int   |  [Int]   | t = []     | UNSOUND

  If a is a minimal whnf, we run into trouble. Note that
  row 5 above does newtype enrichment on the ty_rtty parameter.

  7 | (Just _:_)|    t b    |[Maybe a] | t = [],    | UNSOUND
    |                       |          | b = Maybe a|

  8 | (Just _:_)|   MkT b   |  MkT a   |  none      | OK
  9 | (Just _:_)|   t Int   |   FAIL   |  none      | OK

  And if t is any more evaluated than whnf, we are still in trouble.
  Because constraints are solved in top-down order, when we reach the
  Maybe subterm what we got is already unsound. This explains why the
  row 9 fails to complete.

  10 | (Just _:_)|  t Int  | [Maybe a]   |  FAIL    | OK
  11 | (Just 1:_)|  t Int  | [Maybe Int] |  FAIL    | OK

  We can undo the failure in row 9 by leaving out the constraint
  coming from the type signature of t (i.e., the 2nd column).
  Note that this type information is still used
  to calculate the improvement. But we fail
  when trying to calculate the improvement, as there is no unifier for
  t Int = [Maybe a] or t Int = [Maybe Int].


  Another set of examples with t :: [MkT (Maybe Int)]  \equiv  [[Maybe (Maybe Int)]]

  # |     t     |    :type t    |  rtti(t)    | improvement | result
    ---------------------------------------------------------------------
  1 |(Just _:_) | [t (Maybe a)] | [[Maybe b]] | t = []      |
    |           |               |             | b = Maybe a |

The checks:
~~~~~~~~~~~
Consider a function obtainType that takes a value and a type and produces
the Term representation and a substitution (the improvement).
Assume an auxiliar rtti' function which does the actual job if recovering
the type, but which may produce a false type.

In pseudocode:

  rtti' :: a -> IO Type  -- Does not use the static type information

  obtainType :: a -> Type -> IO (Maybe (Term, Improvement))
  obtainType v old_ty = do
       rtti_ty <- rtti' v
       if monomorphic rtti_ty || (check rtti_ty old_ty)
        then ...
         else return Nothing
  where check rtti_ty old_ty = check1 rtti_ty &&
                              check2 rtti_ty old_ty

  check1 :: Type -> Bool
  check2 :: Type -> Type -> Bool

Now, if rtti' returns a monomorphic type, we are safe.
If that is not the case, then we consider two conditions.


1. To prevent the class of unsoundness displayed by
   rows 4 and 7 in the example: no higher kind tyvars
   accepted.

  check1 (t a)   = NO
  check1 (t Int) = NO
  check1 ([] a)  = YES

2. To prevent the class of unsoundness shown by row 6,
   the rtti type should be structurally more
   defined than the old type we are comparing it to.
  check2 :: NewType -> OldType -> Bool
  check2 a  _        = True
  check2 [a] a       = True
  check2 [a] (t Int) = False
  check2 [a] (t a)   = False  -- By check1 we never reach this equation
  check2 [Int] a     = True
  check2 [Int] (t Int) = True
  check2 [Maybe a]   (t Int) = False
  check2 [Maybe Int] (t Int) = True
  check2 (Maybe [a])   (m [Int]) = False
  check2 (Maybe [Int]) (m [Int]) = True

-}

check1 :: QuantifiedType -> Bool
check1 :: QuantifiedType -> Bool
check1 ([TyVar]
tvs, RttiType
_) = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (RttiType -> Bool) -> [RttiType] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any RttiType -> Bool
isHigherKind ((TyVar -> RttiType) -> [TyVar] -> [RttiType]
forall a b. (a -> b) -> [a] -> [b]
map TyVar -> RttiType
tyVarKind [TyVar]
tvs)
 where
   isHigherKind :: RttiType -> Bool
isHigherKind = Bool -> Bool
not (Bool -> Bool) -> (RttiType -> Bool) -> RttiType -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TyCoBinder] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([TyCoBinder] -> Bool)
-> (RttiType -> [TyCoBinder]) -> RttiType -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([TyCoBinder], RttiType) -> [TyCoBinder]
forall a b. (a, b) -> a
fst (([TyCoBinder], RttiType) -> [TyCoBinder])
-> (RttiType -> ([TyCoBinder], RttiType))
-> RttiType
-> [TyCoBinder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RttiType -> ([TyCoBinder], RttiType)
splitPiTys

check2 :: QuantifiedType -> QuantifiedType -> Bool
check2 :: QuantifiedType -> QuantifiedType -> Bool
check2 ([TyVar]
_, RttiType
rtti_ty) ([TyVar]
_, RttiType
old_ty)
  | Just (TyCon
_, [RttiType]
rttis) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
rtti_ty
  = case () of
      ()
_ | Just (TyCon
_,[RttiType]
olds) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
old_ty
        -> [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and([Bool] -> Bool) -> [Bool] -> Bool
forall a b. (a -> b) -> a -> b
$ (QuantifiedType -> QuantifiedType -> Bool)
-> [QuantifiedType] -> [QuantifiedType] -> [Bool]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith QuantifiedType -> QuantifiedType -> Bool
check2 ((RttiType -> QuantifiedType) -> [RttiType] -> [QuantifiedType]
forall a b. (a -> b) -> [a] -> [b]
map RttiType -> QuantifiedType
quantifyType [RttiType]
rttis) ((RttiType -> QuantifiedType) -> [RttiType] -> [QuantifiedType]
forall a b. (a -> b) -> [a] -> [b]
map RttiType -> QuantifiedType
quantifyType [RttiType]
olds)
      ()
_ | Just (RttiType, RttiType)
_ <- RttiType -> Maybe (RttiType, RttiType)
splitAppTy_maybe RttiType
old_ty
        -> RttiType -> Bool
isMonomorphicOnNonPhantomArgs RttiType
rtti_ty
      ()
_ -> Bool
True
  | Bool
otherwise = Bool
True

-- Dealing with newtypes
--------------------------
{-
 congruenceNewtypes does a parallel fold over two Type values,
 compensating for missing newtypes on both sides.
 This is necessary because newtypes are not present
 in runtime, but sometimes there is evidence available.
   Evidence can come from DataCon signatures or
 from compile-time type inference.
 What we are doing here is an approximation
 of unification modulo a set of equations derived
 from newtype definitions. These equations should be the
 same as the equality coercions generated for newtypes
 in System Fc. The idea is to perform a sort of rewriting,
 taking those equations as rules, before launching unification.

 The caller must ensure the following.
 The 1st type (lhs) comes from the heap structure of ptrs,nptrs.
 The 2nd type (rhs) comes from a DataCon type signature.
 Rewriting (i.e. adding/removing a newtype wrapper) can happen
 in both types, but in the rhs it is restricted to the result type.

   Note that it is very tricky to make this 'rewriting'
 work with the unification implemented by TcM, where
 substitutions are operationally inlined. The order in which
 constraints are unified is vital as we cannot modify
 anything that has been touched by a previous unification step.
Therefore, congruenceNewtypes is sound only if the types
recovered by the RTTI mechanism are unified Top-Down.
-}
congruenceNewtypes ::  TcType -> TcType -> TR (TcType,TcType)
congruenceNewtypes :: RttiType -> RttiType -> TR (RttiType, RttiType)
congruenceNewtypes RttiType
lhs RttiType
rhs = RttiType -> RttiType -> TR RttiType
go RttiType
lhs RttiType
rhs TR RttiType
-> (RttiType -> TR (RttiType, RttiType)) -> TR (RttiType, RttiType)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \RttiType
rhs' -> (RttiType, RttiType) -> TR (RttiType, RttiType)
forall (m :: * -> *) a. Monad m => a -> m a
return (RttiType
lhs,RttiType
rhs')
 where
   go :: RttiType -> RttiType -> TR RttiType
go RttiType
l RttiType
r
 -- TyVar lhs inductive case
    | Just TyVar
tv <- RttiType -> Maybe TyVar
getTyVar_maybe RttiType
l
    , TyVar -> Bool
isTcTyVar TyVar
tv
    , TyVar -> Bool
isMetaTyVar TyVar
tv
    = TR RttiType -> TR RttiType -> TR RttiType
forall r. TcM r -> TcM r -> TcM r
recoverTR (RttiType -> TR RttiType
forall (m :: * -> *) a. Monad m => a -> m a
return RttiType
r) (TR RttiType -> TR RttiType) -> TR RttiType -> TR RttiType
forall a b. (a -> b) -> a -> b
$ do
         Indirect RttiType
ty_v <- TyVar -> TcM MetaDetails
readMetaTyVar TyVar
tv
         SDoc -> TR ()
traceTR (SDoc -> TR ()) -> SDoc -> TR ()
forall a b. (a -> b) -> a -> b
$ [SDoc] -> SDoc
fsep [String -> SDoc
text String
"(congruence) Following indirect tyvar:",
                          TyVar -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyVar
tv, SDoc
equals, RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
ty_v]
         RttiType -> RttiType -> TR RttiType
go RttiType
ty_v RttiType
r
-- FunTy inductive case
    | Just (RttiType
l1,RttiType
l2) <- RttiType -> Maybe (RttiType, RttiType)
splitFunTy_maybe RttiType
l
    , Just (RttiType
r1,RttiType
r2) <- RttiType -> Maybe (RttiType, RttiType)
splitFunTy_maybe RttiType
r
    = do RttiType
r2' <- RttiType -> RttiType -> TR RttiType
go RttiType
l2 RttiType
r2
         RttiType
r1' <- RttiType -> RttiType -> TR RttiType
go RttiType
l1 RttiType
r1
         RttiType -> TR RttiType
forall (m :: * -> *) a. Monad m => a -> m a
return (RttiType -> RttiType -> RttiType
mkVisFunTy RttiType
r1' RttiType
r2')
-- TyconApp Inductive case; this is the interesting bit.
    | Just (TyCon
tycon_l, [RttiType]
_) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
lhs
    , Just (TyCon
tycon_r, [RttiType]
_) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe RttiType
rhs
    , TyCon
tycon_l TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
/= TyCon
tycon_r
    = TyCon -> RttiType -> TR RttiType
upgrade TyCon
tycon_l RttiType
r

    | Bool
otherwise = RttiType -> TR RttiType
forall (m :: * -> *) a. Monad m => a -> m a
return RttiType
r

    where upgrade :: TyCon -> Type -> TR Type
          upgrade :: TyCon -> RttiType -> TR RttiType
upgrade TyCon
new_tycon RttiType
ty
            | Bool -> Bool
not (TyCon -> Bool
isNewTyCon TyCon
new_tycon) = do
              SDoc -> TR ()
traceTR (String -> SDoc
text String
"(Upgrade) Not matching newtype evidence: " SDoc -> SDoc -> SDoc
<>
                       TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
new_tycon SDoc -> SDoc -> SDoc
<> String -> SDoc
text String
" for " SDoc -> SDoc -> SDoc
<> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
ty)
              RttiType -> TR RttiType
forall (m :: * -> *) a. Monad m => a -> m a
return RttiType
ty
            | Bool
otherwise = do
               SDoc -> TR ()
traceTR (String -> SDoc
text String
"(Upgrade) upgraded " SDoc -> SDoc -> SDoc
<> RttiType -> SDoc
forall a. Outputable a => a -> SDoc
ppr RttiType
ty SDoc -> SDoc -> SDoc
<>
                        String -> SDoc
text String
" in presence of newtype evidence " SDoc -> SDoc -> SDoc
<> TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
new_tycon)
               (TCvSubst
_, [TyVar]
vars) <- [TyVar] -> TR (TCvSubst, [TyVar])
instTyVars (TyCon -> [TyVar]
tyConTyVars TyCon
new_tycon)
               let ty' :: RttiType
ty' = TyCon -> [RttiType] -> RttiType
mkTyConApp TyCon
new_tycon ([TyVar] -> [RttiType]
mkTyVarTys [TyVar]
vars)
                   rep_ty :: RttiType
rep_ty = RttiType -> RttiType
unwrapType RttiType
ty'
               TcCoercionN
_ <- TcM TcCoercionN -> TcM TcCoercionN
forall a. TcM a -> TcM a
liftTcM (Maybe (HsExpr GhcRn) -> RttiType -> RttiType -> TcM TcCoercionN
unifyType Maybe (HsExpr GhcRn)
forall a. Maybe a
Nothing RttiType
ty RttiType
rep_ty)
        -- assumes that reptype doesn't ^^^^ touch tyconApp args
               RttiType -> TR RttiType
forall (m :: * -> *) a. Monad m => a -> m a
return RttiType
ty'


zonkTerm :: Term -> TcM Term
zonkTerm :: Term -> TR Term
zonkTerm = TermFoldM (IOEnv (Env TcGblEnv TcLclEnv)) Term -> Term -> TR Term
forall (m :: * -> *) a. Monad m => TermFoldM m a -> Term -> m a
foldTermM (TermFoldM :: forall (m :: * -> *) a.
TermProcessor a (m a)
-> (RttiType -> [Word] -> m a)
-> (ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> m a)
-> (RttiType -> Either String DataCon -> a -> m a)
-> (RttiType -> a -> m a)
-> TermFoldM m a
TermFoldM
             { fTermM :: TermProcessor Term (TR Term)
fTermM = \RttiType
ty Either String DataCon
dc ForeignHValue
v [Term]
tt -> RttiType -> TR RttiType
zonkRttiType RttiType
ty    TR RttiType -> (RttiType -> TR Term) -> TR Term
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \RttiType
ty' ->
                                       Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return (TermProcessor Term Term
Term RttiType
ty' Either String DataCon
dc ForeignHValue
v [Term]
tt)
             , fSuspensionM :: ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> TR Term
fSuspensionM  = \ClosureType
ct RttiType
ty ForeignHValue
v Maybe Name
b -> RttiType -> TR RttiType
zonkRttiType RttiType
ty TR RttiType -> (RttiType -> TR Term) -> TR Term
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \RttiType
ty ->
                                             Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return (ClosureType -> RttiType -> ForeignHValue -> Maybe Name -> Term
Suspension ClosureType
ct RttiType
ty ForeignHValue
v Maybe Name
b)
             , fNewtypeWrapM :: RttiType -> Either String DataCon -> Term -> TR Term
fNewtypeWrapM = \RttiType
ty Either String DataCon
dc Term
t -> RttiType -> TR RttiType
zonkRttiType RttiType
ty TR RttiType -> (RttiType -> TR Term) -> TR Term
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \RttiType
ty' ->
                                           Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return(Term -> TR Term) -> Term -> TR Term
forall a b. (a -> b) -> a -> b
$ RttiType -> Either String DataCon -> Term -> Term
NewtypeWrap RttiType
ty' Either String DataCon
dc Term
t
             , fRefWrapM :: RttiType -> Term -> TR Term
fRefWrapM     = \RttiType
ty Term
t -> (RttiType -> Term -> Term)
-> IOEnv (Env TcGblEnv TcLclEnv) (RttiType -> Term -> Term)
forall (m :: * -> *) a. Monad m => a -> m a
return RttiType -> Term -> Term
RefWrap  IOEnv (Env TcGblEnv TcLclEnv) (RttiType -> Term -> Term)
-> TR RttiType -> IOEnv (Env TcGblEnv TcLclEnv) (Term -> Term)
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
`ap`
                                        RttiType -> TR RttiType
zonkRttiType RttiType
ty IOEnv (Env TcGblEnv TcLclEnv) (Term -> Term) -> TR Term -> TR Term
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
`ap` Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return Term
t
             , fPrimM :: RttiType -> [Word] -> TR Term
fPrimM        = (Term -> TR Term
forall (m :: * -> *) a. Monad m => a -> m a
return(Term -> TR Term) -> ([Word] -> Term) -> [Word] -> TR Term
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) (([Word] -> Term) -> [Word] -> TR Term)
-> (RttiType -> [Word] -> Term) -> RttiType -> [Word] -> TR Term
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RttiType -> [Word] -> Term
Prim })

zonkRttiType :: TcType -> TcM Type
-- Zonk the type, replacing any unbound Meta tyvars
-- by RuntimeUnk skolems, safely out of Meta-tyvar-land
zonkRttiType :: RttiType -> TR RttiType
zonkRttiType RttiType
ty= do { ZonkEnv
ze <- ZonkFlexi -> TcM ZonkEnv
mkEmptyZonkEnv ZonkFlexi
RuntimeUnkFlexi
                    ; ZonkEnv -> RttiType -> TR RttiType
zonkTcTypeToTypeX ZonkEnv
ze RttiType
ty }

--------------------------------------------------------------------------------
-- Restore Class predicates out of a representation type
dictsView :: Type -> Type
dictsView :: RttiType -> RttiType
dictsView RttiType
ty = RttiType
ty


-- Use only for RTTI types
isMonomorphic :: RttiType -> Bool
isMonomorphic :: RttiType -> Bool
isMonomorphic RttiType
ty = Bool
noExistentials Bool -> Bool -> Bool
&& Bool
noUniversals
 where ([TyVar]
tvs, [RttiType]
_, RttiType
ty')  = RttiType -> ([TyVar], [RttiType], RttiType)
tcSplitSigmaTy RttiType
ty
       noExistentials :: Bool
noExistentials = RttiType -> Bool
noFreeVarsOfType RttiType
ty'
       noUniversals :: Bool
noUniversals   = [TyVar] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TyVar]
tvs

-- Use only for RTTI types
isMonomorphicOnNonPhantomArgs :: RttiType -> Bool
isMonomorphicOnNonPhantomArgs :: RttiType -> Bool
isMonomorphicOnNonPhantomArgs RttiType
ty
  | Just (TyCon
tc, [RttiType]
all_args) <- HasCallStack => RttiType -> Maybe (TyCon, [RttiType])
RttiType -> Maybe (TyCon, [RttiType])
tcSplitTyConApp_maybe (RttiType -> RttiType
unwrapType RttiType
ty)
  , [TyVar]
phantom_vars  <- TyCon -> [TyVar]
tyConPhantomTyVars TyCon
tc
  , [RttiType]
concrete_args <- [ RttiType
arg | (TyVar
tyv,RttiType
arg) <- TyCon -> [TyVar]
tyConTyVars TyCon
tc [TyVar] -> [RttiType] -> [(TyVar, RttiType)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [RttiType]
all_args
                           , TyVar
tyv TyVar -> [TyVar] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [TyVar]
phantom_vars]
  = (RttiType -> Bool) -> [RttiType] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all RttiType -> Bool
isMonomorphicOnNonPhantomArgs [RttiType]
concrete_args
  | Just (RttiType
ty1, RttiType
ty2) <- RttiType -> Maybe (RttiType, RttiType)
splitFunTy_maybe RttiType
ty
  = (RttiType -> Bool) -> [RttiType] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all RttiType -> Bool
isMonomorphicOnNonPhantomArgs [RttiType
ty1,RttiType
ty2]
  | Bool
otherwise = RttiType -> Bool
isMonomorphic RttiType
ty

tyConPhantomTyVars :: TyCon -> [TyVar]
tyConPhantomTyVars :: TyCon -> [TyVar]
tyConPhantomTyVars TyCon
tc
  | TyCon -> Bool
isAlgTyCon TyCon
tc
  , Just [DataCon]
dcs <- TyCon -> Maybe [DataCon]
tyConDataCons_maybe TyCon
tc
  , [TyVar]
dc_vars  <- (DataCon -> [TyVar]) -> [DataCon] -> [TyVar]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap DataCon -> [TyVar]
dataConUnivTyVars [DataCon]
dcs
  = TyCon -> [TyVar]
tyConTyVars TyCon
tc [TyVar] -> [TyVar] -> [TyVar]
forall a. Eq a => [a] -> [a] -> [a]
\\ [TyVar]
dc_vars
tyConPhantomTyVars TyCon
_ = []

type QuantifiedType = ([TyVar], Type)
   -- Make the free type variables explicit
   -- The returned Type should have no top-level foralls (I believe)

quantifyType :: Type -> QuantifiedType
-- Generalize the type: find all free and forall'd tyvars
-- and return them, together with the type inside, which
-- should not be a forall type.
--
-- Thus (quantifyType (forall a. a->[b]))
-- returns ([a,b], a -> [b])

quantifyType :: RttiType -> QuantifiedType
quantifyType RttiType
ty = ( (TyVar -> Bool) -> [TyVar] -> [TyVar]
forall a. (a -> Bool) -> [a] -> [a]
filter TyVar -> Bool
isTyVar ([TyVar] -> [TyVar]) -> [TyVar] -> [TyVar]
forall a b. (a -> b) -> a -> b
$
                    RttiType -> [TyVar]
tyCoVarsOfTypeWellScoped RttiType
rho
                  , RttiType
rho)
  where
    ([TyVar]
_tvs, RttiType
rho) = RttiType -> QuantifiedType
tcSplitForAllTys RttiType
ty