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 > >