{$O-}
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, PaxProgram, PaxCompiler, PaxCompilerDebugger,
  PaxRegister,
  PaxCompilerExplorer;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Memo2: TMemo;
    Label1: TLabel;
    Label2: TLabel;
    Button1: TButton;
    PaxCompiler1: TPaxCompiler;
    PaxPascalLanguage1: TPaxPascalLanguage;
    PaxProgram1: TPaxProgram;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    PaxCompilerDebugger1: TPaxCompilerDebugger;
    PaxCompilerExplorer1: TPaxCompilerExplorer;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
  private
    { Private declarations }
    procedure Trace(RunMode: Integer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses IMPORT_Classes, Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
begin
  PaxCompiler1.Reset;

  PaxCompiler1.RegisterLanguage(PaxPascalLanguage1);
  PaxCompiler1.AddModule('1', PaxPascalLanguage1.LanguageName);
  PaxCompiler1.AddCode('1', Memo1.Lines.Text);

  PaxCompiler1.DebugMode := true;

  if PaxCompiler1.Compile(PaxProgram1) then
  begin
    ShowMessage('Script has been successfully recompiled.');
    PaxCompilerExplorer1.RegisterCompiler(PaxCompiler1);
    PaxCompilerDebugger1.RegisterCompiler(PaxCompiler1, PaxProgram1);
  end
  else
    for I:=0 to PaxCompiler1.ErrorCount - 1 do
      ShowMessage(PaxCompiler1.ErrorMessage[I]);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Trace(_rmRUN);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  Trace(_rmTRACE_INTO);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  Trace(_rmSTEP_OVER);
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  if not PaxCompilerDebugger1.Valid then
  begin
    ShowMessage('You have to compile script. Press "Compile" button.');
    Exit;
  end;

  Form2.ShowModal;
  
  if Form2.ModalResult = mrOK then
    Trace(_rmRUN_TO_CURSOR);
end;

procedure TForm1.Trace(RunMode: Integer);

procedure AddFields(StackFrameNumber, Id: Integer);
var
  I, K: Integer;
  OwnerName, S: String;
begin
  K := PaxCompilerExplorer1.GetFieldCount(Id);
  if K = 0 then
    Exit;

  OwnerName := PaxCompilerExplorer1.Names[Id];
  if PaxCompilerDebugger1.GetValueAsString(Id) = 'nil' then
    Exit;

  for I:=0 to K - 1 do
  begin
    S := OwnerName + '.' + PaxCompilerExplorer1.GetFieldName(Id, I);
    S := '      ' + S + '=' + PaxCompilerDebugger1.GetFieldValueAsString(
      StackFrameNumber, Id, I);
    Memo2.Lines.Add(S);
  end;
end;

procedure AddArrayElements(StackFrameNumber, Id: Integer);
var
  I, K1, K2: Integer;
  OwnerName, S: String;
begin
  if not PaxCompilerExplorer1.HasArrayType(Id) then
    Exit;

  K1 := PaxCompilerExplorer1.GetArrayLowBound(Id);
  K2 := PaxCompilerExplorer1.GetArrayHighBound(Id);

  OwnerName := PaxCompilerExplorer1.Names[Id];

  for I:=K1 to K2 do
  begin
    S := OwnerName + '[' + IntToStr(I) + ']';
    S := '      ' + S + '=' + PaxCompilerDebugger1.GetArrayItemValueAsString(
      StackFrameNumber, Id, I);
    Memo2.Lines.Add(S);
  end;
end;

procedure AddDynArrayElements(StackFrameNumber, Id: Integer);
var
  I, L: Integer;
  OwnerName, S: String;
begin
  if not PaxCompilerExplorer1.HasDynArrayType(Id) then
    Exit;

  L := PaxCompilerDebugger1.GetDynArrayLength(StackFrameNumber, Id);

  OwnerName := PaxCompilerExplorer1.Names[Id];

  for I:=0 to L - 1 do
  begin
    S := OwnerName + '[' + IntToStr(I) + ']';
    S := '      ' + S + '=' + PaxCompilerDebugger1.GetDynArrayItemValueAsString(
      StackFrameNumber, Id, I);
    Memo2.Lines.Add(S);
  end;
end;

var
  SourceLineNumber: Integer;
  ModuleName: String;
  StackFrameNumber, J, K, SubId, Id: Integer;
  S, V: String;
begin
  if not PaxCompilerDebugger1.Valid then
  begin
    ShowMessage('You have to compile script. Press "Compile" button.');
    Exit;
  end;

  PaxCompilerDebugger1.RunMode := RunMode;
  PaxCompilerDebugger1.Run;

  Memo2.Lines.Clear;
  if PaxCompilerDebugger1.IsPaused then
  begin
    ModuleName := PaxCompilerDebugger1.ModuleName;
    SourceLineNumber := PaxCompilerDebugger1.SourceLineNumber;

    Memo2.Lines.Add('Paused at line ' + IntTosTr(SourceLineNumber));
    Memo2.Lines.Add(PaxCompiler1.Modules[ModuleName][SourceLineNumber]);
    Memo2.Lines.Add('------------------------------------------------------');

    if PaxCompilerDebugger1.CallStackCount > 0 then
    begin
      Memo2.Lines.Add('Call stack:');
      for StackFrameNumber:=0 to PaxCompilerDebugger1.CallStackCount - 1 do
      begin
        SubId := PaxCompilerDebugger1.CallStack[StackFrameNumber];
        S := '(';
        K := PaxCompilerExplorer1.GetParamCount(SubId);
        for J:=0 to K - 1 do
        begin
          Id := PaxCompilerExplorer1.GetParamId(SubId, J);
          V := PaxCompilerDebugger1.GetValueAsString(StackFrameNumber, Id);
          S := S + V;
          if J < K - 1 then
            S := S + ',';
        end;
        S := PaxCompilerExplorer1.Names[SubId] + S + ')';
        Memo2.Lines.Add(S);
      end;
      Memo2.Lines.Add('------------------------------------------------------');

      Memo2.Lines.Add('Local scope:');
      StackFrameNumber := PaxCompilerDebugger1.CallStackCount - 1;
      SubId := PaxCompilerDebugger1.CallStack[StackFrameNumber];
      K := PaxCompilerExplorer1.GetLocalCount(SubId);
      for J:=0 to K - 1 do
      begin
        Id := PaxCompilerExplorer1.GetLocalId(SubId, J);
        V := PaxCompilerDebugger1.GetValueAsString(StackFrameNumber, Id);
        S := PaxCompilerExplorer1.Names[Id] + '=' + V;
        Memo2.Lines.Add(S);

        AddFields(StackFrameNumber, Id);
        AddArrayElements(StackFrameNumber, Id);
        AddDynArrayElements(StackFrameNumber, Id);
      end;
      Memo2.Lines.Add('------------------------------------------------------');
    end;

    Memo2.Lines.Add('Global scope:');
    K := PaxCompilerExplorer1.GetGlobalCount(0);
    for J:=0 to K - 1 do
    begin
      Id := PaxCompilerExplorer1.GetGlobalId(0, J);
      V := PaxCompilerDebugger1.GetValueAsString(Id);
      S := PaxCompilerExplorer1.Names[Id] + '=' + V;
      Memo2.Lines.Add(S);

      AddFields(0, Id);
      AddArrayElements(0, Id);
      AddDynArrayElements(0, Id);
    end;
    Memo2.Lines.Add('------------------------------------------------------');

  end
  else
    Memo2.Lines.Add('Finished');

  Memo2.SelStart := 0;
  Memo2.SelLength := 0;
end;

procedure Print(I: Integer);
begin
  ShowMessage(IntToStr(I));
end;

initialization

RegisterHeader(0, 'procedure Print(I: Integer);', @Print);

end.
