I'm writing an IDE for DWScript and have got it stepping through code using the debugger. I now wish to add a display of 'local variables' (i.e those in scope). Can someone give me a pointer to the means of doing this? I can get a list of all symbols but do not understand how to get the current scope part of things. Thanks.
Cast the IdwsProgramExecution to TdwsProgramExecution, you'll gain access to a "CurrentProg", property, a TdwsProgram which is either a TdwsMainProgram (if you're in the main) or a TdwsProcedure (if you're in a proc/func/method). Those will have a Table property, which lists the local symbols, that's the most direct scope. That Table will have one or more Parents, which refers the parent scopes (hierarchically, in terms of source code scope).
If in a TdwsProcedure, you may also want to look at its FuncSymbol property, which will have a table of parameters (useful if you want to directly isolate the parameters from the rest of the local scope)
For any others reading this question, I will show some supplementary info concerned with getting the value of a symbol. The symbol is found as described by Eric above but it is hard to work out how to get the actual value of the symbol. The code below is a procedure that populates a TMemo (memLocalVariables) with local variables each time it is called. There are some features missing like neat formatting of the variable value and access to calling parameters. I call this from the debugger 'dsDebugSuspended' state. The less intuitive bit is the access to the symbol data on the stack and the use of the stack base pointer. A great way to learn how the compiler works! But, maybe there is a utility function somewhere I've not found...? Eric?
procedure DrawLocalVariables;
var
ProgramExecution : TdwsProgramExecution;
I : integer;
Sym : TSymbol;
V : variant;
Adr : integer;
SymbolTable : TSymbolTable;
begin
memLocalVariables.Lines.Clear;
ProgramExecution := TdwsProgramExecution( dwsDebugger1.Execution );
SymbolTable := ProgramExecution.CurrentProg.Table;
For I := 0 to SymbolTable.Count-1 do
begin
Sym := SymbolTable[I];
if Sym is TDataSymbol then
begin
Adr := TDataSymbol( Sym).StackAddr + ProgramExecution.Stack.BasePointer;
ProgramExecution.Stack.ReadValue( Adr, V );
memLocalVariables.Lines.Add( Format( '%s = %s', [ Sym.Name, VarToStr(V) ] ));
end;
end;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With