Piers Cawley writes:
> Simon Cozens <[EMAIL PROTECTED]> writes:
> > But it isn't, and I don't know why it isn't, and so we end up
> > spending loads of time discussing things that can be punted out to
> > modules. Designing Perl 6 is hard enough; let's not try to fill
> > CP6AN at the same time.
>
> But the vast majority of us *aren't* designing Perl 6, that's Larry
> and his team's job. We're in the position of taking the work that's
> been done on the language so far and working out how we'd use it (and
> yes, we're in the business of thinking about the sort of thing
> that will go in CP6AN). Considered in that light, Luke's question is a
> really good one, it points up an ugly idiom and considers how one
> would generate a better idiom in Perl 6. Where he falls down is in
> proposing new syntax to solve the problem rather than in proposing the
> new syntax and then offering a sketch of its implementation as a macro
> in Perl 6. After all, problems with 'implemented' solutions are simply
> demonstrations that the design is sound, and that's good feedback to
> Larry and his team. These things only become real design issues if
> there appears to be no good way to solve such problems.
Ok, back to the concrete side of things then. How *would* one implement
a new loop hook?
Let's look at C<while>. It might be implemented as such:
my sub while_impl(&cond, &block) {
my &cc := Continuation.new;
try {
&block.PRE.() if &block.PRE;
if cond() {
block();
throw X::Next;
}
else {
throw X::Last;
}
CATCH {
when X::Next { &block.NEXT.() if &block.NEXT; cc() }
when X::Last { &block.POST.() if &block.POST; }
}
}
}
macro while($cond, $block) {
my (&cond, &block) := ($cond, $block)Â.Âparse;
return -> { while_impl(&cond, &block) }
}
Neglecting things like C<redo>. And so to implement FINISH, you'd need
to stick a C<&block.FINISH.() if &block.FINISH> right before C<throw
X::Last>.
But it would be really nice if you could do this without rewriting
C<while>. One way is to wrap &cond:
wrap &cond: {
call or &_.FINISH.()
};
But then you need to associate FINISH with the condition instead of the
execution block. Or just wrap it when you can see the FINISH block.
Like:
macro FINISH($code) {
# When it's a macro/rule, caller naturally returns the parse stack
CallerContext $c = caller &Perl6::Grammar::while;
my &code := $code.parse;
$c[-1].MY.{'&cond'}.wrap({
call or code()
});
return -> {};
}
Okay, that's pretty evil. Pretty really evil. I took a currently
executing sub, extracted, and I<changed> one of its lexicals. Evil
enough to make the optimizer very unhappy, in any case.
But such is the life of the Aspect-Oriented programmer.
Can anyone think of a cleaner way?
Luke
Ã