For Programmers: Free Programming Magazines  


Home > Archive > Tcl > October 2006 > Don't understand eval









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Don't understand eval
crvoss@up-link.net

2006-10-20, 4:10 am

I am developing a Tcl app that needs a macro language. I need to
insulate the user from the normal Tcl scripting language and make it
application specific -- since the users are not programmers. Often each
macro command will execute several Tcl statements. These statements
were put into lists then executed with the eval command -- with no
luck. I tried concat -- also with no luck. Here is some test code I was
trying.

package require BWidget
set var {tangerine banana apple}
pack [ComboBox .c -helptext "It is the ComboBox" -values $var]
set vMc [concat ".c setvalue @1" "set vVal [.c get]"]
eval $vMc

What's the right way to do this? Is eval the right approach? Where can
I find some good documentation on eval?

Eckhard Lehmann

2006-10-20, 4:10 am


crvoss@up-link.net wrote:

> package require BWidget
> set var {tangerine banana apple}
> pack [ComboBox .c -helptext "It is the ComboBox" -values $var]
> set vMc [concat ".c setvalue @1" "set vVal [.c get]"]
> eval $vMc


What does $vMc look like? Is it a string or list that [eval] can
handle?

> Where can
> I find some good documentation on eval?


In the usual manpage: http://www.tcl.tk/man/tcl8.4/TclCmd/eval.htm


Eckhard

billposer@alum.mit.edu

2006-10-20, 4:10 am

crvoss@up-link.net wrote:
> I am developing a Tcl app that needs a macro language. I need to
> insulate the user from the normal Tcl scripting language and make it
> application specific -- since the users are not programmers.


The easiest way to provide your users with a language
is to run a slave interpreter. If you don't want them to be able
to do file i/o and so forth, make it a safe interpreter. By default,
none
of the procedures or data in your program will be accessible to them,
but you can expose what you want them to have access to. To provide
them
with commands that are equivalent to several Tcl commands, just write
procedures
and expose them in the slave interpreter.

mjanssen

2006-10-20, 4:10 am



On Oct 20, 9:20 am, crv...@up-link.net wrote:
> I am developing a Tcl app that needs a macro language. I need to
> insulate the user from the normal Tcl scripting language and make it
> application specific -- since the users are not programmers. Often each
> macro command will execute several Tcl statements. These statements
> were put into lists then executed with the eval command -- with no
> luck. I tried concat -- also with no luck. Here is some test code I was
> trying.
>
> package require BWidget
> set var {tangerine banana apple}
> pack [ComboBox .c -helptext "It is the ComboBox" -values $var]
> set vMc [concat ".c setvalue @1" "set vVal [.c get]"]
> eval $vMc
>
> What's the right way to do this? Is eval the right approach? Where can
> I find some good documentation on eval?


I suspect you're at least missing a semicolon in the vMc var. Now you
are trying to eval for example:
..c setvalue @1 set vVal banana

probably leading to the error:
wrong # args: should be "ComboBox::setvalue path index"

Try:
set vMc [concat ".c setvalue @1" ";" "set vVal [.c get]"]
instead.

