On Mon, Oct 04, 2004 at 11:25:47AM -0400, Dan Sugalski wrote:
> Okay, since we've got the *basic* semantics down (unified namespace, 
> namespace entries get a post-pended null character) it's time for the 
> ops to handle them, as well as some extended semantics.

I agree with Larry when he said "But I really don't care so much
what the flag is, as long as it's visible on printout.  I think
even / would be better than \0."

But if you _really_ want to go with a null, Larry also had a point
when he said "Well, I'd prepend the null just to reduce confusion
(or rather, to force the confusion earlier)".


> What I want to keep is:
> 
>    $Px = find_global 'name'
>    $Px = find_global [key; key; key], 'name'

> These load [...] from the current namespace and the specified 
> namespace respectively.

How do you define "current"? Compile-time, load-time, run-time,
run-time for each sub? From what you say later I'm guessing
you mean "run-time for each sub". So "current namespace" is an
attribute of the sub?

If so, then how is that represented within the interpreter struct
when it enters an anonymous subroutine via a continuation?

I ask partly because I'm (still) not paying enough attention,
and because once you add...

> Next I want to add in the op variants:
> 
>    $Px = find_global [key; key]
>    $Px = find_global $Px, [key; key]
>    $Px = find_global $Py, 'name'

Then "$Px = find_global 'name'" could be changed by the compiler
(or byteloader?) into "$Px = find_global $Py, 'name'" where $Py is
the register, or "pseudo register", holding the "current" namespace.


> The case where the namespace is specified by 
> string I think should go away. (And this'll impact me quite a bit, 
> but it's still the right thing to do)

I agree.

> to fetch out namespace PMCs and work with fetched namespace PMCs. 

>    $P0 = find_global ['Foo']
>    $P1 = find_global $P0, ['Bar'; 'Baz']
>    $P2 = find_global $P1, 'xyzzy'

> That is, if we don't specify the name of the thing in the namespace 
> we get the namespace PMC itself, which we can then go look things up 
> in. This is handy since it means code can cache the namespace PMC so 
> if there are a dozen variables to go fetch out, we don't have to do 
> the multi-level hash lookup each time. (That'd be nasty)

Yeap.

> Right *now* I'm not inclined to have a store_global variant to do 
> this, but if we want to completely hide all namespace operations 
> behind ops I'm OK with that.

The issue here is the postpending of a null to indicate a namespace?
If the application does it then it's breaking the encapsulation of
that concept?  Yeap, that's bad and should be avoided.

By the way, you said:

>    store_global 'name', $Px
>    store_global [key; key; key], $Px

but shouldn't that be:?

     store_global 'name', $Px
     store_global [key; key; key], 'name', $Px    # 'name' was missing

Then a store_global variant without the name param would be how you'd
store a namespace:

     store_global [key1; key2; key3], $Px

I think that's worth adding up front.

Other random thoughts:

I presume that store_global will auto-vivify namespace in the list.

You'll may need to define a way to explicitly get the root namespace.

I think some minimal top-level namespace policy needs to be set now
to limit the risk of confusion and/or polution later. I'd suggest:

* Every Language gets a top-level namespace named after the language.
  So the Perl compiler adds 'Perl'; to all the namespace lookups
  (or something equivalent to that in effect).

* Every Language namespace uses "ParrotRoot" as the way to access
  the root namespace (so find_global ['Perl'; 'ParrotRoot'] returns
  the root namespace).  That way any number of languages can coexist
  within Parrot at runtime with no risk of clashing. The only
  "polution" is the single "ParrotRoot" name.  The Python language
  root namespace, for example, would be visible to all other languages
  as ParrotRoot.Python.



> Now, with that out of the way, let's talk about overlaid namespaces.

I don't think I ever read a description of what the purpose of this was.
I get the "what" but not the "why". Without the "why" it's hard to
critique the "how".

> The namespace specification has always allowed for multiple 
> overlapping namespaces. What this is supposed to allow you do to is 
> have two or more full namespace trees available at once, with lookups 
> and stores automatically running through each of the namespaces until 
> the appropriate thing is found.

I understand that, but...

> (And the fact that we want to do this, and do it sorta-kinda lexically,
> is a reason for the namespace ops)

... not that. But let's ignore that for now. I'll come back to it below.

> For this, we're going to add the ops:
> 
>     overlay_namespace $Px
>     overlay_namespace $Px, $Iy
> 
>     remove_namespace $Px
>     remove_namespace $Ix
> 
> The first two add the namespace $Px to the current search list 

There's that "current" word again. Same confusion in my mind.

Unless "current" can be explained *really simply* I'd suggest it's
not used anywhere. All namespace ops that assume a "current"
namespace could be removed and the "currrent" namespace would then
become explicit: it would just be another register.  Unless I'm
missing something I think the gain in clarity would be worth it.

> the first version makes it the first space that will be searched, the 
> second form puts it at $Ix in the list of namespaces to search.

"puts" or "inserts"?

So a "namespace is like a hash" is now "a namespace is like an
ordered list of hashes"? Okay.

But if I do:

  $P0 = find_global ['Foo']
  overlay_namespace $P0

and the namespace in $P0 had already been overlayed, would we then
have a "list of lists of hashes"?

Or, are you saying that the overlay "magic" is related to the
vague (to me) concept of "current" and that's where the "sorta-kinda
lexically" comes in?

All seems rather complicated to me (but I could easily be missing
the point).  I'm also concerned that while most of Parrot is pushing
logic into PMCs in order that it's encapsulated *and overridable*,
namespace behaviour is being hard-wired into ops.

Here's what I'd suggest:

A. Let all operations on namespaces be explicit about the namespace
   they're operating on. Define a pseudo-register for current namespace.

B. Define a vtable interface for a Namespace PMC.  Namespace PMC
   should search themselves and insert entries into themselves.

C. Define a NamespaceList PMC that has the same interface as a
   Namespace PMC but delegates to a list of one or more Namespace PMCs.

D. Instead of using an overlay_namespace op a sub would create/manipulate
   a NamespaceList PMC. That NamespaceList PMC could be passed around
   and act just like a Namespace PMC.

E. [extra thought] Namespace PMCs would auto-vivify namespaces below
   themselves to be of the same type of PMC. Languages could install
   language-specific PMCs at their root (which would then auto-vivify
   down the tree) to support any language-specific behaviour that might
   be useful - though still supporting Parrot mandated behaviour.

Feel free to shoot me down ([1] especially as I don't know what I'm
talking about when it comes to parrot internals like vtables).


> Right now (and I expect this will change, but we're starting simple) 
> store_global will *always* store into the first namespace in the list

By using a NamespaceList PMC subs could implement whatever behaviour
they want.

Tim.

Reply via email to