Re: Aliasing an array slice

2003-07-18 Thread Benjamin Goldberg


David Storrs wrote:
> 
> Thinking about it, I'd rather see lvalue slices become a nicer version
> of C.
> 
>  my @start = (0..5);
>  my @a = @start;
> 
>  @a[1..3] = qw/ a b c d e /;
>  print @a;   #  0 a b c d e 4 5

What would happen if I used 1,2,3 instead of 1..3?  Would it do the same
thing?  I wanna know what happens if I do:

   @a[0,2,4] = qw/ a b c d e /;

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Re: Aliasing an array slice

2003-07-18 Thread Benjamin Goldberg


Luke Palmer wrote:
> 
> > David Storrs wrote:
> > >
> > > Thinking about it, I'd rather see lvalue slices become a nicer version
> > > of C.
> > >
> > >  my @start = (0..5);
> > >  my @a = @start;
> > >
> > >  @a[1..3] = qw/ a b c d e /;
> > >  print @a;   #  0 a b c d e 4 5
> >
> > What would happen if I used 1,2,3 instead of 1..3?  Would it do the
> > same thing?
> 
> Of course.
> 
> > I wanna know what happens if I do:
> >
> >@a[0,2,4] = qw/ a b c d e /;
> 
> It would probably do the same as in Perl 5; the same thing as:
> 
> @a[0,2,4] = << a b c >>;
> 
> (those << >> brackets are new shorthand for qw, not that qw is going
> anywhere)

Hmm... so, if I were to do:

   @x = map int(rand(6)), 1..3;
   @[EMAIL PROTECTED] = "a" .. "e";
   print @a.length;

Then, if the three integers in @x are consecutive, @a grows, but
otherwise it doesn't?

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Re: Aliasing an array slice

2003-07-18 Thread Benjamin Goldberg
Dave Whipp wrote:
> "Luke Palmer" wrote:
> > Benjamin Goldberg wrote:
> > > David Storrs wrote:
> > > >  @a[1..3] = qw/ a b c d e /;
> > > >  print @a;   #  0 a b c d e 4 5
> > >
> > > What would happen if I used 1,2,3 instead of 1..3?
> > > Would it do the same  thing?
> >
> > Of course.
> 
> I tend to agree, I think. But see below
> 
> > > I wanna know what happens if I do:
> > >
> > >@a[0,2,4] = qw/ a b c d e /;
> >
> > It would probably do the same as in Perl 5; the same thing as:
> >
> > @a[0,2,4] = << a b c >>;
> 
> But that would be awful:
> 
>@a[$x,$y] = <>
> 
> would insert all 5 elements if ($y == $x+1); but only the first two
> otherwise. Belch.
> 
> If we wanted the array-splice thing to resize arrays for us, then either
> we trigger the behavior only when rx/ \[  \.\.  \]/, or

AFAIK, in perl6, $a..$b doesn't create an expanded list... it creates a
lazy list, which gets expanded as-needed.  Most likely, this list
object, and the list object representing the values being stored there,
would be handed directly to the @a array object, just as if we'd done
code like:

   @a[ new LazyIntRange(1,3) ] = new LazyStrRange("a","e");

So, @a can say, "hey, this is a Range, not merely a list of 1,2,3... I
should instead splice() the values in"

> we need to define the spilling algorithm in a way that makes sense (e.g.
> all remaining items go into the element of the righmost index).
>
> But perhaps there's a better way to beet the desire. Perhaps ellipses
> could be emplyed to indicate that the splice is allowed to resize the
> array:
> 
>   @a[1...3] = qw(a b c d e);

That might work, too.

My way is more invisible, but then again, if someone *wants* to have
@a[1,2,3,4,5,6,7,8,9] = @x, and writes it as @a[1..9] = @x, and is
surprised by perl doing a splice, it would be bad; with "..." it would
only splice when the user asks for a splice.

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Re: The Perl 6 Summary -- preprocessors

