Skip to content

Commit 0c24905

Browse files
committed
feat: Return structured result for all evaluation
In the previous commit we used a contrived approach to returning a structured representation for only variables which were evaluated. However, we can go further and (even more easily/uniformly!) display all evaluated expressions in their structured form. The unstructured form can still be gotten by `show` or `print` (In fact, all expressions evaluated end up being `print`ed to stdout so you see them currently, besides the structured representation, even without manually printing them). Fixes #116 BETTER
1 parent efe6d35 commit 0c24905

File tree

7 files changed

+41
-46
lines changed

7 files changed

+41
-46
lines changed

haskell-debugger/GHC/Debugger/Evaluation.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,10 @@ handleExecResult = \case
192192
ExecComplete {execResult} -> do
193193
case execResult of
194194
Left e -> return (EvalException (show e) "SomeException")
195-
Right [] -> return (EvalCompleted "" "") -- Evaluation completed without binding any result.
195+
Right [] -> return (EvalCompleted "" "" NoVariables) -- Evaluation completed without binding any result.
196196
Right (n:_ns) -> inspectName n >>= \case
197-
Just VarInfo{varValue, varType} -> return (EvalCompleted varValue varType)
197+
Just VarInfo{varValue, varType, varRef} -> do
198+
return (EvalCompleted varValue varType varRef)
198199
Nothing -> liftIO $ fail "doEval failed"
199200
ExecBreak {breakNames = _, breakPointId = Nothing} ->
200201
-- Stopped at an exception

haskell-debugger/GHC/Debugger/Interface/Messages.hs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,13 @@ data BreakFound
243243
deriving (Show, Generic)
244244

245245
data EvalResult
246-
= EvalCompleted { resultVal :: String, resultType :: String }
246+
= EvalCompleted { resultVal :: String
247+
, resultType :: String
248+
, resultStructureRef :: VariableReference
249+
-- ^ A structured representation of the result of evaluating
250+
-- the expression given as a "virtual" 'VariableReference'
251+
-- that the user can expand as a normal variable.
252+
}
247253
| EvalException { resultVal :: String, resultType :: String }
248254
| EvalStopped { breakId :: Maybe GHC.InternalBreakpointId {-^ Did we stop at an exception (@Nothing@) or at a breakpoint (@Just@)? -} }
249255
-- | Evaluation failed for some reason other than completed/completed-with-exception/stopped.

