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

Ã

Reply via email to