Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 785
Brian Frost Avatar asked Sep 09 '11 08:09

Brian Frost


2 Answers

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)

like image 65
Eric Grange Avatar answered Nov 05 '22 20:11

Eric Grange


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;
like image 2
Brian Frost Avatar answered Nov 05 '22 18:11

Brian Frost