2003-07-23 Thread Benjamin Goldberg
Luke Palmer wrote:
> 
> > grammar Grammars::Languages::C::Preprocessor {
> >   rule CompilationUnit {
> > (  |  )*
> >   }
> >
> >   rule Directive {
> >  ( Include
> >| Line
> >| Conditional
> >| Define
> > ) *
> >   }
> >
> >   rule Hash { /^\s*#\s*/ }
> >   rule Include {...}
> >   rule Line {...}
> >   rule Conditional {...}
> >   rule Define {...}
> >   rule Continuation {...}
> >   rule UnprocessedStuff {...}
> > }
> 
> We're not quite in the world of ACME::DWIM, so you can't just replace
> the important stuff with ... .  :-)
> 
> You're not outputting a parse tree, you're just outputting more text
> to be parsed with another, text-based, grammar.  It seems to me like
> it's a big s//ubstitution, of sorts.

Hmm... well, think about yacc for a moment.  You could either have the
handlers for rules assign to $$, based on $1, etc., and thus build a
huge structure, OR, you could have the handlers for rules print stuff to
stdout (which might possibly be a pipe to another process).

ISTM that we also want our grammers to be able to do things like that...

We want to be able to produce a tree, *and*, we want to be able to act
as a filter.  And probably also some combination thereof -- some rules
produce trees, and other rules within the same grammer (which contain
the tree-producing ones) somehow process and output those trees.

> Or maybe not, maybe we make an output stream which will be fed to
> Grammars::Languages::C.  Here's an implementation a #include
> processor, using as little made-up syntax as possible.
> 
> use Pattern::Common;
> 
> grammar Preprocessor {
> rule include {
> :w(/\h*/)
> \# include "" $$
> { $0 := (<<< open "< $filename") ~~ // }
> }
> 
> rule main {
> $0 := ( [ | .]* )
> }
> }

Alas, this doesn't work right with a fairly common idiom:

   #ifdef HAVE_FOO_H
   #include 
   #endif

Nor the even more common:

   #ifndef SYS_SOMEFILE_H
   #define SYS_SOMEFILE_H
   lots of stuff, possibly including some #includes, and some typedefs.
   #endif /* SYS_SOMEFILE_H */

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Re: Protocols

2003-07-24 Thread Benjamin Goldberg
Chromatic wrote:
[snip]
> > I think you want to declare "I comply with ruleset X" at the callee
> > object level. That enables the compiler to (1) check that you're not
> > lying; and (2) optimize based on (1).
> 
> At least one of us is using "caller/callee" in the X11 sense.  What I
> mean and what I think you mean is:
> 
> method foo ( Thingie $t ) { ... }
> 
> $object->foo( $behaves_like_thingie );
> 
> foo() says, "Give me something that I can treat like a Thingie.  I
> don't care HOW it does it, I just want it to do something sane."
> 
> $behaves_like_thingie is an instance of a class that somehow says,
> "Hey, I act like Thingie.  I'm substitutable for Thingie if you don't
> break my encapsulation."

If this were Java, the way to do this would be to define a Thingie
interface, and then an (archetypical) ThingieObject class... any time
that we want to actually *create* Thingies, we would use "new
ThingieObject", but everywhere else, we would use the typename
"Thingie".  This way, when we want a class which "acts like" a Thingie,
but without inheriting any of it's innards, simply implement the Thingie
interface, instead of inheriting the ThingyObject class.


Here's a possible idea -- have a method of the Class class, which
returns (creates) an anonymous Interface object, which provides all of
the public methods of that class, and which is magically one of the
parents of that class.

This way, when one wants to define a new class X which "acts like" some
other class Y, but which doesn't *really* inherit from Y (none of the
internal data, etc.), we can define X as implementing the Y.interface()
Interface.  For our "isa" operator, and (perhaps more importantly) for
multimethod dispatch and/or sub prototype checking, we only check if an
object inherits from a class's magic parent interface, and *don't* check
if it *really* inherits from that class itself.


Of course, this by itself wouldn't let us delegate to the ThingyObject's
versions of the methods... that would require another extra layer of
nonsense^Windirection.


> If we're just confused over a bit of terminology, we're in violent
> agreement on the idea, which is much more important.

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Re: Macro arguments themselves

2003-08-02 Thread Benjamin Goldberg
Larry Wall wrote:
[snip]
> Nope.  $x and $p are syntax trees.



Macros are passed syntax trees as arguments, but return coderefs?

That's... odd.

I would expect that a macro would be expected to *return* a syntax
tree... which could then undergo (more) macro-expansion.

Sortof like how in lisp, a macro recieves lists as arguments (those
lists being un-evaluated code) and then returns a list, which then has
more macro expansion done on it, and then gets parsed and evaluated.

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Re: "As soon as she walked through my door..."