Also notice that just using eval like this puts a great trust in the
user. What will happen if the user types for instance [puts "not
secure"] in the combobox?
It will probably display "not secure" showing that the command typed in
is executed. Now imagine a user typing in a proper form of [exec
format].
Therefore the suggestion of doing this in slave interpreters a put
forward in this thread is a very good one.

Mark

Ralf Fassel

2006-10-20, 4:10 am

* crvoss@up-link.net
| set vMc [concat ".c setvalue @1" "set vVal [.c get]"]
| eval $vMc
|
| What's the right way to do this? Is eval the right approach? Where
| can I find some good documentation on eval?

It's difficult to tell what you want to achieve here. Better describe
what you expect to happen.

After consulting my glass bubble and from the context, it looks like
you want two commands to be executed
.c setvalue @1
set vVal [.c get]

In order to put these two statements in *one* variable and have 'eval'
execute the *two* commands, you need to separate the two statements by
something that the TCL parser will accept as statement separator:
usually newline or semicolon.

.c setvalue @1 ; set vVal [.c get]

In order to keep the number of words in each statement, you need to
use 'list' to be on the safe side.

# caution this will not work, see below
set cmd [list .c setvalue @1 \; set vVal [.c get]]
set cmd [list .c setvalue @1 \n set vVal [.c get]]

This does not work, since newlines and semicolons (and other special
characters) are quoted by 'list', so they are not recognized as
statement separators (or special characters) by the TCL parser any
more.

In these cases I usually do something like that:
set cmd "[list .c setvalue @1] ; [list set vVal [.c get]]"
eval $cmd
I.e. set up the individual commands via list, and put them into one
string, separated by semicolon. BUT.

However, the next question then is whether the [.c get] should run
before or after the [.c setvalue]. In the above form, [.c get] is
evaluated right now, the return value is passed to the list command,
and the eval will never ask .c for its contents. This is probably not
what you want, since .c is set by the first statement.

So you need to delay the execution of [.c get] by quoting it yourself:
set cmd "[list .c setvalue @1] ; set vVal \[.c get\]"
eval $cmd

Docs for eval:
http://www.tcl.tk/man/tcl8.4/TclCmd/eval.htm
http://wiki.tcl.tk/eval
http://wiki.tcl.tk/2?eval

HTH
R'
Cameron Laird

2006-10-20, 7:04 pm

In article <1161331635.173506.19230@k70g2000cwa.googlegroups.com>,
<billposer@alum.mit.edu> wrote:
>crvoss@up-link.net wrote:
>
>The easiest way to provide your users with a language
>is to run a slave interpreter. If you don't want them to be able
>to do file i/o and so forth, make it a safe interpreter. By default,
>none
>of the procedures or data in your program will be accessible to them,
>but you can expose what you want them to have access to. To provide
>them
>with commands that are equivalent to several Tcl commands, just write
>procedures
>and expose them in the slave interpreter.
>


Me, too, crvoss; that is, I strongly urge you to follow Bill's
advice to consider a slave interpreter, and leverage of [proc].
I suspect that what you have in mind to do with [eval] is
probably better reformulated in terms of [proc].

If you want to pursue this, a valuable next step might be a
specific example of how you're providing something simpler for
your users than "the normal Tcl scripting language".
Michael Schlenker

2006-10-20, 7:04 pm

crvoss@up-link.net schrieb:
> I am developing a Tcl app that needs a macro language. I need to
> insulate the user from the normal Tcl scripting language and make it
> application specific -- since the users are not programmers. Often each
> macro command will execute several Tcl statements. These statements
> were put into lists then executed with the eval command -- with no
> luck. I tried concat -- also with no luck. Here is some test code I was
> trying.
>
> package require BWidget
> set var {tangerine banana apple}
> pack [ComboBox .c -helptext "It is the ComboBox" -values $var]
> set vMc [concat ".c setvalue @1" "set vVal [.c get]"]
> eval $vMc
>
> What's the right way to do this? Is eval the right approach? Where can
> I find some good documentation on eval?
>


The best way to do it is to use a slave interpreter to isolate problems
with user scripts from your main app.

If you are after something like user created plugins, also take a look
at the tcllib pluginmgr module, which provides a simple framework to
load plugins into safe interpreters.

Michael
crvoss@up-link.net

2006-10-20, 7:04 pm

Thanks to all of you -- this has gotten me off "top-dead-center". Many
of you have suggested a slave interpreter but I am using a method that
restricts the user to a specific app oriented command set which is not
the Tcl language -- such as LU.Mu.Ds.Btn which is a hierarchy of object
acronyms which leads to a specific button and invokes that button. The
macro language is held in an array. The specific command for the
example above is assigned like this:

set aMc(LU.Mu.Ds.Btn) [list $lData(LETab).fraMu.btnDs invoke]

and executed like this:

eval $aMc(LU.Mu.Ds.Btn)

When the user wants to emplement the command he types:

LU.Mu.Ds.Btn

in a simple editor within the app along with other commands as needed
to accomplish the automated task they are after. The macros are edited,
saved and loaded as needed.

There is no chance for the user to gain access to the base Tcl language
since no macro commands are made available to them for such.

I am still "scratching my head" over how to implement loops though --
eval doesn't work with a loop that is not closed within the same eval
statement. The loop will contain many commands similar to the example
above (the only difference is that some macro commands sometimes
contain multiple Tcl comands). This would sure be a good place for a
goto command with line labels! If any of you have suggestions for this
loop problem I would sure appreciate your comments.

Thanks again for getting this thing going again.
Charles

Michael Schlenker wrote:
> crvoss@up-link.net schrieb:
>
> The best way to do it is to use a slave interpreter to isolate problems
> with user scripts from your main app.
>
> If you are after something like user created plugins, also take a look
> at the tcllib pluginmgr module, which provides a simple framework to
> load plugins into safe interpreters.
>
> Michael


Bruce Hartweg

2006-10-20, 7:04 pm

crvoss@up-link.net wrote:
> Thanks to all of you -- this has gotten me off "top-dead-center". Many
> of you have suggested a slave interpreter but I am using a method that
> restricts the user to a specific app oriented command set which is not
> the Tcl language -- such as LU.Mu.Ds.Btn which is a hierarchy of object
> acronyms which leads to a specific button and invokes that button. The
> macro language is held in an array. The specific command for the
> example above is assigned like this:
>
> set aMc(LU.Mu.Ds.Btn) [list $lData(LETab).fraMu.btnDs invoke]
>
> and executed like this:
>
> eval $aMc(LU.Mu.Ds.Btn)
>
> When the user wants to emplement the command he types:
>
> LU.Mu.Ds.Btn
>


but this user interface does NOT restrict you from using a slave interp to
runt hose commands (or even within the main interp) instead of putting
all your code into an array and trying to eval it, put your command into
a procedure and then create a command "LU.Mu.Ds.Btn" to be th at proc.


> in a simple editor within the app along with other commands as needed
> to accomplish the automated task they are after. The macros are edited,
> saved and loaded as needed.
>
> There is no chance for the user to gain access to the base Tcl language
> since no macro commands are made available to them for such.
>
> I am still "scratching my head" over how to implement loops though --
> eval doesn't work with a loop that is not closed within the same eval
> statement. The loop will contain many commands similar to the example
> above (the only difference is that some macro commands sometimes
> contain multiple Tcl comands). This would sure be a good place for a
> goto command with line labels! If any of you have suggestions for this
> loop problem I would sure appreciate your comments.
>



anytime you think you need goto - is a good sign a differnet approach is needed ;)

