3

DWScript を使用して Read–eval–print ループ (REPL) を作成しようとしていますが、これが可能かどうかわかりません。

名前に基づいて、RecompileInContextそのコンテキストでは問題なく機能すると思いましたが、いくつかの制限が発生しています。

  • バグのある行はプログラムに永遠に含まれます: その行が原因で、将来の実行は常に失敗します
  • 入力するだけで変数の値を出力する方法が見つかりませんでした。たとえば、var test = "content";thenと入力するとtestcontentが表示されます。私が知る限り、実行ごとに実行されるため、使用printまたはprintln機能しません

だから私の質問は: DWScript を使用して REPL を作成することは可能ですか?

これが私がこれまでに得たものです:

program DwsRepl;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  dwsComp,
  dwsCompiler,
  dwsExprs;

var
  oCompiler: TDelphiWebScript;
  oProgram: IdwsProgram;
  oExecution: IdwsProgramExecution;
  sInput: string;
begin
  try
    oCompiler := TDelphiWebScript.Create(nil);
    try
      oProgram := oCompiler.Compile('', 'ReplScript');
      oExecution := oProgram.BeginNewExecution;
      try
        while True do
        begin
          Write('> ');
          // Read user input
          Readln(sInput);
          // Exit if needed
          if sInput = '' then Break;
          // Compile
          oCompiler.RecompileInContext(oProgram, sInput);
          if not oProgram.Msgs.HasErrors then
          begin
            oExecution.RunProgram(0);
            // Output
            if not oExecution.Msgs.HasErrors then
             Writeln(oExecution.Result.ToString)
            else
             Writeln('EXECUTION ERROR: ' + oExecution.Msgs.AsInfo);
          end
          else
           Writeln('COMPILE ERROR: ' + oProgram.Msgs.AsInfo);
        end;
      finally
        oExecution.EndProgram;
      end;
    finally
      oCompiler.Free();
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
4

1 に答える 1

3

TdwsCompiler.Evaluate を使用してスニペットを IdwsEvaluateExpr にコンパイルできます。その後、含まれている式を yourEvaluateExpr.Expression.EvalAsString で文字列に評価できます。

上記は、デバッグ評価、式の監視、または条件付きブレークポイントに使用する典型的なメカニズムです (常に文字列として評価されるわけではありませんが、式はオブジェクト、配列などを返すことができます。また、何も返さないステートメントを保持することもできます)。

RecompileInContext は宣言を保持しますが、「メイン」コードを破棄するため、メイン コードのバグは今後の実行には影響しませんが、変数の型に問題があるか、関数の実装に問題があると宣言した場合、それはそのまま残ります。スクリプト コンテキスト。

ただし、メッセージ リストは自動的にクリアされないため、自分でクリアする必要があります (もともと RecompileInContext は、より大きなソースで小さなスクリプト スニペットを処理することを目的としていたため、メッセージ リストにできるだけ多くのエラーを保持することが望ましい動作でした。最後のスクリプトは、誤った最初のスクリプトのエラーを「消去」しません)

于 2016-02-15T07:50:25.433 に答える