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

Reply via email to