Bruce
Glenn Jackman

2006-10-20, 7:04 pm

At 2006-10-20 04:15PM, "Bruce Hartweg" wrote:
> but this user interface does NOT restrict you from using a slave interp to
> runt hose commands (or even within the main interp) instead of putting

^^^^^^^^^

Truly excellent typo. Thanks for the smile (thanks fort he smile)


--
Glenn Jackman
Ulterior Designer
crvoss@up-link.net

2006-10-20, 7:04 pm

Okay, you have a point with the procs as long as the code is linear but
I avoided that because of my previous post -- how do you handle loops
or conditional statements? These can have many macro statements in
their bodies. It seems to me that an eval command can be assembled on
the fly (somehow) to include the opening statement (LoopStart), the
body (LU.Mu.Ds.Btn ; LU.Ex.Sd.PB.Set ; Ed.Mu.LU.Btn ...) and the
closing statement (LoopEnd) -- and similiarly for conditionals. This
becomes a simple process with a goto statement but problematic with the
preexisting Tcl looping command set. Another problem with procs is that
there may be any number of loops in a macro and the procs would have to
be uniquly named. But then again, I haven't figured out all the "ins
and outs" with eval either. Maybe you have some things on your mind
that will solve it all. If so lay them out here in a simple enough
fashion that I can understand.

Thanks for your help
Charles

Bruce Hartweg wrote:
> crvoss@up-link.net wrote:
>
> but this user interface does NOT restrict you from using a slave interp to
> runt hose commands (or even within the main interp) instead of putting
> all your code into an array and trying to eval it, put your command into
> a procedure and then create a command "LU.Mu.Ds.Btn" to be th at proc.
>
>
>
>
> anytime you think you need goto - is a good sign a differnet approach is needed ;)
>
> Bruce


Bryan Oakley

2006-10-20, 7:04 pm

crvoss@up-link.net wrote:
> Okay, you have a point with the procs as long as the code is linear but
> I avoided that because of my previous post -- how do you handle loops
> or conditional statements? These can have many macro statements in
> their bodies. It seems to me that an eval command can be assembled on
> the fly (somehow) to include the opening statement (LoopStart), the
> body (LU.Mu.Ds.Btn ; LU.Ex.Sd.PB.Set ; Ed.Mu.LU.Btn ...) and the
> closing statement (LoopEnd) -- and similiarly for conditionals. This
> becomes a simple process with a goto statement but problematic with the
> preexisting Tcl looping command set. Another problem with procs is that
> there may be any number of loops in a macro and the procs would have to
> be uniquly named. But then again, I haven't figured out all the "ins
> and outs" with eval either. Maybe you have some things on your mind
> that will solve it all. If so lay them out here in a simple enough
> fashion that I can understand.


