Patrick R. Michaud wrote:

Of course, in the previous object model I think there was only one place to look, and find_method did the searching.

In the previous model, there was no distinction between subroutines and methods. Any method could be called as a subroutine, and any subroutine could be called as a method (you would only get a runtime error if the first parameter of the subroutine wasn't a PMC). It was horribly wrong, and horribly broken.

My initial
reaction is that the right thing to do is to store the method's
PMC in both locations.  That way it's still possible to distinguish
a method from a normal sub or other symbol table entry.  If
the dispatch always looks in both locations, it might be more
difficult to create a symbol in the namespace that isn't also treatable as a method.

The thing I don't like about storing the method in both places is that it's not possible to distinguish a normal sub from a method.

But, as long as it's not the default, and users have to specifically request it with a flag, I'm happy to provide the feature. (Though I hope it will only be used very rarely.)

In order for inheritance to work in grammars, it's vital that
regex lookup and invocation be able to work like methods -- i.e.,
invoking <abc> within a pattern should be able to find the 'abc'
regex in a parent grammar.

If you dispatch it as a subroutine call, it's not going to respect the rules of inheritance, which may bite users who expect that calling <abc> will have the same effect in all cases.

However, there are also times that regexes act like subs -- for
instance, consider the following:

    module Foo {
        rule abc { ... }
        rule def { ... <abc> ... }
        ...
    }

Here 'abc' can't really be a method, because there's not a class
to which it can be added.  So, we need to make sure that 'abc'
gets an entry in the 'Foo' namespace somehow.  Things become a lot
simpler overall if PGE can simply generate subs that are methods
and automatically appear in the namespace.

Agreed that the lookup is simpler in this case if they are treated as subs. Does the Apocalypse/Synopsis specify that when the 'rule' keyword is used in a 'module' block that it acts like a 'sub' rather than a 'method'?

It would certainly be possible to say that declaring a 'rule' in a 'module' block will create a grammar class with the same name as the module that hosts all the rules declared in that module.

To a certain extent, you're going to have to perform a little extra magic on these calls anyway, to provide a sensible invocant as the first argument of the call.

The specific case that prompted the ticket is dealing with
anonymous regexes, as in:

    $a ~~ / foo \d+ /;

This again generates a regex that isn't a method in a class, and
the only way to look it up is by its internally generated name.

I would see this as an singleton anonymous class with a single method (which could have a standard name like 'match').

It's entirely possible that PGE should have a flag on it that says
"generate a regex method" versus "generate a regex sub", and we
may end up with that anyway.  But I can also envision situations
where we'll want to be able to locate methods via namespace entries,
it's much easier to have a compile-time flag to tell imcc to put
a method into a namespace than it is to generate :load :init
instructions to make the mapping.  (Or to use PGE's present workaround,
which is to generate a separate :method wrapper around a sub.)

Flag approved, on the general principle of allowing flexibility to compiler writers. I'm thinking of the flag name :namespace, and of giving it an optional string parameter of the name to use in the namespace.

# Store subroutine 'foo' in the namespace
.sub foo

# Store method 'foo' in the namespace, overriding default
.sub foo :method :namespace

# Store method 'foo' as a vtable override named 'bar' and in the namespace as 'baz'
.sub foo :method :vtable('bar') :namespace('baz')

Allison

Reply via email to