I've published a second version of a patch to add a method
keyword to Perl 5. The main difference in this patch is building up the optree to perform my $self = shift;
instead of stuffing that code into the lexer at the appropriate place:
methbody : '{' remember addimplicitshift stmtseq '}'
{
if (PL_parser->copline > (line_t)IVAL($1))
PL_parser->copline = (line_t)IVAL($1);
$$ = block_end($3, op_append_list(OP_LINESEQ, $3, $4));
TOKEN_GETMAD($2,$$,'{');
TOKEN_GETMAD($4,$$,'}');
}
;
addimplicitshift :
{ OP *selfsv = newOP(OP_PADSV, 0);
OP *rv2av = newUNOP(OP_RV2AV, 0, newGVOP(OP_GV, 0, PL_defgv));
OP *shift = newUNOP(OP_SHIFT, 0, rv2av);
selfsv->op_targ = (I32)Perl_allocmy(aTHX_ STR_WITH_LEN("$self"), 0);
$$ = newSTATEOP(0, NULL,
newASSIGNOP(OPf_STACKED, selfsv, 0, shift));
}
;
The second production is most interesting. It does the work of creating the Perl 5 optree you can see from running:
$ perl -MO=Concise,meth -e 'sub meth { my $self = shift; }'
main::meth:
7 <1> leavesub[1 ref] K/REFC,1 ->(end)
- <@> lineseq KP ->7
1 <;> nextstate(main 1 -e:1) v ->2
6 <2> sassign sKS/2 ->7
4 <1> shift sK/1 ->5
3 <1> rv2av[t2] sKRM/1 ->4
2 <$> gv(*_) s ->3
5 <0> padsv[$self:1,2] sRM*/LVINTRO ->6
You don't have to understand all of that, but you can see that this is
obviously a tree structure. addimplicitshift
creates the branch
staring at nextstate
(op 1) with a sibling sassign
(op 6). Other productions have already set up the body of the sub and its
lexical scope, so the call to Perl_allocmy
only has to give the
name of a new lexical ($self
). Its return value is the location of
the created variable in the lexical storage pad, so that the opcode to access
the value of $self
can retrieve it correctly.
With that lexical created before the parser parses the literal body of the method from the source code, any other references to $self
refer to the lexical implicitly created thanks to the method
keyword such that:
use feature 'method';
method oops
{
my $self = shift;
}
... produces a warning:
"my" variable $self masks earlier declaration in same scope
I suspect there's a reasonably easy way to make the method
keyword work nicely with projects such as MooseX::Declare in code such as:
use 5.014;
use MooseX::Declare;
method register(Str $name, Int $age) { ... }
... but despite the
advantages of a method
keyword in Perl 5, I've done about as
much coding on this as I want to do without more support that it might
eventually go into Perl 5.
Is there any way that an ordinary Perl 5 user, who has no strong C chops or p5p clout, can help you land this into the core? I'd love to see the feature but I'm not sure how I could help make it reality.
Test it with code you care about, report bugs (especially on p5p), and encourage other people to do the same. That's as much help as anything.
Would you mind providing more guidance for getting or creating your patched version of perl to test with? The most involved I've gotten with the source code for perl is following the instructions for downloading and compiling perl as outlined in item 110 of Effective Perl Programming (2nd ed.).
Thanks for working on this. I would really like this feature to be available in Perl.
Certainly! I'll post instructions later this week.