How to create a 'local variables' display using DWScript and its debugger
Asked Answered
B

2

6

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.

Balcony answered 9/9, 2011 at 8:44 Comment(0)
A
9

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)

Abbeyabbi answered 9/9, 2011 at 10:30 Comment(0)
B
2

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;
Balcony answered 9/9, 2011 at 15:53 Comment(1)
You can use TdwsCompiler.Evaluate to evaluate the variable or an expression using local variables (the debugger's watcher use that). The direct stack access is the most efficient way though, if you only want the value of the variable, but Evaluate allows to get the ClassName of a class variable more easily f.i.Abbeyabbi

© 2022 - 2024 — McMap. All rights reserved.