(Cross-posting the new ruling from p6l to p6c to discuss implementation 
strategy)

On Mon, Jul 11, 2005 at 06:29:28PM -0700, Larry Wall wrote:
> {
>     let $Larry.decisive = 1;
> 
>     Okay, this is what we're gonna do.  We're gonna go back pretty close to
>     where we were originally, but with a twist.  That is, .foo is always
>     a call on the current topic, but the invocant is (again) always the
>     topic in the outer scope of a method.  The difference from before
>     is that we simply outlaw .foo notation at *compile* time in those
>     scopes where we know (at compile time) that $_ and $?SELF diverge.
>     In such a scope you *must* specify $_ or $?SELF (or equivalent).
>     (If necessary we can also compile .foo inside methods down to code
>     that checks at runtime whether $_ has diverged from $?SELF and pitch
>     a run-time fit for those situations we can't detect at compile time.
>     Or we can just declare it erroneous.)  Basically, you can't use .foo
>     inside a "given" or a "for" inside a method.
> 
>     That's the default, and I'm not changing my mind ever again, at least
>     till next week.  That being said, if you mutate your language with
>     anything like:
> 
>       use self "this";
>       use self "self";
>       use self "o";
>       use self "./";
>       use self "";
>       ...
> 
>     then the pragma is allowed to warp .foo semantics to make it *always*
>     refer to $_ everywhere, provided it *also* undoes the default binding
>     of $_ := $?SELF, so people that people aren't tempted to use .foo to
>     mean $?SELF.foo in that scope.
> 
>     Yes, this is possibly a hazard for cut-n-pasters.  But then,
>     you weren't supposed to be cutting-n-pasting anymore, were you?
>     Shame on you.  Move the common code to a role, or a base class.
> }

Normally, I try to comply with new rulings as soon as they become
available, but the implementation of this is nontrivial, so I'd welcome
more input.

The obvious thought is to have yet another magical, $^H like flag, to
denote the current dialect.  If it is set, then the parser can emit
.method as $_.method, instead of $?IMPLICIT_INVOCANT.method.  If it is
not set, the parser needs to emit this as the first statement in any
method body:

    $_ := $?SELF

The compiler, in turn inspect whether there's an bound $_ in scope
with $?SELF set.  It is not trivial, because this should work:

    sub baz (&c) { c() }
    method foo { baz { .bar } }     # $_ is free in inner closure

But this needs to fail:

    sub baz (&c) { c(1) }
    method foo { baz { .bar } }     # $_ is bound in inner closure

Clearly we need a way to statically determine &statement:<given>
and &statement:<for> will always assign at least one argument to
its block argument.  Without that, the compile-time analysis mandated by
Larry is infeasible.

Then, we need to figure out the structure for the magic flag set by
self.pm on behalf of its caller.  We are not using $^H anymore, so
there needs to be a way to pass lexical settings to the caller.

To use MJD's lexical pragma design:

    module self;
    use pragma;
    sub import ($caller, $dialect) {
        install_pragma_value('$?SELF_MAGICAL', $dialect);
    }

This will create a lexically scoped hint in the importer's scope;
the parser and compiler will be hard-wired to recognise that magic
and act accordingly.

Does this seem sane?  The static detection of $_ is the showstopper
currently, and Pugs will need to separate the compiler with PIL evaluator
to implement the pragma.pm above.  Before that happens, I'll still
pretend that:

    use self './';

is in scope.  If people are uncomfortable with that, maybe we can
retrofit all tests and examples using the ./ syntax to add that dummy
line on top of their code, and ship with a stub self.pm that does
nothing.  Will that do as a interim solution?

Thanks,
/Autrijus/

Attachment: pgpN8udhQ2SUX.pgp
Description: PGP signature

Reply via email to