2016-02-12 35 views
3

我想用DWScript創建一個Read-Eval-print循環(REPL),我不確定這是可能的。是否可以使用DWScript創建Read-eval-print循環(REPL)?

基礎上的名字,我認爲RecompileInContext將正常工作在這方面,但我遇到一些限制:

  • 一車線是永遠列入計劃:未來的運行將總是由於失敗行
  • 我沒有找到一種方法來輸出一個變量的值,只需輸入它的值。例如,在輸入var test = "content";時應顯示test,content。據我所知,使用printprintln不能工作,因爲他們會在每次運行

執行所以我的問題是:是否有可能創建一個REPL使用DWScript?

這裏是我到目前爲止有:

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. 

回答

3

您可以使用TdwsCompiler.Evaluate編譯代碼段的IdwsEvaluateExpr,則有可能對包含的表達式評估與yourEvaluateExpr的字符串。 Expression.EvalAsString

以上是用於調試評估,表達式監視或條件斷點的典型機制(儘管不總是以字符串形式評估,表達式可以返回對象,數組等等,或者可以持有一個語句什麼都不返回)。

RecompileInContext將保留聲明,但會丟棄「main」代碼,因此主代碼中的錯誤不會影響將來的運行,但是如果聲明錯誤類型的變量或錯誤的函數實現,它會留在腳本上下文中。

但是,消息列表不會自動清除,您必須自己清除它(最初RecompileInContext旨在處理較大源代碼中的小型腳本片段,因此在消息列表中儘可能多地保留錯誤是期望的行爲,以便正確的最後一個腳本不會「擦除」不正確的第一個腳本的錯誤)

+0

謝謝埃裏克。我試過TdwsCompiler.Evaluate,但它似乎僅限於平凡的表達式和執行:我還沒有能夠評估變量賦值,例如「var test = 2」。這個想法是與現有的腳本進行交互並將其用於實時編程。一個簡單的例子就是Laravel Tinker命令:http://laravel-recipes.com/recipes/280/interacting-with-your-application – jonjbar

相關問題