Matt Diephouse wrote:
Let's try this again, starting from the Tcl side of things. Tcl code
can exist outside of subroutines. This, for example, is a valid Tcl
program:
set number 5
puts $number
[...]
But things get a
little hairier when we start using namespaces in Tcl:
namespace eval test {
set number 5
puts $number
}
This is the equivalent of running the first example in a different
namespace. So, again, the simplified, ideal PIR is:
.HLL 'tcl', 'tcl_group'
.namespace ['test']
.sub 'main' :anon :main
.local pmc number
number = new .TclInt
number = 5
set_global 'number', number
say number
.end
Okay, so we're basically solving the same problem as Perl 5's "main"
routine, which it stuffs in an obscure C variable internal to the
interpreter, not accessible from the symbol table. (Talk about
less-than-transparent introspection.)
I don't fully grok Tcl, so a few questions (which may or may not be
relevant): Where do mainstream implementations of Tcl store that
executable "main" block of code? Or, more importantly, where do they
store 'number' in the case without the namespace and the case with the
namespace?
But here we run across the behavior that led me to file RT#40955: I
have an anon namespace that uses the notion of the current namespace.
The code is the same, but the PIR example doesn't work because the
"current namespace" inside the :anon sub is the root HLL namespace. So
while
set_global 'number', number
would normally be equivalent to
set_hll_global ['test'], 'number', number
in this case, it's actually equivalent to
set_hll_global 'number', number.
All this because when Parrot sees an :anon sub it attaches the root
HLL namespace to it (or did, before I applied my "fix"). It's not that
it doesn't attach any namespace to it, it's that always attaches the
root HLL namespace regardless of the namespace it's declared in.
That, at least, ought to change.
Agreed, that is b0rken. (Namespaces are new enough that Parrot still has
a bad habit of defaulting to root namespaces.) And, agreed that
set_global and related opcodes need some namespace to default to.
Still, I'm curious to see what reasons there are for not attaching a
namespace to an :anon sub when (1) it seems convenient and (2) all of
Parrot's tests still pass. Does this break anything? Or did this just
signal to you that there may a problem here that needs its own
solution?
Yes and yes. One common use of anonymous subs in a dynamic language is
for later exporting them into another package (or multiple different
packages). In that case, you really don't want the sub to retain a link
to its defining namespace, you want it to fully adopt the namespace it's
pushed into. Which has everything to do with the earlier Perl example of
creating anonymous subroutines, but little to do with creating "main"
routines, since they don't change packages. (Code examples are helpful.)
Let's see... for :main, :load, :method, and :vtable compilation units it
makes sense to default lookups to the namespace where they were defined,
even if they're anonymous. For an ordinary :anon .sub (with no :vtable,
:method, :load, :main, etc) I could argue it either way, but with the
other uses remaining tied to the namespace where they were defined,
let's default to your fix (consistency is good).
Then for exporting (and other dynamic tricks), let's look into a feature
that allows you to change the namespace a compilation unit uses for
default lookups, after it's compiled.
Allison