【问题标题】:How to obtain the line numbers of executable lines from DWScript context map or symbol table如何从 DWScript 上下文映射或符号表中获取可执行行的行号
【发布时间】:2011-09-01 08:14:34
【问题描述】:

我正在编写一个与 Delphi DWScript 一起使用的 IDE,现在有一个简单的可调试脚本。我现在想突出显示源代码中的可执行行(如 Delphi 源代码左侧的蓝点)。挖掘示例/信息我看到有一个程序'SymbolDictionary',我可以在其中调用'FindSymbolUsage(suReference)' - 这似乎给了我'被引用'的符号位置,我想我可以用'再次调用它suImplementation' 以获取有分配的行。这让我意识到,虽然我可以理解 ContextMap 和 SymbolDictionary 的结构和目的实际上是什么。有没有人列出脚本的可执行行号的例子?

我的初出茅庐的代码复制如下,正在等待关键分析:-) 谢谢

  TExecutableLines = class( TObject )
    constructor Create;
    destructor  Destroy; override;
  PRIVATE
    FLines : TBits;
    function GetIsExecutable(ALineNumber: integer): boolean;
    procedure SetIsExecutable(ALineNumber: integer; const Value: boolean);
  PUBLIC
    procedure Clear;

    procedure Evaluate( AProgram : IdwsProgram; const AUnitName : string );

    property  IsExecutable[ALineNumber : integer] : boolean
                read GetIsExecutable
                write SetIsExecutable;
  end;





{ TExecutableLines }

procedure TExecutableLines.Clear;
begin
  FLines.Size := 0;
  FLines.Size := 1024;
end;

constructor TExecutableLines.Create;
begin
  inherited;

  FLines := TBits.Create;
end;

destructor TExecutableLines.Destroy;
begin
  FreeAndnil( FLines );
  inherited;
end;

procedure TExecutableLines.Evaluate(AProgram: IdwsProgram; const AUnitName : string);
var
  I : integer;
  Pos : TSymbolPosition;
begin
  Clear;
  For I := 0 to AProgram.SymbolDictionary.Count-1 do
    begin
    Pos := AProgram.SymbolDictionary.FindSymbolPosList(
      AProgram.SymbolDictionary[I].Symbol ).FindUsage( suReference);
    if Pos <> nil then
      If Pos.ScriptPos.IsMainModule then
        IsExecutable[ Pos.ScriptPos.Line ] := True
       else
         if SameText( Pos.UnitName, AUnitName ) then
            IsExecutable[ Pos.ScriptPos.Line ] := True
    end;

end;

function TExecutableLines.GetIsExecutable(ALineNumber: integer): boolean;
begin
  if ALineNumber = 0 then
    raise Exception.Create('Lines numbers are 1..n' );

  if ALineNumber < FLines.Size then
    Result := FLines[ALineNumber]
   else
     Result := False;
end;

procedure TExecutableLines.SetIsExecutable(ALineNumber: integer;
  const Value: boolean);
begin
  if ALineNumber = 0 then
    raise Exception.Create('Lines numbers are 1..n' );

  if ALineNumber >= FLines.Size then
    FLines.Size := ALineNumber+1;
  FLines[ALineNumber] := Value;
end;

【问题讨论】:

    标签: delphi debug-symbols dwscript


    【解决方案1】:

    TdwsSymbolDictionary 有不同的用途,主要是知道在哪里(如果)声明或使用符号,以及简化重命名重构等操作(请参阅http://delphitools.info/2011/02/19/spotlight-on-tsymboldictionary/)。

    TdwsSourceContextMap 用于了解源代码中的代码“块”在哪里(例如,类声明的开始和结束位置,函数实现的开始和结束位置等)​​,“跳转”到某个位置都很有用在代码中,或者根据符号知道光标在哪里。

    您所追求的是另一个信息,它是与编译表达式相对应的行。为此,您需要查看编译的内容,TExprBase.SubExpr/SubExprCount 是您的主力,或者包装它们的实用函数 RecursiveEnumerateSubExprs。使用该函数,您可以查看程序中的所有表达式,从 TdwsProgram.Expr 和 TdwsProgram.InitExpr 开始(您可以将 IdwsProgram 转换为 TdwsProgram 以获取这些属性)。

    这些是您可以设置断点的地方。

    作为一个例子,假设你有

    1.   function Dummy : Integer;
    2.   var i : Integer;
    3.   begin
    4.      while i<10 do begin
    5.         Inc(i);
    6.         if i>5 then
    7.            break;
    8.      end;
    9.   end;
    

    如果我没记错的话(突然就这么做了):

    • 符号字典将在 1 处列出“Dummy”的声明,a 在 1 和 2 处使用“Integer”,在 2 处声明“i”,在 2 处使用“i” 4、5 和 6。

    • 上下文映射将有一个功能块,主块 和while循环。

    • 编译表达式的行将是 2 (.InitExpr) 和 4, 5, 6 & 7 (.Expr)

    【讨论】:

      猜你喜欢
      • 2011-06-29
      • 2011-04-26
      • 1970-01-01
      • 2021-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多