{-# LANGUAGE CPP, NamedFieldPuns, TupleSections, LambdaCase,
DuplicateRecordFields, RecordWildCards, TupleSections, ViewPatterns,
TypeApplications, ScopedTypeVariables, BangPatterns #-}
module GHC.Debugger.Stopped.Variables where
import Data.IORef
import Control.Monad
import Control.Monad.Reader
import Control.Monad.IO.Class
import GHC
import GHC.Types.FieldLabel
import GHC.Runtime.Eval
import GHC.Core.DataCon
import GHC.Types.Id as GHC
import qualified GHC.Runtime.Debugger as GHCD
import qualified GHC.Runtime.Heap.Inspect as GHCI
import GHC.Debugger.Monad
import GHC.Debugger.Interface.Messages
import GHC.Debugger.Runtime
import GHC.Debugger.Runtime.Term.Key
import GHC.Debugger.Runtime.Term.Cache
import GHC.Debugger.Utils
tyThingToVarInfo :: TyThing -> Debugger VarInfo
tyThingToVarInfo :: TyThing -> Debugger VarInfo
tyThingToVarInfo = \case
t :: TyThing
t@(AConLike ConLike
c) -> String -> String -> String -> Bool -> VariableReference -> VarInfo
VarInfo (String
-> String -> String -> Bool -> VariableReference -> VarInfo)
-> Debugger String
-> Debugger
(String -> String -> Bool -> VariableReference -> VarInfo)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ConLike -> Debugger String
forall a. Outputable a => a -> Debugger String
display ConLike
c Debugger (String -> String -> Bool -> VariableReference -> VarInfo)
-> Debugger String
-> Debugger (String -> Bool -> VariableReference -> VarInfo)
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TyThing -> Debugger String
forall a. Outputable a => a -> Debugger String
display TyThing
t Debugger (String -> Bool -> VariableReference -> VarInfo)
-> Debugger String
-> Debugger (Bool -> VariableReference -> VarInfo)
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TyThing -> Debugger String
forall a. Outputable a => a -> Debugger String
display TyThing
t Debugger (Bool -> VariableReference -> VarInfo)
-> Debugger Bool -> Debugger (VariableReference -> VarInfo)
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Bool -> Debugger Bool
forall a. a -> Debugger a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False Debugger (VariableReference -> VarInfo)
-> Debugger VariableReference -> Debugger VarInfo
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VariableReference -> Debugger VariableReference
forall a. a -> Debugger a
forall (f :: * -> *) a. Applicative f => a -> f a
pure VariableReference
NoVariables
t :: TyThing
t@(ATyCon TyCon
c) -> String -> String -> String -> Bool -> VariableReference -> VarInfo
VarInfo (String
-> String -> String -> Bool -> VariableReference -> VarInfo)
-> Debugger String
-> Debugger
(String -> String -> Bool -> VariableReference -> VarInfo)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TyCon -> Debugger String
forall a. Outputable a => a -> Debugger String
display TyCon
c Debugger (String -> String -> Bool -> VariableReference -> VarInfo)
-> Debugger String
-> Debugger (String -> Bool -> VariableReference -> VarInfo)
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TyThing -> Debugger String
forall a. Outputable a => a -> Debugger String
display TyThing
t Debugger (String -> Bool -> VariableReference -> VarInfo)
-> Debugger String
-> Debugger (Bool -> VariableReference -> VarInfo)
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TyThing -> Debugger String
forall a. Outputable a => a -> Debugger String
display TyThing
t Debugger (Bool -> VariableReference -> VarInfo)
-> Debugger Bool -> Debugger (VariableReference -> VarInfo)
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Bool -> Debugger Bool
forall a. a -> Debugger a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False Debugger (VariableReference -> VarInfo)
-> Debugger VariableReference -> Debugger VarInfo
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VariableReference -> Debugger VariableReference
forall a. a -> Debugger a
forall (f :: * -> *) a. Applicative f => a -> f a
pure VariableReference
NoVariables
t :: TyThing
t@(ACoAxiom CoAxiom Branched
c) -> String -> String -> String -> Bool -> VariableReference -> VarInfo
VarInfo (String
-> String -> String -> Bool -> VariableReference -> VarInfo)
-> Debugger String
-> Debugger
(String -> String -> Bool -> VariableReference -> VarInfo)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CoAxiom Branched -> Debugger String
forall a. Outputable a => a -> Debugger String
display CoAxiom Branched
c Debugger (String -> String -> Bool -> VariableReference -> VarInfo)
-> Debugger String
-> Debugger (String -> Bool -> VariableReference -> VarInfo)
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TyThing -> Debugger String
forall a. Outputable a => a -> Debugger String
display TyThing
t Debugger (String -> Bool -> VariableReference -> VarInfo)
-> Debugger String
-> Debugger (Bool -> VariableReference -> VarInfo)
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TyThing -> Debugger String
forall a. Outputable a => a -> Debugger String
display TyThing
t Debugger (Bool -> VariableReference -> VarInfo)
-> Debugger Bool -> Debugger (VariableReference -> VarInfo)
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Bool -> Debugger Bool
forall a. a -> Debugger a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False Debugger (VariableReference -> VarInfo)
-> Debugger VariableReference -> Debugger VarInfo
forall a b. Debugger (a -> b) -> Debugger a -> Debugger b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VariableReference -> Debugger VariableReference
forall a. a -> Debugger a
forall (f :: * -> *) a. Applicative f => a -> f a
pure VariableReference
NoVariables
AnId Id
i -> do
let key :: TermKey
key = Id -> TermKey
FromId Id
i
term <- TermKey -> Debugger Term
obtainTerm TermKey
key
termToVarInfo key term
termVarFields :: TermKey -> Term -> Debugger VarFields
termVarFields :: TermKey -> Term -> Debugger VarFields
termVarFields TermKey
top_key Term
top_term =
case Term
top_term of
Term
_ | RttiType -> Bool
isBoringTy (Term -> RttiType
GHCI.termType Term
top_term) ->
VarFields -> Debugger VarFields
forall a. a -> Debugger a
forall (m :: * -> *) a. Monad m => a -> m a
return VarFields
NoFields
Term{dc :: Term -> Either String DataCon
dc=Right DataCon
dc, subTerms :: Term -> [Term]
subTerms=[Term]
_} -> do
case DataCon -> [FieldLabel]
dataConFieldLabels DataCon
dc of
[] -> do
let keys :: [TermKey]
keys = (Int -> Scaled RttiType -> TermKey)
-> [Int] -> [Scaled RttiType] -> [TermKey]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Int
ix Scaled RttiType
_ -> TermKey -> PathFragment -> TermKey
FromPath TermKey
top_key (Int -> PathFragment
PositionalIndex Int
ix)) [Int
1..] (DataCon -> [Scaled RttiType]
dataConOrigArgTys DataCon
dc)
[VarInfo] -> VarFields
IndexedFields ([VarInfo] -> VarFields)
-> Debugger [VarInfo] -> Debugger VarFields
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (TermKey -> Debugger VarInfo) -> [TermKey] -> Debugger [VarInfo]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\TermKey
k -> TermKey -> Debugger Term
obtainTerm TermKey
k Debugger Term -> (Term -> Debugger VarInfo) -> Debugger VarInfo
forall a b. Debugger a -> (a -> Debugger b) -> Debugger b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= TermKey -> Term -> Debugger VarInfo
termToVarInfo TermKey
k) [TermKey]
keys
[FieldLabel]
dataConFields -> do
let keys :: [TermKey]
keys = (FieldLabel -> TermKey) -> [FieldLabel] -> [TermKey]
forall a b. (a -> b) -> [a] -> [b]
map (TermKey -> PathFragment -> TermKey
FromPath TermKey
top_key (PathFragment -> TermKey)
-> (FieldLabel -> PathFragment) -> FieldLabel -> TermKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> PathFragment
LabeledField (Name -> PathFragment)
-> (FieldLabel -> Name) -> FieldLabel -> PathFragment
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FieldLabel -> Name
flSelector) [FieldLabel]
dataConFields
[VarInfo] -> VarFields
LabeledFields ([VarInfo] -> VarFields)
-> Debugger [VarInfo] -> Debugger VarFields
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (TermKey -> Debugger VarInfo) -> [TermKey] -> Debugger [VarInfo]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\TermKey
k -> TermKey -> Debugger Term
obtainTerm TermKey
k Debugger Term -> (Term -> Debugger VarInfo) -> Debugger VarInfo
forall a b. Debugger a -> (a -> Debugger b) -> Debugger b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= TermKey -> Term -> Debugger VarInfo
termToVarInfo TermKey
k) [TermKey]
keys
NewtypeWrap{dc :: Term -> Either String DataCon
dc=Right DataCon
dc, wrapped_term :: Term -> Term
wrapped_term=Term
_} -> do
case DataCon -> [FieldLabel]
dataConFieldLabels DataCon
dc of
[] -> do
let key :: TermKey
key = TermKey -> PathFragment -> TermKey
FromPath TermKey
top_key (Int -> PathFragment
PositionalIndex Int
1)
wvi <- TermKey -> Debugger Term
obtainTerm TermKey
key Debugger Term -> (Term -> Debugger VarInfo) -> Debugger VarInfo
forall a b. Debugger a -> (a -> Debugger b) -> Debugger b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= TermKey -> Term -> Debugger VarInfo
termToVarInfo TermKey
key
return (IndexedFields [wvi])
[FieldLabel
fld] -> do
let key :: TermKey
key = TermKey -> PathFragment -> TermKey
FromPath TermKey
top_key (Name -> PathFragment
LabeledField (FieldLabel -> Name
flSelector FieldLabel
fld))
wvi <- TermKey -> Debugger Term
obtainTerm TermKey
key Debugger Term -> (Term -> Debugger VarInfo) -> Debugger VarInfo
forall a b. Debugger a -> (a -> Debugger b) -> Debugger b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= TermKey -> Term -> Debugger VarInfo
termToVarInfo TermKey
key
return (LabeledFields [wvi])
[FieldLabel]
_ -> String -> Debugger VarFields
forall a. HasCallStack => String -> a
error String
"unexpected number of Newtype fields: larger than 1"
Term
_ -> VarFields -> Debugger VarFields
forall a. a -> Debugger a
forall (m :: * -> *) a. Monad m => a -> m a
return VarFields
NoFields
termToVarInfo :: TermKey -> Term -> Debugger VarInfo
termToVarInfo :: TermKey -> Term -> Debugger VarInfo
termToVarInfo TermKey
key Term
term0 = do
let
isThunk :: Bool
isThunk
| Suspension{} <- Term
term0 = Bool
True
| Bool
otherwise = Bool
False
ty :: RttiType
ty = Term -> RttiType
GHCI.termType Term
term0
term <- if Bool -> Bool
not Bool
isThunk Bool -> Bool -> Bool
&& RttiType -> Bool
isBoringTy RttiType
ty
then TermKey -> Term -> Debugger Term
forceTerm TermKey
key Term
term0
else Term -> Debugger Term
forall a. a -> Debugger a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Term
term0
let
termHead Term
t
| RttiType -> Bool
isBoringTy RttiType
ty = Term
t
| Bool
otherwise = case Term
t of
Term{} -> Term
t{subTerms = []}
NewtypeWrap{Term
wrapped_term :: Term -> Term
wrapped_term :: Term
wrapped_term} -> Term
t{wrapped_term = termHead wrapped_term}
Term
_ -> Term
t
varName <- display key
varType <- display ty
varValue <- display =<< GHCD.showTerm (termHead term)
varRef <- do
if GHCI.isFullyEvaluatedTerm term ||
(not isThunk && (isBoringTy ty || not (hasDirectSubTerms term)))
then do
return NoVariables
else do
ir <- getVarReference key
return (SpecificVariable ir)
return VarInfo{..}
where
hasDirectSubTerms :: Term -> Bool
hasDirectSubTerms = \case
Suspension{} -> Bool
False
Prim{} -> Bool
False
NewtypeWrap{} -> Bool
True
RefWrap{} -> Bool
True
Term{[Term]
subTerms :: Term -> [Term]
subTerms :: [Term]
subTerms} -> Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [Term] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Term]
subTerms
forceTerm :: TermKey -> Term -> Debugger Term
forceTerm :: TermKey -> Term -> Debugger Term
forceTerm TermKey
key Term
term = do
let ty :: RttiType
ty = Term -> RttiType
GHCI.termType Term
term
term' <- if RttiType -> Bool
isBoringTy RttiType
ty
then Term -> Debugger Term
deepseqTerm Term
term
else Term -> Debugger Term
seqTerm Term
term
asks termCache >>= \IORef TermCache
r -> IO () -> Debugger ()
forall a. IO a -> Debugger a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Debugger ()) -> IO () -> Debugger ()
forall a b. (a -> b) -> a -> b
$ IORef TermCache -> (TermCache -> TermCache) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef TermCache
r (TermKey -> Term -> TermCache -> TermCache
insertTermCache TermKey
key Term
term')
return term'