[fpc-pascal] fpDebug extension for Visual Studio Code

Martin Frb lazarus at mfriebe.de
Wed May 20 20:48:01 CEST 2020

Ok, here are some of my ideas/hopes/dreams/wishes for the IDE....
They are all "ideas only", with on knowledge of when/if they may be done.

I provide them, in the hope they will help choosing a path for the backend.

The IDE should receive a "TWatchWhateverValue" from any of the backend, 
that provides:

1) async interface (that is actually for the benefit of the backends)
Currently the IDE would call a method (example callstack)
- IDE calls "count" => not yet known = 0
- the backend starts retriving the value, and once the value is avail, 
it triggers an "changed" event
- IDE calls count again.
- IDE starts accessing the items in the list.
   They may be available, but if not the return "evaluating" (or 
whatever dummy value), and the backend will get them and trigger 
"change" again.

Alternative, there could be a CountState, that would return if the count 
is already avail. The trigger to get the count, would still be to call 

However, the backend must be able to retrieve any requested data from 
fpdebug, and that should be in a format that is ready for the IDE. 
(TDebuggerIntf classes)

Evaluating huge data, may need to be "interruptible" => either called in 
small blocks (like the callstack at current), or by run in a thread, and 
check for an "abort state".
For single watches this is currently not needed.

2) the IDE must be able to retrieve values in different formats, with 
minimum work of the backend (but allowing for async)
- An ordinal value must either be known as ordinal (none text form), 
then the IDE can do dec/hex/bin...
   or it can be retrieved from the TWatchWhateverValue in any of those 
formats (and does not need complete re-eval)
- Hex representation: this can do a re-eval if needed
- A structure may have different text formats (more or less verbose...)
- objects for fields/members (array element) can be retrieved.
   array element, probably re-use one instance, changing the value. One 
would not want to create thousands of instances....

Because any op can be async, the current way of just calling the getter, 
and getting a dummy "evaluating" value/object works well.
The IDE does not need to differ if the value is final or not. If it is 
not final a "changed" event is triggered, and the IDE starts again (same 
as if the debugger entered pause)

3) The TWatchWhateverValue must be able to store (and serialize) its 
data. Or a part of it.
It must be able to "work on the stored data only".
Watches are added to debug history. If viewed from history, no further 
eval is possible. The debugged app has changed its state...
Currently this stores the display-text. Limiting changed to display format.
It would be up to the IDE how match the watch stores, and the watch 
would then only be able to return the stored subset of data.
It also must be able to serialize, as the history can be saved/loaded 
to/from xml.


The async part may make things tricky

IF a watch asks for the list of fields, it gets TDbgFields or similar.
But a field may be an object with fields of its own.
So if this TDbgField is asked for its field, that must somehow be async to.

Yet the baseclass may not necessary need that implementation..
So PascalBuilder would need to create Fields, but the exact subclass 
could be given by the backend.

Disclaimer: I have not fully thought that through.... And many thinks 
should probably only be added, when they will be needed.
As I said, just to help keeping the design flexible enough.

More information about the fpc-pascal mailing list