[Lazarus] triggered by the frontend / Representation of an "watch" [[was: Re: Playing with debuggers]]

Martin Frb lazarus at mfriebe.de
Sun Nov 21 17:23:59 CET 2021


> 1) Events to be more frontend centric.
> 2) Actions (eval watch) to be triggered by the frontend
> 3) Representation of an "watch"  (Should methods be on the Watch 
> object, or the Debugger object)

=====> 2) Actions (eval watch) to be triggered by the frontend

The evaluation of a watch is triggered when the frontend attempts to 
access it. The backend then gets a call to
      TWatchesSupplier.InternalRequestData(AWatchValue: TWatchValue)
for that one watch.

For all I can see neither gdb, nor Fp backends will evaluate any watch, 
unless the frontend asks.


=====> 3) Representation of an "watch"  (Should methods be on the Watch 
object, or the Debugger object)

You introduced a new method to get a watch value.
   Debugger.EvaluateExpression(S, Debugger.GetCurrentFrameID, 
FLatestRef, @EvaluateCallback)

and then in the callback the data is in an object: 
TLazDebugExtensionVariable
TLazDebugExtensionVariable has a reference, where the debugger can store 
any data it wants: integer or object


I am trying to see, what advantage this should bring over the current 
system:

* TIdeWatch / TCurrentWatch
   => those can nicely store all the data a frontend needs to store with 
the watch (any options the user did chose).
   => this also stores (as TWatchValue) the result returned from the 
debugger.
   => Each frontend can subclass it as it wants.
* The frontend decides when it wants the data. The backend then receives 
a single call for this/each watch.
* The backend then send a notification for the frontend, when the data 
is there.

Same flow? Main difference is that the methods to invoke the evaluation 
are on the TWatch.

--------------
So far so good.
- The TWatch class is currently quite big. It might benefit from some 
cut down, but that is not related to any of the things you implemented.

- An advantage is, that a watch eval can be aborted.
   Your concept is to discard unwanted results, but the backend still 
spends time on evaluating it. Of course you could add
      dbg.AbortEval(reference);
   In the end, I prefer to encapsulate this into the TWatch.

- Watches are stored in a list.
That is needed by the frontend. Because the History wants to know about 
the watches.
However, this may not be needed by the backend. That can be reviewed.

--------------
Collapsing / Expanding

Currently watches can only be added by the frontend. That may need to be 
changed.
Each watch needs a way to ask the debugger for the TWatchValue data of 
its children.
=> For that the Watch could call the backend
   dbg.GetChildren(self);
=>  The backend would then for each child call
   watch.GetChildWatch
and the backend would put the data in.

Something like that.....

As for the TWatches list:
The watch window would know, which watches are visible (expanded) and 
evaluate them.
For the history, each watch could have a "parent" and/or 
"CurrentVisible" field. Or the watch has an "Owner" (the window), which 
can be asked.


On 14/09/2021 16:11, Joost van der Sluis via lazarus wrote:
> The big advantage of the tree-view, is that you do not evaluate 
> sub-watches, only when they have to be shown. So only those fields 
> that need to be shown have to be evaluated by gdb. (It also solves the 
> endless loop you sometimes have)
Well at latest when the debugger is idle, evaluation of watches "not 
scrolled in" should start.
So when the user starts scrolling, values can be shown immediately.






-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20211121/5d77d122/attachment.html>


More information about the lazarus mailing list