2003-08-03 Thread Benjamin Goldberg
Miko O Sullivan wrote:
> 
> Congratulations to Damian on a great opening in Ex 6.  Anybody can spoof
> the classic detective novel setup, but it takes real talent to have it
> actually make sense in the context of a technical document.

How long till Ex 6 is online, for those of us who weren't there? :)

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Re: Perl 6's for() signature

2003-08-14 Thread Benjamin Goldberg


Jonadab The Unsightly One wrote:
> 
> John Siracusa <[EMAIL PROTECTED]> writes:
> 
> > Did this ever get resolved to anyone's satisfaction?  While reading
> > EX6, I found myself wonder exactly what for() would look like in
> > Perl 6 code...
> 
> A for loop[1] is basically syntax sugar for a while loop.  In general,
> where foo, bar, baz, and quux are expressions, the following are equivalent:
> 
> for (foo; bar; baz) { quux }
> foo; while (bar) { quux; baz }

Well, except that in the second, any variables declared in foo will leak
into the scope after the end of the for loop.  Also, in the second,
"baz" is inside the same scope as quux, whereas in the normal C-style
for loop, it's not.

Thus, "for (foo; bar; baz) { quux }" is really more like:

   {
  foo;
  start_for_loop:
  if( !bar ) { goto end_for_loop }
  { quux }
  baz;
  goto start_for_loop;
  end_for_loop:
   };

> If Perl6 has enough syntax-sugar ability to let you turn the former
> into the latter, then you don't need to worry about for's signature.

Well, yes.  But the point of this discussion is, precisely what *kind*
of syntactic sugar will be used.

> [1]  Of course I mean a C-style for loop.

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Re: PerlHash.get_pmc_keyed of non existing key

2003-08-24 Thread Benjamin Goldberg


Gordon Henriksen wrote:
> 
> Taking a thread from Perl 6 Internals. Will Perl 6 support this behavior?
> 
> $ perl <<'EOT'
> my @ary;
> my $ref = \$ary[0];
> $$ref = "value";
> print '$ary[0] : ', $ary[0], "\n";
> EOT
> $ary[0] : value
> 
> Presumably the Perl 6 would be:
> 
> my @ary;
> my $ref = [EMAIL PROTECTED];
> $$ref = "value";
> print '@ary[0] : ', @ary[0], "\n";   # -> @ary[0] : value
> 
> If that's supported, then how will this behave?
> 
> my @cows of Cow;
> my $slot = [EMAIL PROTECTED];
> $$slot = new Dog;

Well, Perl6 can infer (at compile time) that $slot is a reference to a
Cow, and from that, it can infer that $$slot may only contain a Cow. 
Thus, it should be catchable at compile time.

OTOH, the following is not catchable at compile time:

   my @cows of Cow;
   my @dogs of Dog;
   my $ref = int(rand(2)) ? [EMAIL PROTECTED] : [EMAIL PROTECTED];
   $$ref = new Dog;

All that Perl6 can infer at compile time about $ref is that it is a
reference to any(Cow, Dog).  So, the assignment is legal at compile
time.

Thus, *some* sort of runtime check needs to be made.

I suppose that instead of $ref being a PerlRef (or however we manage
references), it would be a PerlTypeConstrainedRef, which throws an
exception if you try to store a value the wrong type into it.

> Do we wind up with Clarus or an exception? (Never mind whether you take
> exception with Clarus.)

Clarus would be if we had an object whose type was all(Cow, Dog), eh?:)

> Hopefully an exception, from a user's POV.

An exception at compile time the code you presented, an exception at run
time for the code I presented.

> And this?
> 
> my @cows of Cow:
> my @cats of Cat;
> my $ref = [EMAIL PROTECTED];

Ok.

> @cats[0] := $$ref;

Ok, although this is mostly a no-op.

> @cats[1] := @cows[0];   # Just to hammer the point home

A compile time error.

> $$ref = new Dog;

A compile time error due to type inferencing.
(If type inferencing were insufficient, it would be a run-time error).

> But then there's a question for p6i as to how all the above happens.

I suppose that a PerlRef would be a PMC which has another PMC stored in
it's ->cache.struct_value component; storing and fetching it's contents
would be done via VTABLE_set_pmc and VTABLE_get_pmc.

