Allison, as I've mentioned before is getting this party started with some serious refactors to the way function calls happen. All calling paths are being migrated to use CallSignature PMCs, which contain the call signature, the list of passed arguments, the list of returns, and assorted other information. Patrick and Jonathan were also asking for some features that have been on the TODO list for a while: named-only parameters, named-if-possible parameters, and an ability to override the invoke VTABLE from PIR without TEH FAILZ.
The current semantics of named parameters is to fill in the list of parameters with the given positionals first, and then fill in any extra named parameters that have been provided. However, this system doesn't support a case where a parameter should not be filled by a positional parameter in any circumstances; that is if the parameter is "named only". It also doesn't count the case where we want a parameter to attempt to be be filled by a named if available, and a positional otherwise (a reverse of the current semantics). Apparently this issue was discussed at length on the mailing list, and I need to review all that. I think, based on what we talked about yesterday, that the parameter declaration flags are going to look like this:
- :named, parameters that can be filled in by a positional argument or a named argument otherwise
- :namedonly, parameters that can only be filled in by a named argument
- :lookahead, Parameters that can be filled by named arguments preferably, or positional arguments otherwise (reverse of :named)
The reasons why we have such difficulty with this particular issue because of two reasons: The way that we pass arguments around in PIR, and the semantic differences between different notions of the word "self". Consider two cases:
In the first case, the
$P0object is being invoked, which will call the invoke VTABLE on it. In the second case, a method on
$P0is invoked instead. These are obviously two different cases, so it doesnt make sense that within the subroutine body we refer to this quantity by the same name both times. In the first example,
$P0is the subroutine being invoked, and in the second it is the invocant on which a subroutine (method) is invoked. If we invoke a method directly as a subroutine without an invocant, do we expect that
selfwill refer to anything at all, much less the Sub object itself? And when we do invoke the method on the invocant, we obviously expect that
selfrefers to the invocant. Seeing the difference here, we have to assume that Sub should not change it's behavior based on the way it is called, or should even be aware of the way it's invoked. That's bad for encapsulation.
The solution here is to provide two separate access points for the two separate concepts: a
selfkeyword which represents the invocant, and something else (like, say,
this_sub) that will refer to the currently executing Sub PMC. Normal methods will use the former without breaking anything. The invoke VTABLE can use the later to suddenly become useful.
There are two methods on the horizon to make this possible: Allisons work where we will have a CallSignature PMC made available from which the current invocant and the current Sub PMCs can be extracted, and my work where we will have access to a Context PMC which contains these same pieces of information. In the long term future, as I mentioned in my previous post, these two PMC types are likely to be merged together.
Allison says her stuff is scheduled to land by the 1.4 release. I'll definitely be doing my Context work shortly after that (I don't want to be developing two separate in-depth branches on the same subsystem simultaneously, to prevent TEH FAILZ). So things will get moving soon on all this work, and there will be much rejoicing.