Tk Library Source Code

View Ticket
Login
Ticket UUID: 1886636
Title: [clock] inside snit::widgetadaptor
Type: Bug Version: None
Submitter: nobody Created on: 2008-02-04 23:06:38
Subsystem: snit Assigned To: duquette
Priority: 6 Severity:
Status: Closed Last Modified: 2013-07-04 17:26:17
Resolution: Not Applicable Here Closed By:
    Closed on:
Description:
In Tcl 8.5.0 with snit 2.2.1:

----
package require snit
snit::widgetadaptor sframe {
option -foo[clock format [clock seconds] -format "%Y"]
constructor {args} { installhull using frame }
}
----

Produces:
----
invalid command name "::tcl::clock::format"
----
User Comments: [email protected] added on 2008-02-06 09:50:47:
Logged In: NO 

Thanks, Jeff.  That does make sense, as it means global scope commands can also be available.  I'll take a look at it.

Kevin, you're right, it's an odd place to call "clock".  I imagine it was intended to set a default option value to a timestamp, which (on the other hand) is a reasonable thing to do.  So it really ought to work.

kennykb added on 2008-02-06 03:50:38:
Logged In: YES 
user_id=99768
Originator: NO

For what it's worth, the list of core commands on which [clock] 
depends is fairly long (unsurprising for a large module coded in
Tcl).  I don't want to guarantee that the list will never expand,
but I attach the current known dependencies. (On Windows systems,
there is also a dependency on 'registry', not shown here.)
File Added: commandlist

kennykb added on 2008-02-06 03:50:37:

File Added - 265175: commandlist

kennykb added on 2008-02-06 03:25:27:
Logged In: YES 
user_id=99768
Originator: NO

By the way, the way that [clock] command is evaluated in the 
slave strikes me as a trifle strange.

I see:

snit::widgetadaptor sframe {
    option -foo [clock format [clock seconds] -format %Y]
    constructor args {installhull using frame}
}

How does that differ in principle from

proc foo {} {return bar}
snit::widgetadaptor sframe {
    option -foo [foo]
    constructor args {installhull using frame}
}

The second case fails with

invalid command name "foo"

because, of course, [foo] exists in the master interp and not the
compiler interp.

In short, it's arguably the widgetadaptor definition that's making 
the mistake (evaluating arbitrary Tcl code inside the compiler interp) 
rather than Snit. Is it actually reasonable to expect arbitrary Tcl
code to work there?

hobbs added on 2008-02-06 03:08:13:
Logged In: YES 
user_id=72656
Originator: NO

The patch should be rather self-explanatory.  It does all the snit stuff in the same interp in ::snit::compiler instead of in a separate interp.  This has benefits and disadvantages, but I think that the benefits may outweigh in the long run.

duquette added on 2008-02-05 10:02:56:
Logged In: YES 
user_id=372859
Originator: NO

Sorry, Kevin, I don't mean to be difficult.  It wasn't clear how you were using proc--I assumed it was just how the code was loaded, rather than being part of a scheme to compile code dynamically.  To the extent the core commands place serious restrictions on what you can do with an interpreter without breaking them, those constraints need to be clearly documented.  Are they?

Jeff, I don't understand what you mean by "turning the snit compiler into a fully namespace-encapsulated solution for 8.5" and "independent namespacing".  Are you using a namespace *instead* of an interpreter?  Or putting the Snit compilation commands into a namespace *within* the current slave interpreter?  I'd like some better notion of what you're doing before I dive into your code.

hobbs added on 2008-02-05 09:56:28:

File Deleted - 265077: 



File Added - 265078: namespace-snit.diff

Logged In: YES 
user_id=72656
Originator: NO

Update to one that still works with interp method
File Added: namespace-snit.diff

hobbs added on 2008-02-05 09:54:21:

File Deleted - 265076:

hobbs added on 2008-02-05 09:54:20:

File Added - 265077: namespace-snit.diff

Logged In: YES 
user_id=72656
Originator: NO

Updated my patch to correct one.
File Added: namespace-snit.diff

hobbs added on 2008-02-05 09:53:06:

File Added - 265076: namespace-snit.diff

Logged In: YES 
user_id=72656
Originator: NO

While not necessarily a short-term solution for this, turning the snit compiler into a fully namespace-encapsulated solution for 8.5 seems possible.

It would really depend on what level of importance independent namespacing has for snit.  Most of the code I see doesn't rely on that.

I just created the following patch that is a first pass at this.  It runs our TclApp, VFSE and Inspector from TDK locally with only one change (where we had ::typevariable used in the snit body).  I of course don't have full tests for this, so it would need further vetting.

It is built so you can switch the modes (from namespace to interp) at 1 point.

File Added: namespace-snit.diff

kennykb added on 2008-02-05 08:41:53:
Logged In: YES 
user_id=99768
Originator: NO

I don't think I can do what you're asking.

[clock scan] and [clock format] both work by compiling new 
Tcl code (defining a proc) every time a new format string is 
encountered.  They rather depend on ::proc being there to do
so. (And they suffer dreadfully in performance if they can't
compile code.)

Also, Snit overloads ::variable, and nearly every procedure
in the [clock] implementation begins with one or more
[variable] commands.  I don't really see how to avoid that
one without using fully qualified variable names everywhere
and eschewing [variable] entirely. Are you looking to inflict
that level of unreadability on core code so that you can
overload ::variable?

I suspect that what you're really saying here is that you find it
unacceptable that every Core command doesn't stand entirely
alone -- that some of the Core is written in Tcl, so depends
on other pieces of Tcl being there.  If you consider it a bug
that not all Core commands are written in C, please bring that
up on tcl-core, because we're moving more and more to
using Tcl for at least some non-critical things.

duquette added on 2008-02-05 06:53:20:
Logged In: YES 
user_id=372859
Originator: NO

This strikes me as being *not* a Snit bug, but a bug in the new implementation of "clock", etc.  Standard Tcl commands, it seems to me, should function normally in any interp, unless excluded for reasons of safety.  At the very least, they should be fully defined in a new interp *before* the interp's user starts changing things, rather than being defined lazily.

I'm certainly willing to add a fix for this in Snit if it's determined that that's the right thing to do...but I'm not at all sure that it is.

kennykb added on 2008-02-05 06:18:14:
Logged In: YES 
user_id=99768
Originator: NO

What's going on here is that the 8.5 [clock] command is implemented in
Tcl, A number of procedures, including ::tcl::clock::format (the guts
of [clock format] are created at run time. The fact that the $compiler
interpreter in Comp.Init overlaods ::proc and ::variable means that
the Tcl code inside [clock] cannot function normally.

A workaround - perhaps a fix, but I don't claim to understand what
the compiler is actually doing - is to add the line:

$compiler alias clock ::clock

to the set of compilation aliases.  This will cause all [clock]
commands to be evaluated in the master interp, obviating the need
to run [clock]'s Tcl code in the slave. This at least got the original
poster over the fault in initialization.

I would anticipate the same sort of trouble if commands such
as [msgcat::*], [package], [auto_load] or [parray] were to be 
evaluated in the $compiler interp, since they, too, are implemented
in Tcl and use [proc] and [variable].

Any thoughts?

Attachments: