[Edinburgh-pm] Perl code generator

Wim Vanderbauwhede wim.vanderbauwhede at gmail.com
Sat Apr 13 09:36:08 PDT 2013

Hi folks,

I told some of you at the last .pm that I wanted to write a code generator
that converts a Perl script into source code in my GPIR language, simply by
running the script. For example:

use GPRM;
use GPRM::DocFilter;

my @dfs = map {new GPRM::DocFilter($_)} 1..8;
my $df2 = new GPRM::DocFilter(9);

        my @vals;
        for my $i (1..8) {
            push @vals, $dfs[$i-1]->score($i)

What this does is generate code that will score a document collection using
8 threads and aggregate the results. The score and aggregate methods are
assumed to be provided by the DocFilter class.
The 'use GPRM' does the heavy lifting: it reads the source in the GPRM.pm
module, transforms it, and then uses exec() to call perl on the new code.
The GPRM::DocFilter module does not exist, a stub is created to keep perl
What happens is that a call like $df2->aggregate() uses AUTOLOAD to
generate the code in my GPIR language. The result is something like this:

; docfilter.yml
(label L_1 (c1.DocFilter.DocFilter.score '1))
(label L_2 (c2.DocFilter.DocFilter.score '2))
(label L_3 (c3.DocFilter.DocFilter.score '3))
(label L_4 (c4.DocFilter.DocFilter.score '4))
(label L_5 (c5.DocFilter.DocFilter.score '5))
(label L_6 (c6.DocFilter.DocFilter.score '6))
(label L_7 (c7.DocFilter.DocFilter.score '7))
(label L_8 (c8.DocFilter.DocFilter.score '8))
(label L_9 (c0.Ctrl.Ctrl.begin ))
(label L_10 (c9.DocFilter.DocFilter.aggregate L_1 L_2 L_3 L_4 L_5 L_6 L_7
(label L_11 (c0.Ctrl.Ctrl.begin L_10))

This gets compiled into bytecode and runs on my GPRM VM.

At the last .pm meeting, I got a number of interesting suggestions.
In the end it turned out I had to do a lot more parsing and analysis for
the transformations than I thought, so I ended up using PPI. It's not
pretty but it works.

You can find it on GitHub:

I created two modules, PPI::Visitors and PPI::Generators, which are
general-purpose. The first provides a tree walker that you can provide with
your own node transformations and context. The second provides a number of
functions to generate PPI nodes and often-used compounds like method calls.

The actual code transformations are in GPRM::Transformer
The code generation is in GPRM

I would really value some feedback on this. It's still buggy but I've
uploaded it anyway. So if you can spare a moment, have a look.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.pm.org/pipermail/edinburgh-pm/attachments/20130413/d6cb5f23/attachment.html>

More information about the Edinburgh-pm mailing list