ghc-debugger 0.2.0.0 → 0.3.0.0
raw patch · 6 files changed
+54/−15 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ GHC.Debugger.Stopped.Variables: forceTerm :: TermKey -> Term -> Debugger Term
Files
- README.md +22/−0
- ghc-debugger.cabal +1/−1
- ghc-debugger/GHC/Debugger/Breakpoint.hs +1/−1
- ghc-debugger/GHC/Debugger/Runtime.hs +1/−1
- ghc-debugger/GHC/Debugger/Stopped.hs +2/−7
- ghc-debugger/GHC/Debugger/Stopped/Variables.hs +27/−5
README.md view
@@ -118,3 +118,25 @@ ### Conditionals - [ ] Conditional breakpoints (breakpoint is hit only if condition is satisfied) - [ ] Hit conditional breakpoints (stop after N number of hits)++# Building from source++To build `ghc-debug-adapter`:+```+cabal build -w /path/to/recent/ghc exe:ghc-debug-adapter+```++To build the VSCode extension+```+cd vscode-extension+nix-build+```++## Testing++```+cd test/integration-tests+nix-shell+make GHC=/path/to/recent/ghc \+ DEBUGGER=$(cd ../.. && cabal list-bin -w /path/to/recent/ghc exe:ghc-debug-adapter)+```
ghc-debugger.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: ghc-debugger-version: 0.2.0.0+version: 0.3.0.0 synopsis: A step-through machine-interface debugger for GHC Haskell
ghc-debugger/GHC/Debugger/Breakpoint.hs view
@@ -96,7 +96,7 @@ , sourceSpan = realSrcSpanToSourceSpan spn , breakId = bid }- case findBreakForBind fun_str modBreaks of+ case maybe [] (findBreakForBind fun_str) modBreaks of [] -> do liftIO $ logOutput logger (text $ "No breakpoint found by name " ++ function ++ ". Ignoring...") return BreakNotFound
ghc-debugger/GHC/Debugger/Runtime.hs view
@@ -56,7 +56,7 @@ PositionalIndex ix -> subTerms !! (ix-1) LabeledField fl -> case L.findIndex (== fl) (map flSelector $ dataConFieldLabels dc) of- Just ix -> subTerms !! (ix-1)+ Just ix -> subTerms !! ix Nothing -> error "Couldn't find labeled field in dataConFieldLabels" NewtypeWrap{wrapped_term} -> wrapped_term -- regardless of PathFragment
ghc-debugger/GHC/Debugger/Stopped.hs view
@@ -176,13 +176,8 @@ -- It is a "lazy" DAP variable: our reply can ONLY include -- this single variable. - let ty = GHCI.termType term- term' <- if isBoringTy ty- then deepseqTerm term -- deepseq boring types like String, because it is more helpful to print them whole than their structure.- else seqTerm term- -- update cache with the forced term right away instead of invalidating it.- -- TODO: is this the best place to have this update? what's the better abstraction?- asks termCache >>= \r -> liftIO $ modifyIORef' r (insertTermCache key term')+ term' <- forceTerm key term+ vi <- termToVarInfo key term' return (Left vi)
ghc-debugger/GHC/Debugger/Stopped/Variables.hs view
@@ -3,7 +3,10 @@ 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@@ -17,6 +20,7 @@ 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 -- | 'TyThing' to 'VarInfo'. The 'Bool' argument indicates whether to force the@@ -69,14 +73,19 @@ -- | Construct a 'VarInfo' from the given 'Name' of the variable and the 'Term' it binds termToVarInfo :: TermKey -> Term -> Debugger VarInfo-termToVarInfo key term = do+termToVarInfo key term0 = do -- Make a VarInfo for a term let isThunk- | Suspension{} <- term = True+ | Suspension{} <- term0 = True | otherwise = False- ty = GHCI.termType term+ ty = GHCI.termType term0 + term <- if not isThunk && isBoringTy ty+ then forceTerm key term0 -- make sure that if it's an evaluated boring term then it is /fully/ evaluated.+ else pure term0++ let -- We scrape the subterms to display as the var's value. The structure is -- displayed in the editor itself by expanding the variable sub-fields termHead t@@ -96,12 +105,12 @@ -- We only want to return @SpecificVariable@ (which allows expansion) for -- values with sub-fields or thunks. varRef <- do- if GHCI.isFullyEvaluatedTerm term+ if GHCI.isFullyEvaluatedTerm term || -- Even if it is already evaluated, we do want to display a -- structure as long if it is not a "boring type" (one that does not -- provide useful information from being expanded) -- (e.g. consider how awkward it is to expand Char# 10 and I# 20)- && (isBoringTy ty || not (hasDirectSubTerms term))+ (not isThunk && (isBoringTy ty || not (hasDirectSubTerms term))) then do return NoVariables else do@@ -117,3 +126,16 @@ RefWrap{} -> True Term{subTerms} -> not $ null subTerms +-- | Forces a term to WHNF in the general case, or to NF in the case of 'isBoringTy'.+-- The term is updated at the given key.+forceTerm :: TermKey -> Term -> Debugger Term+forceTerm key term = do+ let ty = GHCI.termType term+ term' <- if isBoringTy ty+ -- deepseq boring types like String, because it is more helpful+ -- to print them whole than their structure.+ then deepseqTerm term+ else seqTerm term+ -- update cache with the forced term right away instead of invalidating it.+ asks termCache >>= \r -> liftIO $ modifyIORef' r (insertTermCache key term')+ return term'