The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Module::Pragma - Support for implementation of pragmas

SYNOPSIS

        # Foo.pm
        package Foo;
        use base qw(Module::Pragma);

        __PACKAGE__->register_tags(qw(-SHA1 -MD5));
        __PACKAGE__->exclusive_tag( __PACKAGE__->tags );

        sub something
        {
                # ...
                if(__PACKAGE__->enabled(-SHA1)){
                        $mod = 'Digest::SHA1';
                }
                elsif(__PACKAGE__->enabled(-MD5)){
                        $mod = 'Digest::MD5';
                }
                else{
                        $mod = $Digest_Default;
                }
                # ...
        }
        # ...
        1;
        __END__

        # foo.pl
        use Foo;

        Foo->something(); # Foo->enabled(-SHA1) is true
        {
                use Foo -MD5;
                Foo->something(); # Foo->enabled(-MD5) is true
        }
        Foo->something(); # Foo->enabled(-SHA1) is true

        # ...

DESCRIPTION

With perl 5.10.0 you can write lexical pragma modules, which influence some aspect of the compile time or run time behavior of Perl programs. Module::Pragma helps to write such a module.

Module::Pragma supports bitmask-based options. That is, a subpragma takes only a bool, true or false. And a pragma uses an integer for its storage, so the number of subpragmas is limited to at most 32 or 64 (depends on the perl integer size).

How to set it up

Module::Pragma is designed as Object-Oriented and all the methods are class methods.

First, load the module and set it a super class.

        package mypragma;
        use base qw(Module::Pragma);

Next, register subpragmas (called tags in this module) with register_tags() method.

        __PACKAGE__->register_tags(qw(foo bar baz));

You can also make a bundle of tags with register_bunlde() method.

        __PACKAGE__->register_bundle('foobar' => ['foo', 'bar']);

To make some tags exclusive, call regsiter_exclusive() method.

        __PACKAGE__->register_exclusive('foo', 'baz');

Here you have finished setting up a new pragma. It's used like other pragmas.

        use mypragma 'foo';
        use mypragma 'baz';     # 'foo' and 'baz' are exclusive;
                                #  'foo' removed and 'baz' set on.
        use mypragma ':foobar'; # 'baz' removed ,and 'foo' and 'bar' set on.

This pragma requires explicit arguments and refuses unknown tags by default.

        use mypragma;        # die!
        use mypragma 'fooo'; # die!

If you don't want this behavior, you can override default_import() and unknown_tag().

METHODS

Registration of tags

PRAGMA->register_tags(tagname [ => flag] [, more tags ...])

Registers tags and returns the last value of tags. Each tag is assigned to a bitmask automatically unless othewise specified.

For example:

        PRAGMA->register_tags(
                'A' =>   0b00100,
                'B',   # 0b01000
                'C',   # 0b10000
                'D' =>   0b00001,
                'E',   # 0b00010
        ); # -> returns 0b00010 (corresponding to 'E')

Cannot register those which begin with triple underscores, because they are reserved for Module::Pragma internals.

PRAGMA->register_bundle(bundlename => tags...)

Makes a bundle of tags. To use the bundle, add a semicolon to the bundlename as a prefix.

PRAGMA->register_exclusive(tags...)

Declares tags exclusive. Exclusive tags are not specified simultaneously.

Checking Effects

PRAGMA->enabled(tags...)

Checks at the run time whether tags are in effect. If no argument is supplied, it returns the state of PRAGMA.

When scalar context (including bool context) is wanted then it returns an integer, otherwise it returns a list of the tags enabled;

use/no Directives

Module::Pragma itself do nothing on import() nor unimport(). They work only when called as methods of subclass;

These two methods call check_exclusive(), so if exclusive tags are supplied at the same time, it will cause _die().

PRAGMA->import(tags...)

Enables tags and disables the exclusive tags.

If no argument list is suplied, it calls default_import(), and if it doesn't _die() then it will use the return value as the arguments.

PRAGMA->unimport(tags...)

Disables tags and enables the exclusive tags.

if no argument is suplied, it disables all the effect.

Handling Exception

There are some exception handlers which are overridable.

PRAGMA->default_import( )

Called in import() when the arguments are not supplied. It will _die() by default. So if needed, you can override it. The return values are used as the arguments of import().

PRAGMA->unknown_tag(tagname)

Called in tag() when an unknown tagname is found. It will _die() by default. To change the behavior, override it. Expected to return an integer used as a bitmask.

Utilities

Module::Pragma provides pragma module authors with utilities.

PRAGMA->hint([level_to_go_back])

Returns the state of PRAGMA.

PRAGMA->_die(messages...)

Loads Carp.pm and calls croak() with PRAGMA and messages.

PRAGMA->tag(tagname)

Returns the bitmask corresponding to tagname.

If tagname is unregistered, it will call unknown_tag() with tagname.

PRAGMA->tags( )

Returns all the registered tags.

Note that tags beginning with double underscores are ignored.

PRAGMA->pack_tags(tags...)

Returns the logical sum of tags.

PRAGMA->unpack_tags(bits)

Returns the names of tags corresponding to bits.

PRAGMA->exclusive_tags(tags...)

Returns tags which are exclusive to tags.

PRAGMA->check_exclusive(tags...)

Checks whether tags are exclusive and if so, causes _die().

EXAMPLES

An implementation of less.pm

The minimal implementation of less.pm would be something like this:

        package less;
        use base qw(Module::Pragma);
        sub default_import{
                return 'please';
        }
        sub unknown_tag{
                my($class, $tag) = @_;
                return $class->register_tags($tag);
        }
        1; # End of file

This is almost equal to the standard less.pm module (but the interface is a little different).

        require less;
        sub foo{
                if(less->enabled()){
                        foo_using_less_resource();
                }
                else{
                        foo_using_more_resource();
                }
        }

        {
                use less; # or use less 'CPU' etc.
                foo(); # in foo(), less->enabled() returns true
        }
        foo(); # less->enabled() returns false

BUGS

Please report bugs relevant to Module::Pragma to <gfuji(at)cpan.org>.

SEE ALSO

See perlpragma for the internal details.

AUTHOR

Goro Fuji (藤 吾郎) <gfuji(at)cpan.org>

COPYRIGHT AND LICENSE

Copyright (c) 2008 Goro Fuji.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.