@@ -42,6 +42,8 @@ import qualified Data.IntMap as IM
42
42
import Control.Monad.Reader
43
43
44
44
import GHC.Debugger.Interface.Messages
45
+ import GHC.Debugger.Runtime.Term.Key
46
+ import GHC.Debugger.Runtime.Term.Cache
45
47
import System.Posix.Signals
46
48
47
49
-- | A debugger action.
@@ -57,20 +59,21 @@ data DebuggerState = DebuggerState
57
59
{ activeBreakpoints :: IORef (ModuleEnv (IM. IntMap (BreakpointStatus , BreakpointKind )))
58
60
-- ^ Maps a 'BreakpointId' in Trie representation to the
59
61
-- 'BreakpointStatus' it was activated with.
60
- , varReferences :: IORef (IM. IntMap (Name , Term ), NameEnv Int )
62
+
63
+ , varReferences :: IORef (IM. IntMap TermKey , TermKeyMap Int )
61
64
-- ^ When we're stopped at a breakpoint, this maps variable reference to
62
65
-- Terms to allow further inspection and forcing by reference.
63
66
--
64
67
-- This map is only valid while stopped in this context. After stepping
65
68
-- or resuming evaluation in any available way, this map becomes invalid
66
69
-- and should therefore be cleaned.
67
70
--
68
- -- The NameEnv map is a reverse lookup map to find which references already exist for given names
69
- , varFieldsMap :: IORef ( NameEnv ( IM. IntMap Name ))
70
- -- ^ A mapping from Name to an IntMap mapping indices to their unique Names
71
- -- e.g. `x :-> { 1 :-> _1, 2 :-> _2 }
72
- -- This map allows us to re-use Names for sub-fields rather than creating
73
- -- them new every time. See 'mkIndexVarName'
71
+ -- The TermKeyMap map is a reverse lookup map to find which references
72
+ -- already exist for given names
73
+
74
+ , termCache :: IORef TermCache
75
+ -- ^ TermCache
76
+
74
77
, genUniq :: IORef Int
75
78
-- ^ Generates unique ints
76
79
}
@@ -309,54 +312,29 @@ getModuleByPath path = do
309
312
--------------------------------------------------------------------------------
310
313
311
314
-- | Find a variable's associated Term and Name by reference ('Int')
312
- lookupVarByReference :: Int -> Debugger (Maybe ( Name , Term ) )
315
+ lookupVarByReference :: Int -> Debugger (Maybe TermKey )
313
316
lookupVarByReference i = do
314
317
ioref <- asks varReferences
315
318
(rm, _) <- readIORef ioref & liftIO
316
319
return $ IM. lookup i rm
317
320
318
- -- | Inserts a mapping from the given variable reference to the variable's
319
- -- associated Term and the Name it is bound to for display
320
- --
321
- -- Returns: the variable reference (either a fresh one, or the existing one for this name)
322
- insertVarReference :: Name -> Term -> Debugger Int
323
- insertVarReference name term = do
324
- ioref <- asks varReferences
325
- (rm, nm) <- readIORef ioref & liftIO
326
- (i, nm') <- case lookupNameEnv nm name of
327
- Nothing -> do
321
+ -- | Finds or creates an integer var reference for the given 'TermKey'.
322
+ -- TODO: Arguably, this mapping should be part of the debug-adapter, and
323
+ -- ghc-debugger should deal in 'TermKey' terms only.
324
+ getVarReference :: TermKey -> Debugger Int
325
+ getVarReference key = do
326
+ ioref <- asks varReferences
327
+ (rm, tkm) <- readIORef ioref & liftIO
328
+ (i, tkm') <- case lookupTermKeyMap key tkm of
329
+ Nothing -> do
328
330
new_i <- freshInt
329
- return (new_i, extendNameEnv nm name new_i)
330
- Just existing ->
331
- return (existing, nm)
332
- let
333
- rm' = IM. insert i (name, term) rm
334
- writeIORef ioref (rm', nm') & liftIO
331
+ return (new_i, insertTermKeyMap key new_i tkm)
332
+ Just existing_i ->
333
+ return (existing_i, tkm)
334
+ let rm' = IM. insert i key rm
335
+ writeIORef ioref (rm', tkm') & liftIO
335
336
return i
336
337
337
- -- | Create or find the 'Name' for a parent Name by positional index
338
- --
339
- -- The name is cached the first time it is created and re-used for subsequent
340
- -- accesses in the same context.
341
- mkPositionalVarFieldName :: Name {-^ Parent Name -} -> Int {-^ Index -} -> Debugger Name
342
- mkPositionalVarFieldName parent ix = do
343
- vfm_ref <- asks varFieldsMap
344
- vfm <- liftIO $ readIORef vfm_ref
345
- let ixmap = case lookupNameEnv vfm parent of
346
- Nothing -> mempty
347
- Just ixm -> ixm
348
- case IM. lookup ix ixmap of
349
- Just fieldName -> return fieldName
350
- Nothing -> do
351
- u <- liftIO $ uniqFromTag ' F'
352
- let
353
- fieldName
354
- = mkDerivedInternalName (\ nocc -> mkVarOcc (" _" ++ show @ Int ix))
355
- u parent
356
- liftIO $ writeIORef vfm_ref $
357
- extendNameEnv vfm parent (IM. insert ix fieldName ixmap)
358
- return fieldName
359
-
360
338
-- | Whenever we run a request that continues execution from the current
361
339
-- suspended state, such as Next,Step,Continue, this function should be called
362
340
-- to delete the variable references that become invalid as we leave the
@@ -367,17 +345,18 @@ mkPositionalVarFieldName parent ix = do
367
345
-- See also section "Lifetime of Objects References" in the DAP specification.
368
346
leaveSuspendedState :: Debugger ()
369
347
leaveSuspendedState = do
370
- -- TODO:
371
- -- [ ] Preserve bindings introduced by evaluate requests?
372
348
ioref <- asks varReferences
373
- vfRef <- asks varFieldsMap
374
349
liftIO $ writeIORef ioref mempty
375
- liftIO $ writeIORef vfRef mempty
376
350
377
351
--------------------------------------------------------------------------------
378
352
-- Utilities
379
353
--------------------------------------------------------------------------------
380
354
355
+ defaultDepth :: Int
356
+ defaultDepth = 2 -- the depth determines how much of the runtime structure is traversed.
357
+ -- @obtainTerm@ and friends handle fetching arbitrarily nested data structures
358
+ -- so we only depth enough to get to the next level of subterms.
359
+
381
360
-- | Evaluate a suspended Term to WHNF.
382
361
--
383
362
-- Used in @'getVariables'@ to reply to a variable introspection request.
@@ -393,9 +372,11 @@ seqTerm term = do
393
372
() <- fromEvalResult r
394
373
let
395
374
forceThunks = False {- whether to force the thunk subterms -}
396
- forceDepth = 5
375
+ forceDepth = defaultDepth
397
376
cvObtainTerm hsc_env forceDepth forceThunks ty val
398
- NewtypeWrap {wrapped_term} -> seqTerm wrapped_term
377
+ NewtypeWrap {wrapped_term} -> do
378
+ wrapped_term' <- seqTerm wrapped_term
379
+ return term{wrapped_term= wrapped_term'}
399
380
_ -> return term
400
381
401
382
-- | Evaluate a Term to NF
0 commit comments