From: Matthias Meier on
Hello,

i want to "reset" an Interpreter after evaluating a script to the state it was after initialisation.
(that means: delete all the vars/procs which were created during the script-evaluation)

i.E

--------------------------------------
int fkt ( char* script )
{
static Tcl_Interp* interp = (Tcl_Interp*)0;

if( !interp ) interp = Tcl_CreateInterp();

Tcl_Eval( interp, script );
fprintf( stderr, "Result = '%s'\n", interp->result );

Tcl_ResetResult( interp );

// Reset interp to the state after Tcl_CreateInterp()
// ??

return(0);
}


fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
---------------------------------------

should print
Result = '1'
Result = '1'

and not - as it is -

Result = '1'
Result = '2'


I could delete the interpreter and create it new, every time i call the function, but this consumes to much time.

I could delete all global vars (procs) after calling my script:

fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
fkt( "foreach var [info globals] { unset $var }" );
fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
fkt( "foreach var [info globals] { unset $var }" );

but this would delete all 'system-vars' too (tcl_version ...).

Is there a posibility to 'duplicate' an interpreter (which ist faster then create a new one?) or to 'reset' an interpreter to the state it was bevore the script was evaluated or to the state it was after initialisation?


Thanks for all hints!

Matthias





From: Alexandre Ferrieux on
On Apr 29, 11:39 am, Matthias Meier <Me...(a)FuH-E.de> wrote:
> Hello,
>
> i want to "reset" an Interpreter after evaluating a script to the state it was after initialisation.
> (that means: delete all the vars/procs which were created during the script-evaluation)
>
> i.E
>
> --------------------------------------
> int fkt ( char* script )
> {
>         static Tcl_Interp* interp = (Tcl_Interp*)0;
>
>         if( !interp ) interp = Tcl_CreateInterp();
>
>         Tcl_Eval( interp, script );
>         fprintf( stderr, "Result = '%s'\n", interp->result );
>
>         Tcl_ResetResult( interp );
>
>         // Reset interp to the state after Tcl_CreateInterp()
>         // ??
>
>         return(0);
>
> }
>
> fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
> fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
> ---------------------------------------
>
> should print
>         Result = '1'
>         Result = '1'
>
> and not - as it is -
>
>         Result = '1'
>         Result = '2'
>
> I could delete the interpreter and create it new, every time i call the function, but this consumes to much time.
>
> I could delete all global vars (procs) after calling my script:
>
>         fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
>         fkt( "foreach var [info globals] { unset $var }" );
>         fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
>         fkt( "foreach var [info globals] { unset $var }" );
>
> but this would delete all 'system-vars' too (tcl_version ...).
>
> Is there a posibility to 'duplicate' an interpreter (which ist faster then create a new one?) or to 'reset' an interpreter to the state it was bevore the script was evaluated or to the state it was after initialisation?
>
> Thanks for all hints!
>
> Matthias

You could just delete the new vars and procs:

foreach var [info globals] {set oldvar($var) 1}
# same for procs
CODE
foreach var [info globals] {if {![info exists oldvar($var)]}
{unset $var}}
# same for procs

But may I ask what you're trying to do ?

-Alex
From: Alexandre Ferrieux on
On Apr 30, 12:27 am, Alexandre Ferrieux <alexandre.ferri...(a)gmail.com>
wrote:
> On Apr 29, 11:39 am, Matthias Meier <Me...(a)FuH-E.de> wrote:
>
>
>
>
>
> > Hello,
>
> > i want to "reset" an Interpreter after evaluating a script to the state it was after initialisation.
> > (that means: delete all the vars/procs which were created during the script-evaluation)
>
> > i.E
>
> > --------------------------------------
> > int fkt ( char* script )
> > {
> >         static Tcl_Interp* interp = (Tcl_Interp*)0;
>
> >         if( !interp ) interp = Tcl_CreateInterp();
>
> >         Tcl_Eval( interp, script );
> >         fprintf( stderr, "Result = '%s'\n", interp->result );
>
> >         Tcl_ResetResult( interp );
>
> >         // Reset interp to the state after Tcl_CreateInterp()
> >         // ??
>
> >         return(0);
>
> > }
>
> > fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
> > fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
> > ---------------------------------------
>
> > should print
> >         Result = '1'
> >         Result = '1'
>
> > and not - as it is -
>
> >         Result = '1'
> >         Result = '2'
>
> > I could delete the interpreter and create it new, every time i call the function, but this consumes to much time.
>
> > I could delete all global vars (procs) after calling my script:
>
> >         fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
> >         fkt( "foreach var [info globals] { unset $var }" );
> >         fkt( "if { ![info exists anz] } { set anz 0 }; incr anz; return $anz" );
> >         fkt( "foreach var [info globals] { unset $var }" );
>
> > but this would delete all 'system-vars' too (tcl_version ...).
>
> > Is there a posibility to 'duplicate' an interpreter (which ist faster then create a new one?) or to 'reset' an interpreter to the state it was bevore the script was evaluated or to the state it was after initialisation?
>
> > Thanks for all hints!
>
> > Matthias
>
> You could just delete the new vars and procs:
>
>       foreach var [info globals] {set oldvar($var) 1}
>       # same for procs
>       CODE
>       foreach var [info globals] {if {![info exists oldvar($var)]}
> {unset $var}}
>       # same for procs


of course:

foreach var [info globals] {if {($var!="oldvar")&&![info
exists oldvar($var)]}
{unset $var}}

-Alex
From: Erik Leunissen on
Matthias Meier wrote:
> Hello,
>
> i want to "reset" an Interpreter after evaluating a script to the state
> it was after initialisation.
> (that means: delete all the vars/procs which were created during the
> script-evaluation)
>

Alex has shown you how to delete variables and procs using an simple
bookkeeping mechanism.

If "resetting" an interpreter also includes restoring values that were
changed, and restoring procs to their original after they were
redefined, then additional bookkeeping is required which is tedious and
error prone.

In that case you might reconsider spawning a separate interp for each
script to evaluate.

If safety is one of your concerns, you may want to use the safe slave
interp mechanism using [interp create -safe], cf: http://wiki.tcl.tk/4204

Or maybe the safe base mechanism is something for you:

http://www.tcl.tk/man/tcl8.4/TclCmd/safe.htm

Erik
--
leunissen@ nl | Merge the left part of these two lines into one,
e. hccnet. | respecting a character's position in a line.
From: Matthias Meier on
Alexandre Ferrieux schrieb:
> On Apr 29, 11:39 am, Matthias Meier <Me...(a)FuH-E.de> wrote:
>> Hello,
>>
>> i want to "reset" an Interpreter after evaluating a script to the state it was after initialisation.
>> (that means: delete all the vars/procs which were created during the script-evaluation)
>>
> But may I ask what you're trying to do ?

I have an tcl-interpreter in a long running (c-written) server-process.
During server livetime various scripts (which have nothing to do with each other) are interpreted and i want to
ensure that the scripts are don't affect each other.
(i.E. just because one script uses variables (variable names) which an other Script uses too)
Therefore i would like to evaluate each script in a 'new'/clean interpreter.
But creating a new interpreter ( Tcl_CreateInterp() ) every time would consume too much time.

Because the problem is time-critical im looking for the most performant way to 'reset' the interpreter.
(I hoped there is a more performant way to do it then unsetting the vars one by one)


Matthias