Yep. Good idea.
> pmclass Env extends default {
What do you think of:
- Env extends PerlHash
- interpreter has an empty env variable created at interpreter creation
- on first access to it, the hash gets populated, writing to the hash
  does a setenv(3) too.
- delete_keyed does an unsetenv(3), if available of course.
- defined_keyed, exists_keyed delegate (after possibly) filling the hash
  to SUPER().
leo
It was about time. :) And trivial, as too much of the pending stuff has been.
>  >   pmclass Env extends default {
>
>What do you think of:
>- Env extends PerlHash
Thought about it, but I couldn't think of a reason why. The only 
thing really hashlike about them is that you read and write by name. 
Which, granted, is awfully hashlike, but none of the rest of the hash 
stuff seemed needed. It's not like you can access environment 
variables by index, or that there's any sort of multidimensionality 
to them.
I can see throwing together the code to take and return PMCs, which 
really ought to be in but isn't. Past that, I don't know if it's 
worth much. (Though env variables are, arguably, multidimensional in 
a trivial sense)
>- interpreter has an empty env variable created at interpreter creation
>- on first access to it, the hash gets populated, writing to the hash
>   does a setenv(3) too.
I'd considered that, but I don't think it's necessarily a great idea, 
as it introduces a layer of caching that can get defeated by threads, 
since we're not sharing a single PMC across all the threads. (Though 
we probably ought to)
>- delete_keyed does an unsetenv(3), if available of course.
Good point, that should be in there. And it will be as soon as I sync 
up with CVS. :)
>- defined_keyed, exists_keyed delegate (after possibly) filling the hash
>   to SUPER().
Possibly, yeah, I can see that.
I'm also considering means to override the way this behaves since in 
an embedded context direct get/set/unset will be potentially 
overridden, and then there are platform-specific overrides that folks 
may want. (For VMS and Windows, for example)
I think ultimately we may want to have an interpreter-specific env 
PMC that is, by default, an Env PMC, but can be overridden at 
creation time, and we just disallow "new Px, .Env" calls, or 
something of that sort.
-- 
                                         Dan
--------------------------------------"it's like this"-------------------
Dan Sugalski                          even samurai
d...@sidhe.org                         have teddy bears and even
                                       teddy bears get drunk
> Thought about it, but I couldn't think of a reason why.
%ENV{'something'), keys(%ENV), iterating over %ENV ...
> I'd considered that, but I don't think it's necessarily a great idea,
> as it introduces a layer of caching that can get defeated by threads,
> since we're not sharing a single PMC across all the threads. (Though
> we probably ought to)
What about ParrotIO PMCs? You are sure, we don't share PMCs?
>>- defined_keyed, exists_keyed delegate (after possibly) filling the hash
>>   to SUPER().
> Possibly, yeah, I can see that.
> I'm also considering means to override the way this behaves since in
> an embedded context direct get/set/unset will be potentially
> overridden, and then there are platform-specific overrides that folks
> may want. (For VMS and Windows, for example)
The platform specific part is already hidden by using Parrot_*env()
functions. Or do you think of an intermediate layer between platform and
Env PMC?
> I think ultimately we may want to have an interpreter-specific env
> PMC that is, by default, an Env PMC, but can be overridden at
> creation time, and we just disallow "new Px, .Env" calls, or
> something of that sort.
I think one Env PMC ought to be enough. And that one may have e.g. an
Iterator ettached, which simplest is done by deriving it from an hash
like PMC.
leo
Yeah, fair enough. We need to talk about your iterator stuff in 
general, though it's applicable here. I think it's time to add some 
iterator support to the vtables, since we need them in a bunch of 
places. (I was trying to keep them out of the core just to cut down 
on the complexity we need to manage, but I think we're past the point 
where that's feasable)
>  > I'd considered that, but I don't think it's necessarily a great idea,
>>  as it introduces a layer of caching that can get defeated by threads,
>>  since we're not sharing a single PMC across all the threads. (Though
>>  we probably ought to)
>
>What about ParrotIO PMCs? You are sure, we don't share PMCs?
Sorry, what I meant is that there isn't just one environment PMC 
that's shared across all interpreters. We certainly can share PMCs 
across interpreters, that's pretty much required.
>  >>- defined_keyed, exists_keyed delegate (after possibly) filling the hash
>>>    to SUPER().
>
>>  Possibly, yeah, I can see that.
>
>>  I'm also considering means to override the way this behaves since in
>>  an embedded context direct get/set/unset will be potentially
>>  overridden, and then there are platform-specific overrides that folks
>>  may want. (For VMS and Windows, for example)
>
>The platform specific part is already hidden by using Parrot_*env()
>functions. Or do you think of an intermediate layer between platform and
>Env PMC?
It's more than that. On windows and VMS, the environment is a bit 
more complex than Unix's. With Windows you've two levels of 
environment (user and everyone) and with VMS you've got multiple 
levels, multiple tables at each level, and each entry in the 
environment may actually be an array of entries rather than a single 
entry. (akin to the ; as separator thing that Unix uses, only 
built-in)
>  > I think ultimately we may want to have an interpreter-specific env
>>  PMC that is, by default, an Env PMC, but can be overridden at
>>  creation time, and we just disallow "new Px, .Env" calls, or
>>  something of that sort.
>
>I think one Env PMC ought to be enough. And that one may have e.g. an
>Iterator ettached, which simplest is done by deriving it from an hash
>like PMC.
Potentially, yes. We still ought not cache, since otherwise process 
environment changes made outside the interpreter won't register with 
us, which would be bad.
Which is AFAIK only possible for Win* and VMS.
We could do something like this:
  init: PMC_data = NULL
        cache.struct_val = NULL
  getenv: Parrot_getenv;
  setenv: Parrot_setenv; if (PMC_data) SUPER.set_string_keyed()
  unsetenv: Parrot_unsetenv; if (PMC_data) SUPER.delete_keyed()
  iteration init:
       p = NULL;
       if (!PMC_data || cache.struct_val != (p=Parrot_all_environ())) {
          cache.struct_val = p ?: Parrot_all_environ()
	  build hash from this
       }
       SUPER() ...
Parrot_all_environ() is a function returning the current char *envp[] as
a NAME=value string array.
#ifdef linux
#  include <unistd.h>
#  define Parrot_all_environ() __environ
#endif
This would allow caching as long as the Parrot_all_environ() returns the
same pointer and the hash is built only on demand i.e. for accessing
the whole %ENV. Iteration would use the hash (no changed keys of process
environment during iteration are reflected in the env hash).
leo
Nope, not for this--I'm not talking about anything at all complex. 
Rather simple stuff like your code calls into a C library via the NCI 
interface, and that C code does a setenv().
>This would allow caching as long as the Parrot_all_environ() returns the
>same pointer and the hash is built only on demand i.e. for accessing
>the whole %ENV. Iteration would use the hash (no changed keys of process
>environment during iteration are reflected in the env hash).
Perl 5 on VMS does this sort of thing now (building the full list 
needs spawning a subprocess, which is really annoying. Don't ask, you 
don't want to know) and it's problematic. The cost of fetching isn't 
much, and the cache just isn't worth the hassle.
Ah. There is always one more possibility ;-)
> .... The cost of fetching isn't
> much, and the cache just isn't worth the hassle.
Ok. Then no hash at all.
leo