I suppose that a PerlTypeConstrainedRef would, in addition, have a
PerlClass PMC in it's PMC_data, and check for the appropriate isa
relationship before allowing new data to be stored into it.

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Re: Junctions & Set Theory

2003-09-02 Thread Benjamin Goldberg
Luke Palmer wrote:
> 
> Wow, what an old thread...
> 
> Jonadab the Unsightly One writes:
> > "Abhijit A. Mahabal" <[EMAIL PROTECTED]> writes:
> >
> > > On the other hand, if you wanted to say "true for all except exactly
> > > one value, I can't think of a way.
> >
> > Easy.  The following two statements are equivalent:
> >
> > F(x) is true for all but exactly one x
> > (not F(x)) is true for exactly one x
> >
> > The only additional possibility that can't be phrased in terms of the
> > four given is the complex generalised case:
> >
> > F(x) is true for at least n but not more than m values of x
> 
> Oh, I wouldn't say that
> 
> use HypotheticalModules::List::Combinations 'combinations';
> 
> sub between($low, $high, [EMAIL PROTECTED]) {
> any(
> $low..$high ==> map -> $num {
> any( map { all(@$_) } combinations($num, @values) )
> }
> )
> }
> 
> Efficient?  No.  Blows out memory for (20, 30, 1..50)?  Yes.
> Works?  Yes.
> 
> We also have:
> 
> class Betwunction is Junction {
> submethod BUILD($.low, $.high, @.values) { }
>
> method evaluate() {
> my Int $n = grep { ? $_ } @.values;
> $.low <= $n <= $.high;
> }
> }
> sub between($low, $high, @values) {
> new Betwunction: $low, $high, @values;
> }
> 
> Or something.  But I guess this one breaks the constraint of "in terms
> of the four given".

Also, it tests more values for truth than it has to.

If there are fewer elements in the array than $.low, then obviously, we
should fail immediately.  Actually I should say, "elements remaining",
instead of just "elements", and should say "$.low - the number of true
elements so far" instead of "$.low".  In otherwords, this bit of short-
circuiting could be done on every iteration, so as to test fewer
elements of the array for truth, if we can.

If there are fewer elements in the array than $.high, then (assuming we
already know that there are at least $.low elements) we can succeed
immediately.  Likewise, this short-circuiting can be done on every
iteration.

   method evaluate() {
  my Iterator $i = Iterator.new($.values);
  my Int $need = $.low;
  while( $need > 0 ) {
 return false if $i < $need;
 --$need if ? $i.shift;
  }
  my Int $limit = $.high - $.low;
  while( $limit >= 0 ) {
 return true if $i < $limit;
 --$limit if ? $i.shift;
  }
  return false;
   }

This *should* do no more boolean tests on the elements of $.values than
absolutely necessary.

> > So for example you could have a list of fifty values for x and test
> > whether the condition is true for at least ten but not more than
> > fourty of them.  (Or, x could be the condition; you could have a list
> > of fifty conditions and test whether between twenty and thirty of them
> > were true.)  My guess is, however, that the frequency with which
> > anyone would use such a capability would not be overwhelming.
> >
> > It would be great for obfuscation, though, particularly if some of the
> > conditions had side effects with an impact on the value of the other
> > conditions to be tested...  That would be sufficiently interesting
> > that it's almost a shame I can't think of a real reason to request
> > such a feature, since I rather doubt anyone's going to much fancy
> > implementing it just for obfuscatory value ;-)
> 
> Who needs reasons?

It's at least as useful as the proposed "fortytwo" op for parrot. :)

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Timely object destruction

2003-06-03 Thread Benjamin Goldberg


Piers Cawley wrote:
> 
> The Perl 6 Summary for the week ending 20030601
> Another Monday, another Perl 6 Summary. Does this man never take a
> holiday? (Yes, but only to go to Perl conferences this year, how did
> that happen?)
> 
> We start with the internals list as usual.
> 
>   More on timely destruction
> The discussion of how to get timely destruction with Parrot's Garbage
> Collection system continued. Last week Dan announced that, for languages
> that make commitments to call destructors as soon as a thing goes out of
> scope, there would be a set of helpful ops to allow languages to trigger
> conditional DOD (Dead Object Detection) runs at appropriate times.
> People weren't desperately keen on the performance hit that this entails
> (though the performance hit involved with reference counting is pretty
> substantial...) but we didn't manage to come up with a better solution
> to the issue.
> 
> http://xrl.us/iu5

