copying a proc to a namespace in TCL - namespaces

This is a simplified case of a problem. I am trying to copy a procedure to a namespace, so that it would be using the namespace own's context. Using import does not work (probably because it just creates aliases) See code below:
proc me_namespace {} {
puts "namespace is:[namespace current]"
puts "called namespace is:[uplevel 1 namespace current ]"
}
namespace eval foo {} {
me_namespace
puts "Now import"
namespace import ::::me_namespace
me_namespace
}
The code output is:
namespace is:::
called namespace is:::foo
Now import
namespace is:::
called namespace is:::foo
namespace is:::foo
Ideally, the proc me_namespace 1st line output, after the copying, should be:
::::me_namespace
Any ideas? The only thing that I can think of is having the procedures definitions be in a file, and then reading the file, and using eval, but I was looking for something more elegant.
The reason that I do not just use uplevel, is that at times (in particular when using variable with uplevel is that the runtime, a times, is far too slow. TCL version is 8.6

Procedures are bound to their containing namespace. Rename the procedure, change its binding. (I hate that!) To recreate a procedure in another namespace, you effectively have to either rename (a move) or to rerun the proc that created the original.
Now, while I'd really recommend looking at using TclOO when you're getting into this sort of thing, you might be able to use a different technique. The namespace upvar command is reasonably fast, and you might be able to use it like this:
proc master_version_of_foo {ns args} {
namespace upvar $ns abc local1 def local2
# ... continue with your code in here
}
# Stamp out some copies
namespace eval ::x {}
interp alias {} ::x::foo {} ::master_version_of_foo ::x
namespace eval ::y {}
interp alias {} ::y::foo {} ::master_version_of_foo ::y
namespace eval ::z {}
interp alias {} ::z::foo {} ::master_version_of_foo ::z
These true command aliases are pretty fast, the variable binding is pretty fast too (similar in speed to the global command; they use virtually the same bytecode operations internally) and you'll be sharing the compilation of the procedure which is itself pretty fast.
The main reason for not doing this is if you need different command resolution in the three cases. At that point, the fastest routes all go through TclOO (which tames quite a few of the advanced capabilities of Tcl to the point of being usable) and probably require some serious redesign on your part to use well.

Related

tcl switching namespaces and proc arguments

I have a little problem which I cannot explain at the moment. I created a minimalistic code snippet to show my problem or lack of understanding how tcl namespaces are working.
So I have the file test.tcl:
namespace eval test {
proc print {file_name} {
namespace inscope ::test2 {
printFileName $::test::file_name
}
}
}
namespace eval test2 {
proc printFileName {file_name} {
puts $file_name
}
}
Than I use tclsh and run:
source test.tcl
test::print test.dat
Which returns:
can't read "::test::file_name": no such variable
Why is that should the argument of test::print not be in the ::test namescope?
I have an easy workaround with set ::test::filename $filename before namespace inscope {}.
But I am not satisfied since I miss something here.
I cannot just run ::test2::printFileName $file_name since my real world code is more complex and does not run just one command it sources a list of commands which are all in a different namespace.
Local variables are not namespace variables. In particular, even with variable linking (the mechanism underlying upvar and global and variable etc.) formal parameter variables are never namespace variables in any way. That's just how the variables are mapped, because it's very fast to do; the procedure entry code is one of the hottest parts of Tcl's implementation code, so great efforts are taken to keep it as fast as possible.
But all is not lost!
You can copy the value to a namespace variable easily enough, or even do tricks with traces and upvar to make it appear like the local variable can be written back to from that interior scope. (You'll probably have to use info level to search back up the stack for where to inject the write, which will be horribly messy, but it will work.)
But what I'd instead do is make commands to provide the values (and possibly allow writing back as necessary). I think it's a bit cleaner.
namespace eval test {
proc print {file_name} {
proc ::test2::file_name {} [list return $file_name]
namespace eval ::test2 {
printFileName [file_name]
}
}
}
namespace eval test2 {
proc printFileName {file_name} {
puts $file_name
}
}
You can make this more elegant through the use of namespace path so that you don't have to build a whole new procedure each time you call. interp alias can help too (it's a good way to do argument currying, if you're familiar with that sort of thing from functional programming).
The problem here is that ::test::file_name refers to the file_name variable in the ::test namespace and not the local variable file_name as it seems that you want. That's just the way variable name resolution works. Local variables that are arguments to commands don't reside in the enclosing namespace.
Also, it is unusual to see namespace inscope invoked directly in a script. I would write this instead:
namespace eval test {
proc print {file_name} {
{*}[namespace eval ::test2 namespace code printFileName] $file_name
}
}
namespace eval test2 {
proc printFileName {file_name} {
puts $file_name
}
}
Or some variation if you don't have {*} in your version of Tcl.
But your last comment about not being able to run the command directly makes me suspect that this approach may not yet solve your problem.

Command to return library (not work) name of a path in modelsim

I want to find a way to return the name of a library of a certain path in a VHDL Design in Modelsim.
Given a VHDL Design with a path like "/mega_tb/D0". This is compiled in a library that is NOT 'work', say "libnwork".
I can of course take a look in my 'do' file to get the correct lib name. Or I can search in ModelSim's Library tab. But I want to have or create a modelsim command which I can later use in a Tcl script, to get the correct library name.
One of the easiest ways to find something in a Tcl script file – which is all a Modelsim “do” file is — is to evaluate it. Tcl's very good at that. Of course, you don't want to have the commands do all the conventional things. Instead, we'll evaluate in a context where we can make everything do nothing except for the command that produces the information we want:
# Set up our evaluation context, 'worker'
interp create worker -safe
interp eval worker {proc unknown args {}}; # Our do-nothing handler
interp alias worker theInterestingCommand {} ourHandler
proc ourHandler args {
puts "We were called with: $args"
}
# Parse the file!
set f [open /the/file.tcl]
interp eval worker [read $f]
# Clean up
close $f
interp delete worker
Now you just have to make theInterestingCommand have the right name and extract the interesting information from the arguments. Which should be relatively easy…
Te only way I've found is to use the command
write report -tcl
This prints a long list where I have search for the lib names with regexps.
Something like
set data [ write report -tcl]
foreach_regexp { _ type lib entity} $data{
if {$type == "Entity" && $entity == [entity_of_path /mega_tb/D0] } {
....
}
}
Where I of course had to define my "foreach_regexp" procedure and my "entity_of_path" procedure. I then can use something like regsub to extract the library name.
I am still looking for a better and easier way.

__PACKAGE__ equivalent in tcl

Is there a way(a method call) to find out the name of the current package in tcl??
Eg:
package provides abc
proc A {
// I need to print the package name abc.
}
I know the class name here is obviously "abc" but still I want to print it out using a tcl command. I'm working on some debug modules and hence need this. (Similar to what perl provides: __PACKAGE__)
I am not aware of anything like that. However, you can work around:
set __PACKAGE__ foo
package provide $__PACKAGE__ 1.0
# Use can use the variable $__PACKAGE__ from now on
You are missing a few pieces of the puzzle. Even though you declared proc A in a file that is part of a package, A is still created globally.
The package command really just helps tcl figure out which file to source. You usually want to mix package provide with namespace
package provide abc
namespace eval ::abc {
proc A {} {puts stdout "I am in namespace [namespace current]"}
proc B {} {..}
proc C {} {..}
}
In order to call this function you would say
::abc::A
From inside the body of A you can tell what namespace you are in by using namespace current
An alternate way of writing this would be
namespace eval ::abc {}
proc ::abc::A {} {puts stdout "I am in namespace [namespace current]"}
proc ::abc::B {} {..}
proc ::abc::C {} {..}
There is not a one to one mapping between packages and namespaces. So one package could create many namespaces (or like in your example, no namespaces).
Check out this page for how to build libraries:
http://www.tcl.tk/man/tcl8.5/tutorial/Tcl31.html
And this page for full instructions on package and namespace
http://www.tcl.tk/man/tcl8.6/TclCmd/contents.htm

SWIG TCL : Renaming the class constructor name from new_* to create_*

Can we rename constructors like we rename functions using the %rename directive?
%rename(create_cell) Cell(string);
Basically, I want to end up with something like create_cell instead of new_Cell.
I suspect that you can't at that point (did you try it to see if it works?) but there are a few things you can do. (Only do one of them, of course.)
Edit the generated code (SWIG writes the C++–Tcl binding code that is then compiled) so that the string "new_Cell" is "create_cell". I think you should be able to find the place to change in an argument a function call like Tcl_CreateCommand or Tcl_CreateObjCommand, but might also be in a macro depending on how the code generation is done. (I've never actually looked.)
Use load to get the code into Tcl and then rename the command afterwards. Names are not fixed in stone. The load might be inside the implementation of a call to package require; just do what you would normally do to get the code working with the wrong name first, and then do this:
rename new_Cell create_cell
Add a wrapper command or procedure; any of these will do:
proc create_cell args {
eval new_Cell $args
}
# With 8.5 or later
proc create_cell args {
new_Cell {*}$args
}
# With 8.6
proc create_cell args {
tailcall new_Cell {*}$args
}
# Or do this; not a procedure, an alias
interp alias {} create_cell {} new_Cell

Why namespace with empty braces is used in packages

I am having a package TEX.
package require ABC
package provide TEX 1.0
namespace eval ::65FGA {
}
proc ::65FGA::runSuite {{setupFile ""} args} {
Proc body
proc body
}
I am not getting why namespace with empty braces is used..
It may just be a matter of style:
namespace eval ::my_namespace {}
proc ::my_namespace::procname {} {...}
versus
namespace eval ::my_namespace {
proc procname {} {...}
}
Do you mean that
namespace eval ::65FGA {
}
bit?
This command just creates a namespace "65FGA" and then evaluates an empty string (empty script if this sounds more sensible to you). As a result, the said namespace is created but it does not yet contain anything in it.
In this code, you could remove the command invocation being discussed and it won't affect anything. Hence most probably it serves narrative purpose stating clear that the package is creating the said namespace (which it then populates with at leat one procedure).
UPDATE: Struck through the false statement (thanks to Eric Melski). The namespace must exist, indeed, before an attempt is made to create anything in it (via proc or set commands).