PDA

View Full Version : QtScript: how to reload current script?



eyeofhell
11th January 2010, 13:22
Hello.

QScriptEngine has evaluate() method that can be used to load script, execute it and to run a specified function from already loaded script. But how to clear current script and load a new one? For example, i use evaluate() to load a script from file and then evaluate() to get a script functions and call them. But what can i do to clear current script and load a new one from a different file? Deleting and creating QScriptEngine seems like a solution, but it likes to be created in GUI thread (due to QScriptEngineDebugger) while all script operations are performed in separate thread. So is it any way to clear current script without re-creating QScriptEngine object?

wysota
11th January 2010, 18:38
There is no such thing as "current script". You pass a string to evaluate() so it's enough to pass a different one. Remember that QScriptEngine is not thread-safe! You have to create and use the script engine in the same thread.

eyeofhell
11th January 2010, 20:45
There is no such thing as "current script". You pass a string to evaluate() so it's enough to pass a different one

If next call to evaluate() will erase previous one, how following can work:



evaluate( "function foo() { this.DoSomething(); }" );
evaluate( "foo" );


Second call will return an object and evoking call() method on it will call "foo" function (with DoSomething() etc). How this can be possible if evaluate( "foo" ) erases previous call to evaluate() with function body?

wysota
11th January 2010, 20:54
If next call to evaluate() will erase previous one, how following can work:



evaluate( "function foo() { this.DoSomething(); }" );
evaluate( "foo" );

It works because the first script makes changes to the script context present in the script engine.

You can always push a new context prior to executing a script and then pop it back to make sure all changes made to the context by previous execution are removed. Just make sure you use activationObject() instead of globalObject() to modify the environment of the script.

eyeofhell
12th January 2010, 06:31
It seems i'm a bit lost. "There is no such thing as 'current script'" and "first script makes changes to the script context present in the script engine" seems totally opposite to me O_O. What's the difference between "script context" and "current script"? Why evaluating "function foo() {}" will change script context but evaluating "foo" will not? Is it any rules available how evaluation changes script context? :)

wysota
12th January 2010, 09:41
Script context is just like a "stack frame" for regular computer applications. Functions and variables are local to the context (stack frame) they were declared in. When a function is executed, a new context is created for it and when it ends, the context is removed. So all local changes made inside a function will be gone when the function ends because the context of the function is removed. The context is not removed between evaluate() calls thus the top-level context remains the same and changes made to it are persistant. You need to explicitely push a context before calling evaluate() and pop it afterwards.

See the example (not tested):

QScriptEngine engine;
QScriptContext *context = engine.context();
context->activationObject().setProperty("x", 7);
contet = engine.pushContext(); // new context
context->activationObject().setProperty("y", 8);
engine.evaluate("x+y");
engine.popContext();
engine.evaluate("x+y"); // "y" is undefined

The same happens if you call a function. But the function itself is defined in the context surrounding the function itself.

If you wish to have a clean context for every evaluate() call, do this (indentation of the code below should help you understand):

QScriptEngine engine;
engine.pushContext();
engine.evaluate("...");
engine.popContext();
engine.pushContext();
engine.evaluate("...");
engine.popContext();

eyeofhell
12th January 2010, 10:45
So, basically, it's a 'context' that accumulate functions and variables defined inside evaluate() and this context can be called "current script". Context does not change between evaluate, so following code:


evaluate( "var a = 1;" );
evaluate( "var b = 2;" );
evaluate( "a + b" );

Will evaluate to "3". Am i correct?

Also, what do you means by

But the function itself is defined in the context surrounding the function itself
Sorry for boring you with this stupid questions, but Qt documentation about scripting is a kind of limited and it's very important for me to know how it works :).

So, as i understand for now, my original task will be like following:
1. push empty context
2. evaluate script from file.
3. As application executes, call script functions from time to time using evaluate( "function name" ).call()
4. If another script must be loaded, pop context, push empty one and goto step 2.

wysota
12th January 2010, 11:28
So, basically, it's a 'context' that accumulate functions and variables defined inside evaluate() and this context can be called "current script".
No, it can't. The following uses three different contexts and that's just a single script:

function x() { return 7; }
function y() { return x()+5; }
y();


Context does not change between evaluate, so following code:


evaluate( "var a = 1;" );
evaluate( "var b = 2;" );
evaluate( "a + b" );

Will evaluate to "3". Am i correct?
Correct.


Also, what do you means by


But the function itself is defined in the context surrounding the function itself

It means this script will not be valid...

function x() {
function y() { return 7; }
return 5;
}

y();

... because function "y" exists only in the context of execution of function "x".


Sorry for boring you with this stupid questions, but Qt documentation about scripting is a kind of limited and it's very important for me to know how it works :).
It has nothing to do with Qt. It's all about how today's computers work. The same concept applies to every C/C++ application as well.