2012-06-09 18 views
9

La aplicación en la que estoy trabajando permite incrustar secuencias de comandos en un documento. Por ejemplo:¿Hay alguna manera de mantener los valores de las variables al ejecutar un DWScript dos veces?

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

Resultados

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

estoy usando DWScript. Internamente se compila el primer fragmento de script &. Que el siguiente es RecompiledInContext y se ejecuta, y así sucesivamente. Una función/variable/etc. declarada en un fragmento se vuelve disponible en todos los fragmentos posteriores. Sin embargo, los valores de las variables se pierden entre los fragmentos. Por ejemplo:

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

Después de generar el documento:

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

Aquí es una aplicación de ejemplo que ilustra el problema:

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. 

¿Hay una manera de "transferencia" o "mantener "los valores variables entre ejecuciones?

Aquí es un código actualizado de la respuesta de Andrew que no funciona:

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 ... El comando de secuencia de comandos de intercambio interrumpe la ejecución. Parece que la única forma de que haga funcionar esta característica es profundizando en la biblioteca con el depurador. ¡Buena suerte para ti con DWSCript! :) – Andrew

Respuesta

1

El problema es que cuando RecompileInContext() agrega nuevas variables globales, no tienen espacio asignado, ya que la asignación de espacio es realizada por BeginNewExecution, pero debería funcionar si las variables existen previamente, o si las nuevas variables son agregado dentro de una función así son los vars locales, en lugar de los globales).

Así que si cambia el "código actualizado" a algo como esto, que funcionará

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(); 

Editar: esto ahora que ha fijado por r1513 en el DWScript SVN.

+0

Hola Eric, funciona como se esperaba con la última fuente. ¡Esto es asombroso! Gracias por arreglar esto. –

5

se puede tratar de utilizar BeginNewExecution/RunProgram/EndProgram bloque en lugar (probado en 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

Esto no es confiable. Acabo de probar el siguiente código y resulta en un error AV. (¿Tiene que publicarlo como una respuesta, ya que no cabe como un comentario) –

+0

@RM qué versión de Delphi tiene? – Andrew

+0

Actualización 4 de Delphi XE2 (incluida la corrección) + fuente más reciente de DWScript –

Cuestiones relacionadas