=head1 NAME

ExtUtils::XSpp::Plugin - XS++ plugin interface

=head1 DESCRIPTION

The XS++ plugin interface is B<EXPERIMENTAL> and subject to change.
If you still want to use it, read the source of this module.

=begin internal

=head1 SYNTAX

    %loadplugin{MyPlugin};

    int foo(int y) %FuncTag{Foo};

    class klass
    {
        %ClassTag{Klass};

        void bar() %MethodTag{Bar};
    };

There are two ways a plugin can modify the code emitted by XS++: it
can run after the parsing completes and modify the expression tree
before it is emitted or it can handle custom annotation tags
associated with a class/function/method.

A custom tag can have either positional or named parameters:

    # positional
    %Foo{Id}{% multi
               line
               block %}{AnotherId};

    # named
    %Bar{
        %AParam{Id};
        %AnotherParam{% block %};
        %AThirdParam{AnotherId};
    };

No check is performed on parameter names/types/count.  The parser only
gives an error if the annotation is not handled by any plugin.

Positional parameters are passed to tag handlers as an array reference
in the C<any_positional_arguments> parameter; named handlers are passed as
an hash reference in the C<any_named_arguments> parameter.

The value of a special block parameter is an array reference with an
element for each line in the special block.  For consistency, the
value of an identifier parameter is a single-element array reference.

=head1 XS++ METHODS

These methods are defined in the parser object.

=head2 add_post_process_plugin

    $parser->add_post_process_plugin( plugin => $instance );

Registers a post-processing plugin to be called after the parsing
finishes.

=head2 add_function_tag_plugin

    $parser->add_function_tag_plugin( plugin => $instance,
                                      # optional
                                      tag    => $tag,
                                      );

Add a plugin to handle functions annotated with tags.

=head2 add_class_tag_plugin

    $parser->add_class_tag_plugin( plugin => $instance,
                                   # optional
                                   tag    => $tag,
                                   );

Add a plugin to handle classes annotated with tags.

=head2 add_method_tag_plugin

    $parser->add_method_tag_plugin( plugin => $instance,
                                    # optional
                                    tag    => $tag,
                                    );

Add a plugin to handle methods annotated with tags.

=head2 add_toplevel_tag_plugin

    $parser->add_toplevel_tag_plugin( plugin => $instance,
                                      # optional
                                      tag    => $tag,
                                      );

Add a plugin to handle top-level directives.

=head1 PLUGIN METHODS

These methods can be defined by the plugin to modify the emitted code.

=head2 register_plugin

    sub register_plugin {
        my( $class, $parser ) = @_;

        # call the various add_*_plugin methods to register the plugin
    }

This method is called once for each loaded plugin, the first time the
parser sees the C<%loadplugin> directive.

TODO add another method that is called once for each C<%loadplugin>
declaration, and allow passing parameters to the plugin.

=head2 post_process

    sub post_process {
        my( $self, $nodes ) = @_;

        # process and mutate the list of nodes
    }

=head2 handle_function_tag

    sub handle_function_tag {
        my( $self, $function, $tag, %args ) = @_;

        # do something useful
    }

C<$function> is a C<Function> node.  C<$tag> is the tag string,
without the C<%> prefix.  C<%args> are the arguments passed to the
tag.

If the method handles the tag, it must return C<1> to the caller.

=head2 handle_class_tag

    sub handle_class_tag {
        my( $self, $class, $tag, %args ) = @_;

        # do something useful
    }

C<$class> is a C<Class> node.  C<$tag> is the tag string, without the
C<%> prefix.  C<%args> are the arguments passed to the tag.  The
handler for the class is called after the handlers for its methods.

If the method handles the tag, it must return C<1> to the caller.

=head2 handle_method_tag

    sub handle_method_tag {
        my( $self, $method, $tag, %args ) = @_;

        # do something useful
    }

C<$method> is a C<Method> node.  C<$tag> is the tag string, without
the C<%> prefix.  C<%args> are the arguments passed to the tag.

If the method handles the tag, it must return C<1> to the caller.

=head2 handle_toplevel_tag

    sub handle_toplevel_tag {
        my( $self, undef, $tag, %args ) = @_;

        # do something useful
    }

C<$tag> is the tag string, without the C<%> prefix.  C<%args> are the
arguments passed to the tag.  The C<undef> value is for uniformity
with other tag handlers.

If the method handles the tag, it must return C<1> to the caller.

=end internal

=cut
