The Method Keyword, take two


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));

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; }'
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.

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

sponsored by the How to Make a Smoothie guide



About this Entry

This page contains a single entry by chromatic published on January 31, 2011 4:07 PM.

CGI is Okay, but Bad Code is Irresponsible was the previous entry in this blog.

Politely Suggesting Improvements is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Powered by the Perl programming language

what is programming?