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) { ... }