I'd like to reiterate (and clarify) my idea, of a hybrid scheme
combining refcounting and DoD.

All values needing timely destruction would inherit from a class
RefCounted.  They should (in the normal scheme of things) be stored in
variables with an "is refcounted" trait (or a trait which inherits or
includes that trait, if that's possible).

Hopefully, only a *small* number of objects in a system need timely
destruction, and (for best performance) all variables which will hold
those objects will have the "is refcounted" trait set on them.

(If most or all objects needed timely destruction, then we wouldn't be
moving away from perl5's pure-refcount GC, would we?)

All operations on a variable or variables having the "is refcounted"
trait result in opcodes to call the refcount(inc|dec) method(s) of the
values in those variables.

Under normal circumstances, when a refcounted value's refcount goes
to zero, it self destructs^W^W cleans itself up.

This is quite perl5-esque, and of course slower than simply letting
the DoD-GC handle everything, BUT, in the absence of circular reference
loops, it does produce timely cleanup of those objects which need it,
which pure-DoD wouldn't, and DOESN'T result in numerous, and thus
expensive, requests for full DoD runs.

For all of the other schemes, full DoD runs would be run on every scope
exit, even if there's only one single variable in scope which needs
timely destruction.

Here's where the non-normal circumstances are described, and how they're
handled:

It's legal for a refcounted value to end up referenced by a non-
refcounted variable.  This has to be so, since adding the "is refcounted"
trait everywhere would get cumbersome; also we may sometimes *need*, for
one reason or another, to store refcounted values in the same containers
which also hold non-refcounted values.

Thus, if a refcounted value gets stored in a non-refcounted variable,
then that value could quite easily still be reachable when it's refcount
goes to zero.  Obviously, when this is the case, we need to avoid a
premature cleanup.

To avoid premature cleanup, any time that the contents of a
refcounted variable is assigned to a non-refcounted variable, an opcode
to set a "reachable by non-refcounted variable" flag on the value
precedes the assignment.  If a refcounted values's refcount goes to
zero, and it has this flag set, it does NOT self-destruct[*].

A global counter keeps track of how many values have a refcount of zero
and have this flag set.

>From here, we are in a similar situation as other proposals -- for the
timeliest possible destruction, then on every single scope exit, we
check if this global counter is nonzero, and if so, do a DoD run.

For potentially less timely destruction, we do this check whenever we
leave a scope where a refcounted variable was declared, but not when
we leave other scopes.

Which of these two is done is a choice of the language designer, but
might possibly be controlled by a pragma.

Note that in the absence of marking any variables with the "is refcounted"
trait, and with the use of the first option here (at every scope exit,
check the counter and maybe do DoD), this scheme behaves *identically*
with one of the other schemes proposed.

It would be *no* slower at run time, since the refcount(inc|dec) methods
are only called when doing operations dealing with variables with the
"is refcounted" trait, and if noone uses that trait, there's no extra
work.  DoD would be a tiny bit slower with my scheme than the other,
due to the extra flag checking, but (assuming that *most* code with
objects needing timely destruction properly marks it's variables with
the necessary "is refcounted" trait) that's a small price to pay for
doing fewer DoD runs.

[*] How does this flag get cleared, you might ask?

Simplest would be to not clear it at all.  This would be mostly harmless
in terms of when objects get destructed, but would probably result in
more DoD runs than we really need -- blech. [**]

A mor

Re: Timely object destruction

2003-06-04 Thread Benjamin Goldberg


Miko O'Sullivan wrote:
> 
> On Mon, 2 Jun 2003, Benjamin Goldberg wrote:
> 
> > All values needing timely destruction would inherit from a class
> > RefCounted.
> 
> I like this concept a lot, but maybe we can take it a little further
> and make it transparent to the programmer.  Suppose that the internals
> only tracked objects that have a DESTROY method (or whatever it will
> be called in Perl6)?  You get the same benefit without the additional
> brain-overhead of manually indicating that the class needs to be
> tracked.

That's a good idea, one which I left out because I was trying to
simplyfy/clarify my description.

-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


Re: Timely object destruction

2003-06-04 Thread Benjamin Goldberg

After reading Leopold Toetsch's post, I'm going to simplify part of my
proposal slightly.

Benjamin Goldberg wrote:
[snip]
> To avoid premature cleanup, any time that the contents of a
> refcounted variable is assigned to a non-refcounted variable, an
> opcode to set a "reachable by non-refcounted variable" flag on the
> value precedes the assignment.

Actually, as Leopold suggested, we could merely set a global
interpreter->needs_lazy_dod flag to true.

[snip]
> [*] How does this flag get cleared, you might ask?
> 
> Simplest would be to not clear it at all.  This would be mostly
> harmless in terms of when objects get destructed, but would probably
> result in more DoD runs than we really need -- blech. [**]
> 
> A more "proper" solution would be to clear it during/after each DoD
> run.
> 
> During the course of a DoD run, when we look for what PMCs are
> reachable, we keep track of what each thing was reachable *from*.

This needs a bit of clarification, I think.

IIRC, DoD normally happens something vaguely like this:

   for my $p (@all_pmcs) {
  clear_is_live_flag($p);
   }
   our $traverse;
   sub set_is_live_flag($p) {
  if( !test_is_live_flag($p) and test_is_agregate($p) ) {
 $traverse = [$p, $traverse];
  }
  really_set_is_live_flag($p);
   }
   set_is_live_flag($_) for @rootset;
   while( $traverse ) {
  ((my $p), $traverse) = splice @$traverse;
  $p->set_live_flag_on_contained_objects();
   }
   for my $p (@all_pmcs) {
  next if test_is_live_flag($p);
  free_pmc($p);
   }

My proposal would change the set_is_live_flag to something like:

   sub set_is_live_flag($p, $contained_in) {
  if( test_uses_refcounting($p) and
 not test_has_refcount_trait($contained_in) ) {
 $needs_lazy_dod = 1;
  }
  if( !test_is_live_flag($p) and test_is_agregate($p) ) {
 $traverse = [$p, $traverse];
  }
  really_set_is_live_flag($p);
   }

Where $contained_in would be the variable (or agregate object) which the
object $p is contained in.


-- 
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED]
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}