So, I guess you define your own "looping commands" that somehow take
arguments? Do your looping commands work like tcl looping commands --
they take a condition and a body as arguments? Or, are they more
primitive, using GOTO?

I think the point you may be missing that others have tried to suggest
is that you can create actual bona fide tcl commands named
"LU.Mu.Ds.Btn" and eval those directly, unaltered, in a slave
interpreter. Thus, if you have a macro that looks like this:

set macro {
your.special.loop {
LLU.Mu.Ds.Btn
LU.Ex.Sd.PB.Set
Ed.Mu.LU.Btn
...
}
}

You can run that code by simply doing "slave eval $macro". You don't
have to parse each line and convert it, you simpy ask tcl to run their
macro directly. To hide the real tcl commands, simply make them
unavailable in the interpreter. And to make your commands aliases for
real tcl commands (eg: for your.special.loop to be the equivalent of
"while 1") use the interp alias features.

Does that make sense?
Bruce Hartweg

2006-10-21, 8:01 am

crvoss@up-link.net wrote:
> Okay, you have a point with the procs as long as the code is linear but
> I avoided that because of my previous post -- how do you handle loops
> or conditional statements? These can have many macro statements in
> their bodies. It seems to me that an eval command can be assembled on
> the fly (somehow) to include the opening statement (LoopStart), the
> body (LU.Mu.Ds.Btn ; LU.Ex.Sd.PB.Set ; Ed.Mu.LU.Btn ...) and the
> closing statement (LoopEnd) -- and similiarly for conditionals. This
> becomes a simple process with a goto statement but problematic with the
> preexisting Tcl looping command set. Another problem with procs is that
> there may be any number of loops in a macro and the procs would have to
> be uniquly named. But then again, I haven't figured out all the "ins
> and outs" with eval either. Maybe you have some things on your mind
> that will solve it all. If so lay them out here in a simple enough
> fashion that I can understand.
>


Well,
to get more detail, I'll need to see more of the actual things you
are trying to do. But in short - using eval on complex multi-statement
commands requires a lot of special handling and can be fragile. Writing
and calling procs is extremely straightforward. putting a GUI/non-programmer
interface takes a little work but (in general) isn't that hard.

Bruce


> Thanks for your help
> Charles
>
> Bruce Hartweg wrote:
>

crvoss@up-link.net

2006-10-21, 7:03 pm

Okay Bryan, I think I'm beginning to catch on (call me bird brain).
Just one question -- does a slave interperter isolate you from the
master interpereter's GUI objects? The macro needs to access all the
controls and their values.

Be patient with me,
Charles

Bryan Oakley wrote:
> crvoss@up-link.net wrote:
>
> So, I guess you define your own "looping commands" that somehow take
> arguments? Do your looping commands work like tcl looping commands --
> they take a condition and a body as arguments? Or, are they more
> primitive, using GOTO?
>
> I think the point you may be missing that others have tried to suggest
> is that you can create actual bona fide tcl commands named
> "LU.Mu.Ds.Btn" and eval those directly, unaltered, in a slave
> interpreter. Thus, if you have a macro that looks like this:
>
> set macro {
> your.special.loop {
> LLU.Mu.Ds.Btn
> LU.Ex.Sd.PB.Set
> Ed.Mu.LU.Btn
> ...
> }
> }
>
> You can run that code by simply doing "slave eval $macro". You don't
> have to parse each line and convert it, you simpy ask tcl to run their
> macro directly. To hide the real tcl commands, simply make them
> unavailable in the interpreter. And to make your commands aliases for
> real tcl commands (eg: for your.special.loop to be the equivalent of
> "while 1") use the interp alias features.
>
> Does that make sense?


Cameron Laird

2006-10-21, 7:03 pm

In article <1161447233.479448.37690@f16g2000cwb.googlegroups.com>,
<crvoss@up-link.net> wrote:
>Okay Bryan, I think I'm beginning to catch on (call me bird brain).
>Just one question -- does a slave interperter isolate you from the
>master interpereter's GUI objects? The macro needs to access all the
>controls and their values.

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com