2012-06-09 9 views
9

Die Anwendung, an der ich arbeite, ermöglicht das Einbetten von Skript sinpets in ein Dokument. Zum Beispiel:Gibt es eine Möglichkeit, variable Werte beizubehalten, wenn ein DWScript zweimal ausgeführt wird?

SomeText 
<* PrintLn("This line is generated by a script"); *> 
Some other text 
<* PrintLn("This line is generated by a script, too"); *> 
Some more lines 

Ergebnisse

SomeText 
This line is generated by a script 
Some other text 
This line is generated by a script, too 
Some more lines 

ich DWScript verwende. Intern wird das erste Skript-Snippet kompiliert & ausgeführt. Als nächstes ist RecompiledInContext und ausgeführt und so weiter. Eine in einem Snippet deklarierte Funktion/Variable/etc ist in allen späteren Snippets verfügbar. Die Variablenwerte gehen jedoch zwischen den Snippets verloren. Zum Beispiel:

SomeText 
<* var x: Integer = 5; *> 
Some other text 
<* PrintLn(x); *> 
Some more lines 

Nach dem Erstellen des Dokuments:

SomeText 
Some other text 
0 <-- I would like this to be 5 
Some more lines 

Hier ist eine Beispielanwendung, die das Problem veranschaulicht:

program POC.Variable; 

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    dwsExprs, 
    dwsComp, 
    dwsCompiler; 

var 
    FDelphiWebScript: TDelphiWebScript; 
    FProgram: IdwsProgram; 
    FExecutionResult: IdwsProgramExecution; 

begin 
    FDelphiWebScript := TDelphiWebScript.Create(nil); 
    try 
    FProgram := FDelphiWebScript.Compile('var x: Integer = 2;'); 
    FProgram.Execute; 

    FDelphiWebScript.RecompileInContext(FProgram, 'PrintLn(x);'); 

    FExecutionResult := FProgram.Execute; 
    // The next line fails, Result[1] is '0' 
    Assert(FExecutionResult.Result.ToString[1] = '2'); 
    finally 
    FDelphiWebScript.Free; 
    end 
end. 

Gibt es eine Möglichkeit, "Transfer" oder „halten "die variablen Werte zwischen den Ausführungen? Hier

ist eine aktualisierte Code von Andrew Antwort, die nicht funktioniert:

begin 
    FDelphiWebScript := TDelphiWebScript.Create(nil); 
    try 
    FProgram := FDelphiWebScript.Compile('PrintLn("Hello");'); 

    FExecution:= FProgram.BeginNewExecution(); 

    FDelphiWebScript.RecompileInContext(FProgram, 'var x: Integer;'); 
    FExecution.RunProgram(0); 
    WriteLn('Compile Result:'); 
    WriteLn(FExecution.Result.ToString); 

    FDelphiWebScript.RecompileInContext(FProgram, 'x := 2; PrintLn(x);'); 
    FExecution.RunProgram(0); // <-- Access violation 
    WriteLn('Compile Result:'); 
    WriteLn(FExecution.Result.ToString); 

    FExecution.EndProgram(); 
    ReadLn; 
    finally 
    FDelphiWebScript.Free; 
    end 
end; 
+0

Urgh ... Das Vertauschen von Skriptbefehlen unterbricht die Ausführung. Scheint die einzige Möglichkeit für Sie, diese Funktion zu arbeiten, ist tief in Bibliothek mit dem Debugger zu graben. Viel Glück für Sie mit DWSCript! :) – Andrew

Antwort

1

Das Problem ist, dass wenn RecompileInContext() neue globale Variablen hinzufügt, ihnen kein Speicherplatz zugewiesen wird, da die Speicherplatzzuordnung von BeginNewExecution ausgeführt wird, aber es sollte funktionieren, wenn die Variablen vorhanden sind oder wenn neue Variablen vorhanden sind innerhalb einer Funktion hinzugefügt, so sind lokale vars, anstatt globale).

Also, wenn Sie die „aktualisierte Code“, um so etwas wie dies zu ändern, wird es

FProgram := DelphiWebScript1.Compile('PrintLn("Hello");' 
            +'var x: Integer;'); 

FExecution:= FProgram.BeginNewExecution(); 

FExecution.RunProgram(0); 
SynEdit1.Lines.Add('Compile Result:'); 
SynEdit1.Lines.Add(FExecution.Result.ToString); 

DelphiWebScript1.RecompileInContext(FProgram, 'x := 2; PrintLn(x);'); 
FExecution.RunProgram(0); // <-- Access violation 
SynEdit1.Lines.Add('Compile Result:'); 
SynEdit1.Lines.Add(FExecution.Result.ToString); 

FExecution.EndProgram(); 

bearbeiten arbeiten: dies wie jetzt von r1513 im DWScript SVN fest.

+0

Hallo Eric, funktioniert wie erwartet mit der neuesten Quelle. Das ist fantastisch! Danke, dass du das getan hast. –

5

Sie können versuchen, stattdessen BeginNewExecution/RunProgram/EndProgram Block zu verwenden (getestet auf DWScript 2.2):

begin 
    FDelphiWebScript := TDelphiWebScript.Create(nil); 
    try 
    FProgram := FDelphiWebScript.Compile('var x: Integer;'); 

    FExecution:= FProgram.BeginNewExecution(); 

    FDelphiWebScript.RecompileInContext(FProgram, 'x := 2; PrintLn(x);'); 
    FExecution.RunProgram(0); 
    WriteLn('Compile Result:'); 
    WriteLn(FExecution.Result.ToString); 

    FDelphiWebScript.RecompileInContext(FProgram, 'x := x + 3; PrintLn(x);'); 
    FExecution.RunProgram(0); 
    WriteLn('Recompile Result: '); 
    WriteLn(FExecution.Result.ToString); 

    FExecution.EndProgram(); 

    ReadLn; 
    finally 
    FDelphiWebScript.Free; 
    end 
end. 
+0

Dies ist nicht zuverlässig. Ich habe gerade den folgenden Code ausprobiert und es kommt zu einem AV-Fehler. (Muss es als Antwort posten da passt das nicht als Kommentar) –

+0

@RM welche Delphi Version hast du? – Andrew

+0

Delphi XE2 Update 4 (einschließlich Hotfix) + neueste DWScript-Quelle –

Verwandte Themen