RE: Lessons to learn from ithreads (was: threads?)

2010-10-16 Thread Benjamin Goldberg

> Date: Tue, 12 Oct 2010 23:46:48 +0100
> From: tim.bu...@pobox.com
> To: faw...@gmail.com
> CC: ben-goldb...@hotmail.com; perl6-language@perl.org
> Subject: Lessons to learn from ithreads (was: threads?)
> 
> On Tue, Oct 12, 2010 at 03:42:00PM +0200, Leon Timmermans wrote:
> > On Mon, Oct 11, 2010 at 12:32 AM, Ben Goldberg  
> > wrote:
> > > If thread-unsafe subroutines are called, then something like ithreads
> > > might be used.
> > 
> > For the love of $DEITY, let's please not repeat ithreads!
> 
> It's worth remembering that ithreads are far superior to the older
> 5005threads model, where multiple threads ran with an interpreter.
> [Shudder]
> 
> It's also worth remembering that real O/S level threads are needed to
> work asynchronously with third-party libraries that would block.
> Database client libraries that don't offer async support are an
> obvious example.
> 
> I definitely agree that threads should not be the dominant form of
> concurrency, and I'm certainly no fan of working with O/S threads.
> They do, however, have an important role and can't be ignored.
> 
> So I'd like to use this sub-thread to try to identify when lessons we
> can learn from ithreads. My initial thoughts are:
> 
> - Don't clone a live interpreter.
> Start a new thread with a fresh interpreter.
> 
> - Don't try to share mutable data or data structures.
> Use message passing and serialization.
> 
> Tim.

If the starting subroutine for a thread is reentrant, then no message passing 
is needed,and the only serialization that might be needed is for the initial 
arguments and for thereturn values (which will be gotten by the main thread via 
join).
As for starting a new thread in a fresh interpreter, I think that it might be 
necessary topopulate that fresh interpreter with (copies of) data which is 
reachable from thesubroutine that the thread calls... reachability can probably 
be identified by usingthe same technique the garbage collector uses.  This 
would provide an effect similar toithreads, but only copying what's really 
needed.
To minimize copying, we would only treat things as reachable when we have to -- 
forexample, if there's no eval-string used a given sub, then the sub only 
"reaches" thosescopes (lexical and global) which it actually uses, not every 
scope that it could use.