Instead of duplicating the method calls, a simpler approach might be
to create a Perl6Env class that has Env and Mapping as parents, then
change %*ENV to create a Perl6Env instead of a Env.  This should
cause %*ENV to inherit all of Mapping's methods.  (For other examples,
see how Mapping, List, and Complex are set up to inherit from Parrot
built-in PMC types.)

This might also make it easier for us to create proxies that do
the correct thing with the real environment when values are stored
into %*ENV.

Thanks!

Pm

On Wed, Dec 24, 2008 at 10:19:23AM -0800, Cory Spencer via RT wrote:
> 
> This patch maps %*ENV onto the Mapping interface, allowing the
> fmt/keys/kv/pairs/values methods to work.
> 
> Please let me know if their are any issues to be corrected in it!
> 
> Thanks,
> 
> Cory
> 
> On Tue Nov 11 13:59:46 2008, pmichaud wrote:
> > On Thu Oct 16 06:31:14 2008, masak wrote:
> > > Here's a thorough investigation of the strange properties of %*ENV.
> > 
> > Here's an explanation -- I'll start with the summary first and then look
> > at the examples.
> > 
> > > In summary:
> > > 
> > > 1. Ordinary strings and strings in %*ENV are unequally treated. You
> > can call
> > > .trans(), or .trans([]) on the former, but you have to send in two non-
> > > invocant arguments to the latter.
> > 
> > Rakudo's %*ENV is simply an instance of Parrot's Env PMC.  Whenever we
> > fetch something from the Env PMC, we get back a String PMC.  This isn't
> > a full Rakudo Str object, though, so their behaviors are a bit latter.
> > 
> > In particular, Parrot's String PMC already has a .trans method defined
> > on it, so Rakudo's .trans method for Str doesn't override it.
> > 
> > > 2. The result of a successful .trans call on an %*ENV item returns
> > something
> > > which, when touched in any way, causes Rakudo to explode.
> > 
> > The .trans method on String PMC doesn't return a value at all -- it does
> > an inplace modification.  So, the return value is garbage that indeed
> > causes Parrot to go boom.
> > 
> > > 3. Actively modifying the %*ENV item using .=trans produces a Null PMC
> > > access
> > > in another Parrot sub, and doing this from within a subroutine, produces
> > > a Null
> > > PMC acces in yet another Parrot sub.
> > 
> > Since %*ENV returns a Parrot String PMC, and since the .trans method on
> > the String PMC returns garbage, the inplace modifier ends up trying to
> > store garbage back into the String PMC.
> > 
> > > 4. Setting an %*ENV item using infix:<=> has no effect. Setting it using
> > > infix:<:=> works. 
> > 
> > The values that come back from %*ENV are String PMCs that aren't tied to
> > the environment at all, thus assigning to those PMCs has no effect.
> > 
> > However, binding an item using <:=> does activate the set_*_keyed VTABLE
> > of the underlying Env PMC, so that does work.
> > 
> > > Setting %*ENV itself using infix:<=> produces a Parrot VM
> > > error.
> > 
> > The Env PMC is a singleton PMC that doesn't understand assignment. 
> > We'll need to map this somehow so that it understands how to rebuild
> > itself from a list or hash. 
> > 
> > > Setting it using infix:<:=> works. 
> > 
> > You can rebind %*ENV to a different hash, but then it loses its magical
> > Env properties.  (This may also end up being the case for infix:<=>
> above.)
> > 
> > > Assigning %*ENV to another
> > > variable
> > > using infix:<=> produces another Parrot VM error.
> > 
> > The Parrot Env PMC is a singleton PMC, so apparently there's not a way
> > to clone or copy it.  This will probably be fixed via ObjectRefs, if
> > it's not fixed already.
> > 
> > > 5. When calling the methods .keys, .values, .kv or .perl on %*ENV,
> > something
> > > fails with "No applicable methods". 
> > 
> > Since %*ENV (and the Env PMC) is not really a Hash or Mapping, none of
> > those methods yet apply.  This is probably fixable if we map the Env PMC
> > onto Rakudo's Mapping class.
> > 
> > 
> > So, with those points out of the way, here are the explanations of the
> > examples:
> > 
> > 
> > > say %*ENV<Q>.WHAT;
> > > # Str
> > 
> > %*ENV<Q> actually returns a Parrot String PMC, which we've mapped onto
> > the Rakudo Str type, so it reports 'Str' as its type (even though it
> isn't).
> > 
> > > say %*ENV<Q>.trans();
> > > # too few arguments passed (1) - 3 params expected
> > 
> > Since the String PMC has its own .trans method, the Str.trans method
> > doesn't get invoked (and the signatures are different).
> > 
> > 
> > > say %*ENV<Q>.trans( [], [] );
> > > # Null PMC access in get_string()
> > > say %*ENV<Q>.trans( [], [] ).WHAT;
> > > # Null PMC access in find_method()
> > 
> > This invocation matches the signature for String.trans (not Str.trans),
> > but that .trans is an inplace modification that returns PMCNULL.
> > 
> > > 
> > > %*ENV<Q> .= trans([ "A" => "B" ], [])'
> > > # Null PMC access in name()
> > 
> > This ends up calling %*ENV<Q>.trans( ... ), which returns PMCNULL and
> > cannot be assigned back to %*ENV<Q>.
> > 
> > > %*ENV<A> = "OH HAI"; say %*ENV<A>.perl
> > > # ""
> > > %*ENV<A> := "OH HAI"; say %*ENV<A>.perl
> > > # "OH HAI"
> > 
> > Assignment doesn't work, but binding does.
> > 
> > 
> > 
> > Hope this helps -- I'll see which of the above I can clean up.
> > 
> > Pm
> 
> 


Reply via email to