The goal of the top-level package file is to make as many function of the MPFQ API reachable. The top-level package file also must define a Perl object. We discuss by example the file provided in the MPFQ distribution as an example, under src/gf7/gf7.pm
.
We proceed through this file line by line (comments, which exist in the file, are stripped off here).
package gf7; use strict; use warnings;
Not much to say about the first fragment above. The package name must match the file name.
use Mpfq::engine::handler; our @ISA = qw/Mpfq::engine::handler/; sub new { return bless({},shift); }
Here we set up the object mechanism. Not much (well actually nothing) is conveyed within the object in terms of data[1]. The main use of the object is to contain a reference to a given package.
use Mpfq::defaults; use Mpfq::defaults::flatdata; use Mpfq::defaults::poly; our @parents = qw/ Mpfq::defaults Mpfq::defaults::flatdata Mpfq::defaults::poly /;
The fragment above lists the parents of the given package. All package files may mention such parents.
our $resolve_conflicts = { vec_set => 'Mpfq::defaults::flatdata', vec_ur_set => 'Mpfq::defaults::flatdata', };
This is optional, and is used to disambiguate possible conflicts.
sub code_for_add { return [ 'inline(K!, z, x, y)', "z = (x+y)%7;" ]; }
This is one of the code generation functions expected in this file.
sub code_for_sub_helper { return { kind=>'inline(z, x, y)', name=>'sub_helper', requirements=>'dst_elt src_elt src_elt', code=>'z = x-y;', }; } # The function called by the automatic generator should return as usual # its proto and its code, but additionnally a hash describing the helper # function (there might be several of them). sub code_for_sub { my $proto = 'inline(k, z, x, y)'; my $code = ''; $code .= "@!sub_helper(z, x, y);\n"; $code .= "if ((long)z < 0)\n"; $code .= " z += 7;\n"; return [ $proto, $code ], code_for_sub_helper(); }
This example is slightly more complicated and uses the extended syntax allowed for code_for_xxx
, where dependencies between functions are possible.
sub init_handler { my $types = { elt => "typedef unsigned long @!elt\[1\];", dst_elt => "typedef unsigned long * @!dst_elt;", src_elt => "typedef const unsigned long * @!src_elt;", elt_ur => "typedef unsigned long @!elt_ur\[1\];", dst_elt_ur => "typedef unsigned long * @!dst_elt_ur;", src_elt_ur => "typedef const unsigned long * @!src_elt_ur;", field => 'typedef void * @!field;', dst_field => 'typedef void * @!dst_field;', }; return { types => $types }; } 1;
This finished the package file (note the 1;
). The init_handler
provides some typedefs to be included in the generated code.