haskell-debugger/GHC/Debugger/Utils.hs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
{-# LANGUAGE CPP, NamedFieldPuns, TupleSections, LambdaCase,
22
DuplicateRecordFields, RecordWildCards, TupleSections, ViewPatterns,
33
TypeApplications, ScopedTypeVariables, BangPatterns #-}
4-
module GHC.Debugger.Utils where
4+
module GHC.Debugger.Utils
5+
( module GHC.Debugger.Utils
6+
, module GHC.Utils.Outputable
7+
, module GHC.Utils.Trace
8+
) where
59

610
import GHC
711
import GHC.Data.FastString
8-
import GHC.Driver.DynFlags as GHC
9-
import GHC.Driver.Ppr as GHC
10-
import GHC.Utils.Outputable as GHC
12+
import GHC.Driver.DynFlags
13+
import GHC.Driver.Ppr
14+
import GHC.Utils.Outputable
15+
import GHC.Utils.Trace
1116

1217
import GHC.Debugger.Monad
1318
import GHC.Debugger.Interface.Messages

hdb/Development/Debug/Adapter/Evaluation.hs

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{-# LANGUAGE RecordWildCards, OverloadedRecordDot, DuplicateRecordFields #-}
22
module Development.Debug.Adapter.Evaluation where
33

4-
import Control.Monad
54
import qualified Data.Text as T
65
import qualified Data.Map as M
76
import qualified Data.IntSet as IS
@@ -38,10 +37,8 @@ startExecution = do
3837
commandEvaluate :: DebugAdaptor ()
3938
commandEvaluate = do
4039
EvaluateArguments {evaluateArgumentsFrameId=_todo, ..} <- getArguments
41-
-- TODO: Proper support for threads/stack frames/scopes id.
42-
-- Currently: ignore `evaluateArgumentsFrameId` and always use instead:
4340

44-
let notAVarResp res ty = EvaluateResponse
41+
let simpleEvalResp res ty = EvaluateResponse
4542
{ evaluateResponseResult = res
4643
, evaluateResponseType = ty
4744
, evaluateResponsePresentationHint = Nothing
@@ -51,38 +48,24 @@ commandEvaluate = do
5148
, evaluateResponseMemoryReference = Nothing
5249
}
5350

54-
-- Only evaluate expression if it is not a variable found in the given `evaluateArgumentsFrameId`
55-
let doEvaluate = do
56-
DidEval er <- sendSync (DoEval (T.unpack evaluateArgumentsExpression))
57-
case er of
58-
EvalStopped{} -> error "impossible, execution is resumed automatically for 'DoEval'"
59-
EvalAbortedWith e -> do
60-
-- Evaluation failed, we report it but don't terminate.
61-
sendEvaluateResponse (notAVarResp (T.pack e) (T.pack ""))
62-
_ -> do
63-
sendEvaluateResponse (notAVarResp (T.pack $ resultVal er) (T.pack $ resultType er))
64-
65-
-- Shortcut. Single word expression may be variable in scope (#116)
66-
case T.words evaluateArgumentsExpression of
67-
[possiblyVar] -> do
68-
GotScopes scopes <- sendSync (GetScopes {-todo: use evaluateArgumentsFrameId-})
69-
foundVars <- forM (filter (not . expensive) scopes) $ \scope -> do
70-
GotVariables vars <- sendSync (GetVariables (scopeToVarRef scope.kind))
71-
return (either (:[]) id vars)
72-
case filter ((==possiblyVar) . T.pack . (.varName)) (concat foundVars) of
73-
foundOne:_ -> -- found it!
74-
sendEvaluateResponse EvaluateResponse
75-
{ evaluateResponseResult = T.pack foundOne.varValue
76-
, evaluateResponseType = T.pack foundOne.varType
77-
, evaluateResponsePresentationHint = Nothing
78-
, evaluateResponseVariablesReference = fromEnum foundOne.varRef
79-
, evaluateResponseNamedVariables = Nothing
80-
, evaluateResponseIndexedVariables = Nothing
81-
, evaluateResponseMemoryReference = Nothing
82-
}
83-
[] -> doEvaluate
84-
_ -> doEvaluate
85-
51+
DidEval er <- sendSync (DoEval (T.unpack evaluateArgumentsExpression))
52+
case er of
53+
EvalStopped{} -> error "impossible, execution is resumed automatically for 'DoEval'"
54+
EvalAbortedWith e ->
55+
-- Evaluation failed, we report it but don't terminate.
56+
sendEvaluateResponse (simpleEvalResp (T.pack e) (T.pack ""))
57+
EvalException {resultVal, resultType} ->
58+
sendEvaluateResponse (simpleEvalResp (T.pack resultVal) (T.pack resultType))
59+
EvalCompleted{resultVal, resultType, resultStructureRef} -> do
60+
sendEvaluateResponse EvaluateResponse
61+
{ evaluateResponseResult = T.pack resultVal
62+
, evaluateResponseType = T.pack resultType
63+
, evaluateResponsePresentationHint = Nothing
64+
, evaluateResponseVariablesReference = fromEnum resultStructureRef
65+
, evaluateResponseNamedVariables = Nothing
66+
, evaluateResponseIndexedVariables = Nothing
67+
, evaluateResponseMemoryReference = Nothing
68+
}
8669

8770
--------------------------------------------------------------------------------
8871
-- * Utils

test/golden/T61/T61.hdb-stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[1 of 2] Compiling Main ( <TEMPORARY-DIRECTORY>/x/Main.hs, interpreted )[main]
22
(hdb) wrks
3-
EvalCompleted {resultVal = "()", resultType = "()"}
3+
EvalCompleted {resultVal = "()", resultType = "()", resultStructureRef = NoVariables}
44
(hdb) Exiting...

test/golden/T79/T79.hdb-stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99

1010
[1 of 2] Compiling Main ( <TEMPORARY-DIRECTORY>-tmp]
1111
(hdb) Hello, Haskell!
12-
EvalCompleted {resultVal = "()", resultType = "()"}
12+
EvalCompleted {resultVal = "()", resultType = "()", resultStructureRef = NoVariables}
1313
(hdb)

test/golden/T83/T83.hdb-stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[1 of 2] Compiling Main ( <TEMPORARY-DIRECTORY>/Main.hs, interpreted )[main]
22
(hdb) Heli
3-
EvalCompleted {resultVal = "()", resultType = "()"}
3+
EvalCompleted {resultVal = "()", resultType = "()", resultStructureRef = NoVariables}
44
(hdb) Exiting...

0 commit comments

Comments
 (0)